From 519f8747123964cc4907c26c3cbde98579266fe9 Mon Sep 17 00:00:00 2001 From: Emma Stensland Date: Thu, 2 Jul 2026 09:44:51 -0600 Subject: [PATCH 1/3] F-1302 F-1303 F-1304 F-1308 F-3471 F-3691 F-4601: fix buffer overflows, malloc/realloc NULL checks, and padding validation in crypto file-encryption examples --- certfields/all-fields/main.c | 2 +- crypto/3des/3des-file-encrypt.c | 165 +++++++++++++++++++------- crypto/aes-modes/aes-keywrap.c | 56 ++++++--- crypto/aes/aes-file-encrypt.c | 179 ++++++++++++++++++++-------- crypto/aes/aescfb-file-encrypt.c | 181 +++++++++++++++++++++-------- crypto/aes/aesctr-file-encrypt.c | 142 +++++++++++++++------- crypto/aes/aesgcm-file-encrypt.c | 85 +++++++++----- crypto/camellia/camellia-encrypt.c | 160 +++++++++++++++++++------ tls/client-tls-uart.c | 2 +- tls/server-tls-uart.c | 2 +- 10 files changed, 702 insertions(+), 272 deletions(-) diff --git a/certfields/all-fields/main.c b/certfields/all-fields/main.c index f8324e975..0468b5235 100644 --- a/certfields/all-fields/main.c +++ b/certfields/all-fields/main.c @@ -64,7 +64,7 @@ int main(int argc, char** argv) RsaKey pubKeyRsa; ecc_key pubKeyEcc; - WOLFSSL_X509* cert; + WOLFSSL_X509* cert = NULL; WOLFSSL_EVP_PKEY* pubKeyTmp; WOLFSSL_X509_NAME* name; diff --git a/crypto/3des/3des-file-encrypt.c b/crypto/3des/3des-file-encrypt.c index aa82d372a..f1c4a3444 100644 --- a/crypto/3des/3des-file-encrypt.c +++ b/crypto/3des/3des-file-encrypt.c @@ -27,6 +27,7 @@ #include #include #include +#include #define DES3_BLOCK_SIZE 24 /* size of encryption blocks */ #define SALT_SIZE 8 @@ -82,12 +83,24 @@ int Des3Encrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) padCounter++; } - input = malloc(length); - output = malloc(length); + input = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1012; + } ret = wc_InitRng(&rng); if (ret != 0) { printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1030; } @@ -127,12 +140,12 @@ int Des3Encrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, length); - memset(output, 0, length); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, length); + wc_ForceZero(output, length); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -161,62 +174,126 @@ int Des3Decrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); + if (length < SALT_SIZE + DES3_BLOCK_SIZE) { + printf("Input file is too small.\n"); + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1011; + } + + input = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1012; + } - wc_InitRng(&rng); + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1030; + } /* reads from inFile and writes whatever is there to the input array */ ret = fread(input, 1, length, inFile); if (ret == 0) { printf("Input file does not exist.\n"); - return -1010; - } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; + ret = -1010; } - for (i = SALT_SIZE; i < DES3_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + if (ret > 0) { + for (i = 0; i < SALT_SIZE; i++) { + /* finds salt from input message */ + salt[i] = input[i]; + } + for (i = SALT_SIZE; i < DES3_BLOCK_SIZE + SALT_SIZE; i++) { + /* finds iv from input message */ + iv[i - SALT_SIZE] = input[i]; + } + + /* replicates old key if keys match */ + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; } - /* replicates old key if keys match */ - ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, 4096, - size, WC_SHA256); - if (ret != 0) - return -1050; + if (ret == 0) { + /* sets key */ + ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); + if (ret != 0) + ret = -1002; + } - /* sets key */ - ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); - if (ret != 0) - return -1002; + if (ret == 0) { + /* change length to remove salt/iv block from being decrypted */ + length -= (DES3_BLOCK_SIZE + SALT_SIZE); + for (i = 0; i < length; i++) { + /* shifts message: ignores salt/iv on message*/ + input[i] = input[i + (DES3_BLOCK_SIZE + SALT_SIZE)]; + } + /* decrypts the message to output based on input length + padding */ + ret = wc_Des3_CbcDecrypt(des3, output, input, length); + if (ret != 0) + ret = -1006; + } - /* change length to remove salt/iv block from being decrypted */ - length -= (DES3_BLOCK_SIZE + SALT_SIZE); - for (i = 0; i < length; i++) { - /* shifts message: ignores salt/iv on message*/ - input[i] = input[i + (DES3_BLOCK_SIZE + SALT_SIZE)]; + if (ret != 0) { + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return ret; } - /* decrypts the message to output based on input length + padding */ - ret = wc_Des3_CbcDecrypt(des3, output, input, length); - if (ret != 0) - return -1006; if (salt[0] != 0) { /* reduces length based on number of padded elements */ + if (length < 1 || output[length-1] < 1 || + output[length-1] > length || + output[length-1] > DES3_BLOCK_SIZE) { + printf("Error: invalid padding value\n"); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return -1013; + } length -= output[length-1]; } /* writes output to the outFile based on shortened length */ fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, aSize); - memset(output, 0, aSize); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -340,7 +417,7 @@ int main(int argc, char** argv) } else if (ret == 0 && choice != 'n') { - key = malloc(size); /* sets size memory of key */ + key = XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ ret = NoEcho((char*)key, size); if (choice == 'e') Des3Encrypt(&des3, key, size, inFile, outFile); diff --git a/crypto/aes-modes/aes-keywrap.c b/crypto/aes-modes/aes-keywrap.c index 51a669a8e..96eecf86f 100644 --- a/crypto/aes-modes/aes-keywrap.c +++ b/crypto/aes-modes/aes-keywrap.c @@ -38,6 +38,7 @@ #include #include #include +#include #if !defined(NO_AES) && defined(HAVE_AES_KEYWRAP) @@ -61,7 +62,7 @@ static int read_file(const char* filename, byte** data, word32* dataSz) fileSz = ftell(fp); fseek(fp, 0, SEEK_SET); - *data = (byte*)malloc(fileSz); + *data = (byte*)XMALLOC(fileSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (*data == NULL) { fclose(fp); printf("Error: Memory allocation failed\n"); @@ -112,16 +113,25 @@ static int wrap_file(const char* inFile, const char* outFile, /* Wrapped output is input + 8 bytes (integrity check value) */ /* Also store original size (4 bytes) at beginning */ wrappedSz = 4 + paddedSz + KEYWRAP_BLOCK; - wrapped = (byte*)malloc(wrappedSz); + wrapped = (byte*)XMALLOC(wrappedSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (wrapped == NULL) { - free(plaintext); + wc_ForceZero(plaintext, plaintextSz); + XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1; } /* Apply padding if needed */ if (padLen > 0) { - plaintext = (byte*)realloc(plaintext, paddedSz); - memset(plaintext + plaintextSz, 0, padLen); + byte* tmp = (byte*)XREALLOC(plaintext, paddedSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + wc_ForceZero(plaintext, plaintextSz); + XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } + plaintext = tmp; + XMEMSET(plaintext + plaintextSz, 0, padLen); } /* One-shot key wrap */ @@ -129,8 +139,9 @@ static int wrap_file(const char* inFile, const char* outFile, wrapped + 4, wrappedSz - 4, NULL); if (ret < 0) { - free(plaintext); - free(wrapped); + wc_ForceZero(plaintext, paddedSz); + XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -142,8 +153,9 @@ static int wrap_file(const char* inFile, const char* outFile, ret = write_file(outFile, wrapped, wrappedSz); - free(plaintext); - free(wrapped); + wc_ForceZero(plaintext, paddedSz); + XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf("AES-KEYWRAP wrapping complete (one-shot)\n"); return ret; @@ -164,7 +176,7 @@ static int unwrap_file(const char* inFile, const char* outFile, if (ret != 0) return ret; if (wrappedSz < 4 + KEYWRAP_BLOCK * 2) { - free(wrapped); + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf("Error: File too small\n"); return -1; } @@ -177,9 +189,14 @@ static int unwrap_file(const char* inFile, const char* outFile, /* Unwrapped size is wrapped - 4 (size header) - 8 (integrity check) */ plaintextSz = wrappedSz - 4 - KEYWRAP_BLOCK; - plaintext = (byte*)malloc(plaintextSz); + if (originalSz > plaintextSz) { + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); + printf("Error: Invalid decrypted size\n"); + return -1; + } + plaintext = (byte*)XMALLOC(plaintextSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (plaintext == NULL) { - free(wrapped); + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1; } @@ -188,8 +205,9 @@ static int unwrap_file(const char* inFile, const char* outFile, plaintext, plaintextSz, NULL); if (ret < 0) { - free(wrapped); - free(plaintext); + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_ForceZero(plaintext, plaintextSz); + XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf("Error: Key unwrap failed (integrity check may have failed)\n"); return ret; } @@ -197,8 +215,9 @@ static int unwrap_file(const char* inFile, const char* outFile, /* Use original size to remove padding */ ret = write_file(outFile, plaintext, originalSz); - free(wrapped); - free(plaintext); + XFREE(wrapped, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_ForceZero(plaintext, plaintextSz); + XFREE(plaintext, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf("AES-KEYWRAP unwrapping complete (one-shot, no streaming API " "available)\n"); @@ -220,12 +239,13 @@ int main(int argc, char** argv) wolfCrypt_Init(); /* Use a fixed key for demonstration */ - memset(key, 0x0C, AES_KEY_SIZE); + XMEMSET(key, 0x0C, AES_KEY_SIZE); /* Wrap to temporary file */ ret = wrap_file(argv[1], "temp_wrapped.bin", key, AES_KEY_SIZE); if (ret != 0) { printf("Wrapping failed: %d\n", ret); + wc_ForceZero(key, AES_KEY_SIZE); wolfCrypt_Cleanup(); return 1; } @@ -234,6 +254,7 @@ int main(int argc, char** argv) ret = unwrap_file("temp_wrapped.bin", argv[2], key, AES_KEY_SIZE); if (ret != 0) { printf("Unwrapping failed: %d\n", ret); + wc_ForceZero(key, AES_KEY_SIZE); wolfCrypt_Cleanup(); return 1; } @@ -243,6 +264,7 @@ int main(int argc, char** argv) printf("Success! Unwrapped file written to %s\n", argv[2]); + wc_ForceZero(key, AES_KEY_SIZE); wolfCrypt_Cleanup(); return 0; } diff --git a/crypto/aes/aes-file-encrypt.c b/crypto/aes/aes-file-encrypt.c index 1da8f4ed5..aecb3fdc8 100644 --- a/crypto/aes/aes-file-encrypt.c +++ b/crypto/aes/aes-file-encrypt.c @@ -31,6 +31,7 @@ #include #include #include +#include #if defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) @@ -90,12 +91,24 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) padCounter++; } - input = malloc(length); - output = malloc(length); + input = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1012; + } ret = wc_InitRng(&rng); if (ret != 0) { printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1030; } @@ -144,12 +157,12 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, length); - memset(output, 0, length); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, length); + wc_ForceZero(output, length); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -178,71 +191,137 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); + if (length < SALT_SIZE + AES_BLOCK_SIZE) { + printf("Input file is too small.\n"); + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1011; + } - wc_InitRng(&rng); + input = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1012; + } + + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1030; + } /* reads from inFile and writes whatever is there to the input array */ ret = fread(input, 1, length, inFile); if (ret == 0) { printf("Input file does not exist.\n"); - return -1010; - } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; + ret = -1010; } - for (i = SALT_SIZE; i < AES_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + if (ret > 0) { + for (i = 0; i < SALT_SIZE; i++) { + /* finds salt from input message */ + salt[i] = input[i]; + } + for (i = SALT_SIZE; i < AES_BLOCK_SIZE + SALT_SIZE; i++) { + /* finds iv from input message */ + iv[i - SALT_SIZE] = input[i]; + } + + /* replicates old key if keys match */ + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; } - /* replicates old key if keys match */ - ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, 4096, - size, WC_SHA256); - if (ret != 0) - return -1050; + if (ret == 0) { + /* inits aes structure */ + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + printf("AesInit returned: %d\n", ret); + ret = -1001; + } + } - /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1001; + if (ret == 0) { + /* sets key */ + ret = wc_AesSetKey(aes, key, size, iv, AES_DECRYPTION); + if (ret != 0) { + printf("SetKey returned: %d\n", ret); + ret = -1002; + } } - /* sets key */ - ret = wc_AesSetKey(aes, key, size, iv, AES_DECRYPTION); - if (ret != 0) { - printf("SetKey returned: %d\n", ret); - return -1002; + if (ret == 0) { + /* change length to remove salt/iv block from being decrypted */ + length -= (AES_BLOCK_SIZE + SALT_SIZE); + for (i = 0; i < length; i++) { + /* shifts message: ignores salt/iv on message*/ + input[i] = input[i + (AES_BLOCK_SIZE + SALT_SIZE)]; + } + /* decrypts the message to output based on input length + padding*/ + ret = wc_AesCbcDecrypt(aes, output, input, length); + if (ret != 0) + ret = -1006; } - /* change length to remove salt/iv block from being decrypted */ - length -= (AES_BLOCK_SIZE + SALT_SIZE); - for (i = 0; i < length; i++) { - /* shifts message: ignores salt/iv on message*/ - input[i] = input[i + (AES_BLOCK_SIZE + SALT_SIZE)]; + if (ret != 0) { + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return ret; } - /* decrypts the message to output based on input length + padding*/ - ret = wc_AesCbcDecrypt(aes, output, input, length); - if (ret != 0) - return -1006; if (salt[0] != 0) { /* reduces length based on number of padded elements */ + if (length < 1 || output[length-1] < 1 || + output[length-1] > length || + output[length-1] > AES_BLOCK_SIZE) { + printf("Error: invalid padding value\n"); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return -1013; + } length -= output[length-1]; } /* writes output to the outFile based on shortened length */ fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, aSize); - memset(output, 0, aSize); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -375,7 +454,7 @@ int main(int argc, char** argv) printf(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n' && inFile != NULL) { - key = malloc(size); /* sets size memory of key */ + key = XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ ret = NoEcho((char*)key, size); if (choice == 'e') AesEncrypt(&aes, key, size, inFile, outFile); diff --git a/crypto/aes/aescfb-file-encrypt.c b/crypto/aes/aescfb-file-encrypt.c index 5c173687f..ca1f3e4fa 100644 --- a/crypto/aes/aescfb-file-encrypt.c +++ b/crypto/aes/aescfb-file-encrypt.c @@ -27,6 +27,7 @@ #include #include #include +#include #if defined(WOLFSSL_AES_CFB) && defined(HAVE_PBKDF2) && \ !defined(NO_PWDBASED) @@ -83,12 +84,24 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) padCounter++; } - input = malloc(length); - output = malloc(length); + input = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1012; + } ret = wc_InitRng(&rng); if (ret != 0) { printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1030; } @@ -137,12 +150,12 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, length); - memset(output, 0, length); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, length); + wc_ForceZero(output, length); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -171,72 +184,138 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); + if (length < SALT_SIZE + AES_BLOCK_SIZE) { + printf("Input file is too small.\n"); + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1011; + } - wc_InitRng(&rng); + input = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1012; + } + + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1030; + } /* reads from inFile and writes whatever is there to the input array */ ret = fread(input, 1, length, inFile); if (ret == 0) { printf("Input file does not exist.\n"); - return -1010; - } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; + ret = -1010; } - for (i = SALT_SIZE; i < AES_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + if (ret > 0) { + for (i = 0; i < SALT_SIZE; i++) { + /* finds salt from input message */ + salt[i] = input[i]; + } + for (i = SALT_SIZE; i < AES_BLOCK_SIZE + SALT_SIZE; i++) { + /* finds iv from input message */ + iv[i - SALT_SIZE] = input[i]; + } + + /* replicates old key if keys match */ + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; } - /* replicates old key if keys match */ - ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, 4096, - size, WC_SHA256); - if (ret != 0) - return -1050; + if (ret == 0) { + /* inits aes structure */ + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + printf("AesInit returned: %d\n", ret); + ret = -1002; + } + } - /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1002; + if (ret == 0) { + /* sets key */ + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("SetKey returned: %d\n", ret); + ret = -1002; + } } - /* sets key */ - /* decrypt uses AES_ENCRYPTION */ - ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("SetKey returned: %d\n", ret); - return -1002; + if (ret == 0) { + /* change length to remove salt/iv block from being decrypted */ + length -= (AES_BLOCK_SIZE + SALT_SIZE); + for (i = 0; i < length; i++) { + /* shifts message: ignores salt/iv on message*/ + input[i] = input[i + (AES_BLOCK_SIZE + SALT_SIZE)]; + } + /* decrypts the message to output based on input length + padding*/ + ret = wc_AesCfbDecrypt(aes, output, input, length); + if (ret != 0) + ret = -1006; } - /* change length to remove salt/iv block from being decrypted */ - length -= (AES_BLOCK_SIZE + SALT_SIZE); - for (i = 0; i < length; i++) { - /* shifts message: ignores salt/iv on message*/ - input[i] = input[i + (AES_BLOCK_SIZE + SALT_SIZE)]; + if (ret != 0) { + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return ret; } - /* decrypts the message to output based on input length + padding*/ - ret = wc_AesCfbDecrypt(aes, output, input, length); - if (ret != 0) - return -1006; if (salt[0] != 0) { /* reduces length based on number of padded elements */ + if (length < 1 || output[length-1] < 1 || + output[length-1] > length || + output[length-1] > AES_BLOCK_SIZE) { + printf("Error: invalid padding value\n"); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return -1013; + } length -= output[length-1]; } /* writes output to the outFile based on shortened length */ fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, aSize); - memset(output, 0, aSize); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -369,7 +448,7 @@ int main(int argc, char** argv) printf(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n' && inFile != NULL) { - key = malloc(size); /* sets size memory of key */ + key = XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ ret = NoEcho((char*)key, size); if (choice == 'e') AesEncrypt(&aes, key, size, inFile, outFile); diff --git a/crypto/aes/aesctr-file-encrypt.c b/crypto/aes/aesctr-file-encrypt.c index 366d694eb..ec3c3678b 100644 --- a/crypto/aes/aesctr-file-encrypt.c +++ b/crypto/aes/aesctr-file-encrypt.c @@ -27,6 +27,7 @@ #include #include #include +#include #if defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) && \ defined(WOLFSSL_AES_COUNTER) @@ -70,12 +71,24 @@ int AesCtrEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) length = ftell(inFile); fseek(inFile, 0, SEEK_SET); - input = malloc(length); - output = malloc(length); + input = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1012; + } ret = wc_InitRng(&rng); if (ret != 0) { printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1030; } @@ -120,12 +133,12 @@ int AesCtrEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, length); - memset(output, 0, length); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, length); + wc_ForceZero(output, length); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -140,68 +153,107 @@ int AesCtrDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) { byte* input; byte* output; - byte* salt; - byte* iv; - byte* c; + byte* salt = NULL; + byte* iv = NULL; + byte* c = NULL; int ret = 0; int bufSz; - int cSz; + int cSz = 0; fseek(inFile, 0, SEEK_END); bufSz = ftell(inFile); fseek(inFile, 0, SEEK_SET); - input = malloc(bufSz); - output = malloc(bufSz); + if (bufSz < SALT_SIZE + AES_BLOCK_SIZE) { + printf("Input file is too small.\n"); + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1011; + } + + input = XMALLOC(bufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(bufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1012; + } /* reads from inFile and writes whatever is there to the input array */ ret = fread(input, 1, bufSz, inFile); if (ret == 0) { printf("Input file does not exist.\n"); - return -1010; + ret = -1010; } - salt = input; - iv = input + SALT_SIZE; - c = input + SALT_SIZE + AES_BLOCK_SIZE; - cSz = bufSz - SALT_SIZE - AES_BLOCK_SIZE; + if (ret > 0) { + salt = input; + iv = input + SALT_SIZE; + c = input + SALT_SIZE + AES_BLOCK_SIZE; + cSz = bufSz - SALT_SIZE - AES_BLOCK_SIZE; + + /* replicates old key if keys match */ + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; + } - /* replicates old key if keys match */ - ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, 4096, - size, WC_SHA256); - if (ret != 0) - return -1050; + if (ret == 0) { + /* inits aes structure */ + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + printf("AesInit returned: %d\n", ret); + ret = -1002; + } + } - /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1002; + if (ret == 0) { + /* sets key */ + /* decrypt uses AES_ENCRYPTION */ + ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("SetKey returned: %d\n", ret); + ret = -1002; + } } - /* sets key */ - /* decrypt uses AES_ENCRYPTION */ - ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("SetKey returned: %d\n", ret); - return -1002; + if (ret == 0) { + ret = wc_AesCtrEncrypt(aes, output, c, cSz); + if (ret != 0) + ret = -1006; } - ret = wc_AesCtrEncrypt(aes, output, c, cSz); - if (ret != 0) - return -1006; + if (ret != 0) { + wc_ForceZero(input, bufSz); + wc_ForceZero(output, bufSz); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return ret; + } /* writes output to the outFile based on shortened length */ fwrite(output, 1, cSz, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, bufSz); - memset(output, 0, bufSz); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, bufSz); + wc_ForceZero(output, bufSz); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); @@ -333,7 +385,7 @@ int main(int argc, char** argv) printf(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n' && inFile != NULL) { - key = malloc(size); /* sets size memory of key */ + key = XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ ret = NoEcho((char*)key, size); if (choice == 'e') AesCtrEncrypt(&aes, key, size, inFile, outFile); diff --git a/crypto/aes/aesgcm-file-encrypt.c b/crypto/aes/aesgcm-file-encrypt.c index 65f3551b5..8073a5992 100644 --- a/crypto/aes/aesgcm-file-encrypt.c +++ b/crypto/aes/aesgcm-file-encrypt.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -212,26 +213,26 @@ int encrypt_file_AesGCM(const char *in_file, const char *out_file, buffer_size = MIN_BUFFER_SIZE; } - in_buf = malloc(buffer_size); + in_buf = XMALLOC(buffer_size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (in_buf == NULL) { perror("malloc"); close(in_fd); close(out_fd); exit(EXIT_FAILURE); } - out_buf = malloc(buffer_size); + out_buf = XMALLOC(buffer_size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (out_buf == NULL) { perror("malloc"); close(in_fd); close(out_fd); - free(in_buf); + XFREE(in_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); exit(EXIT_FAILURE); } - memset(&gcm, 0, sizeof(Aes)); - memset(iv, 0, AES_IV_SIZE); - memset(key, 0, AES_KEY_SIZE); - memset(tag_enc, 0, AESGCM_TAG_SIZE); + XMEMSET(&gcm, 0, sizeof(Aes)); + XMEMSET(iv, 0, AES_IV_SIZE); + XMEMSET(key, 0, AES_KEY_SIZE); + XMEMSET(tag_enc, 0, AESGCM_TAG_SIZE); strncpy((char *)iv, iv_str, AES_IV_SIZE); strncpy((char *)key, key_str, AES_KEY_SIZE); @@ -303,11 +304,20 @@ int encrypt_file_AesGCM(const char *in_file, const char *out_file, } printf("File encryption with AES GCM complete.\n"); exit: - free(in_buf); - free(out_buf); + wc_ForceZero(key, AES_KEY_SIZE); + wc_ForceZero(iv, AES_IV_SIZE); + wc_ForceZero(tag_enc, AESGCM_TAG_SIZE); + if (in_buf != NULL) + wc_ForceZero(in_buf, buffer_size); + if (out_buf != NULL) + wc_ForceZero(out_buf, buffer_size); + XFREE(in_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(out_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); close(in_fd); close(out_fd); - + if (ret != 0) { + unlink(out_file); + } return ret; } @@ -376,26 +386,26 @@ int decrypt_file_AesGCM(const char *in_file, const char *out_file, buffer_size = MIN_BUFFER_SIZE; } - in_buf = malloc(buffer_size); + in_buf = XMALLOC(buffer_size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (in_buf == NULL) { perror("malloc"); close(in_fd); close(out_fd); exit(EXIT_FAILURE); } - out_buf = malloc(buffer_size); + out_buf = XMALLOC(buffer_size, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (out_buf == NULL) { perror("malloc"); close(in_fd); close(out_fd); - free(in_buf); + XFREE(in_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); exit(EXIT_FAILURE); } - memset(&gcm, 0, sizeof(Aes)); - memset(iv, 0, AES_IV_SIZE); - memset(key, 0, AES_KEY_SIZE); - memset(tag, 0, AESGCM_TAG_SIZE); + XMEMSET(&gcm, 0, sizeof(Aes)); + XMEMSET(iv, 0, AES_IV_SIZE); + XMEMSET(key, 0, AES_KEY_SIZE); + XMEMSET(tag, 0, AESGCM_TAG_SIZE); strncpy((char *)key, key_str, AES_KEY_SIZE); /* Extract a WOLFCRYPT MAGIC | TAG | IV from the cipher file */ @@ -447,10 +457,20 @@ int decrypt_file_AesGCM(const char *in_file, const char *out_file, ret = wc_AesGcmDecryptFinal(&gcm, tag, AESGCM_TAG_SIZE); } exit: - free(in_buf); - free(out_buf); + wc_ForceZero(key, AES_KEY_SIZE); + wc_ForceZero(iv, AES_IV_SIZE); + wc_ForceZero(tag, AESGCM_TAG_SIZE); + if (in_buf != NULL) + wc_ForceZero(in_buf, buffer_size); + if (out_buf != NULL) + wc_ForceZero(out_buf, buffer_size); + XFREE(in_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(out_buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); close(in_fd); close(out_fd); + if (ret != 0) { + unlink(out_file); + } printf("File decryption with AES GCM complete.\n"); return ret; @@ -496,9 +516,9 @@ int encrypt_file(const char *in_file, const char *out_file, return -1; } - memset(iv, 0, AES_IV_SIZE); - memset(key, 0, AES_KEY_SIZE); - memset(tag_enc, 0, AESGCM_TAG_SIZE); + XMEMSET(iv, 0, AES_IV_SIZE); + XMEMSET(key, 0, AES_KEY_SIZE); + XMEMSET(tag_enc, 0, AESGCM_TAG_SIZE); strncpy((char *)iv, iv_str, AES_IV_SIZE); strncpy((char *)key, key_str, AES_KEY_SIZE); @@ -590,9 +610,15 @@ int encrypt_file(const char *in_file, const char *out_file, } printf("File encryption with EVP GCM complete.\n"); exit: + wc_ForceZero(key, AES_KEY_SIZE); + wc_ForceZero(iv, AES_IV_SIZE); + wc_ForceZero(tag_enc, AESGCM_TAG_SIZE); EVP_CIPHER_CTX_free(ctx); close(in_fd); close(out_fd); + if (ret != WOLFSSL_SUCCESS) { + unlink(out_file); + } return ret; } @@ -641,10 +667,10 @@ int decrypt_file(const char *in_file, const char *out_file, const char *key_str) return -1; } - memset(iv, 0, AES_IV_SIZE); - memset(key, 0, AES_KEY_SIZE); - memset(tag_enc, 0, AESGCM_TAG_SIZE); - memset(tag_dec, 0, AESGCM_TAG_SIZE); + XMEMSET(iv, 0, AES_IV_SIZE); + XMEMSET(key, 0, AES_KEY_SIZE); + XMEMSET(tag_enc, 0, AESGCM_TAG_SIZE); + XMEMSET(tag_dec, 0, AESGCM_TAG_SIZE); strncpy((char *)key, key_str, AES_KEY_SIZE); /* Extract a WOLFCRYPT MAGIC | TAG | IV from the cipher file */ @@ -731,9 +757,16 @@ int decrypt_file(const char *in_file, const char *out_file, const char *key_str) printf("File decryption with EVP GCM complete.\n"); exit: + wc_ForceZero(key, AES_KEY_SIZE); + wc_ForceZero(iv, AES_IV_SIZE); + wc_ForceZero(tag_enc, AESGCM_TAG_SIZE); + wc_ForceZero(tag_dec, AESGCM_TAG_SIZE); EVP_CIPHER_CTX_free(ctx); close(in_fd); close(out_fd); + if (ret != WOLFSSL_SUCCESS) { + unlink(out_file); + } return ret; } #endif diff --git a/crypto/camellia/camellia-encrypt.c b/crypto/camellia/camellia-encrypt.c index e638337c0..81e24decf 100644 --- a/crypto/camellia/camellia-encrypt.c +++ b/crypto/camellia/camellia-encrypt.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #define SALT_SIZE 8 @@ -82,12 +83,24 @@ int CamelliaEncrypt(Camellia* cam, byte* key, int size, FILE* inFile, padCounter++; } - input = malloc(length); - output = malloc(length); + input = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1012; + } ret = wc_InitRng(&rng); if (ret != 0) { printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); return -1030; } @@ -125,12 +138,12 @@ int CamelliaEncrypt(Camellia* cam, byte* key, int size, FILE* inFile, fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, length); - memset(output, 0, length); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, length); + wc_ForceZero(output, length); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); wc_FreeRng(&rng); @@ -160,36 +173,83 @@ int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile, fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); + if (length < SALT_SIZE + CAMELLIA_BLOCK_SIZE) { + printf("Input file is too small.\n"); + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1011; + } - wc_InitRng(&rng); + input = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + printf("Failed to allocate memory\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1012; + } + + ret = wc_InitRng(&rng); + if (ret != 0) { + printf("Failed to initialize random number generator\n"); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + return -1030; + } /* reads from inFile and writes whatever is there to the input array */ ret = fread(input, 1, length, inFile); if (ret == 0) { printf("Input file does not exist.\n"); - return -1010; + ret = -1010; } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; - } - for (i = SALT_SIZE; i < CAMELLIA_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + if (ret > 0) { + for (i = 0; i < SALT_SIZE; i++) { + /* finds salt from input message */ + salt[i] = input[i]; + } + for (i = SALT_SIZE; i < CAMELLIA_BLOCK_SIZE + SALT_SIZE; i++) { + /* finds iv from input message */ + iv[i - SALT_SIZE] = input[i]; + } + + /* replicates old key if keys match */ + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; } - /* replicates old key if keys match */ - ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, 4096, - size, WC_SHA256); - if (ret != 0) - return -1050; + if (ret == 0) { + /* sets key */ + ret = wc_CamelliaSetKey(cam, key, CAMELLIA_BLOCK_SIZE, iv); + if (ret != 0) + ret = -1002; + } - /* sets key */ - ret = wc_CamelliaSetKey(cam, key, CAMELLIA_BLOCK_SIZE, iv); - if (ret != 0) - return -1002; + if (ret != 0) { + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return ret; + } /* change length to remove salt/iv block from being decrypted */ length -= (CAMELLIA_BLOCK_SIZE + SALT_SIZE); @@ -198,24 +258,52 @@ int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile, input[i] = input[i + (CAMELLIA_BLOCK_SIZE + SALT_SIZE)]; } /* decrypts the message to output based on input length + padding */ - wc_CamelliaCbcDecrypt(cam, output, input, length); + ret = wc_CamelliaCbcDecrypt(cam, output, input, length); + if (ret != 0) { + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return -1006; + } if (salt[0] != 0) { /* reduces length based on number of padded elements */ + if (length < 1 || output[length-1] < 1 || + output[length-1] > length || + output[length-1] > CAMELLIA_BLOCK_SIZE) { + printf("Error: invalid padding value\n"); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + wc_FreeRng(&rng); + return -1013; + } length -= output[length-1]; } /* writes output to the outFile based on shortened length */ fwrite(output, 1, length, outFile); /* closes the opened files and frees the memory*/ - memset(input, 0, aSize); - memset(output, 0, aSize); - memset(key, 0, size); - free(input); - free(output); - free(key); + wc_ForceZero(input, aSize); + wc_ForceZero(output, aSize); + wc_ForceZero(key, size); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); + wc_FreeRng(&rng); return 0; } @@ -336,7 +424,7 @@ int main(int argc, char** argv) } else if (ret == 0 && choice != 'n') { - key = malloc(size); /* sets size memory of key */ + key = XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ ret = NoEcho((char*)key, size); if (choice == 'e') CamelliaEncrypt(&cam, key, size, inFile, outFile); diff --git a/tls/client-tls-uart.c b/tls/client-tls-uart.c index 8e58eacfe..59b6a111d 100644 --- a/tls/client-tls-uart.c +++ b/tls/client-tls-uart.c @@ -88,7 +88,7 @@ static int uartIORx(WOLFSSL *ssl, char *buf, int sz, void *ctx) if (recvd > sz) recvd = sz; XMEMCPY(buf, cbCtx->buf, recvd); - XMEMCPY(cbCtx->buf, cbCtx->buf + recvd, cbCtx->pos - recvd); + XMEMMOVE(cbCtx->buf, cbCtx->buf + recvd, cbCtx->pos - recvd); cbCtx->pos -= recvd; } diff --git a/tls/server-tls-uart.c b/tls/server-tls-uart.c index bacf99f1b..4954ef403 100644 --- a/tls/server-tls-uart.c +++ b/tls/server-tls-uart.c @@ -91,7 +91,7 @@ static int uartIORx(WOLFSSL *ssl, char *buf, int sz, void *ctx) if (recvd > sz) recvd = sz; XMEMCPY(buf, cbCtx->buf, recvd); - XMEMCPY(cbCtx->buf, cbCtx->buf + recvd, cbCtx->pos - recvd); + XMEMMOVE(cbCtx->buf, cbCtx->buf + recvd, cbCtx->pos - recvd); cbCtx->pos -= recvd; } From b2358318558cf763f4d507dbc131bcf2befd8177 Mon Sep 17 00:00:00 2001 From: Emma Stensland Date: Thu, 2 Jul 2026 09:45:05 -0600 Subject: [PATCH 2/3] F-1305 F-1306 F-1714 F-2111 F-2905 F-2906 F-2909 F-3897 F-4125 F-4608 F-6288: fix NULL-deref, fd-leak, unaligned-access, and buffer-overflow bugs across CAN, PKCS7, embedded, and PEM-printing examples --- RPi-Pico/src/tlsClient_main.c | 3 ++- can-bus/common.c | 9 +++++---- custom-io-callbacks/file-server/file-server.c | 8 ++++++-- embedded/sockets.h | 9 +++++++-- embedded/tls-info.h | 17 +++++++++++++---- pkcs7/signedData-EncryptedFirmwareCB.c | 7 ++++++- pq/stateful_hash_sig/xmss_example.c | 6 ++++-- .../tcpEcho_Server_TivaTM4C1294NCPDT/tcpEcho.c | 2 +- tls/memory-tls.c | 17 +++++++++++++++++ 9 files changed, 61 insertions(+), 17 deletions(-) diff --git a/RPi-Pico/src/tlsClient_main.c b/RPi-Pico/src/tlsClient_main.c index dfa7eb42b..2ca9c01a6 100644 --- a/RPi-Pico/src/tlsClient_main.c +++ b/RPi-Pico/src/tlsClient_main.c @@ -158,11 +158,12 @@ void tlsClient_test(void *arg) goto exit; } - ret = wolfSSL_read(ssl, buffer, BUFF_SIZE); + ret = wolfSSL_read(ssl, buffer, BUFF_SIZE - 1); if (ret < 0) { printf("Failed to read data. err=%d\n", ret); goto exit; } + buffer[ret] = '\0'; printf("Message: %s\n", buffer); wolfSSL_free(ssl); diff --git a/can-bus/common.c b/can-bus/common.c index 66ccffb0a..03b8fbd12 100644 --- a/can-bus/common.c +++ b/can-bus/common.c @@ -103,7 +103,8 @@ int can_connect(const char *address, uint16_t filter) /* Set the filter */ setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter)); - strcpy(ifr.ifr_name, address); + strncpy(ifr.ifr_name, address, IFNAMSIZ - 1); + ifr.ifr_name[IFNAMSIZ - 1] = '\0'; ioctl(sock, SIOCGIFINDEX, &ifr); memset(&addr, 0, sizeof(addr)); @@ -196,11 +197,11 @@ int setup_ssl(enum service_type type, WOLFSSL_CTX **new_ctx, return -1; } - wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL); - if (type == SERVICE_TYPE_CLIENT) { - ret = wolfSSL_CTX_load_verify_locations(ctx, "client.pem", NULL); + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_PEER, NULL); + ret = wolfSSL_CTX_load_verify_locations(ctx, "ca.crt", NULL); } else { + wolfSSL_CTX_set_verify(ctx, WOLFSSL_VERIFY_NONE, NULL); ret = wolfSSL_CTX_use_certificate_file(ctx, "server.pem", WOLFSSL_FILETYPE_PEM); } diff --git a/custom-io-callbacks/file-server/file-server.c b/custom-io-callbacks/file-server/file-server.c index aad2f3bf2..3482b64df 100644 --- a/custom-io-callbacks/file-server/file-server.c +++ b/custom-io-callbacks/file-server/file-server.c @@ -259,8 +259,12 @@ int main(int argc, char** argv) wolfSSL_CTX_free(ctxServ); wolfSSL_Cleanup(); /* Reset the contents of the receive and send files for next run */ - fclose(fopen(SR, "wb")); - fclose(fopen(CR, "wb")); + { + FILE* f = fopen(SR, "wb"); + if (f != NULL) fclose(f); + f = fopen(CR, "wb"); + if (f != NULL) fclose(f); + } return -1; } diff --git a/embedded/sockets.h b/embedded/sockets.h index ddced04d1..090110a9a 100644 --- a/embedded/sockets.h +++ b/embedded/sockets.h @@ -35,8 +35,13 @@ typedef int socklen_t ; static unsigned long inet_addr(const char *cp) { - unsigned int a[4] ; unsigned long ret ; - sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) ; + unsigned int a[4] = {0, 0, 0, 0} ; unsigned long ret ; int i ; + if (sscanf(cp, "%u.%u.%u.%u", &a[0], &a[1], &a[2], &a[3]) != 4) + return 0xFFFFFFFFUL ; /* INADDR_NONE */ + for (i = 0; i < 4; i++) { + if (a[i] > 255) + return 0xFFFFFFFFUL ; /* INADDR_NONE */ + } ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; return(ret) ; } diff --git a/embedded/tls-info.h b/embedded/tls-info.h index 559299947..a82c8fbc0 100644 --- a/embedded/tls-info.h +++ b/embedded/tls-info.h @@ -145,14 +145,23 @@ static WC_INLINE void ShowX509Chain(WOLFSSL_X509_CHAIN* chain, int count, const char* hdr) { int i; - int length; + int ret; + int length = 0; unsigned char buffer[3072]; WOLFSSL_X509* chainX509; for (i = 0; i < count; i++) { - wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length); - buffer[length] = 0; - printf("\n%s: %d has length %d data = \n%s\n", hdr, i, length, buffer); + ret = wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), + &length); + if (ret == WOLFSSL_SUCCESS && length >= 0 && + length < (int)sizeof(buffer)) { + buffer[length] = 0; + printf("\n%s: %d has length %d data = \n%s\n", hdr, i, length, + buffer); + } + else { + printf("\n%s: %d failed to get chain cert pem\n", hdr, i); + } chainX509 = wolfSSL_get_chain_X509(chain, i); if (chainX509) diff --git a/pkcs7/signedData-EncryptedFirmwareCB.c b/pkcs7/signedData-EncryptedFirmwareCB.c index b0d906946..caf267bef 100644 --- a/pkcs7/signedData-EncryptedFirmwareCB.c +++ b/pkcs7/signedData-EncryptedFirmwareCB.c @@ -192,7 +192,7 @@ static int myDecryptionFunc(PKCS7* pkcs7, int encryptOID, byte* iv, int ivSz, printf("%02X", keyIdRaw[i]); printf("\n"); } - keyId = *(int*)(keyIdRaw + 2); + XMEMCPY(&keyId, keyIdRaw + 2, sizeof(keyId)); printf("\t\tStripping off OCTET TAG and length the keyId = %d\n", keyId); } @@ -473,6 +473,11 @@ static int verifyBundle(byte* derBuf, word32 derSz) int decodedSz = 2048; pkcs7 = wc_PKCS7_New(NULL, 0); + if (pkcs7 == NULL) { + printf("\tError allocating PKCS7 structure\n"); + ret = MEMORY_E; + goto exit; + } /* Test verify */ ret = wc_PKCS7_Init(pkcs7, NULL, INVALID_DEVID); diff --git a/pq/stateful_hash_sig/xmss_example.c b/pq/stateful_hash_sig/xmss_example.c index 11acd364f..f08d4ec81 100644 --- a/pq/stateful_hash_sig/xmss_example.c +++ b/pq/stateful_hash_sig/xmss_example.c @@ -20,6 +20,8 @@ */ #include #include +#include +#include #include #include @@ -116,8 +118,8 @@ write_key_file(const byte * priv, /* Create the file if it didn't exist. */ file = fopen(filename, "w+"); if (!file) { - fprintf(stderr, "error: fopen(%s, \"w+\") failed: %d\n", filename, - ferror(file)); + fprintf(stderr, "error: fopen(%s, \"w+\") failed: %s\n", filename, + strerror(errno)); return WC_XMSS_RC_WRITE_FAIL; } } diff --git a/tirtos_ccs_examples/tcpEcho_Server_TivaTM4C1294NCPDT/tcpEcho.c b/tirtos_ccs_examples/tcpEcho_Server_TivaTM4C1294NCPDT/tcpEcho.c index 5e5e2859c..75d551b94 100644 --- a/tirtos_ccs_examples/tcpEcho_Server_TivaTM4C1294NCPDT/tcpEcho.c +++ b/tirtos_ccs_examples/tcpEcho_Server_TivaTM4C1294NCPDT/tcpEcho.c @@ -211,7 +211,7 @@ Void tcpHandler(UArg arg0, UArg arg1) /* Wait for incoming request */ if ((clientfd = accept(lSocket, (struct sockaddr*)&client_addr, &addrlen)) == -1) { - System_printf("tcpHandler: Accept failed %d\n"); + System_printf("tcpHandler: Accept failed %d\n", fdError()); exitApp(ctx); } diff --git a/tls/memory-tls.c b/tls/memory-tls.c index 4ac7e1c49..cbe2baffb 100644 --- a/tls/memory-tls.c +++ b/tls/memory-tls.c @@ -52,11 +52,22 @@ pthread_mutex_t client_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_cond_t client_cond = PTHREAD_COND_INITIALIZER; +/* Manual test for the buffer-full guard below: shrink to_server/to_client + * to a small size (e.g. 1024) and have client_thread() call wolfSSL_write() + * with a message larger than that buffer; ServerSend/ClientSend should + * return WOLFSSL_CBIO_ERR_GENERAL instead of overflowing the array. */ + /* server send callback */ int ServerSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) { pthread_mutex_lock(&client_mutex); + if (client_write_idx + sz > (int)sizeof(to_client)) { + pthread_cond_signal(&client_cond); + pthread_mutex_unlock(&client_mutex); + return WOLFSSL_CBIO_ERR_GENERAL; + } + memcpy(&to_client[client_write_idx], buf, sz); client_write_idx += sz; client_bytes += sz; @@ -95,6 +106,12 @@ int ClientSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) { pthread_mutex_lock(&server_mutex); + if (server_write_idx + sz > (int)sizeof(to_server)) { + pthread_cond_signal(&server_cond); + pthread_mutex_unlock(&server_mutex); + return WOLFSSL_CBIO_ERR_GENERAL; + } + memcpy(&to_server[server_write_idx], buf, sz); server_write_idx += sz; server_bytes += sz; From 34ccbb97d19d03e4108981c9cb96aeb9de5af90b Mon Sep 17 00:00:00 2001 From: Emma Stensland Date: Thu, 2 Jul 2026 09:45:17 -0600 Subject: [PATCH 3/3] F-1715 F-2114 F-3224 F-3460 F-3690 F-4120 F-4124 F-5614 F-5615: replace hardcoded/UAF-prone secrets and keys with RNG-generated values, zeroize key material before free, and flag non-constant-time secret comparisons --- ccb_vaultic/ccb_vaultic.c | 37 +++++++++- certgen/csr_example.c | 3 + dtls-mcast/mcast-peer.c | 86 ++++++++++++++++++++-- dtls/client-dtls13-earlydata.c | 6 +- dtls/dtls-export-common.h | 89 +++++++++++++++++++---- dtls/server-dtls-demux.c | 21 +++++- dtls/server-dtls13-event.c | 35 +++++++-- pk/ecdh_generate_secret/ecdh_gen_secret.c | 41 ++++++++++- tls/client-tls-pkcallback.c | 66 ++++++++++------- tls/server-tls-pkcallback.c | 66 ++++++++++------- 10 files changed, 361 insertions(+), 89 deletions(-) diff --git a/ccb_vaultic/ccb_vaultic.c b/ccb_vaultic/ccb_vaultic.c index 74e51994f..f2c7e5804 100644 --- a/ccb_vaultic/ccb_vaultic.c +++ b/ccb_vaultic/ccb_vaultic.c @@ -87,6 +87,7 @@ /* wolfcrypt includes */ #include "wolfssl/wolfcrypt/types.h" /* types and X-defines */ +#include "wolfssl/wolfcrypt/memory.h" /* For wc_ForceZero */ #ifndef CCBVAULTIC_NO_SHA #include "wolfssl/wolfcrypt/hash.h" /* For HASH_FLAGS and types */ @@ -156,6 +157,31 @@ static void hexdump(const unsigned char* p, size_t len) } #endif +#ifdef WOLF_CRYPTO_CB +/* Constant-time buffer compare for secret material. + * + * wolfSSL's own constant-time compare (ConstantCompare() in + * wolfcrypt/src/misc.c) is WOLFSSL_LOCAL and not exported, so it can't be + * called from application code. Every byte is compared regardless of where + * a mismatch occurs, so the runtime doesn't leak position information via + * early-exit timing. + * + * Returns 0 if the buffers are equal, non-zero otherwise. */ +static int const_time_memcmp(const void* a, const void* b, size_t len) +{ + const byte* pa = (const byte*)a; + const byte* pb = (const byte*)b; + byte diff = 0; + size_t i; + + for (i = 0; i < len; i++) { + diff |= (byte)(pa[i] ^ pb[i]); + } + + return (int)diff; +} +#endif /* WOLF_CRYPTO_CB */ + /* Helper to translate vlt return codes to wolfSSL code */ static int translateError(int vlt_rc) { @@ -233,8 +259,10 @@ void ccbVaultIc_Cleanup(ccbVaultIc_Context *c) /* Free allocated buffers */ if (c->m != NULL) XFREE(c->m, NULL, NULL); - if (c->aescbc_key != NULL) + if (c->aescbc_key != NULL) { + wc_ForceZero(c->aescbc_key, c->aescbc_keylen); XFREE(c->aescbc_key, NULL, NULL); + } clearContext(c); @@ -975,10 +1003,12 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info, vlt_mode = VLT_DECRYPT_MODE; } - /* Check if key is not the same as last time */ + /* Check if key is not the same as last time. Uses a constant-time + * compare since this is secret key material, even though this + * check only gates a cache refresh (not authentication). */ if ((c->aescbc_key == NULL) || (c->aescbc_keylen != aes->keylen) || - (XMEMCMP(c->aescbc_key, aes->devKey, aes->keylen))) { + (const_time_memcmp(c->aescbc_key, aes->devKey, aes->keylen))) { #if defined(CCBVAULTIC_DEBUG_ALL) XPRINTF(" New AES Key: ckey:%p clen:%lu akey:%p alen:%u\n", c->aescbc_key,c->aescbc_keylen, aes->devKey, aes->keylen); @@ -986,6 +1016,7 @@ static int HandleCipherCallback(int devId, wc_CryptoInfo* info, #endif /* Free the current key buffer if necessary */ if (c->aescbc_key != NULL) { + wc_ForceZero(c->aescbc_key, c->aescbc_keylen); XFREE(c->aescbc_key, NULL, NULL); c->aescbc_key = NULL; c->aescbc_keylen = 0; diff --git a/certgen/csr_example.c b/certgen/csr_example.c index 861b4b7cb..b5d946d55 100644 --- a/certgen/csr_example.c +++ b/certgen/csr_example.c @@ -218,6 +218,7 @@ static int init_pk_key(Cert* req, void** keyPtr, WC_RNG* rng, byte* der, ret = wc_ecc_init((ecc_key*)*keyPtr); if (ret != 0) { XFREE(*keyPtr, NULL, DYNAMIC_TYPE_ECC); + *keyPtr = NULL; break; } ret = wc_ecc_make_key_ex(rng, 32, (ecc_key*)*keyPtr, ECC_SECP256R1); @@ -249,6 +250,7 @@ static int init_pk_key(Cert* req, void** keyPtr, WC_RNG* rng, byte* der, ret = wc_InitRsaKey((RsaKey*)*keyPtr, NULL); if (ret != 0) { XFREE(*keyPtr, NULL, DYNAMIC_TYPE_RSA); + *keyPtr = NULL; break; } ret = wc_MakeRsaKey((RsaKey*)*keyPtr, 2048, WC_RSA_EXPONENT, rng); @@ -280,6 +282,7 @@ static int init_pk_key(Cert* req, void** keyPtr, WC_RNG* rng, byte* der, ret = wc_ed25519_init((ed25519_key*)*keyPtr); if (ret != 0) { XFREE(*keyPtr, NULL, DYNAMIC_TYPE_ED25519); + *keyPtr = NULL; break; } ret = wc_ed25519_make_key(rng, ED25519_KEY_SIZE, diff --git a/dtls-mcast/mcast-peer.c b/dtls-mcast/mcast-peer.c index fed7a4218..2190a17d8 100644 --- a/dtls-mcast/mcast-peer.c +++ b/dtls-mcast/mcast-peer.c @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include #include #include @@ -61,7 +64,8 @@ /* Epoch for the multicast session */ #define MCAST_EPOCH 1 -#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_MULTICAST) && \ + defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) /* Global flag for clean shutdown */ static volatile sig_atomic_t running = 1; @@ -230,14 +234,80 @@ int main(int argc, char** argv) #endif /* Initialize the pre-shared secrets (same for all peers) */ - memset(pms, 0x23, sizeof(pms)); - memset(clientRandom, 0xA5, sizeof(clientRandom)); - memset(serverRandom, 0x5A, sizeof(serverRandom)); + { + const char* envSecret = getenv("DTLS_MCAST_SECRET"); + char genSecret[2 * PMS_SIZE + 1]; + const char* secret; + size_t len; + + if (envSecret != NULL) { + secret = envSecret; + } + else { + byte secretBytes[PMS_SIZE]; + WC_RNG rng; + + printf("WARNING: DTLS_MCAST_SECRET not set. Generating a random " + "multicast secret for this run.\n" + " Export the printed value as DTLS_MCAST_SECRET " + "on ALL peers so they can share the same secret.\n"); + + ret = wc_InitRng(&rng); + if (ret != 0) { + fprintf(stderr, "Error: wc_InitRng failed: %d\n", ret); + return 1; + } + ret = wc_RNG_GenerateBlock(&rng, secretBytes, sizeof(secretBytes)); + wc_FreeRng(&rng); + if (ret != 0) { + fprintf(stderr, "Error: Failed to generate random multicast " + "secret: %d\n", ret); + wc_ForceZero(secretBytes, sizeof(secretBytes)); + return 1; + } + + for (i = 0; i < (int)sizeof(secretBytes); i++) + snprintf(&genSecret[i * 2], 3, "%02x", secretBytes[i]); + wc_ForceZero(secretBytes, sizeof(secretBytes)); + + printf("Generated multicast secret (hex): %s\n" + "Export this value as DTLS_MCAST_SECRET on ALL peers.\n", + genSecret); + + secret = genSecret; + } + + len = strlen(secret); + + /* PBKDF2 guards against a weak DTLS_MCAST_SECRET; distinct salts + * keep pms/clientRandom/serverRandom independent yet peer-shared. */ + ret = wc_PBKDF2(pms, (byte*)secret, (int)len, + (byte*)"mcast-pms", 9, 4096, sizeof(pms), WC_SHA256); + if (ret == 0) + ret = wc_PBKDF2(clientRandom, (byte*)secret, (int)len, + (byte*)"mcast-client-random", 19, 4096, + sizeof(clientRandom), WC_SHA256); + if (ret == 0) + ret = wc_PBKDF2(serverRandom, (byte*)secret, (int)len, + (byte*)"mcast-server-random", 19, 4096, + sizeof(serverRandom), WC_SHA256); + if (ret != 0) { + fprintf(stderr, "Error: Failed to derive multicast secret: %d\n", + ret); + wc_ForceZero(pms, sizeof(pms)); + wc_ForceZero(clientRandom, sizeof(clientRandom)); + wc_ForceZero(serverRandom, sizeof(serverRandom)); + return 1; + } + } /* Initialize wolfSSL */ ret = wolfSSL_Init(); if (ret != WOLFSSL_SUCCESS) { fprintf(stderr, "Error: wolfSSL_Init failed: %d\n", ret); + wc_ForceZero(pms, sizeof(pms)); + wc_ForceZero(clientRandom, sizeof(clientRandom)); + wc_ForceZero(serverRandom, sizeof(serverRandom)); return 1; } @@ -423,6 +493,9 @@ int main(int argc, char** argv) printf("\nNode %d: Shutting down...\n", myId); cleanup: + wc_ForceZero(pms, sizeof(pms)); + wc_ForceZero(clientRandom, sizeof(clientRandom)); + wc_ForceZero(serverRandom, sizeof(serverRandom)); if (sslTx != NULL) { wolfSSL_free(sslTx); } @@ -451,7 +524,8 @@ int main(int argc, char** argv) #else int main() { - fprintf(stderr, "Please configure the wolfssl library with --enable-dtls --enable-mcast.\n"); + fprintf(stderr, "Please configure the wolfssl library with " + "--enable-dtls --enable-mcast --enable-pwdbased.\n"); return EXIT_FAILURE; } -#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST */ +#endif /* WOLFSSL_DTLS && WOLFSSL_MULTICAST && HAVE_PBKDF2 && !NO_PWDBASED */ diff --git a/dtls/client-dtls13-earlydata.c b/dtls/client-dtls13-earlydata.c index 9da46a4f3..233095378 100644 --- a/dtls/client-dtls13-earlydata.c +++ b/dtls/client-dtls13-earlydata.c @@ -208,8 +208,10 @@ int main(int argc, char** argv) ret = 0; /* Success */ cleanup: - wolfSSL_shutdown(ssl); - if (ssl) wolfSSL_free(ssl); + if (ssl) { + wolfSSL_shutdown(ssl); + wolfSSL_free(ssl); + } if (session) wolfSSL_SESSION_free(session); if (ctx) wolfSSL_CTX_free(ctx); if (sockfd >= 0) close(sockfd); diff --git a/dtls/dtls-export-common.h b/dtls/dtls-export-common.h index 70f0a184c..4ae67a7b0 100644 --- a/dtls/dtls-export-common.h +++ b/dtls/dtls-export-common.h @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include #include #include @@ -39,13 +41,25 @@ #define DEFAULT_CLIENT_SESSION_FILE "dtls_client_session.bin" #define DEFAULT_SERVER_SESSION_FILE "dtls_server_session.bin" -/* AES-256-CBC key (32 bytes) - In production, use a securely generated key.*/ -static const unsigned char AES_KEY[32] = { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, - 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, - 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20 -}; +/* AES-256-CBC key (32 bytes), derived from a passphrase via PBKDF2. In + * production, set DTLS_SESSION_EXPORT_KEY to a real secret. */ +static int GetSessionEncryptionKey(unsigned char* keyBuf) +{ + const char* envPass = getenv("DTLS_SESSION_EXPORT_KEY"); + const char* pass = envPass ? envPass : "default_dtls_session_export_passphrase"; + static const byte salt[] = "dtls-export-session-key"; + static int warned = 0; + + if (envPass == NULL && !warned) { + warned = 1; + printf("WARNING: DTLS_SESSION_EXPORT_KEY is not set; using an " + "insecure demo passphrase. Do not use this outside of a " + "demo/test.\n"); + } + + return wc_PBKDF2(keyBuf, (const byte*)pass, (int)strlen(pass), + (byte*)salt, (int)(sizeof(salt) - 1), 4096, 32, WC_SHA256); +} /* AES block size */ #define AES_BLOCK_SZ 16 @@ -68,6 +82,7 @@ int SaveEncryptedSession(const char* filename, Aes aes; WC_RNG rng; unsigned char iv[AES_BLOCK_SZ]; + unsigned char key[32]; unsigned char* paddedData = NULL; unsigned char* encryptedData = NULL; unsigned int paddedSz; @@ -76,6 +91,12 @@ int SaveEncryptedSession(const char* filename, int aesInit = 0; int rngInit = 0; + ret = GetSessionEncryptionKey(key); + if (ret != 0) { + printf("Error: Failed to derive encryption key: %d\n", ret); + return -1; + } + /* Calculate padded size (must be multiple of AES_BLOCK_SZ) */ padding = AES_BLOCK_SZ - (sessionSz % AES_BLOCK_SZ); paddedSz = sessionSz + padding; @@ -84,6 +105,7 @@ int SaveEncryptedSession(const char* filename, ret = wc_InitRng(&rng); if (ret != 0) { printf("Error: wc_InitRng failed: %d\n", ret); + wc_ForceZero(key, sizeof(key)); return -1; } rngInit = 1; @@ -117,7 +139,7 @@ int SaveEncryptedSession(const char* filename, aesInit = 1; /* Set AES key for encryption */ - ret = wc_AesSetKey(&aes, AES_KEY, sizeof(AES_KEY), iv, AES_ENCRYPTION); + ret = wc_AesSetKey(&aes, key, sizeof(key), iv, AES_ENCRYPTION); if (ret != 0) { printf("Error: wc_AesSetKey failed: %d\n", ret); goto cleanup; @@ -170,8 +192,12 @@ int SaveEncryptedSession(const char* filename, ret = 0; cleanup: + wc_ForceZero(key, sizeof(key)); if (fp != NULL) fclose(fp); - if (paddedData != NULL) free(paddedData); + if (paddedData != NULL) { + wc_ForceZero(paddedData, paddedSz); + free(paddedData); + } if (encryptedData != NULL) free(encryptedData); if (aesInit) wc_AesFree(&aes); if (rngInit) wc_FreeRng(&rng); @@ -190,6 +216,7 @@ unsigned char* LoadEncryptedSession(const char* filename, FILE* fp = NULL; Aes aes; unsigned char iv[AES_BLOCK_SZ]; + unsigned char key[32]; unsigned char sizeBuf[4]; unsigned char* encryptedData = NULL; unsigned char* decryptedData = NULL; @@ -199,10 +226,17 @@ unsigned char* LoadEncryptedSession(const char* filename, int ret = 0; int aesInit = 0; + ret = GetSessionEncryptionKey(key); + if (ret != 0) { + printf("Error: Failed to derive decryption key: %d\n", ret); + return NULL; + } + /* Open file */ fp = fopen(filename, "rb"); if (fp == NULL) { printf("Error: Cannot open file %s for reading\n", filename); + wc_ForceZero(key, sizeof(key)); return NULL; } @@ -214,6 +248,7 @@ unsigned char* LoadEncryptedSession(const char* filename, if (fileSize < (4 + AES_BLOCK_SZ + AES_BLOCK_SZ)) { printf("Error: File too small to contain valid session data\n"); fclose(fp); + wc_ForceZero(key, sizeof(key)); return NULL; } @@ -221,6 +256,7 @@ unsigned char* LoadEncryptedSession(const char* filename, if (fread(sizeBuf, 1, 4, fp) != 4) { printf("Error: Failed to read size from file\n"); fclose(fp); + wc_ForceZero(key, sizeof(key)); return NULL; } originalSz = ((unsigned int)sizeBuf[0] << 24) | @@ -232,6 +268,7 @@ unsigned char* LoadEncryptedSession(const char* filename, if (fread(iv, 1, AES_BLOCK_SZ, fp) != AES_BLOCK_SZ) { printf("Error: Failed to read IV from file\n"); fclose(fp); + wc_ForceZero(key, sizeof(key)); return NULL; } @@ -263,7 +300,7 @@ unsigned char* LoadEncryptedSession(const char* filename, aesInit = 1; /* Set AES key for decryption */ - ret = wc_AesSetKey(&aes, AES_KEY, sizeof(AES_KEY), iv, AES_DECRYPTION); + ret = wc_AesSetKey(&aes, key, sizeof(key), iv, AES_DECRYPTION); if (ret != 0) { printf("Error: wc_AesSetKey failed: %d\n", ret); goto cleanup; @@ -276,15 +313,35 @@ unsigned char* LoadEncryptedSession(const char* filename, goto cleanup; } - /* Verify padding and original size */ - if (originalSz > encryptedSz) { - printf("Error: Invalid original size in file\n"); + /* Verify PKCS#7 padding and cross-check against the file's originalSz */ + if (encryptedSz == 0 || encryptedSz % AES_BLOCK_SZ != 0) { + printf("Error: Invalid encrypted data size in file\n"); goto cleanup; } + { + unsigned char pad = decryptedData[encryptedSz - 1]; + unsigned int i; + + if (pad < 1 || pad > AES_BLOCK_SZ || pad > encryptedSz) { + printf("Error: Invalid padding in file\n"); + goto cleanup; + } + for (i = 0; i < pad; i++) { + if (decryptedData[encryptedSz - 1 - i] != pad) { + printf("Error: Invalid padding in file\n"); + goto cleanup; + } + } + if (originalSz != encryptedSz - pad) { + printf("Error: Original size does not match padding\n"); + goto cleanup; + } + } *sessionSz = originalSz; printf("Session loaded from %s (%u bytes)\n", filename, originalSz); + wc_ForceZero(key, sizeof(key)); /* Clean up and return decrypted data */ if (encryptedData != NULL) free(encryptedData); if (aesInit) wc_AesFree(&aes); @@ -292,9 +349,13 @@ unsigned char* LoadEncryptedSession(const char* filename, return decryptedData; cleanup: + wc_ForceZero(key, sizeof(key)); if (fp != NULL) fclose(fp); if (encryptedData != NULL) free(encryptedData); - if (decryptedData != NULL) free(decryptedData); + if (decryptedData != NULL) { + wc_ForceZero(decryptedData, encryptedSz); + free(decryptedData); + } if (aesInit) wc_AesFree(&aes); return NULL; diff --git a/dtls/server-dtls-demux.c b/dtls/server-dtls-demux.c index 4344d8f3c..eb7e19078 100644 --- a/dtls/server-dtls-demux.c +++ b/dtls/server-dtls-demux.c @@ -413,13 +413,26 @@ WOLFSSL_CTX* newCTX(void) return ctx; } +/* Stateless cookie secret, generated once per run. Must stay stable across + * newSSL() calls so in-flight cookie retries from other clients still + * validate. Applications should rotate it periodically (e.g. on a timer), + * not on every call. */ +static byte cookieSecret[32]; +static int cookieSecretSet = 0; + WOLFSSL* newSSL(WOLFSSL_CTX* ctx, int fd, WC_RNG* rng, struct ConnList* connList) { WOLFSSL* ssl = NULL; - /* Applications should update this secret periodically */ - char *secret = "My secret"; byte newCid[CID_SIZE]; + if (!cookieSecretSet) { + if (wc_RNG_GenerateBlock(rng, cookieSecret, sizeof(cookieSecret)) != 0) { + fprintf(stderr, "wc_RNG_GenerateBlock error.\n"); + return NULL; + } + cookieSecretSet = 1; + } + /* Create the WOLFSSL Object */ if ((ssl = wolfSSL_new(ctx)) == NULL) { fprintf(stderr, "wolfSSL_new error.\n"); @@ -427,13 +440,13 @@ WOLFSSL* newSSL(WOLFSSL_CTX* ctx, int fd, WC_RNG* rng, struct ConnList* connList } /* Set the secret for cookie creation */ #if defined(WOLFSSL_SEND_HRR_COOKIE) - if (wolfSSL_send_hrr_cookie(ssl, (byte*)secret, strlen(secret)) != WOLFSSL_SUCCESS) { + if (wolfSSL_send_hrr_cookie(ssl, cookieSecret, sizeof(cookieSecret)) != WOLFSSL_SUCCESS) { fprintf(stderr, "wolfSSL_send_hrr_cookie error.\n"); wolfSSL_free(ssl); return NULL; } #endif - if (wolfSSL_DTLS_SetCookieSecret(ssl, (byte*)secret, strlen(secret)) != 0) { + if (wolfSSL_DTLS_SetCookieSecret(ssl, cookieSecret, sizeof(cookieSecret)) != 0) { fprintf(stderr, "wolfSSL_DTLS_SetCookieSecret error.\n"); wolfSSL_free(ssl); return NULL; diff --git a/dtls/server-dtls13-event.c b/dtls/server-dtls13-event.c index eb575fee4..8941f76d7 100644 --- a/dtls/server-dtls13-event.c +++ b/dtls/server-dtls13-event.c @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -217,6 +218,15 @@ static int newFD(void) return INVALID_SOCKET; } +/* Stateless HRR cookie secret, generated once per run. Must stay stable + * across newPendingSSL() calls so in-flight cookie retries from other + * clients still validate. Applications should rotate it periodically + * (e.g. on a timer), not on every call. */ +#if !defined(USE_DTLS12) && defined(WOLFSSL_SEND_HRR_COOKIE) +static byte cookieSecret[32]; +static int cookieSecretSet = 0; +#endif + static int newPendingSSL(void) { WOLFSSL* ssl; @@ -248,15 +258,28 @@ static int newPendingSSL(void) } #if !defined(USE_DTLS12) && defined(WOLFSSL_SEND_HRR_COOKIE) - { - /* Applications should update this secret periodically */ - char *secret = "My secret"; - if (wolfSSL_send_hrr_cookie(ssl, (byte*)secret, strlen(secret)) - != WOLFSSL_SUCCESS) { - fprintf(stderr, "wolfSSL_send_hrr_cookie error.\n"); + if (!cookieSecretSet) { + WC_RNG rng; + int rngRet; + + rngRet = wc_InitRng(&rng); + if (rngRet == 0) { + rngRet = wc_RNG_GenerateBlock(&rng, cookieSecret, sizeof(cookieSecret)); + wc_FreeRng(&rng); + } + if (rngRet != 0) { + fprintf(stderr, "Failed to generate cookie secret: %d\n", rngRet); wolfSSL_free(ssl); return 0; } + cookieSecretSet = 1; + } + + if (wolfSSL_send_hrr_cookie(ssl, cookieSecret, sizeof(cookieSecret)) + != WOLFSSL_SUCCESS) { + fprintf(stderr, "wolfSSL_send_hrr_cookie error.\n"); + wolfSSL_free(ssl); + return 0; } #endif diff --git a/pk/ecdh_generate_secret/ecdh_gen_secret.c b/pk/ecdh_generate_secret/ecdh_gen_secret.c index 70620b0f1..44a1e3744 100644 --- a/pk/ecdh_generate_secret/ecdh_gen_secret.c +++ b/pk/ecdh_generate_secret/ecdh_gen_secret.c @@ -37,6 +37,30 @@ int do_ecc(void); int do_25519(void); int do_448(void); +/* Constant-time buffer compare for secret material. + * + * wolfSSL's own constant-time compare (ConstantCompare() in + * wolfcrypt/src/misc.c) is WOLFSSL_LOCAL and not exported, so it can't be + * called from application code. This is the pattern to use instead of + * XMEMCMP/memcmp whenever comparing secrets, MACs, or derived key material: + * every byte is compared regardless of where a mismatch occurs, so the + * runtime doesn't leak position information via early-exit timing. + * + * Returns 0 if the buffers are equal, non-zero otherwise. */ +static int const_time_memcmp(const void* a, const void* b, size_t len) +{ + const byte* pa = (const byte*)a; + const byte* pb = (const byte*)b; + byte diff = 0; + size_t i; + + for (i = 0; i < len; i++) { + diff |= (byte)(pa[i] ^ pb[i]); + } + + return (int)diff; +} + int main(int argc, char** argv) { int curveChoice = 0; @@ -111,7 +135,9 @@ int do_ecc(void) wc_ecc_set_rng(&BobKey, &rng); ret = wc_ecc_shared_secret(&BobKey, &AliceKey, BobSecret, &secretLen); if (ret == 0) { - if (XMEMCMP(AliceSecret, BobSecret, secretLen)) + /* Use a constant-time compare (not XMEMCMP) since these buffers + * hold secret key material. See const_time_memcmp() above. */ + if (const_time_memcmp(AliceSecret, BobSecret, secretLen)) printf("Failed to generate a common secret\n"); } else { goto all_three; @@ -172,7 +198,9 @@ int do_25519(void) secretLen = ECC_256_BIT_FIELD; /* explicit reset for best practice */ ret = wc_curve25519_shared_secret(&BobKey, &AliceKey, BobSecret, &secretLen); if (ret == 0) { - if (XMEMCMP(AliceSecret, BobSecret, secretLen)) + /* Use a constant-time compare (not XMEMCMP) since these buffers + * hold secret key material. See const_time_memcmp() above. */ + if (const_time_memcmp(AliceSecret, BobSecret, secretLen)) printf("Failed to generate a common secret\n"); } else { goto all_three; @@ -233,7 +261,9 @@ int do_448(void) secretLen = ECC_448_BIT_FIELD; /* explicit reset for best practice */ ret = wc_curve448_shared_secret(&BobKey, &AliceKey, BobSecret, &secretLen); if (ret == 0) { - if (XMEMCMP(AliceSecret, BobSecret, secretLen)) + /* Use a constant-time compare (not XMEMCMP) since these buffers + * hold secret key material. See const_time_memcmp() above. */ + if (const_time_memcmp(AliceSecret, BobSecret, secretLen)) printf("Failed to generate a common secret\n"); } else { goto all_three; @@ -285,7 +315,10 @@ void Usage(int* curveChoice) if (answer == 'y') { printf("\nEnter an option from the above curve list > "); - scanf("%s", input); + if (scanf("%9s", input) != 1) { + printf("Invalid input\n"); + exit(-1); + } printf("You entered: %s\n", input); sscanf(input, "%d", curveChoice); if (*curveChoice != 1 && *curveChoice != 2) { diff --git a/tls/client-tls-pkcallback.c b/tls/client-tls-pkcallback.c index 9fa1c67bc..bdd42a1c2 100644 --- a/tls/client-tls-pkcallback.c +++ b/tls/client-tls-pkcallback.c @@ -98,7 +98,7 @@ static int load_file(const char* fname, byte** buf, size_t* bufLen) rewind(lFile); if (fileSz > 0) { *bufLen = (size_t)fileSz; - *buf = (byte*)malloc(*bufLen); + *buf = (byte*)XMALLOC(*bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (*buf == NULL) { ret = MEMORY_E; printf("Error allocating %lu bytes\n", (unsigned long)*bufLen); @@ -128,20 +128,24 @@ static int load_key_file(const char* fname, byte** derBuf, word32* derLen) if (ret != 0) return ret; - *derBuf = (byte*)malloc(bufLen); + *derBuf = (byte*)XMALLOC(bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (*derBuf == NULL) { - free(buf); + wc_ForceZero(buf, bufLen); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } ret = wc_KeyPemToDer(buf, (word32)bufLen, *derBuf, (word32)bufLen, NULL); if (ret < 0) { - free(buf); - free(*derBuf); + wc_ForceZero(buf, bufLen); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_ForceZero(*derBuf, bufLen); + XFREE(*derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } *derLen = ret; - free(buf); + wc_ForceZero(buf, bufLen); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return 0; } @@ -168,22 +172,28 @@ static int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, #endif ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz); + if (ret != 0) { +#ifdef WOLFSSL_ASYNC_CRYPT + cbInfo->state = 0; +#endif + return ret; + } + + ret = wc_ecc_init(&cbInfo->keyEcc); if (ret == 0) { - ret = wc_ecc_init(&cbInfo->keyEcc); + word32 idx = 0; + ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz); if (ret == 0) { - word32 idx = 0; - ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz); - if (ret == 0) { - WC_RNG *rng = wolfSSL_GetRNG(ssl); - - printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id); - ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng, - &cbInfo->keyEcc); - } - wc_ecc_free(&cbInfo->keyEcc); + WC_RNG *rng = wolfSSL_GetRNG(ssl); + + printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id); + ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng, + &cbInfo->keyEcc); } + wc_ecc_free(&cbInfo->keyEcc); } - free(keyBuf); + wc_ForceZero(keyBuf, keySz); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #ifdef WOLFSSL_ASYNC_CRYPT cbInfo->state = 0; @@ -218,8 +228,12 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, #endif ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz); - if (ret != 0) + if (ret != 0) { +#ifdef WOLFSSL_ASYNC_CRYPT + cbInfo->state = 0; +#endif return ret; + } ret = wc_InitRsaKey(&cbInfo->keyRsa, NULL); if (ret == 0) { @@ -234,7 +248,8 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, } wc_FreeRsaKey(&cbInfo->keyRsa); } - free(keyBuf); + wc_ForceZero(keyBuf, keySz); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #ifdef WOLFSSL_ASYNC_CRYPT cbInfo->state = 0; #endif @@ -300,7 +315,8 @@ static int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz, } wc_FreeRsaKey(&cbInfo->keyRsa); } - free(keyBuf); + wc_ForceZero(keyBuf, keySz); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf("PK RSA PSS Sign: ret %d, outSz %u\n", ret, *outSz); @@ -325,7 +341,7 @@ int main(int argc, char** argv) /* PK callback context */ PkCbInfo myCtx; - memset(&myCtx, 0, sizeof(myCtx)); + XMEMSET(&myCtx, 0, sizeof(myCtx)); myCtx.keyFile = KEY_FILE; /* Check for proper calling convention */ @@ -351,7 +367,7 @@ int main(int argc, char** argv) } /* Initialize the server address struct with zeros */ - memset(&servAddr, 0, sizeof(servAddr)); + XMEMSET(&servAddr, 0, sizeof(servAddr)); /* Fill in the server address */ servAddr.sin_family = AF_INET; /* using IPv4 */ @@ -477,7 +493,7 @@ int main(int argc, char** argv) /* Get a message for the server from stdin */ printf("Message for server: "); - memset(buff, 0, sizeof(buff)); + XMEMSET(buff, 0, sizeof(buff)); if (fgets(buff, sizeof(buff), stdin) == NULL) { fprintf(stderr, "ERROR: failed to get message for server\n"); ret = -1; @@ -493,7 +509,7 @@ int main(int argc, char** argv) } /* Read the server data into our buff array */ - memset(buff, 0, sizeof(buff)); + XMEMSET(buff, 0, sizeof(buff)); if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) { fprintf(stderr, "ERROR: failed to read\n"); goto exit; diff --git a/tls/server-tls-pkcallback.c b/tls/server-tls-pkcallback.c index 26832ab8a..e8bf4ab12 100644 --- a/tls/server-tls-pkcallback.c +++ b/tls/server-tls-pkcallback.c @@ -98,7 +98,7 @@ static int load_file(const char* fname, byte** buf, size_t* bufLen) rewind(lFile); if (fileSz > 0) { *bufLen = (size_t)fileSz; - *buf = (byte*)malloc(*bufLen); + *buf = (byte*)XMALLOC(*bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (*buf == NULL) { ret = MEMORY_E; printf("Error allocating %lu bytes\n", (unsigned long)*bufLen); @@ -128,20 +128,24 @@ static int load_key_file(const char* fname, byte** derBuf, word32* derLen) if (ret != 0) return ret; - *derBuf = (byte*)malloc(bufLen); + *derBuf = (byte*)XMALLOC(bufLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (*derBuf == NULL) { - free(buf); + wc_ForceZero(buf, bufLen); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return MEMORY_E; } ret = wc_KeyPemToDer(buf, (word32)bufLen, *derBuf, (word32)bufLen, NULL); if (ret < 0) { - free(buf); - free(*derBuf); + wc_ForceZero(buf, bufLen); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_ForceZero(*derBuf, bufLen); + XFREE(*derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } *derLen = ret; - free(buf); + wc_ForceZero(buf, bufLen); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return 0; } @@ -168,22 +172,28 @@ static int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, #endif ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz); + if (ret != 0) { +#ifdef WOLFSSL_ASYNC_CRYPT + cbInfo->state = 0; +#endif + return ret; + } + + ret = wc_ecc_init(&cbInfo->keyEcc); if (ret == 0) { - ret = wc_ecc_init(&cbInfo->keyEcc); + word32 idx = 0; + ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz); if (ret == 0) { - word32 idx = 0; - ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &cbInfo->keyEcc, keySz); - if (ret == 0) { - WC_RNG *rng = wolfSSL_GetRNG(ssl); - - printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id); - ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng, - &cbInfo->keyEcc); - } - wc_ecc_free(&cbInfo->keyEcc); + WC_RNG *rng = wolfSSL_GetRNG(ssl); + + printf("PK ECC Sign: Curve ID %d\n", cbInfo->keyEcc.dp->id); + ret = wc_ecc_sign_hash(in, inSz, out, outSz, rng, + &cbInfo->keyEcc); } + wc_ecc_free(&cbInfo->keyEcc); } - free(keyBuf); + wc_ForceZero(keyBuf, keySz); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #ifdef WOLFSSL_ASYNC_CRYPT cbInfo->state = 0; #endif @@ -217,8 +227,12 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, #endif ret = load_key_file(cbInfo->keyFile, &keyBuf, &keySz); - if (ret != 0) + if (ret != 0) { +#ifdef WOLFSSL_ASYNC_CRYPT + cbInfo->state = 0; +#endif return ret; + } ret = wc_InitRsaKey(&cbInfo->keyRsa, NULL); if (ret == 0) { @@ -233,7 +247,8 @@ static int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, } wc_FreeRsaKey(&cbInfo->keyRsa); } - free(keyBuf); + wc_ForceZero(keyBuf, keySz); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); #ifdef WOLFSSL_ASYNC_CRYPT cbInfo->state = 0; #endif @@ -299,7 +314,8 @@ static int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz, } wc_FreeRsaKey(&cbInfo->keyRsa); } - free(keyBuf); + wc_ForceZero(keyBuf, keySz); + XFREE(keyBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); printf("PK RSA PSS Sign: ret %d, outSz %u\n", ret, *outSz); @@ -326,7 +342,7 @@ int main(int argc, char** argv) /* PK callback context */ PkCbInfo myCtx; - memset(&myCtx, 0, sizeof(myCtx)); + XMEMSET(&myCtx, 0, sizeof(myCtx)); myCtx.keyFile = KEY_FILE; /* declare wolfSSL objects */ @@ -341,7 +357,7 @@ int main(int argc, char** argv) #endif /* Initialize the server address struct with zeros */ - memset(&servAddr, 0, sizeof(servAddr)); + XMEMSET(&servAddr, 0, sizeof(servAddr)); /* Fill in the server address */ servAddr.sin_family = AF_INET; /* using IPv4 */ @@ -497,7 +513,7 @@ int main(int argc, char** argv) /* Read the client data into our buff array */ - memset(buff, 0, sizeof(buff)); + XMEMSET(buff, 0, sizeof(buff)); if ((ret = wolfSSL_read(ssl, buff, sizeof(buff)-1)) == -1) { fprintf(stderr, "ERROR: failed to read\n"); goto exit; @@ -514,7 +530,7 @@ int main(int argc, char** argv) /* Write our reply into buff */ - memset(buff, 0, sizeof(buff)); + XMEMSET(buff, 0, sizeof(buff)); memcpy(buff, reply, strlen(reply)); len = strnlen(buff, sizeof(buff));