From 21f6c0a9cdd5ed67e48bb1f39f72217b5fe4758f Mon Sep 17 00:00:00 2001 From: vnugent Date: Sun, 3 Mar 2024 15:02:02 -0500 Subject: Squashed commit of the following: commit 490dfee4ef22479009627435c6ad728c3cbbab54 Author: vnugent Date: Sun Mar 3 14:59:25 2024 -0500 test: #3 tests for encryption/description and Macs commit efa97490b7ed47f4e2f05bee52e2b33e14e439e6 Merge: 1b84e3c 120022a Author: vnugent Date: Sun Mar 3 14:55:48 2024 -0500 merge master commit 1b84e3c7c2e55b1ff9ffdd09b66873e11c131441 Author: vnugent Date: Sat Mar 2 22:57:36 2024 -0500 fix: #2 constent usage of sizeof() operator on struct types commit 9de5a214c66adea0ef2d0bac63c59449de202a88 Author: vnugent Date: Fri Mar 1 14:30:36 2024 -0500 perf: avoid nc_key struct copy, cast and verify instead commit b917b761120ed684af28d0707673ffadcf14b8fe Author: vnugent Date: Mon Feb 12 22:06:50 2024 -0500 fix: found the constant time memcompare function commit 9f85fff3b9f25da7410569ea94f994b88feb3910 Author: vnugent Date: Fri Feb 9 22:48:35 2024 -0500 feat: added/update MAC functions to sign or verify nip44 payload commit aa5113741bb419b02d6ea416bba571fa3d65db46 Author: vnugent Date: Wed Feb 7 01:37:53 2024 -0500 add missing hmac-key output buffer commit 55f47d22cc9ce4d1e22b70814d608c7ef3b1bbc9 Author: vnugent Date: Sun Feb 4 21:08:13 2024 -0500 simple bug fixes, and public api argument validation tests commit 73c5a713fb164ae8b4ac8a891a8020e08eae0a3b Author: vnugent Date: Fri Feb 2 23:05:48 2024 -0500 update api to return secpvalidate return code instead of internal return codes commit 06c73004e1a39a7ea4ea3a89c22dee0f66adb236 Author: vnugent Date: Fri Feb 2 19:25:17 2024 -0500 change to lgpl license commit 6e79fdb3b6b6739fc7797d47e55a7691306cf736 Author: vnugent Date: Wed Jan 31 21:30:49 2024 -0500 move validation macros, and optionally disable them commit ac1e58837f1ba687939f78b5c03cadd346c10ddd Author: vnugent Date: Tue Jan 30 12:25:05 2024 -0500 couple more tests, renable range checks, set flags for all projects --- tests/test.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 187 insertions(+), 32 deletions(-) (limited to 'tests/test.c') diff --git a/tests/test.c b/tests/test.c index d8fa89c..09e195b 100644 --- a/tests/test.c +++ b/tests/test.c @@ -27,7 +27,7 @@ #include #include -#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32) +#ifdef _NC_IS_WINDOWS #define IS_WINDOWS #endif @@ -46,8 +46,8 @@ #endif /*Prints a string literal to the console*/ -#define PRINTL(x) printf(x); printf("\n"); -#define ENSURE(x) if(!(x)) { printf("Assumption failed!\n"); return 1; } +#define PRINTL(x) puts(x); puts("\n"); +#define ENSURE(x) if(!(x)) { puts("Assumption failed!\n"); return 1; } #define TEST(x, expected) printf("\tTesting %s\n", #x); if(((long)x) != ((long)expected)) \ { printf("FAILED: Expected %ld but got %ld @ callsite %s. Line: %d \n", ((long)expected), ((long)x), #x, __LINE__); return 1; } @@ -58,6 +58,15 @@ #define ZERO_FILL(x, size) memset(x, 0, size) #endif + +#ifdef IS_WINDOWS + #define memmove(dst, src, size) memmove_s(dst, size, src, size) +#else + #include +#endif + +#include "hex.h" + //Pre-computed constants for argument errors #define ARG_ERROR_POS_0 E_NULL_PTR #define ARG_ERROR_POS_1 NCResultWithArgPosition(E_NULL_PTR, 0x01) @@ -83,11 +92,12 @@ #define ARG_INVALID_ERROR_POS_5 NCResultWithArgPosition(E_INVALID_ARG, 0x05) #define ARG_INVALID_ERROR_POS_6 NCResultWithArgPosition(E_INVALID_ARG, 0x06) - - +static int RunTests(void); static void FillRandomData(void* pbBuffer, size_t length); static int TestEcdsa(NCContext* context, NCSecretKey* secKey, NCPublicKey* pubKey); static int InitKepair(NCContext* context, NCSecretKey* secKey, NCPublicKey* pubKey); +static int TestKnownKeys(NCContext* context); +static int TestCorrectEncryption(NCContext* context); #ifndef NC_INPUT_VALIDATION_OFF static int TestPublicApiArgumentValidation(void); @@ -97,13 +107,23 @@ static const uint8_t zero32[32] = { 0 }; static const uint8_t zero64[64] = { 0 }; int main(void) +{ + int result; + result = RunTests(); + + FreeHexBytes(); + + return 0; +} + +static int RunTests(void) { NCContext ctx; uint8_t ctxRandom[32]; NCSecretKey secKey; NCPublicKey pubKey; - PRINTL("Begining basic noscrypt tests\n") + PRINTL("Begining basic noscrypt tests") FillRandomData(ctxRandom, 32); @@ -112,27 +132,37 @@ int main(void) TEST(NCInitContext(&ctx, ctxRandom), NC_SUCCESS) if (InitKepair(&ctx, &secKey, &pubKey) != 0) - { - return 1; - } - + { + return 1; + } + if (TestEcdsa(&ctx, &secKey, &pubKey) != 0) { return 1; } + if (TestKnownKeys(&ctx) != 0) + { + return 1; + } + #ifndef NC_INPUT_VALIDATION_OFF - if(TestPublicApiArgumentValidation() != 0) - { - return 1; - } + if (TestPublicApiArgumentValidation() != 0) + { + return 1; + } #endif - PRINTL("ECDSA tests passed\n") + if (TestCorrectEncryption(&ctx) != 0) + { + return 1; + } TEST(NCDestroyContext(&ctx), NC_SUCCESS) - return 0; + PRINTL("\nSUCCESS All tests passed") + + return 0; } static void _sha256(const uint8_t* data, size_t length, uint8_t digest[32]) @@ -149,7 +179,7 @@ static const char* message = "Test message to sign"; static int InitKepair(NCContext* context, NCSecretKey* secKey, NCPublicKey* pubKey) { - PRINTL("TEST: Keypair\n") + PRINTL("TEST: Keypair") //Get random private key FillRandomData(secKey, sizeof(NCSecretKey)); @@ -163,7 +193,7 @@ static int InitKepair(NCContext* context, NCSecretKey* secKey, NCPublicKey* pubK //Generate a public key from the secret key TEST(NCGetPublicKey(context, secKey, pubKey), NC_SUCCESS); - PRINTL("\nPASSED: Keypair tests completed\n") + PRINTL("\nPASSED: Keypair tests completed") return 0; } @@ -174,7 +204,7 @@ static int TestEcdsa(NCContext* context, NCSecretKey* secKey, NCPublicKey* pubKe uint8_t sigEntropy[32]; uint8_t invalidSig[64]; - PRINTL("TEST: Ecdsa\n") + PRINTL("TEST: Ecdsa") //Init a new secret key with random data FillRandomData(invalidSig, sizeof(invalidSig)); @@ -229,7 +259,7 @@ static int TestEcdsa(NCContext* context, NCSecretKey* secKey, NCPublicKey* pubKe TEST(NCVerifyDigest(context, pubKey, digestToSign, invalidSig), E_INVALID_ARG); } - PRINTL("\nPASSED: Ecdsa tests completed\n") + PRINTL("\nPASSED: Ecdsa tests completed") return 0; } @@ -243,8 +273,9 @@ static int TestPublicApiArgumentValidation(void) NCSecretKey secKey; NCPublicKey pubKey; NCCryptoData cryptoData; + uint8_t hmacKeyOut[NC_HMAC_KEY_SIZE]; - PRINTL("TEST: Public API argument validation tests\n") + PRINTL("TEST: Public API argument validation tests") FillRandomData(ctxRandom, 32); @@ -302,24 +333,25 @@ static int TestPublicApiArgumentValidation(void) cryptoData.outputData = sig64; FillRandomData(&cryptoData.nonce, 32); - TEST(NCEncrypt(NULL, &secKey, &pubKey, &cryptoData), ARG_ERROR_POS_0) - TEST(NCEncrypt(&ctx, NULL, &pubKey, &cryptoData), ARG_ERROR_POS_1) - TEST(NCEncrypt(&ctx, &secKey, NULL, &cryptoData), ARG_ERROR_POS_2) - TEST(NCEncrypt(&ctx, &secKey, &pubKey, NULL), ARG_ERROR_POS_3) + TEST(NCEncrypt(NULL, &secKey, &pubKey, hmacKeyOut, &cryptoData), ARG_ERROR_POS_0) + TEST(NCEncrypt(&ctx, NULL, &pubKey, hmacKeyOut, &cryptoData), ARG_ERROR_POS_1) + TEST(NCEncrypt(&ctx, &secKey, NULL, hmacKeyOut, &cryptoData), ARG_ERROR_POS_2) + TEST(NCEncrypt(&ctx, &secKey, &pubKey, NULL, &cryptoData), ARG_ERROR_POS_3) + TEST(NCEncrypt(&ctx, &secKey, &pubKey, hmacKeyOut, NULL), ARG_ERROR_POS_4) //Test invalid data size cryptoData.dataSize = 0; - TEST(NCEncrypt(&ctx, &secKey, &pubKey, &cryptoData), ARG_RAMGE_ERROR_POS_3) + TEST(NCEncrypt(&ctx, &secKey, &pubKey, hmacKeyOut, &cryptoData), ARG_RAMGE_ERROR_POS_4) //Test null input data cryptoData.dataSize = 32; cryptoData.inputData = NULL; - TEST(NCEncrypt(&ctx, &secKey, &pubKey, &cryptoData), ARG_INVALID_ERROR_POS_3) + TEST(NCEncrypt(&ctx, &secKey, &pubKey, hmacKeyOut, &cryptoData), ARG_INVALID_ERROR_POS_4) //Test null output data cryptoData.inputData = zero32; cryptoData.outputData = NULL; - TEST(NCEncrypt(&ctx, &secKey, &pubKey, &cryptoData), ARG_INVALID_ERROR_POS_3) + TEST(NCEncrypt(&ctx, &secKey, &pubKey, hmacKeyOut, &cryptoData), ARG_INVALID_ERROR_POS_4) //Decrypt cryptoData.dataSize = 32; @@ -343,14 +375,137 @@ static int TestPublicApiArgumentValidation(void) //Test null output data cryptoData.inputData = zero32; cryptoData.outputData = NULL; - TEST(NCDecrypt(&ctx, &secKey, &pubKey, &cryptoData), ARG_INVALID_ERROR_POS_3) + TEST(NCDecrypt(&ctx, &secKey, &pubKey, &cryptoData), ARG_INVALID_ERROR_POS_3) + + { + uint8_t hmacDataOut[NC_ENCRYPTION_MAC_SIZE]; + TEST(NCComputeMac(NULL, hmacKeyOut, zero32, 32, hmacDataOut), ARG_ERROR_POS_0) + TEST(NCComputeMac(&ctx, NULL, zero32, 32, hmacDataOut), ARG_ERROR_POS_1) + TEST(NCComputeMac(&ctx, hmacKeyOut, NULL, 32, hmacDataOut), ARG_ERROR_POS_2) + TEST(NCComputeMac(&ctx, hmacKeyOut, zero32, 0, hmacDataOut), ARG_RAMGE_ERROR_POS_3) + TEST(NCComputeMac(&ctx, hmacKeyOut, zero32, 32, NULL), ARG_ERROR_POS_4) + } + + { + NCMacVerifyArgs macArgs; + macArgs.payload = zero32; + macArgs.payloadSize = 32; - PRINTL("\nPASSED: Public API argument validation tests completed\n") + TEST(NCVerifyMac(NULL, &secKey, &pubKey, &macArgs), ARG_ERROR_POS_0) + TEST(NCVerifyMac(&ctx, NULL, &pubKey, &macArgs), ARG_ERROR_POS_1) + TEST(NCVerifyMac(&ctx, &secKey, NULL, &macArgs), ARG_ERROR_POS_2) + TEST(NCVerifyMac(&ctx, &secKey, &pubKey, NULL), ARG_ERROR_POS_3) + + macArgs.payload = NULL; + TEST(NCVerifyMac(&ctx, &secKey, &pubKey, &macArgs), ARG_INVALID_ERROR_POS_3) + + macArgs.payload = zero32; + macArgs.payloadSize = 0; + TEST(NCVerifyMac(&ctx, &secKey, &pubKey, &macArgs), ARG_RAMGE_ERROR_POS_3) + } + + PRINTL("\nPASSED: Public API argument validation tests completed") return 0; } -#endif +#endif + +static int TestKnownKeys(NCContext* context) +{ + PRINTL("TEST: Known keys") + + NCPublicKey pubKey; + + HexBytes* secKey1 = FromHexString("98c642360e7163a66cee5d9a842b252345b6f3f3e21bd3b7635d5e6c20c7ea36", sizeof(secKey)); + HexBytes* pubKey1 = FromHexString("0db15182c4ad3418b4fbab75304be7ade9cfa430a21c1c5320c9298f54ea5406", sizeof(pubKey)); + + HexBytes* secKey2 = FromHexString("3032cb8da355f9e72c9a94bbabae80ca99d3a38de1aed094b432a9fe3432e1f2", sizeof(secKey)); + HexBytes* pubKey2 = FromHexString("421181660af5d39eb95e48a0a66c41ae393ba94ffeca94703ef81afbed724e5a", sizeof(pubKey)); + + //Test known keys + TEST(NCValidateSecretKey(context, NCToSecKey(secKey1->data)), 1); + + /* Recover a public key from secret key 1 */ + TEST(NCGetPublicKey(context, NCToSecKey(secKey1->data), &pubKey), NC_SUCCESS); + + /* Ensure the public key matches the known public key value */ + TEST(memcmp(pubKey1->data, &pubKey, sizeof(pubKey)), 0); + + /* Repeat with second key */ + TEST(NCValidateSecretKey(context, (NCSecretKey*)secKey2->data), 1); + TEST(NCGetPublicKey(context, (NCSecretKey*)secKey2->data, &pubKey), NC_SUCCESS); + TEST(memcmp(pubKey2->data, &pubKey, sizeof(pubKey)), 0); + + PRINTL("\nPASSED: Known keys tests completed") + return 0; +} + +#define TEST_ENC_DATA_SIZE 128 + +static int TestCorrectEncryption(NCContext* context) +{ + NCSecretKey secKey1; + NCPublicKey pubKey1; + + NCSecretKey secKey2; + NCPublicKey pubKey2; + + NCCryptoData cryptoData; + NCMacVerifyArgs macVerifyArgs; + uint8_t hmacKeyOut[NC_HMAC_KEY_SIZE]; + + uint8_t plainText[TEST_ENC_DATA_SIZE]; + uint8_t cipherText[TEST_ENC_DATA_SIZE]; + uint8_t decryptedText[TEST_ENC_DATA_SIZE]; + + PRINTL("TEST: Correct encryption") + + /* init a sending and receiving key */ + FillRandomData(&secKey1, sizeof(NCSecretKey)); + FillRandomData(&secKey2, sizeof(NCSecretKey)); + FillRandomData(plainText, sizeof(plainText)); + + ENSURE(NCValidateSecretKey(context, &secKey1) == 1); + ENSURE(NCValidateSecretKey(context, &secKey2) == 1); + + ENSURE(NCGetPublicKey(context, &secKey1, &pubKey1) == NC_SUCCESS); + ENSURE(NCGetPublicKey(context, &secKey2, &pubKey2) == NC_SUCCESS); + + /* setup the crypto data structure */ + cryptoData.dataSize = TEST_ENC_DATA_SIZE; + cryptoData.inputData = plainText; + cryptoData.outputData = cipherText; + /* add a random nonce, we will keep it stored in the nonce field of the struct */ + FillRandomData(cryptoData.nonce, NC_ENCRYPTION_NONCE_SIZE); + + /* Try to encrypt the data from sec1 to pub2 */ + TEST(NCEncrypt(context, &secKey1, &pubKey2, hmacKeyOut, &cryptoData), NC_SUCCESS); + + //swap texts + cryptoData.inputData = cipherText; + cryptoData.outputData = decryptedText; + + /* Try to decrypt the data from sec1 to pub2 */ + TEST(NCDecrypt(context, &secKey2, &pubKey1, &cryptoData), NC_SUCCESS); + + /* Ensure the decrypted text matches the original */ + TEST(memcmp(plainText, decryptedText, sizeof(plainText)), 0); + + /* Also try to validate the payload mac */ + memmove(macVerifyArgs.nonce, cryptoData.nonce, NC_ENCRYPTION_NONCE_SIZE); + macVerifyArgs.payload = cipherText; + macVerifyArgs.payloadSize = TEST_ENC_DATA_SIZE; + + /* Compute message mac on ciphertext */ + TEST(NCComputeMac(context, hmacKeyOut, cipherText, sizeof(cipherText), macVerifyArgs.mac), NC_SUCCESS); + + /* Verify the mac */ + TEST(NCVerifyMac(context, &secKey1, &pubKey2, &macVerifyArgs), NC_SUCCESS); + + PRINTL("\nPASSED: Correct encryption tests completed") + return 0; +} static void FillRandomData(void* pbBuffer, size_t length) { @@ -368,4 +523,4 @@ static void FillRandomData(void* pbBuffer, size_t length) TASSERT(fread(pbBuffer, 1, length, f) == length); fclose(f); #endif -} \ No newline at end of file +} -- cgit