diff --git a/src/pk.c b/src/pk.c index 1aaf40d065d..a0df3af2650 100644 --- a/src/pk.c +++ b/src/pk.c @@ -480,6 +480,7 @@ static int der_to_enc_pem_alloc(unsigned char* der, int derSz, byte* tmp = NULL; byte* cipherInfo = NULL; int pemSz = 0; + int derAllocSz = derSz; int hashType = WC_HASH_TYPE_NONE; #if !defined(NO_MD5) hashType = WC_MD5; @@ -515,6 +516,7 @@ static int der_to_enc_pem_alloc(unsigned char* der, int derSz, } else { der = tmpBuf; + derAllocSz = derSz + blockSz; /* Encrypt DER inline. */ ret = EncryptDerKey(der, &derSz, cipher, passwd, passwdSz, @@ -562,7 +564,10 @@ static int der_to_enc_pem_alloc(unsigned char* der, int derSz, XFREE(tmp, NULL, DYNAMIC_TYPE_KEY); XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); - XFREE(der, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (der != NULL) { + ForceZero(der, (word32)derAllocSz); + XFREE(der, heap, DYNAMIC_TYPE_TMP_BUFFER); + } return ret; } @@ -2104,6 +2109,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, (word32)der_max_len); if (derSz < 0) { WOLFSSL_MSG("wc_DsaKeyToDer failed"); + ForceZero(derBuf, (word32)der_max_len); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); return 0; } @@ -2116,6 +2122,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, &cipherInfo, der_max_len, WC_MD5); if (ret != 1) { WOLFSSL_MSG("EncryptDerKey failed"); + ForceZero(derBuf, (word32)der_max_len); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); return ret; } @@ -2131,6 +2138,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, tmp = (byte*)XMALLOC((size_t)*pLen, NULL, DYNAMIC_TYPE_PEM); if (tmp == NULL) { WOLFSSL_MSG("malloc failed"); + ForceZero(derBuf, (word32)der_max_len); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); return 0; @@ -2141,11 +2149,13 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, type); if (*pLen <= 0) { WOLFSSL_MSG("wc_DerToPemEx failed"); + ForceZero(derBuf, (word32)der_max_len); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); return 0; } + ForceZero(derBuf, (word32)der_max_len); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); @@ -7107,6 +7117,7 @@ static int pem_write_mem_pkcs8privatekey(byte** pem, int* pemSz, char password[NAME_SZ]; byte* key = NULL; word32 keySz = 0; + word32 allocSz = 0; int type = PKCS8_PRIVATEKEY_TYPE; /* Validate parameters. */ @@ -7139,9 +7150,11 @@ static int pem_write_mem_pkcs8privatekey(byte** pem, int* pemSz, *pemSz += 54; } + allocSz = (word32)*pemSz; /* Allocate enough memory to hold PEM encoded encrypted key. */ - *pem = (byte*)XMALLOC((size_t)*pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *pem = (byte*)XMALLOC((size_t)allocSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (*pem == NULL) { + allocSz = 0; res = 0; } else { @@ -7198,6 +7211,20 @@ static int pem_write_mem_pkcs8privatekey(byte** pem, int* pemSz, } } + /* Zero any remnants of the DER staging area that persist after PEM + * conversion so plaintext private key material is not left in freed heap + * memory. On success, only the bytes past the actual PEM output need + * clearing; on failure, the whole buffer is zeroed since its state is + * indeterminate. */ + if (*pem != NULL) { + if (res == 1 && (word32)*pemSz < allocSz) { + ForceZero(*pem + *pemSz, allocSz - (word32)*pemSz); + } + else if (res != 1) { + ForceZero(*pem, allocSz); + } + } + /* Return appropriate return code. */ return (res == 0) ? 0 : ret; diff --git a/src/pk_ec.c b/src/pk_ec.c index 66647c9eb77..faed7f20a67 100644 --- a/src/pk_ec.c +++ b/src/pk_ec.c @@ -3524,6 +3524,9 @@ int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *key, unsigned char **out) /* Dispose of any allocated buffer on error. */ if (err && (*out == buf)) { + if (buf != NULL) { + ForceZero(buf, len); + } XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); *out = NULL; } @@ -4095,6 +4098,7 @@ int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec, derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len); if (derSz < 0) { WOLFSSL_MSG("wc_EccKeyToDer failed"); + ForceZero(derBuf, der_max_len); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); ret = 0; } diff --git a/src/pk_rsa.c b/src/pk_rsa.c index c102f4ec21f..682b1d28086 100644 --- a/src/pk_rsa.c +++ b/src/pk_rsa.c @@ -719,6 +719,9 @@ WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out) key = NULL; } /* Dispose of allocated data. */ + if (der != NULL) { + ForceZero(der, (word32)derLen); + } XFREE(der, bio ? bio->heap : NULL, DYNAMIC_TYPE_TMP_BUFFER); return key; } @@ -779,6 +782,7 @@ static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey, { int ret = 1; int derSz = 0; + word32 derAllocSz = 0; byte* derBuf = NULL; WOLFSSL_ENTER("wolfSSL_RSA_To_Der"); @@ -830,6 +834,9 @@ static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey, WOLFSSL_ERROR_MSG("Memory allocation failed"); ret = MEMORY_ERROR; } + else { + derAllocSz = (word32)derSz; + } } } if ((ret == 1) && (outBuf != NULL)) { @@ -863,6 +870,9 @@ static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey, if ((outBuf != NULL) && (*outBuf != derBuf)) { /* Not returning buffer, needs to be disposed of. */ + if ((derBuf != NULL) && (publicKey == 0) && (derAllocSz > 0)) { + ForceZero(derBuf, derAllocSz); + } XFREE(derBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); } WOLFSSL_LEAVE("wolfSSL_RSA_To_Der", ret); diff --git a/src/sniffer.c b/src/sniffer.c index e8664721b15..6c5eba0b14b 100644 --- a/src/sniffer.c +++ b/src/sniffer.c @@ -7242,12 +7242,16 @@ int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, 0, keyType, password); if (ret < 0) { SetError(KEY_FILE_STR, error, NULL, 0); + if (keyBuf != NULL) { + ForceZero(keyBuf, keyBufSz); + } XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509); return WOLFSSL_FATAL_ERROR; } ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER, error); + ForceZero(keyBuf, keyBufSz); XFREE(keyBuf, NULL, DYNAMIC_TYPE_X509); return ret; diff --git a/src/ssl.c b/src/ssl.c index 0d722f4ae09..05e7a79df38 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -18645,6 +18645,7 @@ static int SetStaticEphemeralKey(WOLFSSL_CTX* ctx, #ifndef NO_FILESYSTEM /* done with keyFile buffer */ if (keyFile && keyBuf) { + ForceZero(keyBuf, keySz); XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); } #endif diff --git a/src/ssl_load.c b/src/ssl_load.c index 5c83e88c5af..04fecf2181b 100644 --- a/src/ssl_load.c +++ b/src/ssl_load.c @@ -5365,6 +5365,9 @@ int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa) } /* Dispos of dynamically allocated data. */ + if (der != NULL) { + ForceZero(der, (word32)derSize); + } XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; }