File indexing completed on 2024-04-28 05:50:04

0001 /*
0002  * SPDX-License-Identifier: GPL-3.0-or-later
0003  * SPDX-FileCopyrightText: 2020 Johan Ouwerkerk <jm.ouwerkerk@gmail.com>
0004  */
0005 #include "secrets/secrets.h"
0006 
0007 #include <QTest>
0008 #include <QtDebug>
0009 
0010 #include <string.h>
0011 
0012 class EncryptionDecryptionRoundTripTest: public QObject
0013 {
0014     Q_OBJECT
0015 private Q_SLOTS:
0016     void testEncryptionDecryptionRoundTrip(void);
0017     void testDecryptionOfCorruptInputs(void);
0018 };
0019 
0020 void EncryptionDecryptionRoundTripTest::testEncryptionDecryptionRoundTrip(void)
0021 {
0022     QScopedPointer<secrets::SecureMemory> passwd(secrets::SecureMemory::allocate(13ULL));
0023     QVERIFY2(passwd, "password memory should be allocated");
0024     memcpy(passwd->data(), "Hello, world!", passwd->size());
0025 
0026     std::optional<secrets::KeyDerivationParameters> defaults = secrets::KeyDerivationParameters::create();
0027     QVERIFY2(defaults, "defaults should yield a valid key parameters object");
0028 
0029     QScopedPointer<secrets::SecureMasterKey> masterKey(secrets::SecureMasterKey::derive(passwd.data(), *defaults));
0030     QVERIFY2(masterKey, "key derivation should succeed");
0031 
0032     QScopedPointer<secrets::SecureMemory> payload(secrets::SecureMemory::allocate(42ULL));
0033     QVERIFY2(payload, "allocating the secure memory input buffer should succeed");
0034 
0035     memset(payload->data(), 'B', 42ULL);
0036 
0037     std::optional<secrets::EncryptedSecret> encrypted = masterKey->encrypt(payload.data());
0038     QVERIFY2(encrypted, "encryption of the payload should succeed");
0039 
0040     QScopedPointer<secrets::SecureMemory> decrypted(masterKey->decrypt(*encrypted));
0041     QVERIFY2(decrypted, "decryption should succeed");
0042 
0043     QCOMPARE(decrypted->size(), 42ULL);
0044 
0045     QByteArray copyOfDecrypted;
0046     copyOfDecrypted.append(reinterpret_cast<const char *>(decrypted->constData()), 42ULL);
0047 
0048     QByteArray expected(42, 'B');
0049     QCOMPARE(copyOfDecrypted, expected);
0050 }
0051 
0052 void EncryptionDecryptionRoundTripTest::testDecryptionOfCorruptInputs(void)
0053 {
0054     QScopedPointer<secrets::SecureMemory> passwd(secrets::SecureMemory::allocate(13ULL));
0055     QVERIFY2(passwd, "password memory should be allocated");
0056     memcpy(passwd->data(), "Hello, world!", passwd->size());
0057 
0058     std::optional<secrets::KeyDerivationParameters> defaults = secrets::KeyDerivationParameters::create();
0059     QVERIFY2(defaults, "defaults should yield a valid key parameters object");
0060 
0061     QScopedPointer<secrets::SecureMasterKey> masterKey(secrets::SecureMasterKey::derive(passwd.data(), *defaults));
0062     QVERIFY2(masterKey, "key derivation should succeed");
0063 
0064     QScopedPointer<secrets::SecureMemory> payload(secrets::SecureMemory::allocate(42ULL));
0065     QVERIFY2(payload, "allocating the secure memory input buffer should succeed");
0066 
0067     memset(payload->data(), 'B', 42ULL);
0068 
0069     std::optional<secrets::EncryptedSecret> encrypted = masterKey->encrypt(payload.data());
0070     QVERIFY2(encrypted, "encryption of the payload should succeed");
0071 
0072     QByteArray brokenTag(encrypted->cryptText());
0073     brokenTag[0] = brokenTag[0] ^ ((char) 0xFF);
0074 
0075     std::optional<secrets::EncryptedSecret> fakedTag = secrets::EncryptedSecret::from(brokenTag, encrypted->nonce());
0076     QVERIFY2(fakedTag, "should be able to construct the 'fake' encrypted input (tag)");
0077 
0078     QScopedPointer<secrets::SecureMemory> decryptedUsingFakeTag(masterKey->decrypt(*fakedTag));
0079     QVERIFY2(!decryptedUsingFakeTag, "decryption should fail when the authentication tag has been tampered with");
0080 
0081     QByteArray brokenPayload(encrypted->cryptText());
0082     brokenPayload[brokenPayload.size() - 1] = brokenPayload[brokenPayload.size() - 1] ^ ((char) 0xFF);
0083 
0084     std::optional<secrets::EncryptedSecret> fakedPayload = secrets::EncryptedSecret::from(brokenPayload, encrypted->nonce());
0085     QVERIFY2(fakedPayload, "should be able to construct the 'fake' encrypted input (payload)");
0086 
0087     QScopedPointer<secrets::SecureMemory> decryptedUsingFakePayload(masterKey->decrypt(*fakedPayload));
0088     QVERIFY2(!decryptedUsingFakePayload, "decryption should fail when the payload has been tampered with");
0089 
0090     QByteArray brokenNonce(encrypted->nonce());
0091     brokenNonce[0] = brokenNonce[0] ^ ((char) 0xFF);
0092 
0093     std::optional<secrets::EncryptedSecret> fakedNonce = secrets::EncryptedSecret::from(encrypted->cryptText(), brokenNonce);
0094     QVERIFY2(fakedNonce, "should be able to construct the 'fake' encrypted input (nonce)");
0095 
0096     QScopedPointer<secrets::SecureMemory> decryptedUsingFakeNonce(masterKey->decrypt(*fakedNonce));
0097     QVERIFY2(!decryptedUsingFakeNonce, "decryption should fail when the nonce has been tampered with");
0098 }
0099 
0100 QTEST_APPLESS_MAIN(EncryptionDecryptionRoundTripTest)
0101 
0102 #include "encrypt-decrypt-rt.moc"