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/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/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/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/crypto/3des/3des-file-encrypt.c b/crypto/3des/3des-file-encrypt.c index aa82d372a..f361a3f70 100644 --- a/crypto/3des/3des-file-encrypt.c +++ b/crypto/3des/3des-file-encrypt.c @@ -23,11 +23,17 @@ #include #include #include +#include +#include #include #include #include #include +#ifndef XPRINTF + #define XPRINTF printf +#endif + #define DES3_BLOCK_SIZE 24 /* size of encryption blocks */ #define SALT_SIZE 8 @@ -61,8 +67,8 @@ int Des3Encrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) { WC_RNG rng; byte iv[DES3_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; @@ -70,6 +76,8 @@ int Des3Encrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) int inputLength; int length; int padCounter = 0; + int rngInit = 0; + int des3Init = 0; fseek(inFile, 0, SEEK_END); inputLength = ftell(inFile); @@ -82,62 +90,101 @@ int Des3Encrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) padCounter++; } - input = malloc(length); - output = malloc(length); + input = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1050; + } - ret = wc_InitRng(&rng); - if (ret != 0) { - printf("Failed to initialize random number generator\n"); - return -1030; + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } /* reads from inFile and writes whatever is there to the input array */ - ret = fread(input, 1, inputLength, inFile); if (ret == 0) { - printf("Input file does not exist.\n"); - return -1010; - } - for (i = inputLength; i < length; i++) { - /* pads the added characters with the number of pads */ - input[i] = padCounter; + ret = fread(input, 1, inputLength, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + ret = 0; + for (i = inputLength; i < length; i++) { + /* pads the added characters with the number of pads */ + input[i] = padCounter; + } + } } - ret = wc_RNG_GenerateBlock(&rng, iv, DES3_BLOCK_SIZE); - if (ret != 0) - return -1020; + if (ret == 0) { + ret = wc_RNG_GenerateBlock(&rng, iv, DES3_BLOCK_SIZE); + if (ret != 0) + ret = -1020; + } /* stretches key to fit size */ - ret = GenerateKey(&rng, key, size, salt, padCounter); - if (ret != 0) - return -1040; + if (ret == 0) { + ret = GenerateKey(&rng, key, size, salt, padCounter); + if (ret != 0) + ret = -1040; + } + + /* inits des3 structure */ + if (ret == 0) { + ret = wc_Des3Init(des3, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("Des3Init returned: %d\n", ret); + ret = -1000; + } + else + des3Init = 1; + } /* sets key */ - ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION); - if (ret != 0) - return -1001; + if (ret == 0) { + ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION); + if (ret != 0) + ret = -1001; + } /* encrypts the message to the output based on input length + padding */ - ret = wc_Des3_CbcEncrypt(des3, output, input, length); - if (ret != 0) - return -1005; + if (ret == 0) { + ret = wc_Des3_CbcEncrypt(des3, output, input, length); + if (ret != 0) + ret = -1005; + } - /* writes to outFile */ - fwrite(salt, 1, SALT_SIZE, outFile); - fwrite(iv, 1, DES3_BLOCK_SIZE, outFile); - fwrite(output, 1, length, outFile); + if (ret == 0) { + /* writes to outFile */ + fwrite(salt, 1, SALT_SIZE, outFile); + fwrite(iv, 1, DES3_BLOCK_SIZE, 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); + if (input != NULL) { + wc_ForceZero(input, length); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, length); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (des3Init) + wc_Des3Free(des3); + if (rngInit) + wc_FreeRng(&rng); - return 0; + return ret; } /* @@ -147,81 +194,148 @@ int Des3Decrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) { WC_RNG rng; byte iv[DES3_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; int ret = 0; int length; int aSize; + int rngInit = 0; + int des3Init = 0; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); - - wc_InitRng(&rng); + /* verifies the file is at least large enough to hold the salt and iv + * before any subtraction/allocation is performed on its length, to + * avoid an integer underflow / negative-size allocation on a + * truncated file */ + if (length < SALT_SIZE + DES3_BLOCK_SIZE) { + XPRINTF("Input file is too small.\n"); + ret = -1011; + } - /* 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; + input = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1051; + } } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; + + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } - for (i = SALT_SIZE; i < DES3_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + /* reads from inFile and writes whatever is there to the input array */ + if (ret == 0) { + ret = fread(input, 1, length, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + 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) - return -1050; + if (ret == 0) { + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; + } + + /* inits des3 structure */ + if (ret == 0) { + ret = wc_Des3Init(des3, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("Des3Init returned: %d\n", ret); + ret = -1000; + } + else + des3Init = 1; + } /* sets key */ - ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); - if (ret != 0) - return -1002; + if (ret == 0) { + ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); + if (ret != 0) + ret = -1002; + } - /* 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) { + /* 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; } - /* 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 */ - length -= output[length-1]; + if (ret == 0) { + if (salt[0] != 0) { + /* validates the padding byte before using it to reduce length, + * to avoid an out-of-bounds/garbage-length fwrite on + * corrupted or malicious ciphertext */ + if (length < 1 || output[length-1] < 1 || + output[length-1] > length || + output[length-1] > DES3_BLOCK_SIZE) { + XPRINTF("Error: invalid padding value\n"); + ret = -1013; + } + else { + /* reduces length based on number of padded elements */ + length -= output[length-1]; + } + } + if (ret == 0) { + /* writes output to the outFile based on shortened length */ + fwrite(output, 1, length, outFile); + } } - /* 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); + if (input != NULL) { + wc_ForceZero(input, aSize); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, aSize); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (des3Init) + wc_Des3Free(des3); + if (rngInit) + wc_FreeRng(&rng); - return 0; + return ret; } /* @@ -229,11 +343,11 @@ int Des3Decrypt(Des3* des3, byte* key, int size, FILE* inFile, FILE* outFile) */ void help() { - printf("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); - printf("Usage: ./3des-encrypt <-option> " + XPRINTF("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); + XPRINTF("Usage: ./3des-encrypt <-option> " "\n\n"); - printf("Options\n"); - printf("-d Decryption\n-e Encryption\n-h Help\n"); + XPRINTF("Options\n"); + XPRINTF("-d Decryption\n-e Encryption\n-h Help\n"); } /* @@ -242,29 +356,36 @@ void help() int NoEcho(char* key, int size) { struct termios oflags, nflags; + int isTTY; + + isTTY = isatty(fileno(stdin)); - /* disabling echo */ - tcgetattr(fileno(stdin), &oflags); - nflags = oflags; - nflags.c_lflag &= ~ECHO; - nflags.c_lflag |= ECHONL; + if (isTTY) { + /* disabling echo */ + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; - if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { - printf("Error: tcsetattr failed to disable terminal echo\n"); - return -1060; + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { + XPRINTF("Error: tcsetattr failed to disable terminal echo\n"); + return -1060; + } } - printf("Unique Password: "); + XPRINTF("Unique Password: "); if (fgets(key, size, stdin) == NULL) { - printf("Error: fgets failed to retrieve secure key input\n"); + XPRINTF("Error: fgets failed to retrieve secure key input\n"); return -1070; } key[strlen(key) - 1] = 0; - /* restore terminal */ - if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { - printf("Error: tcsetattr failed to enable terminal echo\n"); - return -1080; + if (isTTY) { + /* restore terminal */ + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + XPRINTF("Error: tcsetattr failed to enable terminal echo\n"); + return -1080; + } } return 0; } @@ -275,7 +396,7 @@ int SizeCheck(int size) if (size != 56 && size != 112 && size != 168) { /* if the entered size does not match acceptable size */ - printf("Invalid 3DES key size\n"); + XPRINTF("Invalid 3DES key size\n"); ret = -1080; } @@ -326,7 +447,7 @@ int main(int argc, char** argv) break; case '?': if (optopt) { - printf("Ending Session\n"); + XPRINTF("Ending Session\n"); return -111; } default: @@ -335,20 +456,36 @@ int main(int argc, char** argv) } if (inCheck == 0 || outCheck == 0) { - printf("Must have both input and output file"); - printf(": -i filename -o filename\n"); + XPRINTF("Must have both input and output file"); + XPRINTF(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n') { - key = malloc(size); /* sets size memory of key */ - ret = NoEcho((char*)key, size); - if (choice == 'e') - Des3Encrypt(&des3, key, size, inFile, outFile); - else if (choice == 'd') - Des3Decrypt(&des3, key, size, inFile, outFile); + key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ + if (key == NULL) { + XPRINTF("Failed to allocate memory for key\n"); + ret = -1050; + fclose(inFile); + fclose(outFile); + } + else { + ret = NoEcho((char*)key, size); + if (ret == 0) { + if (choice == 'e') + ret = Des3Encrypt(&des3, key, size, inFile, outFile); + else if (choice == 'd') + ret = Des3Decrypt(&des3, key, size, inFile, outFile); + } + else { + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + } + } } else if (choice == 'n') { - printf("Must select either -e[56,112,168] or -d[56,112,168] for \ + XPRINTF("Must select either -e[56,112,168] or -d[56,112,168] for \ encryption and decryption\n"); } 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..0de628686 100644 --- a/crypto/aes/aes-file-encrypt.c +++ b/crypto/aes/aes-file-encrypt.c @@ -27,11 +27,17 @@ #include #endif #include +#include +#include #include #include #include #include +#ifndef XPRINTF + #define XPRINTF printf +#endif + #if defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) #define SALT_SIZE 8 @@ -69,8 +75,8 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) { WC_RNG rng; byte iv[AES_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; @@ -78,6 +84,8 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) int inputLength; int length; int padCounter = 0; + int rngInit = 0; + int aesInit = 0; fseek(inFile, 0, SEEK_END); inputLength = ftell(inFile); @@ -90,69 +98,101 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) padCounter++; } - input = malloc(length); - output = malloc(length); + input = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1050; + } - ret = wc_InitRng(&rng); - if (ret != 0) { - printf("Failed to initialize random number generator\n"); - return -1030; + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } /* reads from inFile and writes whatever is there to the input array */ - ret = fread(input, 1, inputLength, inFile); if (ret == 0) { - printf("Input file does not exist.\n"); - return -1010; - } - for (i = inputLength; i < length; i++) { - /* pads the added characters with the number of pads */ - input[i] = padCounter; + ret = fread(input, 1, inputLength, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + ret = 0; + for (i = inputLength; i < length; i++) { + /* pads the added characters with the number of pads */ + input[i] = padCounter; + } + } } - ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE); - if (ret != 0) - return -1020; + if (ret == 0) { + ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE); + if (ret != 0) + ret = -1020; + } /* stretches key to fit size */ - ret = GenerateKey(&rng, key, size, salt, padCounter); - if (ret != 0) - return -1040; + if (ret == 0) { + ret = GenerateKey(&rng, key, size, salt, padCounter); + if (ret != 0) + ret = -1040; + } /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1001; + if (ret == 0) { + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("AesInit returned: %d\n", ret); + ret = -1000; + } + else + aesInit = 1; } /* sets key */ - ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("SetKey returned: %d\n", ret); - return -1001; + if (ret == 0) { + ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); + if (ret != 0) { + XPRINTF("SetKey returned: %d\n", ret); + ret = -1001; + } } /* encrypts the message to the output based on input length + padding */ - ret = wc_AesCbcEncrypt(aes, output, input, length); - if (ret != 0) - return -1005; + if (ret == 0) { + ret = wc_AesCbcEncrypt(aes, output, input, length); + if (ret != 0) + ret = -1005; + } - /* writes to outFile */ - fwrite(salt, 1, SALT_SIZE, outFile); - fwrite(iv, 1, AES_BLOCK_SIZE, outFile); - fwrite(output, 1, length, outFile); + if (ret == 0) { + /* writes to outFile */ + fwrite(salt, 1, SALT_SIZE, outFile); + fwrite(iv, 1, AES_BLOCK_SIZE, 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); + if (input != NULL) { + wc_ForceZero(input, length); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, length); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (aesInit) + wc_AesFree(aes); + if (rngInit) + wc_FreeRng(&rng); return ret; } @@ -164,90 +204,150 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) { WC_RNG rng; byte iv[AES_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; int ret = 0; int length; int aSize; + int rngInit = 0; + int aesInit = 0; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); - - wc_InitRng(&rng); + /* input file must be at least large enough to hold the salt and one + * AES block, otherwise the length arithmetic below would underflow */ + if (length < SALT_SIZE + AES_BLOCK_SIZE) { + XPRINTF("Input file is too small.\n"); + ret = -1011; + } - /* 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; + input = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1051; + } } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; + + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } - for (i = SALT_SIZE; i < AES_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + /* reads from inFile and writes whatever is there to the input array */ + if (ret == 0) { + ret = fread(input, 1, length, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + 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) - return -1050; + if (ret == 0) { + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; + } /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1001; + if (ret == 0) { + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("AesInit returned: %d\n", ret); + ret = -1000; + } + else + aesInit = 1; } /* 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) { + ret = wc_AesSetKey(aes, key, size, iv, AES_DECRYPTION); + if (ret != 0) { + XPRINTF("SetKey returned: %d\n", ret); + ret = -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) { + if (salt[0] != 0) { + /* validate the padding byte before trusting it, to avoid an + * out-of-bounds / garbage-length fwrite on corrupted or + * malicious ciphertext */ + if (length < 1 || output[length-1] < 1 || + output[length-1] > length || + output[length-1] > AES_BLOCK_SIZE) { + XPRINTF("Error: invalid padding value\n"); + ret = -1013; + } + else { + /* reduces length based on number of padded elements */ + length -= output[length-1]; + } + } } - /* 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 */ - length -= output[length-1]; + if (ret == 0) { + /* writes output to the outFile based on shortened length */ + fwrite(output, 1, length, outFile); } - /* 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); + if (input != NULL) { + wc_ForceZero(input, aSize); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, aSize); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (aesInit) + wc_AesFree(aes); + if (rngInit) + wc_FreeRng(&rng); - return 0; + return ret; } /* @@ -255,11 +355,11 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) */ void help() { - printf("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); - printf("Usage: ./aes-file-encrypt <-option> <-i file.in> " + XPRINTF("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); + XPRINTF("Usage: ./aes-file-encrypt <-option> <-i file.in> " "<-o file.out>\n\n"); - printf("Options\n"); - printf("-d Decryption\n-e Encryption\n-h Help\n"); + XPRINTF("Options\n"); + XPRINTF("-d Decryption\n-e Encryption\n-h Help\n"); } /* @@ -268,30 +368,37 @@ void help() int NoEcho(char* key, int size) { struct termios oflags, nflags; + int isTTY; + + isTTY = isatty(fileno(stdin)); - /* disabling echo */ - tcgetattr(fileno(stdin), &oflags); - nflags = oflags; - nflags.c_lflag &= ~ECHO; - nflags.c_lflag |= ECHONL; + if (isTTY) { + /* disabling echo */ + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; - if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { - printf("Error: tcsetattr failed to disable terminal echo\n"); - return -1060; + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { + XPRINTF("Error: tcsetattr failed to disable terminal echo\n"); + return -1060; + } } - printf("Unique Password: "); + XPRINTF("Unique Password: "); if (fgets(key, size, stdin) == NULL) { - printf("Error: fgets failed to retrieve secure key input\n"); + XPRINTF("Error: fgets failed to retrieve secure key input\n"); return -1070; } key[strlen(key) - 1] = 0; - /* restore terminal */ - if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { - printf("Error: tcsetattr failed to enable terminal echo\n"); - return -1080; + if (isTTY) { + /* restore terminal */ + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + XPRINTF("Error: tcsetattr failed to enable terminal echo\n"); + return -1080; + } } return 0; } @@ -312,7 +419,7 @@ int SizeCheck(int *size) } else { /* if the entered size does not match acceptable size */ - printf("Invalid AES key size\n"); + XPRINTF("Invalid AES key size\n"); ret = -1080; } @@ -363,7 +470,7 @@ int main(int argc, char** argv) break; case '?': if (optopt) { - printf("Ending Session\n"); + XPRINTF("Ending Session\n"); return -111; } default: @@ -371,19 +478,35 @@ int main(int argc, char** argv) } } if (inCheck == 0 || outCheck == 0) { - printf("Must have both input and output file"); - printf(": -i filename -o filename\n"); + XPRINTF("Must have both input and output file"); + XPRINTF(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n' && inFile != NULL) { - key = malloc(size); /* sets size memory of key */ - ret = NoEcho((char*)key, size); - if (choice == 'e') - AesEncrypt(&aes, key, size, inFile, outFile); - else if (choice == 'd') - AesDecrypt(&aes, key, size, inFile, outFile); + key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ + if (key == NULL) { + XPRINTF("Failed to allocate memory for key\n"); + ret = -1050; + fclose(inFile); + fclose(outFile); + } + else { + ret = NoEcho((char*)key, size); + if (ret == 0) { + if (choice == 'e') + ret = AesEncrypt(&aes, key, size, inFile, outFile); + else if (choice == 'd') + ret = AesDecrypt(&aes, key, size, inFile, outFile); + } + else { + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + } + } } else if (choice == 'n') { - printf("Must select either -e[128, 192, 256] or -d[128, 192, 256] \ + XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \ for encryption and decryption\n"); ret = -110; } @@ -394,7 +517,7 @@ int main(int argc, char** argv) #else int main() { - printf("pwdbased and HAVE_PBKDF2 not compiled in\n"); + XPRINTF("pwdbased and HAVE_PBKDF2 not compiled in\n"); return 0; } #endif diff --git a/crypto/aes/aescfb-file-encrypt.c b/crypto/aes/aescfb-file-encrypt.c index 5c173687f..374e372f1 100644 --- a/crypto/aes/aescfb-file-encrypt.c +++ b/crypto/aes/aescfb-file-encrypt.c @@ -23,11 +23,17 @@ #include #include #include +#include +#include #include #include #include #include +#ifndef XPRINTF + #define XPRINTF printf +#endif + #if defined(WOLFSSL_AES_CFB) && defined(HAVE_PBKDF2) && \ !defined(NO_PWDBASED) #define SALT_SIZE 8 @@ -62,8 +68,8 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) { WC_RNG rng; byte iv[AES_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; @@ -71,6 +77,8 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) int inputLength; int length; int padCounter = 0; + int rngInit = 0; + int aesInit = 0; fseek(inFile, 0, SEEK_END); inputLength = ftell(inFile); @@ -83,69 +91,101 @@ int AesEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) padCounter++; } - input = malloc(length); - output = malloc(length); + input = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1050; + } - ret = wc_InitRng(&rng); - if (ret != 0) { - printf("Failed to initialize random number generator\n"); - return -1030; + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } /* reads from inFile and writes whatever is there to the input array */ - ret = fread(input, 1, inputLength, inFile); if (ret == 0) { - printf("Input file does not exist.\n"); - return -1010; - } - for (i = inputLength; i < length; i++) { - /* pads the added characters with the number of pads */ - input[i] = padCounter; + ret = fread(input, 1, inputLength, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + ret = 0; + for (i = inputLength; i < length; i++) { + /* pads the added characters with the number of pads */ + input[i] = padCounter; + } + } } - ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE); - if (ret != 0) - return -1020; + if (ret == 0) { + ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE); + if (ret != 0) + ret = -1020; + } /* stretches key to fit size */ - ret = GenerateKey(&rng, key, size, salt, padCounter); - if (ret != 0) - return -1040; + if (ret == 0) { + ret = GenerateKey(&rng, key, size, salt, padCounter); + if (ret != 0) + ret = -1040; + } /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1001; + if (ret == 0) { + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("AesInit returned: %d\n", ret); + ret = -1000; + } + else + aesInit = 1; } /* sets key */ - ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("SetKey returned: %d\n", ret); - return -1001; + if (ret == 0) { + ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); + if (ret != 0) { + XPRINTF("SetKey returned: %d\n", ret); + ret = -1001; + } } /* encrypts the message to the output based on input length + padding */ - ret = wc_AesCfbEncrypt(aes, output, input, length); - if (ret != 0) - return -1005; + if (ret == 0) { + ret = wc_AesCfbEncrypt(aes, output, input, length); + if (ret != 0) + ret = -1005; + } - /* writes to outFile */ - fwrite(salt, 1, SALT_SIZE, outFile); - fwrite(iv, 1, AES_BLOCK_SIZE, outFile); - fwrite(output, 1, length, outFile); + if (ret == 0) { + /* writes to outFile */ + fwrite(salt, 1, SALT_SIZE, outFile); + fwrite(iv, 1, AES_BLOCK_SIZE, 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); + if (input != NULL) { + wc_ForceZero(input, length); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, length); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (aesInit) + wc_AesFree(aes); + if (rngInit) + wc_FreeRng(&rng); return ret; } @@ -157,91 +197,150 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) { WC_RNG rng; byte iv[AES_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; int ret = 0; int length; int aSize; + int rngInit = 0; + int aesInit = 0; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); - - wc_InitRng(&rng); + /* verify the file is at least large enough to hold the salt and IV + * before subtracting/allocating based on its length, otherwise a + * truncated file could underflow the size calculations below */ + if (length < SALT_SIZE + AES_BLOCK_SIZE) { + XPRINTF("Input file is too small.\n"); + ret = -1011; + } - /* 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; + input = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1051; + } } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; + + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } - for (i = SALT_SIZE; i < AES_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + /* reads from inFile and writes whatever is there to the input array */ + if (ret == 0) { + ret = fread(input, 1, length, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + 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) - return -1050; + if (ret == 0) { + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; + } /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1002; + if (ret == 0) { + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("AesInit returned: %d\n", ret); + ret = -1000; + } + else + aesInit = 1; } /* 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_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); + if (ret != 0) { + XPRINTF("SetKey returned: %d\n", ret); + ret = -1002; + } } - /* 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) { + /* 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; } - /* 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 */ - length -= output[length-1]; + if (ret == 0) { + if (salt[0] != 0) { + /* reduces length based on number of padded elements. Validate + * the padding byte before trusting it as a subtraction amount + * to avoid an out-of-bounds/garbage-length fwrite on corrupted + * or malicious ciphertext */ + if (length < 1 || output[length - 1] < 1 || + output[length - 1] > length || + output[length - 1] > AES_BLOCK_SIZE) { + XPRINTF("Error: invalid padding value\n"); + ret = -1013; + } + else { + length -= output[length - 1]; + } + } + if (ret == 0) { + /* writes output to the outFile based on shortened length */ + fwrite(output, 1, length, outFile); + } } - /* 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); + if (input != NULL) { + wc_ForceZero(input, aSize); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, aSize); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (aesInit) + wc_AesFree(aes); + if (rngInit) + wc_FreeRng(&rng); - return 0; + return ret; } /* @@ -249,11 +348,11 @@ int AesDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) */ void help() { - printf("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); - printf("Usage: ./aes-file-encrypt <-option> <-i file.in> " + XPRINTF("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); + XPRINTF("Usage: ./aes-file-encrypt <-option> <-i file.in> " "<-o file.out>\n\n"); - printf("Options\n"); - printf("-d Decryption\n-e Encryption\n-h Help\n"); + XPRINTF("Options\n"); + XPRINTF("-d Decryption\n-e Encryption\n-h Help\n"); } /* @@ -262,30 +361,37 @@ void help() int NoEcho(char* key, int size) { struct termios oflags, nflags; + int isTTY; - /* disabling echo */ - tcgetattr(fileno(stdin), &oflags); - nflags = oflags; - nflags.c_lflag &= ~ECHO; - nflags.c_lflag |= ECHONL; + isTTY = isatty(fileno(stdin)); - if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { - printf("Error: tcsetattr failed to disable terminal echo\n"); - return -1060; + if (isTTY) { + /* disabling echo */ + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { + XPRINTF("Error: tcsetattr failed to disable terminal echo\n"); + return -1060; + } } - printf("Unique Password: "); + XPRINTF("Unique Password: "); if (fgets(key, size, stdin) == NULL) { - printf("Error: fgets failed to retrieve secure key input\n"); + XPRINTF("Error: fgets failed to retrieve secure key input\n"); return -1070; } key[strlen(key) - 1] = 0; - /* restore terminal */ - if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { - printf("Error: tcsetattr failed to enable terminal echo\n"); - return -1080; + if (isTTY) { + /* restore terminal */ + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + XPRINTF("Error: tcsetattr failed to enable terminal echo\n"); + return -1080; + } } return 0; } @@ -306,7 +412,7 @@ int SizeCheck(int *size) } else { /* if the entered size does not match acceptable size */ - printf("Invalid AES key size\n"); + XPRINTF("Invalid AES key size\n"); ret = -1080; } @@ -357,7 +463,7 @@ int main(int argc, char** argv) break; case '?': if (optopt) { - printf("Ending Session\n"); + XPRINTF("Ending Session\n"); return -111; } default: @@ -365,19 +471,35 @@ int main(int argc, char** argv) } } if (inCheck == 0 || outCheck == 0) { - printf("Must have both input and output file"); - printf(": -i filename -o filename\n"); + XPRINTF("Must have both input and output file"); + XPRINTF(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n' && inFile != NULL) { - key = malloc(size); /* sets size memory of key */ - ret = NoEcho((char*)key, size); - if (choice == 'e') - AesEncrypt(&aes, key, size, inFile, outFile); - else if (choice == 'd') - AesDecrypt(&aes, key, size, inFile, outFile); + key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ + if (key == NULL) { + XPRINTF("Failed to allocate memory for key\n"); + ret = -1050; + fclose(inFile); + fclose(outFile); + } + else { + ret = NoEcho((char*)key, size); + if (ret == 0) { + if (choice == 'e') + ret = AesEncrypt(&aes, key, size, inFile, outFile); + else if (choice == 'd') + ret = AesDecrypt(&aes, key, size, inFile, outFile); + } + else { + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + } + } } else if (choice == 'n') { - printf("Must select either -e[128, 192, 256] or -d[128, 192, 256] \ + XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \ for encryption and decryption\n"); ret = -110; } @@ -388,7 +510,7 @@ int main(int argc, char** argv) #else int main() { - printf("AES-CFB or HAVE_PBKDF2 not compiled in\n"); + XPRINTF("AES-CFB or HAVE_PBKDF2 not compiled in\n"); return 0; } #endif diff --git a/crypto/aes/aesctr-file-encrypt.c b/crypto/aes/aesctr-file-encrypt.c index 366d694eb..00a6f1121 100644 --- a/crypto/aes/aesctr-file-encrypt.c +++ b/crypto/aes/aesctr-file-encrypt.c @@ -23,11 +23,17 @@ #include #include #include +#include +#include #include #include #include #include +#ifndef XPRINTF + #define XPRINTF printf +#endif + #if defined(HAVE_PBKDF2) && !defined(NO_PWDBASED) && \ defined(WOLFSSL_AES_COUNTER) #define SALT_SIZE 8 @@ -59,76 +65,109 @@ int AesCtrEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) { WC_RNG rng; byte iv[AES_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int ret = 0; int length; + int rngInit = 0; + int aesInit = 0; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); - input = malloc(length); - output = malloc(length); + input = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1050; + } - ret = wc_InitRng(&rng); - if (ret != 0) { - printf("Failed to initialize random number generator\n"); - return -1030; + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } /* 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 = fread(input, 1, length, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else + ret = 0; } - ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE); - if (ret != 0) - return -1020; + if (ret == 0) { + ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SIZE); + if (ret != 0) + ret = -1020; + } /* stretches key to fit size */ - ret = GenerateKey(&rng, key, size, salt); - if (ret != 0) - return -1040; + if (ret == 0) { + ret = GenerateKey(&rng, key, size, salt); + if (ret != 0) + ret = -1040; + } /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1001; + if (ret == 0) { + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("AesInit returned: %d\n", ret); + ret = -1000; + } + else + aesInit = 1; } /* sets key */ - ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); - if (ret != 0) { - printf("SetKey returned: %d\n", ret); - return -1001; + if (ret == 0) { + ret = wc_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); + if (ret != 0) { + XPRINTF("SetKey returned: %d\n", ret); + ret = -1001; + } } /* encrypts the message to the output based on input length + padding */ - ret = wc_AesCtrEncrypt(aes, output, input, length); - if (ret != 0) - return -1005; + if (ret == 0) { + ret = wc_AesCtrEncrypt(aes, output, input, length); + if (ret != 0) + ret = -1005; + } - /* writes to outFile */ - fwrite(salt, 1, SALT_SIZE, outFile); - fwrite(iv, 1, AES_BLOCK_SIZE, outFile); - fwrite(output, 1, length, outFile); + if (ret == 0) { + /* writes to outFile */ + fwrite(salt, 1, SALT_SIZE, outFile); + fwrite(iv, 1, AES_BLOCK_SIZE, 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); + if (input != NULL) { + wc_ForceZero(input, length); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, length); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (aesInit) + wc_AesFree(aes); + if (rngInit) + wc_FreeRng(&rng); return ret; } @@ -138,74 +177,111 @@ int AesCtrEncrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) */ int AesCtrDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) { - byte* input; - byte* output; - byte* salt; - byte* iv; - byte* c; + byte* input = NULL; + byte* output = NULL; + byte* salt = NULL; + byte* iv = NULL; + byte* c = NULL; int ret = 0; int bufSz; - int cSz; + int cSz = 0; + int aesInit = 0; fseek(inFile, 0, SEEK_END); bufSz = ftell(inFile); fseek(inFile, 0, SEEK_SET); - input = malloc(bufSz); - output = malloc(bufSz); + /* verify the file is large enough to contain the salt and IV before + * allocating buffers or computing sizes from it (prevents a negative + * cSz / integer underflow on a truncated input file) */ + if (bufSz < SALT_SIZE + AES_BLOCK_SIZE) { + XPRINTF("Input file is too small.\n"); + ret = -1011; + } - /* 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; + input = (byte*)XMALLOC(bufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(bufSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1051; + } } - salt = input; - iv = input + SALT_SIZE; - c = input + SALT_SIZE + AES_BLOCK_SIZE; - cSz = bufSz - SALT_SIZE - AES_BLOCK_SIZE; + /* reads from inFile and writes whatever is there to the input array */ + if (ret == 0) { + ret = fread(input, 1, bufSz, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + 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) - return -1050; + if (ret == 0) { + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; + } /* inits aes structure */ - ret = wc_AesInit(aes, NULL, INVALID_DEVID); - if (ret != 0) { - printf("AesInit returned: %d\n", ret); - return -1002; + if (ret == 0) { + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret != 0) { + XPRINTF("AesInit returned: %d\n", ret); + ret = -1000; + } + else + aesInit = 1; } /* 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_AesSetKey(aes, key, size, iv, AES_ENCRYPTION); + if (ret != 0) { + XPRINTF("SetKey returned: %d\n", ret); + ret = -1002; + } } - ret = wc_AesCtrEncrypt(aes, output, c, cSz); - if (ret != 0) - return -1006; + if (ret == 0) { + ret = wc_AesCtrEncrypt(aes, output, c, cSz); + if (ret != 0) + ret = -1006; + } - /* writes output to the outFile based on shortened length */ - fwrite(output, 1, cSz, outFile); + if (ret == 0) { + /* 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); + if (input != NULL) { + wc_ForceZero(input, bufSz); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, bufSz); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); + if (aesInit) + wc_AesFree(aes); - return 0; + return ret; } /* @@ -213,11 +289,11 @@ int AesCtrDecrypt(Aes* aes, byte* key, int size, FILE* inFile, FILE* outFile) */ void help() { - printf("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); - printf("Usage: ./aesctr-file-encrypt <-option> <-i file.in> " + XPRINTF("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); + XPRINTF("Usage: ./aesctr-file-encrypt <-option> <-i file.in> " "<-o file.out>\n\n"); - printf("Options\n"); - printf("-d Decryption\n-e Encryption\n-h Help\n"); + XPRINTF("Options\n"); + XPRINTF("-d Decryption\n-e Encryption\n-h Help\n"); } /* @@ -226,30 +302,37 @@ void help() int NoEcho(char* key, int size) { struct termios oflags, nflags; + int isTTY; + + isTTY = isatty(fileno(stdin)); - /* disabling echo */ - tcgetattr(fileno(stdin), &oflags); - nflags = oflags; - nflags.c_lflag &= ~ECHO; - nflags.c_lflag |= ECHONL; + if (isTTY) { + /* disabling echo */ + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; - if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { - printf("Error: tcsetattr failed to disable terminal echo\n"); - return -1060; + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { + XPRINTF("Error: tcsetattr failed to disable terminal echo\n"); + return -1060; + } } - printf("Unique Password: "); + XPRINTF("Unique Password: "); if (fgets(key, size, stdin) == NULL) { - printf("Error: fgets failed to retrieve secure key input\n"); + XPRINTF("Error: fgets failed to retrieve secure key input\n"); return -1070; } key[strlen(key) - 1] = 0; - /* restore terminal */ - if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { - printf("Error: tcsetattr failed to enable terminal echo\n"); - return -1080; + if (isTTY) { + /* restore terminal */ + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + XPRINTF("Error: tcsetattr failed to enable terminal echo\n"); + return -1080; + } } return 0; } @@ -270,7 +353,7 @@ int SizeCheck(int *size) } else { /* if the entered size does not match acceptable size */ - printf("Invalid AES key size\n"); + XPRINTF("Invalid AES key size\n"); ret = -1080; } @@ -321,7 +404,7 @@ int main(int argc, char** argv) break; case '?': if (optopt) { - printf("Ending Session\n"); + XPRINTF("Ending Session\n"); return -111; } default: @@ -329,19 +412,35 @@ int main(int argc, char** argv) } } if (inCheck == 0 || outCheck == 0) { - printf("Must have both input and output file"); - printf(": -i filename -o filename\n"); + XPRINTF("Must have both input and output file"); + XPRINTF(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n' && inFile != NULL) { - key = malloc(size); /* sets size memory of key */ - ret = NoEcho((char*)key, size); - if (choice == 'e') - AesCtrEncrypt(&aes, key, size, inFile, outFile); - else if (choice == 'd') - AesCtrDecrypt(&aes, key, size, inFile, outFile); + key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ + if (key == NULL) { + XPRINTF("Failed to allocate memory for key\n"); + ret = -1050; + fclose(inFile); + fclose(outFile); + } + else { + ret = NoEcho((char*)key, size); + if (ret == 0) { + if (choice == 'e') + ret = AesCtrEncrypt(&aes, key, size, inFile, outFile); + else if (choice == 'd') + ret = AesCtrDecrypt(&aes, key, size, inFile, outFile); + } + else { + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + } + } } else if (choice == 'n') { - printf("Must select either -e[128, 192, 256] or -d[128, 192, 256] \ + XPRINTF("Must select either -e[128, 192, 256] or -d[128, 192, 256] \ for encryption and decryption\n"); ret = -110; } @@ -352,7 +451,7 @@ int main(int argc, char** argv) #else int main() { - printf("Missing pwdbased, pbkdf2, or aes-ctr from wolfSSL\n"); + XPRINTF("Missing pwdbased, pbkdf2, or aes-ctr from wolfSSL\n"); return 0; } #endif diff --git a/crypto/aes/aesgcm-file-encrypt.c b/crypto/aes/aesgcm-file-encrypt.c index 65f3551b5..bf685781d 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 @@ -179,6 +180,7 @@ int encrypt_file_AesGCM(const char *in_file, const char *out_file, byte key[AES_KEY_SIZE]; byte tag_enc[AESGCM_TAG_SIZE]; Aes gcm; + int aes_initialized = 0; if (!in_file || !out_file || !key_str || !iv_str) { return BAD_FUNC_ARG; @@ -212,26 +214,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); @@ -241,6 +243,7 @@ int encrypt_file_AesGCM(const char *in_file, const char *out_file, printf("AesInit returned: %d\n", ret); goto exit; } + aes_initialized = 1; ret = wc_AesGcmEncryptInit(&gcm, key, AES_KEY_SIZE, iv, AES_IV_SIZE); if (ret == 0) { @@ -303,11 +306,23 @@ 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); + if (aes_initialized) { + wc_AesFree(&gcm); + } + 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; } @@ -342,6 +357,7 @@ int decrypt_file_AesGCM(const char *in_file, const char *out_file, byte key[AES_KEY_SIZE]; byte tag[AESGCM_TAG_SIZE]; Aes gcm; + int aes_initialized = 0; if (!in_file || !out_file || !key_str) { return BAD_FUNC_ARG; @@ -376,26 +392,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 */ @@ -425,6 +441,9 @@ int decrypt_file_AesGCM(const char *in_file, const char *out_file, } ret = wc_AesGcmDecryptInit(&gcm, key, AES_KEY_SIZE, iv, AES_IV_SIZE); + if (ret == 0) { + aes_initialized = 1; + } while (ret == 0) { read_size = read(in_fd, in_buf, buffer_size); @@ -447,10 +466,23 @@ 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); + if (aes_initialized) { + wc_AesFree(&gcm); + } + 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 +528,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 +622,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 +679,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 +769,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..8c6510526 100644 --- a/crypto/camellia/camellia-encrypt.c +++ b/crypto/camellia/camellia-encrypt.c @@ -23,11 +23,17 @@ #include #include #include +#include +#include #include #include #include #include +#ifndef XPRINTF + #define XPRINTF printf +#endif + #define SALT_SIZE 8 /* @@ -61,8 +67,8 @@ int CamelliaEncrypt(Camellia* cam, byte* key, int size, FILE* inFile, { WC_RNG rng; byte iv[CAMELLIA_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; @@ -70,6 +76,7 @@ int CamelliaEncrypt(Camellia* cam, byte* key, int size, FILE* inFile, int inputLength; int length; int padCounter = 0; + int rngInit = 0; fseek(inFile, 0, SEEK_END); inputLength = ftell(inFile); @@ -82,60 +89,84 @@ int CamelliaEncrypt(Camellia* cam, byte* key, int size, FILE* inFile, padCounter++; } - input = malloc(length); - output = malloc(length); + input = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(length, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1050; + } - ret = wc_InitRng(&rng); - if (ret != 0) { - printf("Failed to initialize random number generator\n"); - return -1030; + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } /* reads from inFile and writes whatever is there to the input array */ - ret = fread(input, 1, inputLength, inFile); if (ret == 0) { - printf("Input file does not exist.\n"); - return -1010; - } - for (i = inputLength; i < length; i++) { - /* pads the added characters with the number of pads */ - input[i] = padCounter; + ret = fread(input, 1, inputLength, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + ret = 0; + for (i = inputLength; i < length; i++) { + /* pads the added characters with the number of pads */ + input[i] = padCounter; + } + } } - ret = wc_RNG_GenerateBlock(&rng, iv, CAMELLIA_BLOCK_SIZE); - if (ret != 0) - return -1020; + if (ret == 0) { + ret = wc_RNG_GenerateBlock(&rng, iv, CAMELLIA_BLOCK_SIZE); + if (ret != 0) + ret = -1020; + } /* stretches key to fit size */ - ret = GenerateKey(&rng, key, size, salt, padCounter); - if (ret != 0) - return -1040; + if (ret == 0) { + ret = GenerateKey(&rng, key, size, salt, padCounter); + if (ret != 0) + ret = -1040; + } /* sets key */ - ret = wc_CamelliaSetKey(cam, key, CAMELLIA_BLOCK_SIZE, iv); - if (ret != 0) - return -1001; + if (ret == 0) { + ret = wc_CamelliaSetKey(cam, key, CAMELLIA_BLOCK_SIZE, iv); + if (ret != 0) + ret = -1001; + } - /* encrypts the message to the output based on input length + padding */ - wc_CamelliaCbcEncrypt(cam, output, input, length); + if (ret == 0) { + /* encrypts the message to the output based on input length + padding */ + wc_CamelliaCbcEncrypt(cam, output, input, length); - /* writes to outFile */ - fwrite(salt, 1, SALT_SIZE, outFile); - fwrite(iv, 1, CAMELLIA_BLOCK_SIZE, outFile); - fwrite(output, 1, length, outFile); + /* writes to outFile */ + fwrite(salt, 1, SALT_SIZE, outFile); + fwrite(iv, 1, CAMELLIA_BLOCK_SIZE, 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); + if (input != NULL) { + wc_ForceZero(input, length); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, length); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); - wc_FreeRng(&rng); + if (rngInit) + wc_FreeRng(&rng); - return 0; + return ret; } /* @@ -146,78 +177,130 @@ int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile, { WC_RNG rng; byte iv[CAMELLIA_BLOCK_SIZE]; - byte* input; - byte* output; + byte* input = NULL; + byte* output = NULL; byte salt[SALT_SIZE] = {0}; int i = 0; int ret = 0; int length; int aSize; + int rngInit = 0; fseek(inFile, 0, SEEK_END); length = ftell(inFile); fseek(inFile, 0, SEEK_SET); aSize = length; - input = malloc(aSize); - output = malloc(aSize); - - wc_InitRng(&rng); + /* verifies the file is large enough to contain the salt and iv before + * using its size to allocate buffers, preventing an integer underflow + * / negative-size allocation on a truncated file */ + if (length < SALT_SIZE + CAMELLIA_BLOCK_SIZE) { + XPRINTF("Input file is too small.\n"); + ret = -1011; + } - /* 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; + input = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + output = (byte*)XMALLOC(aSize, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (input == NULL || output == NULL) { + XPRINTF("Failed to allocate memory\n"); + ret = -1051; + } } - for (i = 0; i < SALT_SIZE; i++) { - /* finds salt from input message */ - salt[i] = input[i]; + + if (ret == 0) { + ret = wc_InitRng(&rng); + if (ret != 0) + XPRINTF("Failed to initialize random number generator\n"); + else + rngInit = 1; } - for (i = SALT_SIZE; i < CAMELLIA_BLOCK_SIZE + SALT_SIZE; i++) { - /* finds iv from input message */ - iv[i - SALT_SIZE] = input[i]; + + /* reads from inFile and writes whatever is there to the input array */ + if (ret == 0) { + ret = fread(input, 1, length, inFile); + if (ret == 0) { + XPRINTF("Input file does not exist.\n"); + ret = -1010; + } + else { + 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) - return -1050; + if (ret == 0) { + ret = wc_PBKDF2(key, key, strlen((const char*)key), salt, SALT_SIZE, + 4096, size, WC_SHA256); + if (ret != 0) + ret = -1050; + } /* sets key */ - ret = wc_CamelliaSetKey(cam, key, CAMELLIA_BLOCK_SIZE, iv); - if (ret != 0) - return -1002; - - /* change length to remove salt/iv block from being decrypted */ - length -= (CAMELLIA_BLOCK_SIZE + SALT_SIZE); - for (i = 0; i < length; i++) { - /* shifts message: ignores salt/iv on message*/ - input[i] = input[i + (CAMELLIA_BLOCK_SIZE + SALT_SIZE)]; + if (ret == 0) { + ret = wc_CamelliaSetKey(cam, key, CAMELLIA_BLOCK_SIZE, iv); + if (ret != 0) + ret = -1002; } - /* decrypts the message to output based on input length + padding */ - wc_CamelliaCbcDecrypt(cam, output, input, length); - if (salt[0] != 0) { - /* reduces length based on number of padded elements */ - length -= output[length-1]; + if (ret == 0) { + /* change length to remove salt/iv block from being decrypted */ + length -= (CAMELLIA_BLOCK_SIZE + SALT_SIZE); + for (i = 0; i < length; i++) { + /* shifts message: ignores salt/iv on message*/ + 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); + + if (salt[0] != 0) { + /* validates the padding byte before trusting it as a length, + * preventing an out-of-bounds/garbage-length fwrite on + * corrupted or malicious ciphertext */ + if (length < 1 || output[length-1] < 1 || + output[length-1] > length || + output[length-1] > CAMELLIA_BLOCK_SIZE) { + XPRINTF("Error: invalid padding value\n"); + ret = -1013; + } + else { + /* reduces length based on number of padded elements */ + length -= output[length-1]; + } + } + + if (ret == 0) { + /* writes output to the outFile based on shortened length */ + fwrite(output, 1, length, outFile); + } } - /* 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); + if (input != NULL) { + wc_ForceZero(input, aSize); + XFREE(input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (output != NULL) { + wc_ForceZero(output, aSize); + XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); fclose(inFile); fclose(outFile); + if (rngInit) + wc_FreeRng(&rng); - return 0; + return ret; } /* @@ -225,11 +308,11 @@ int CamelliaDecrypt(Camellia* cam, byte* key, int size, FILE* inFile, */ void help() { - printf("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); - printf("Usage: ./camellia-file-encrypt <-option> <-i file.in> " + XPRINTF("\n~~~~~~~~~~~~~~~~~~~~|Help|~~~~~~~~~~~~~~~~~~~~~\n\n"); + XPRINTF("Usage: ./camellia-file-encrypt <-option> <-i file.in> " "<-o file.out>\n\n"); - printf("Options\n"); - printf("-d Decryption\n-e Encryption\n-h Help\n"); + XPRINTF("Options\n"); + XPRINTF("-d Decryption\n-e Encryption\n-h Help\n"); } /* @@ -238,30 +321,37 @@ void help() int NoEcho(char* key, int size) { struct termios oflags, nflags; + int isTTY; - /* disabling echo */ - tcgetattr(fileno(stdin), &oflags); - nflags = oflags; - nflags.c_lflag &= ~ECHO; - nflags.c_lflag |= ECHONL; + isTTY = isatty(fileno(stdin)); - if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { - printf("Error: tcsetattr failed to disable terminal echo\n"); - return -1060; + if (isTTY) { + /* disabling echo */ + tcgetattr(fileno(stdin), &oflags); + nflags = oflags; + nflags.c_lflag &= ~ECHO; + nflags.c_lflag |= ECHONL; + + if (tcsetattr(fileno(stdin), TCSANOW, &nflags) != 0) { + XPRINTF("Error: tcsetattr failed to disable terminal echo\n"); + return -1060; + } } - printf("Unique Password: "); + XPRINTF("Unique Password: "); if (fgets(key, size, stdin) == NULL) { - printf("Error: fgets failed to retrieve secure key input\n"); + XPRINTF("Error: fgets failed to retrieve secure key input\n"); return -1070; } key[strlen(key) - 1] = 0; - /* restore terminal */ - if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { - printf("Error: tcsetattr failed to enable terminal echo\n"); - return -1080; + if (isTTY) { + /* restore terminal */ + if (tcsetattr(fileno(stdin), TCSANOW, &oflags) != 0) { + XPRINTF("Error: tcsetattr failed to enable terminal echo\n"); + return -1080; + } } return 0; } @@ -272,7 +362,7 @@ int SizeCheck(int size) if (size != 128 && size != 192 && size != 256) { /* if the entered size does not match acceptable size */ - printf("Invalid Camellia key size\n"); + XPRINTF("Invalid Camellia key size\n"); ret = -1080; } @@ -323,7 +413,7 @@ int main(int argc, char** argv) break; case '?': if (optopt) { - printf("Ending Session\n"); + XPRINTF("Ending Session\n"); return -111; } default: @@ -331,20 +421,36 @@ int main(int argc, char** argv) } } if (inCheck == 0 || outCheck == 0) { - printf("Must have both input and output file"); - printf(": -i filename -o filename\n"); + XPRINTF("Must have both input and output file"); + XPRINTF(": -i filename -o filename\n"); } else if (ret == 0 && choice != 'n') { - key = malloc(size); /* sets size memory of key */ - ret = NoEcho((char*)key, size); - if (choice == 'e') - CamelliaEncrypt(&cam, key, size, inFile, outFile); - else if (choice == 'd') - CamelliaDecrypt(&cam, key, size, inFile, outFile); + key = (byte*)XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER); /* sets size memory of key */ + if (key == NULL) { + XPRINTF("Failed to allocate memory for key\n"); + ret = -1050; + fclose(inFile); + fclose(outFile); + } + else { + ret = NoEcho((char*)key, size); + if (ret == 0) { + if (choice == 'e') + ret = CamelliaEncrypt(&cam, key, size, inFile, outFile); + else if (choice == 'd') + ret = CamelliaDecrypt(&cam, key, size, inFile, outFile); + } + else { + wc_ForceZero(key, size); + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + fclose(inFile); + fclose(outFile); + } + } } else if (choice == 'n') { - printf("Must select either -e[128,192,256] or -d[128,192,256] for \ + XPRINTF("Must select either -e[128,192,256] or -d[128,192,256] for \ encryption and decryption\n"); } 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..0de70b654 100644 --- a/dtls/dtls-export-common.h +++ b/dtls/dtls-export-common.h @@ -29,32 +29,72 @@ #include #include +#include +#include #include #include +#include +#include #include #include #include +#ifndef XPRINTF + #define XPRINTF printf +#endif +#ifndef XFPRINTF + #define XFPRINTF fprintf +#endif + /* Default file for session export/import */ #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 -}; +/* Passphrase source for session-file encryption; falls back to a demo + * value if unset. Set this for anything beyond local demos. */ +#define SESSION_PASSPHRASE_ENV "DTLS_SESSION_PASSPHRASE" +#define DEMO_SESSION_PASSPHRASE "dtls-example-demo-passphrase-change-me" -/* AES block size */ -#define AES_BLOCK_SZ 16 +/* AES block size / PBKDF2 salt size / AES-256 key size */ +#define GCM_IV_SZ 12 +#define GCM_TAG_SZ 16 +#define SESSION_SALT_SZ 16 +#define SESSION_KEY_SZ 32 +#define SESSION_PBKDF2_ITERATIONS 100000 /* File format: * [4 bytes: original data length] - * [16 bytes: IV] - * [N bytes: encrypted data (padded to AES_BLOCK_SZ)] + * [16 bytes: PBKDF2 salt] + * [12 bytes: IV] + * [16 bytes: auth tag] + * [N bytes: encrypted data] + */ + +static const char* GetSessionPassphrase(void) +{ + const char* passphrase = getenv(SESSION_PASSPHRASE_ENV); + if (passphrase == NULL || passphrase[0] == '\0') { + XFPRINTF(stderr, + "Warning: %s not set, using demo passphrase. " + "Set %s to a real secret for anything beyond local demos.\n", + SESSION_PASSPHRASE_ENV, SESSION_PASSPHRASE_ENV); + passphrase = DEMO_SESSION_PASSPHRASE; + } + return passphrase; +} + +/* + * Derive an AES-256 key from a passphrase and salt using PBKDF2-HMAC-SHA256. + * Returns 0 on success, negative on error. */ +static int DeriveSessionKey(const char* passphrase, + const unsigned char* salt, unsigned int saltSz, + unsigned char* key, unsigned int keySz) +{ + return wc_PBKDF2(key, (const byte*)passphrase, (int)strlen(passphrase), + salt, (int)saltSz, SESSION_PBKDF2_ITERATIONS, + (int)keySz, WC_SHA256); +} /* * Encrypt session data and save to file @@ -67,114 +107,137 @@ int SaveEncryptedSession(const char* filename, FILE* fp = NULL; Aes aes; WC_RNG rng; - unsigned char iv[AES_BLOCK_SZ]; - unsigned char* paddedData = NULL; + unsigned char iv[GCM_IV_SZ]; + unsigned char tag[GCM_TAG_SZ]; + unsigned char salt[SESSION_SALT_SZ]; + unsigned char key[SESSION_KEY_SZ]; unsigned char* encryptedData = NULL; - unsigned int paddedSz; - unsigned int padding; + unsigned char sizeBuf[4]; int ret = 0; int aesInit = 0; int rngInit = 0; - /* Calculate padded size (must be multiple of AES_BLOCK_SZ) */ - padding = AES_BLOCK_SZ - (sessionSz % AES_BLOCK_SZ); - paddedSz = sessionSz + padding; - - /* Initialize RNG for IV generation */ + /* Initialize RNG for IV/salt generation */ ret = wc_InitRng(&rng); if (ret != 0) { - printf("Error: wc_InitRng failed: %d\n", ret); + XPRINTF("Error: wc_InitRng failed: %d\n", ret); return -1; } rngInit = 1; /* Generate random IV */ - ret = wc_RNG_GenerateBlock(&rng, iv, AES_BLOCK_SZ); + ret = wc_RNG_GenerateBlock(&rng, iv, GCM_IV_SZ); if (ret != 0) { - printf("Error: Failed to generate IV: %d\n", ret); + XPRINTF("Error: Failed to generate IV: %d\n", ret); goto cleanup; } - /* Allocate buffers */ - paddedData = (unsigned char*)malloc(paddedSz); - encryptedData = (unsigned char*)malloc(paddedSz); - if (paddedData == NULL || encryptedData == NULL) { - printf("Error: Memory allocation failed\n"); - ret = -1; + /* Derive AES key from passphrase */ + ret = wc_RNG_GenerateBlock(&rng, salt, SESSION_SALT_SZ); + if (ret != 0) { + XPRINTF("Error: Failed to generate salt: %d\n", ret); goto cleanup; } - /* Copy data and add PKCS#7 padding */ - memcpy(paddedData, sessionData, sessionSz); - memset(paddedData + sessionSz, (int)padding, padding); + ret = DeriveSessionKey(GetSessionPassphrase(), salt, SESSION_SALT_SZ, + key, SESSION_KEY_SZ); + if (ret != 0) { + XPRINTF("Error: Failed to derive session key: %d\n", ret); + goto cleanup; + } + + /* Allocate buffer for encrypted data */ + encryptedData = (unsigned char*)XMALLOC(sessionSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedData == NULL && sessionSz > 0) { + XPRINTF("Error: Memory allocation failed\n"); + ret = -1; + goto cleanup; + } /* Initialize AES */ ret = wc_AesInit(&aes, NULL, INVALID_DEVID); if (ret != 0) { - printf("Error: wc_AesInit failed: %d\n", ret); + XPRINTF("Error: wc_AesInit failed: %d\n", ret); goto cleanup; } aesInit = 1; - /* Set AES key for encryption */ - ret = wc_AesSetKey(&aes, AES_KEY, sizeof(AES_KEY), iv, AES_ENCRYPTION); + /* Set AES key for GCM */ + ret = wc_AesGcmSetKey(&aes, key, sizeof(key)); if (ret != 0) { - printf("Error: wc_AesSetKey failed: %d\n", ret); + XPRINTF("Error: wc_AesGcmSetKey failed: %d\n", ret); goto cleanup; } - /* Encrypt the data */ - ret = wc_AesCbcEncrypt(&aes, encryptedData, paddedData, paddedSz); + /* Prepare AAD: original data length (4 bytes) */ + sizeBuf[0] = (sessionSz >> 24) & 0xFF; + sizeBuf[1] = (sessionSz >> 16) & 0xFF; + sizeBuf[2] = (sessionSz >> 8) & 0xFF; + sizeBuf[3] = sessionSz & 0xFF; + + /* Encrypt the data with GCM */ + ret = wc_AesGcmEncrypt(&aes, encryptedData, sessionData, sessionSz, + iv, GCM_IV_SZ, tag, GCM_TAG_SZ, sizeBuf, 4); if (ret != 0) { - printf("Error: wc_AesCbcEncrypt failed: %d\n", ret); + XPRINTF("Error: wc_AesGcmEncrypt failed: %d\n", ret); goto cleanup; } /* Write to file */ fp = fopen(filename, "wb"); if (fp == NULL) { - printf("Error: Cannot open file %s for writing\n", filename); + XPRINTF("Error: Cannot open file %s for writing\n", filename); ret = -1; goto cleanup; } - /* Write original size (4 bytes, big-endian) */ - { - unsigned char sizeBuf[4]; - sizeBuf[0] = (sessionSz >> 24) & 0xFF; - sizeBuf[1] = (sessionSz >> 16) & 0xFF; - sizeBuf[2] = (sessionSz >> 8) & 0xFF; - sizeBuf[3] = sessionSz & 0xFF; - if (fwrite(sizeBuf, 1, 4, fp) != 4) { - printf("Error: Failed to write size to file\n"); - ret = -1; - goto cleanup; - } + /* Write size */ + if (fwrite(sizeBuf, 1, 4, fp) != 4) { + XPRINTF("Error: Failed to write size to file\n"); + ret = -1; + goto cleanup; + } + + /* Write salt */ + if (fwrite(salt, 1, SESSION_SALT_SZ, fp) != SESSION_SALT_SZ) { + XPRINTF("Error: Failed to write salt to file\n"); + ret = -1; + goto cleanup; } /* Write IV */ - if (fwrite(iv, 1, AES_BLOCK_SZ, fp) != AES_BLOCK_SZ) { - printf("Error: Failed to write IV to file\n"); + if (fwrite(iv, 1, GCM_IV_SZ, fp) != GCM_IV_SZ) { + XPRINTF("Error: Failed to write IV to file\n"); + ret = -1; + goto cleanup; + } + + /* Write tag */ + if (fwrite(tag, 1, GCM_TAG_SZ, fp) != GCM_TAG_SZ) { + XPRINTF("Error: Failed to write tag to file\n"); ret = -1; goto cleanup; } /* Write encrypted data */ - if (fwrite(encryptedData, 1, paddedSz, fp) != paddedSz) { - printf("Error: Failed to write encrypted data to file\n"); + if (sessionSz > 0 && fwrite(encryptedData, 1, sessionSz, fp) != sessionSz) { + XPRINTF("Error: Failed to write encrypted data to file\n"); ret = -1; goto cleanup; } - printf("Session saved to %s (%u bytes encrypted)\n", filename, paddedSz); + XPRINTF("Session saved to %s (%u bytes encrypted)\n", filename, sessionSz); ret = 0; cleanup: if (fp != NULL) fclose(fp); - if (paddedData != NULL) free(paddedData); - if (encryptedData != NULL) free(encryptedData); + if (encryptedData != NULL) { + wc_ForceZero(encryptedData, sessionSz); + XFREE(encryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } if (aesInit) wc_AesFree(&aes); if (rngInit) wc_FreeRng(&rng); + wc_ForceZero(key, sizeof(key)); return ret; } @@ -183,18 +246,24 @@ int SaveEncryptedSession(const char* filename, * Load and decrypt session data from file * Returns allocated session data (caller must free), or NULL on error * sessionSz is set to the size of the returned data + * bufSz, if non-NULL, is set to the full allocated size of the returned + * buffer (>= *sessionSz), for callers that need to wc_ForceZero() the + * entire allocation before freeing it */ unsigned char* LoadEncryptedSession(const char* filename, - unsigned int* sessionSz) + unsigned int* sessionSz, + unsigned int* bufSz) { FILE* fp = NULL; Aes aes; - unsigned char iv[AES_BLOCK_SZ]; + unsigned char iv[GCM_IV_SZ]; + unsigned char tag[GCM_TAG_SZ]; + unsigned char salt[SESSION_SALT_SZ]; + unsigned char key[SESSION_KEY_SZ]; unsigned char sizeBuf[4]; unsigned char* encryptedData = NULL; unsigned char* decryptedData = NULL; unsigned int originalSz; - unsigned int encryptedSz; long fileSize; int ret = 0; int aesInit = 0; @@ -202,7 +271,7 @@ unsigned char* LoadEncryptedSession(const char* filename, /* Open file */ fp = fopen(filename, "rb"); if (fp == NULL) { - printf("Error: Cannot open file %s for reading\n", filename); + XPRINTF("Error: Cannot open file %s for reading\n", filename); return NULL; } @@ -211,15 +280,15 @@ unsigned char* LoadEncryptedSession(const char* filename, fileSize = ftell(fp); fseek(fp, 0, SEEK_SET); - if (fileSize < (4 + AES_BLOCK_SZ + AES_BLOCK_SZ)) { - printf("Error: File too small to contain valid session data\n"); + if (fileSize < (4 + SESSION_SALT_SZ + GCM_IV_SZ + GCM_TAG_SZ)) { + XPRINTF("Error: File too small to contain valid session data\n"); fclose(fp); return NULL; } - /* Read original size */ + /* Read size */ if (fread(sizeBuf, 1, 4, fp) != 4) { - printf("Error: Failed to read size from file\n"); + XPRINTF("Error: Failed to read size from file\n"); fclose(fp); return NULL; } @@ -228,28 +297,55 @@ unsigned char* LoadEncryptedSession(const char* filename, ((unsigned int)sizeBuf[2] << 8) | (unsigned int)sizeBuf[3]; + /* Read salt */ + if (fread(salt, 1, SESSION_SALT_SZ, fp) != SESSION_SALT_SZ) { + XPRINTF("Error: Failed to read salt from file\n"); + fclose(fp); + return NULL; + } + /* Read IV */ - if (fread(iv, 1, AES_BLOCK_SZ, fp) != AES_BLOCK_SZ) { - printf("Error: Failed to read IV from file\n"); + if (fread(iv, 1, GCM_IV_SZ, fp) != GCM_IV_SZ) { + XPRINTF("Error: Failed to read IV from file\n"); + fclose(fp); + return NULL; + } + + /* Read tag */ + if (fread(tag, 1, GCM_TAG_SZ, fp) != GCM_TAG_SZ) { + XPRINTF("Error: Failed to read tag from file\n"); fclose(fp); return NULL; } - /* Calculate encrypted data size */ - encryptedSz = (unsigned int)(fileSize - 4 - AES_BLOCK_SZ); + /* Derive AES key from passphrase */ + ret = DeriveSessionKey(GetSessionPassphrase(), salt, SESSION_SALT_SZ, + key, SESSION_KEY_SZ); + if (ret != 0) { + XPRINTF("Error: Failed to derive session key: %d\n", ret); + fclose(fp); + return NULL; + } - /* Allocate buffers */ - encryptedData = (unsigned char*)malloc(encryptedSz); - decryptedData = (unsigned char*)malloc(encryptedSz); - if (encryptedData == NULL || decryptedData == NULL) { - printf("Error: Memory allocation failed\n"); + if ((unsigned int)(fileSize - 4 - SESSION_SALT_SZ - GCM_IV_SZ - GCM_TAG_SZ) != originalSz) { + XPRINTF("Error: File size does not match expected encrypted data size\n"); goto cleanup; } - /* Read encrypted data */ - if (fread(encryptedData, 1, encryptedSz, fp) != encryptedSz) { - printf("Error: Failed to read encrypted data from file\n"); - goto cleanup; + /* Allocate buffers */ + if (originalSz > 0) { + encryptedData = (unsigned char*)XMALLOC(originalSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + decryptedData = (unsigned char*)XMALLOC(originalSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedData == NULL || decryptedData == NULL) { + XPRINTF("Error: Memory allocation failed\n"); + goto cleanup; + } + + /* Read encrypted data */ + if (fread(encryptedData, 1, originalSz, fp) != originalSz) { + XPRINTF("Error: Failed to read encrypted data from file\n"); + goto cleanup; + } } fclose(fp); fp = NULL; @@ -257,45 +353,54 @@ unsigned char* LoadEncryptedSession(const char* filename, /* Initialize AES */ ret = wc_AesInit(&aes, NULL, INVALID_DEVID); if (ret != 0) { - printf("Error: wc_AesInit failed: %d\n", ret); + XPRINTF("Error: wc_AesInit failed: %d\n", ret); goto cleanup; } aesInit = 1; - /* Set AES key for decryption */ - ret = wc_AesSetKey(&aes, AES_KEY, sizeof(AES_KEY), iv, AES_DECRYPTION); + /* Set AES key */ + ret = wc_AesGcmSetKey(&aes, key, sizeof(key)); if (ret != 0) { - printf("Error: wc_AesSetKey failed: %d\n", ret); + XPRINTF("Error: wc_AesGcmSetKey failed: %d\n", ret); goto cleanup; } - /* Decrypt the data */ - ret = wc_AesCbcDecrypt(&aes, decryptedData, encryptedData, encryptedSz); + /* Decrypt and authenticate the data */ + ret = wc_AesGcmDecrypt(&aes, decryptedData, encryptedData, originalSz, + iv, GCM_IV_SZ, tag, GCM_TAG_SZ, sizeBuf, 4); if (ret != 0) { - printf("Error: wc_AesCbcDecrypt failed: %d\n", ret); - goto cleanup; - } - - /* Verify padding and original size */ - if (originalSz > encryptedSz) { - printf("Error: Invalid original size in file\n"); + XPRINTF("Error: wc_AesGcmDecrypt failed (authentication error): %d\n", ret); goto cleanup; } *sessionSz = originalSz; - printf("Session loaded from %s (%u bytes)\n", filename, originalSz); + if (bufSz != NULL) { + *bufSz = originalSz; + } + XPRINTF("Session loaded from %s (%u bytes)\n", filename, originalSz); /* Clean up and return decrypted data */ - if (encryptedData != NULL) free(encryptedData); + if (encryptedData != NULL) { + wc_ForceZero(encryptedData, originalSz); + XFREE(encryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } if (aesInit) wc_AesFree(&aes); + wc_ForceZero(key, sizeof(key)); return decryptedData; cleanup: if (fp != NULL) fclose(fp); - if (encryptedData != NULL) free(encryptedData); - if (decryptedData != NULL) free(decryptedData); + if (encryptedData != NULL) { + wc_ForceZero(encryptedData, originalSz); + XFREE(encryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + if (decryptedData != NULL) { + wc_ForceZero(decryptedData, originalSz); + XFREE(decryptedData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } if (aesInit) wc_AesFree(&aes); + wc_ForceZero(key, sizeof(key)); 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/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/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/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/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/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/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; 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)); 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; }