diff --git a/src/internal.c b/src/internal.c index 19100f04e..c1d27b1dc 100644 --- a/src/internal.c +++ b/src/internal.c @@ -332,6 +332,8 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, else ret = MEMORY_E; } + /* Zero out Base16 encoded secret and other data. */ + ForceZero(log, buffSz); XFREE(log, ssl->heap, DYNAMIC_TYPE_SECRET); return ret; } @@ -462,6 +464,8 @@ static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, else ret = MEMORY_E; } + /* Zero out Base16 encoded secret and other data. */ + ForceZero(log, buffSz); XFREE(log, ssl->heap, DYNAMIC_TYPE_SECRET); return ret; } @@ -2376,6 +2380,9 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) #endif /* SINGLE_THREADED */ #ifndef NO_CERTS + if (ctx->privateKey != NULL && ctx->privateKey->buffer != NULL) { + ForceZero(ctx->privateKey->buffer, ctx->privateKey->length); + } FreeDer(&ctx->privateKey); #ifdef OPENSSL_ALL wolfSSL_EVP_PKEY_free(ctx->privateKeyPKey); @@ -2613,10 +2620,16 @@ void FreeCiphers(WOLFSSL* ssl) XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #ifdef HAVE_CHACHA + if (ssl->encrypt.chacha) + ForceZero(ssl->encrypt.chacha, sizeof(ChaCha)); + if (ssl->decrypt.chacha) + ForceZero(ssl->decrypt.chacha, sizeof(ChaCha)); XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH) + if (ssl->auth.poly1305) + ForceZero(ssl->auth.poly1305, sizeof(Poly1305)); XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER); #endif #if defined(WOLFSSL_TLS13) && defined(HAVE_NULL_CIPHER) @@ -6238,6 +6251,7 @@ void FreeHandshakeHashes(WOLFSSL* ssl) #if (defined(HAVE_ED25519) || defined(HAVE_ED448)) && \ !defined(WOLFSSL_NO_CLIENT_AUTH) if (ssl->hsHashes->messages != NULL) { + ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length); XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); ssl->hsHashes->messages = NULL; } @@ -6728,7 +6742,7 @@ void FreeArrays(WOLFSSL* ssl, int keep) ssl->session->sessionIDSz = ssl->arrays->sessionIDSz; } if (ssl->arrays->preMasterSecret) { - ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + ForceZero(ssl->arrays->preMasterSecret, ENCRYPT_LEN); XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); ssl->arrays->preMasterSecret = NULL; } @@ -7107,7 +7121,7 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->clientFinished_len = 0; #endif #ifndef NO_DH - if (ssl->buffers.serverDH_Priv.buffer) { + if (ssl->buffers.serverDH_Priv.buffer != NULL) { ForceZero(ssl->buffers.serverDH_Priv.buffer, ssl->buffers.serverDH_Priv.length); } @@ -7135,6 +7149,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) if (ssl->buffers.outputBuffer.dynamicFlag) ShrinkOutputBuffer(ssl); #if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) + if (ssl->buffers.tls13CookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + } XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap, DYNAMIC_TYPE_COOKIE_PWD); #endif @@ -7148,6 +7166,10 @@ void SSL_ResourceFree(WOLFSSL* ssl) XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR); ssl->buffers.dtlsCtx.peer.sa = NULL; #ifndef NO_WOLFSSL_SERVER + if (ssl->buffers.dtlsCookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + } XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap, DYNAMIC_TYPE_COOKIE_PWD); #endif @@ -8607,11 +8629,15 @@ static int EdDSA_Update(WOLFSSL* ssl, const byte* data, int sz) byte* msgs; if (ssl->options.cacheMessages) { - msgs = (byte*)XREALLOC(ssl->hsHashes->messages, - ssl->hsHashes->length + sz, - ssl->heap, DYNAMIC_TYPE_HASHES); + msgs = (byte*)XMALLOC(ssl->hsHashes->length + sz, ssl->heap, + DYNAMIC_TYPE_HASHES); if (msgs == NULL) ret = MEMORY_E; + if ((ret == 0) && (ssl->hsHashes->messages != NULL)) { + XMEMCPY(msgs, ssl->hsHashes->messages, ssl->hsHashes->length); + ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length); + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + } if (ret == 0) { ssl->hsHashes->messages = msgs; XMEMCPY(msgs + ssl->hsHashes->length, data, sz); @@ -9105,6 +9131,11 @@ retry: void ShrinkOutputBuffer(WOLFSSL* ssl) { WOLFSSL_MSG("Shrinking output buffer"); + if (IsEncryptionOn(ssl, 0)) { + ForceZero(ssl->buffers.outputBuffer.buffer - + ssl->buffers.outputBuffer.offset, + ssl->buffers.outputBuffer.bufferSize); + } XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer; @@ -9125,11 +9156,17 @@ void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree) WOLFSSL_MSG("Shrinking input buffer"); - if (!forcedFree && usedLength > 0) + if (!forcedFree && usedLength > 0) { XMEMCPY(ssl->buffers.inputBuffer.staticBuffer, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, usedLength); + } + if (IsEncryptionOn(ssl, 1) || forcedFree) { + ForceZero(ssl->buffers.inputBuffer.buffer - + ssl->buffers.inputBuffer.offset, + ssl->buffers.inputBuffer.bufferSize); + } XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; @@ -9267,10 +9304,16 @@ static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer, ssl->buffers.outputBuffer.length); - if (ssl->buffers.outputBuffer.dynamicFlag) + if (ssl->buffers.outputBuffer.dynamicFlag) { + if (IsEncryptionOn(ssl, 0)) { + ForceZero(ssl->buffers.outputBuffer.buffer - + ssl->buffers.outputBuffer.offset, + ssl->buffers.outputBuffer.bufferSize); + } XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset, ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + } ssl->buffers.outputBuffer.dynamicFlag = 1; #if WOLFSSL_GENERAL_ALIGNMENT > 0 @@ -9341,9 +9384,15 @@ int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, usedLength); - if (ssl->buffers.inputBuffer.dynamicFlag) + if (ssl->buffers.inputBuffer.dynamicFlag) { + if (IsEncryptionOn(ssl, 1)) { + ForceZero(ssl->buffers.inputBuffer.buffer - + ssl->buffers.inputBuffer.offset, + ssl->buffers.inputBuffer.bufferSize); + } XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, - ssl->heap,DYNAMIC_TYPE_IN_BUFFER); + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + } ssl->buffers.inputBuffer.dynamicFlag = 1; #if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 @@ -14406,6 +14455,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, { ssl->options.cacheMessages = 0; if ((ssl->hsHashes != NULL) && (ssl->hsHashes->messages != NULL)) { + ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length); XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); ssl->hsHashes->messages = NULL; @@ -14492,6 +14542,7 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, { ssl->options.cacheMessages = 0; if ((ssl->hsHashes != NULL) && (ssl->hsHashes->messages != NULL)) { + ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length); XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); ssl->hsHashes->messages = NULL; } @@ -15423,6 +15474,7 @@ int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, /* set the counter after getting poly1305 key */ if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 1)) != 0) { ForceZero(nonce, CHACHA20_NONCE_SZ); + ForceZero(poly, sizeof(poly)); return ret; } ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */ @@ -15589,6 +15641,7 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, /* set counter after getting poly1305 key */ if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 1)) != 0) { ForceZero(nonce, CHACHA20_NONCE_SZ); + ForceZero(poly, sizeof(poly)); return ret; } ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */ @@ -31485,8 +31538,10 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if (idSz == 0) { ret = wc_RNG_GenerateBlock(ssl->rng, ssl->session->altSessionID, ID_LEN); - if (ret != 0) + if (ret != 0) { + ForceZero(&it, sizeof(it)); return ret; + } ssl->session->haveAltSessionID = 1; id = ssl->session->altSessionID; idSz = ID_LEN; @@ -31510,6 +31565,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, (ssl->options.mask & WOLFSSL_OP_NO_TICKET) != 0) #endif ) { + ForceZero(&it, sizeof(it)); ret = WOLFSSL_TICKET_RET_FATAL; } else { @@ -31520,6 +31576,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, et->enc_ticket, sizeof(InternalTicket), &encLen, ssl->ctx->ticketEncCtx); if (ret != WOLFSSL_TICKET_RET_OK) { + ForceZero(&it, sizeof(it)); ForceZero(et->enc_ticket, sizeof(it)); } } diff --git a/src/ssl.c b/src/ssl.c index 7a0e15d32..ef782458e 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -6228,7 +6228,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } #endif /* WOLFSSL_TRUST_PEER_CERT */ else if (type == CERT_TYPE) { - if (ssl) { + if (ssl != NULL) { /* Make sure previous is free'd */ if (ssl->buffers.weOwnCert) { FreeDer(&ssl->buffers.certificate); @@ -6243,7 +6243,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif ssl->buffers.weOwnCert = 1; } - else if (ctx) { + else if (ctx != NULL) { FreeDer(&ctx->certificate); /* Make sure previous is free'd */ #ifdef KEEP_OUR_CERT if (ctx->ourCert) { @@ -6256,15 +6256,19 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } } else if (type == PRIVATEKEY_TYPE) { - if (ssl) { + if (ssl != NULL) { /* Make sure previous is free'd */ if (ssl->buffers.weOwnKey) { + ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length); FreeDer(&ssl->buffers.key); } ssl->buffers.key = der; ssl->buffers.weOwnKey = 1; } - else if (ctx) { + else if (ctx != NULL) { + if (ctx->privateKey != NULL && ctx->privateKey->buffer != NULL) { + ForceZero(ctx->privateKey->buffer, ctx->privateKey->length); + } FreeDer(&ctx->privateKey); ctx->privateKey = der; } @@ -6308,6 +6312,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ret = ToTraditionalEnc(der->buffer, der->length, password, passwordSz, &algId); if (ret >= 0) { + ForceZero(der->buffer + ret, der->length - ret); der->length = ret; } /* ignore failures and try parsing as unencrypted */ @@ -14971,6 +14976,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) if (ssl->buffers.weOwnKey) { WOLFSSL_MSG("Unloading key"); + ForceZero(ssl->buffers.key->buffer, ssl->buffers.key->length); FreeDer(&ssl->buffers.key); ssl->buffers.weOwnKey = 0; } @@ -19688,6 +19694,11 @@ void wolfSSL_FreeSession(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) wolfSSL_CRYPTO_cleanup_ex_data(&session->ex_data); #endif + /* Make sure masterSecret is zeroed. */ + ForceZero(session->masterSecret, SECRET_LEN); + /* Session ID is sensitive information too. */ + ForceZero(session->sessionID, ID_LEN); + if (session->type == WOLFSSL_SESSION_TYPE_HEAP) { XFREE(session, session->heap, DYNAMIC_TYPE_SESSION); } diff --git a/src/tls.c b/src/tls.c index 749a6e7bd..2c09b8ba7 100644 --- a/src/tls.c +++ b/src/tls.c @@ -170,21 +170,24 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) int ret; const byte* side = NULL; word32 hashSz = HSHASH_SZ; -#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) +#if !defined(WOLFSSL_ASYNC_CRYPT) || defined(WC_ASYNC_NO_HASH) + byte handshake_hash[HSHASH_SZ]; +#else WC_DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap); if (handshake_hash == NULL) return MEMORY_E; -#else - byte handshake_hash[HSHASH_SZ]; #endif ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); if (ret == 0) { - if (XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + if (XSTRNCMP((const char*)sender, (const char*)client, + SIZEOF_SENDER) == 0) { side = tls_client; - else if (XSTRNCMP((const char*)sender, (const char*)server, SIZEOF_SENDER) - == 0) + } + else if (XSTRNCMP((const char*)sender, (const char*)server, + SIZEOF_SENDER) == 0) { side = tls_server; + } else { ret = BAD_FUNC_ARG; WOLFSSL_MSG("Unexpected sender value"); @@ -210,6 +213,7 @@ int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) ssl->heap, ssl->devId); PRIVATE_KEY_LOCK(); } + ForceZero(handshake_hash, hashSz); #else /* Pseudo random function must be enabled in the configuration. */ ret = PRF_MISSING; @@ -401,12 +405,12 @@ static int _MakeTlsMasterSecret(byte* ms, word32 msLen, void* heap, int devId) { int ret; -#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) +#if !defined(WOLFSSL_ASYNC_CRYPT) || defined(WC_ASYNC_NO_HASH) + byte seed[SEED_LEN]; +#else WC_DECLARE_VAR(seed, byte, SEED_LEN, heap); if (seed == NULL) return MEMORY_E; -#else - byte seed[SEED_LEN]; #endif XMEMCPY(seed, cr, RAN_LEN); @@ -521,6 +525,7 @@ int MakeTlsMasterSecret(WOLFSSL* ssl) handshake_hash, hashSz, IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, ssl->heap, ssl->devId); + ForceZero(handshake_hash, hashSz); } #ifdef WOLFSSL_SMALL_STACK diff --git a/src/tls13.c b/src/tls13.c index 7e6b15729..dc9eb8b36 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1258,12 +1258,14 @@ int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0); if (ret != 0) goto end; + i += ssl->specs.iv_size; } /* Store keys and IVs but don't activate them. */ ret = StoreKeys(ssl, key_dig, provision); end: + ForceZero(key_dig, i); #ifdef WOLFSSL_SMALL_STACK XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); #endif @@ -2051,8 +2053,10 @@ static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, if (ret != 0) return ret; ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 1); - if (ret != 0) + if (ret != 0) { + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ return ret; + } /* Set key for Poly1305. */ ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); @@ -3003,7 +3007,7 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) */ while (current != NULL) { if ((ret = SetupPskKey(ssl, current, 1)) != 0) - return ret; + break; #ifdef HAVE_SESSION_TICKET if (current->resumption) @@ -3014,23 +3018,27 @@ static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) ret = DeriveBinderKey(ssl, binderKey); #endif if (ret != 0) - return ret; + break; /* Derive the Finished message secret. */ ret = DeriveFinishedSecret(ssl, binderKey, ssl->keys.client_write_MAC_secret); if (ret != 0) - return ret; + break; /* Build the HMAC of the handshake message data = binder. */ ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, current->binder, ¤t->binderLen); if (ret != 0) - return ret; + break; current = current->next; } + ForceZero(binderKey, sizeof(binderKey)); + if (ret != 0) + return ret; + /* Data entered into extension, now write to message. */ ret = TLSX_PreSharedKey_WriteBinders((PreSharedKey*)ext->data, output + idx, client_hello, &len); @@ -8407,6 +8415,7 @@ int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, IsAtLeastTLSv1_3(ssl->version)) { ssl->options.cacheMessages = 0; if ((ssl->hsHashes != NULL) && (ssl->hsHashes->messages != NULL)) { + ForceZero(ssl->hsHashes->messages, ssl->hsHashes->length); XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); ssl->hsHashes->messages = NULL; } diff --git a/wolfcrypt/src/aes.c b/wolfcrypt/src/aes.c index dcef0c6ad..2151812a7 100644 --- a/wolfcrypt/src/aes.c +++ b/wolfcrypt/src/aes.c @@ -4454,8 +4454,10 @@ int wc_AesSetIV(Aes* aes, const byte* iv) XTRANSFORM_AESCTRBLOCK(aes, out, in); #else ret = wc_AesEncrypt(aes, (byte*)aes->reg, scratch); - if (ret != 0) + if (ret != 0) { + ForceZero(scratch, AES_BLOCK_SIZE); return ret; + } xorbuf(scratch, in, AES_BLOCK_SIZE); XMEMCPY(out, scratch, AES_BLOCK_SIZE); #endif @@ -4471,8 +4473,10 @@ int wc_AesSetIV(Aes* aes, const byte* iv) /* handle non block size remaining and store unused byte count in left */ if (sz) { ret = wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp); - if (ret != 0) + if (ret != 0) { + ForceZero(scratch, AES_BLOCK_SIZE); return ret; + } IncrementAesCounter((byte*)aes->reg); aes->left = AES_BLOCK_SIZE; @@ -4718,8 +4722,12 @@ int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) if (!((len == 16) || (len == 24) || (len == 32))) return BAD_FUNC_ARG; - if (aes == NULL) + if (aes == NULL) { +#ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); +#endif return BAD_FUNC_ARG; + } #ifdef OPENSSL_EXTRA XMEMSET(aes->aadH, 0, sizeof(aes->aadH)); @@ -10186,18 +10194,26 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, } ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(B, sizeof(B)); return ret; + } if (authInSz > 0) { ret = roll_auth(aes, authIn, authInSz, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } } if (inSz > 0) { ret = roll_x(aes, in, inSz, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } } XMEMCPY(authTag, A, authTagSz); @@ -10205,8 +10221,11 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, for (i = 0; i < lenSz; i++) B[AES_BLOCK_SIZE - 1 - i] = 0; ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } xorbuf(authTag, A, authTagSz); B[15] = 1; @@ -10233,8 +10252,11 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, #endif while (inSz >= AES_BLOCK_SIZE) { ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } xorbuf(A, in, AES_BLOCK_SIZE); XMEMCPY(out, A, AES_BLOCK_SIZE); @@ -10245,14 +10267,17 @@ int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, } if (inSz > 0) { ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } xorbuf(A, in, inSz); XMEMCPY(out, A, inSz); } - ForceZero(A, AES_BLOCK_SIZE); - ForceZero(B, AES_BLOCK_SIZE); + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return 0; } @@ -10334,8 +10359,11 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, #endif while (oSz >= AES_BLOCK_SIZE) { ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } xorbuf(A, in, AES_BLOCK_SIZE); XMEMCPY(o, A, AES_BLOCK_SIZE); @@ -10346,8 +10374,11 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, } if (inSz > 0) { ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } xorbuf(A, in, oSz); XMEMCPY(o, A, oSz); } @@ -10355,8 +10386,11 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, for (i = 0; i < lenSz; i++) B[AES_BLOCK_SIZE - 1 - i] = 0; ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } o = out; oSz = inSz; @@ -10371,26 +10405,38 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, } ret = wc_AesEncrypt(aes, B, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } if (authInSz > 0) { ret = roll_auth(aes, authIn, authInSz, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } } if (inSz > 0) { ret = roll_x(aes, o, oSz, A); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } } B[0] = lenSz - 1; for (i = 0; i < lenSz; i++) B[AES_BLOCK_SIZE - 1 - i] = 0; ret = wc_AesEncrypt(aes, B, B); - if (ret != 0) + if (ret != 0) { + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); return ret; + } xorbuf(A, B, authTagSz); if (ConstantCompare(A, authTag, authTagSz) != 0) { @@ -10407,8 +10453,8 @@ int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, ret = AES_CCM_AUTH_E; } - ForceZero(A, AES_BLOCK_SIZE); - ForceZero(B, AES_BLOCK_SIZE); + ForceZero(A, sizeof(A)); + ForceZero(B, sizeof(B)); o = NULL; return ret; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 7fa7e7cb5..824736503 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -31230,7 +31230,7 @@ int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, if (req == NULL) return BAD_FUNC_ARG; - ForceZero(req, sizeof(OcspRequest)); + XMEMSET(req, 0, sizeof(OcspRequest)); req->heap = heap; if (cert) { diff --git a/wolfcrypt/src/cmac.c b/wolfcrypt/src/cmac.c index d9bcd411c..b5121d40b 100644 --- a/wolfcrypt/src/cmac.c +++ b/wolfcrypt/src/cmac.c @@ -242,6 +242,9 @@ int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz) } #if defined(WOLFSSL_HASH_KEEP) + /* TODO: msg is leaked if wc_CmacFinal() is not called + * e.g. when multiple calls to wc_CmacUpdate() and one fails but + * wc_CmacFinal() not called. */ if (cmac->msg != NULL) { XFREE(cmac->msg, cmac->heap, DYNAMIC_TYPE_TMP_BUFFER); cmac->msg = NULL; diff --git a/wolfcrypt/src/dh.c b/wolfcrypt/src/dh.c index 0a7c1ac77..fecddfdff 100644 --- a/wolfcrypt/src/dh.c +++ b/wolfcrypt/src/dh.c @@ -1754,7 +1754,7 @@ int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 privSz, } } - mp_clear(x); + mp_forcezero(x); mp_clear(q); #ifdef WOLFSSL_SMALL_STACK XFREE(q, key->heap, DYNAMIC_TYPE_DH); @@ -2113,7 +2113,7 @@ static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, if (ret == 0) *agreeSz = mp_unsigned_bin_size(z); - mp_clear(z); + mp_forcezero(z); mp_clear(y); mp_forcezero(x); @@ -2299,7 +2299,7 @@ int wc_DhImportKeyPair(DhKey* key, const byte* priv, word32 privSz, mp_clear(&key->pub); havePub = 0; if (havePriv) { - mp_clear(&key->priv); + mp_forcezero(&key->priv); havePriv = 0; /* set to 0 to error out with failed read pub */ } } else { diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 5aa76176f..e7f2bba48 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -4438,6 +4438,8 @@ static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, } *outlen = x; + mp_forcezero(result->x); + mp_forcezero(result->y); wc_ecc_del_point_ex(result, private_key->heap); wc_ecc_curve_free(curve); @@ -4762,7 +4764,8 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) int err; byte buf[ECC_MAXSIZE_GEN]; - if (rng == NULL || size > ECC_MAXSIZE_GEN || k == NULL || order == NULL) { + if (rng == NULL || size + 8 > ECC_MAXSIZE_GEN || k == NULL || + order == NULL) { return BAD_FUNC_ARG; } @@ -4790,7 +4793,7 @@ int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) err = MP_ZERO_E; } - ForceZero(buf, ECC_MAXSIZE); + ForceZero(buf, ECC_MAXSIZE_GEN); return err; #else @@ -6106,7 +6109,7 @@ static int ecc_sign_hash_sw(ecc_key* key, ecc_key* pubkey, WC_RNG* rng, #endif mp_forcezero(&pubkey->k); } - mp_clear(b); + mp_forcezero(b); #ifdef WOLFSSL_SMALL_STACK XFREE(b, key->heap, DYNAMIC_TYPE_ECC); #endif @@ -6751,6 +6754,7 @@ int wc_ecc_gen_deterministic_k(const byte* hash, word32 hashSz, } while (ret == 0 && err != 0); } + ForceZero(x, MAX_ECC_BYTES); #ifdef WOLFSSL_SMALL_STACK if (z1 != NULL) XFREE(z1, heap, DYNAMIC_TYPE_ECC_BUFFER); @@ -11367,7 +11371,7 @@ static int accel_fp_mul(int idx, const mp_int* k, ecc_point *R, mp_int* a, done: /* cleanup */ mp_clear(order); - mp_clear(tk); + mp_forcezero(tk); #ifdef WOLFSSL_SMALL_STACK XFREE(kb, NULL, DYNAMIC_TYPE_ECC_BUFFER); @@ -11616,8 +11620,8 @@ static int accel_fp_mul2add(int idx1, int idx2, done: /* cleanup */ - mp_clear(tkb); - mp_clear(tka); + mp_forcezero(tkb); + mp_forcezero(tka); mp_clear(order); #ifdef WOLFSSL_SMALL_STACK diff --git a/wolfcrypt/src/ed25519.c b/wolfcrypt/src/ed25519.c index 9c5e55bf8..e89e82e56 100644 --- a/wolfcrypt/src/ed25519.c +++ b/wolfcrypt/src/ed25519.c @@ -229,7 +229,7 @@ int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) } #endif - ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE); + ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE); if (ret != 0) return ret; diff --git a/wolfcrypt/src/kdf.c b/wolfcrypt/src/kdf.c index 8d580f8a1..18b02c16f 100644 --- a/wolfcrypt/src/kdf.c +++ b/wolfcrypt/src/kdf.c @@ -208,26 +208,23 @@ int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret, word32 secLen, const byte* label, word32 labLen, const byte* seed, word32 seedLen, void* heap, int devId) { - int ret = 0; - word32 half = (secLen + 1) / 2; + int ret = 0; + word32 half = (secLen + 1) / 2; + const byte* md5_half; + const byte* sha_half; + byte* md5_result; #ifdef WOLFSSL_SMALL_STACK - byte* md5_half; - byte* sha_half; - byte* md5_result; - byte* sha_result; + byte* sha_result; #else - byte md5_half[MAX_PRF_HALF]; /* half is real size */ - byte sha_half[MAX_PRF_HALF]; /* half is real size */ - byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ - byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ + byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ #endif -#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) +#if !defined(WOLFSSL_ASYNC_CRYPT) || defined(WC_ASYNC_NO_HASH) + byte labelSeed[MAX_PRF_LABSEED]; +#else WC_DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap); if (labelSeed == NULL) return MEMORY_E; -#else - byte labelSeed[MAX_PRF_LABSEED]; #endif if (half > MAX_PRF_HALF || @@ -241,30 +238,18 @@ int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret, } #ifdef WOLFSSL_SMALL_STACK - md5_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); - sha_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); - md5_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); - sha_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); - - if (md5_half == NULL || sha_half == NULL || md5_result == NULL || - sha_result == NULL) { - if (md5_half) XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); - if (sha_half) XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); - if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); - if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); + sha_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); + if (sha_result == NULL) { #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) WC_FREE_VAR(labelSeed, heap); #endif - return MEMORY_E; } #endif - XMEMSET(md5_result, 0, digLen); - XMEMSET(sha_result, 0, digLen); - - XMEMCPY(md5_half, secret, half); - XMEMCPY(sha_half, secret + half - secLen % 2, half); + md5_half = secret; + sha_half = secret + half - secLen % 2; + md5_result = digest; XMEMCPY(labelSeed, label, labLen); XMEMCPY(labelSeed + labLen, seed, seedLen); @@ -274,15 +259,13 @@ int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret, if ((ret = wc_PRF(sha_result, digLen, sha_half, half, labelSeed, labLen + seedLen, sha_mac, heap, devId)) == 0) { /* calculate XOR for TLSv1 PRF */ - XMEMCPY(digest, md5_result, digLen); + /* md5 result is placed directly in digest */ xorbuf(digest, sha_result, digLen); + ForceZero(sha_result, digLen); } } #ifdef WOLFSSL_SMALL_STACK - XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); - XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); - XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); #endif diff --git a/wolfcrypt/src/rsa.c b/wolfcrypt/src/rsa.c index 0beaa0025..710781ee3 100644 --- a/wolfcrypt/src/rsa.c +++ b/wolfcrypt/src/rsa.c @@ -571,15 +571,17 @@ int wc_FreeRsaKey(RsaKey* key) mp_forcezero(&key->p); mp_forcezero(&key->d); } - /* private part */ + else { + /* private part */ #if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) - mp_clear(&key->u); - mp_clear(&key->dQ); - mp_clear(&key->dP); + mp_clear(&key->u); + mp_clear(&key->dQ); + mp_clear(&key->dP); #endif - mp_clear(&key->q); - mp_clear(&key->p); - mp_clear(&key->d); + mp_clear(&key->q); + mp_clear(&key->p); + mp_clear(&key->d); + } #endif /* WOLFSSL_RSA_PUBLIC_ONLY */ /* public part */ @@ -825,7 +827,6 @@ int wc_CheckRsaKey(RsaKey* key) } mp_forcezero(tmp); - mp_clear(tmp); RESTORE_VECTOR_REGISTERS(); @@ -1213,6 +1214,8 @@ static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, idx++; } + /* Zeroize masking bytes so that padding can't be unmasked. */ + ForceZero(seed, hLen); #ifdef WOLFSSL_SMALL_STACK XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); @@ -1541,7 +1544,6 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, byte* tmp = NULL; #else byte tmp[RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ]; - XMEMSET(tmp, 0, RSA_MAX_SIZE/8 + RSA_PSS_PAD_SZ); #endif /* no label is allowed, but catch if no label provided and length > 0 */ if (optLabel == NULL && labelLen > 0) { @@ -1578,6 +1580,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, /* get dbMask value */ if ((ret = RsaMGF(mgf, tmp, hLen, tmp + hLen, pkcsBlockLen - hLen - 1, heap)) != 0) { + ForceZero(tmp, hLen); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, NULL, DYNAMIC_TYPE_RSA_BUFFER); #endif @@ -1589,6 +1592,7 @@ static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, pkcsBlock[hLen + 1 + idx] = pkcsBlock[hLen + 1 + idx] ^ tmp[idx + hLen]; } + ForceZero(tmp, pkcsBlockLen); #ifdef WOLFSSL_SMALL_STACK /* done with use of tmp buffer */ XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); @@ -2611,11 +2615,14 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, if (tmpa != NULL) #endif { - if (cleara) - mp_clear(tmpa); - if (clearb) - mp_clear(tmpb); + if (cleara) { + mp_forcezero(tmpa); + } + if (clearb) { + mp_forcezero(tmpb); + } #ifdef WOLFSSL_SMALL_STACK + /* tmpb is allocated after tmpa. */ XFREE(tmpa, key->heap, DYNAMIC_TYPE_RSA); #endif } @@ -2659,14 +2666,14 @@ static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, *outLen = inLen; #endif - mp_clear(tmp); + mp_forcezero(tmp); #ifdef WOLFSSL_SMALL_STACK XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); #endif #ifdef WC_RSA_BLINDING if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { - mp_clear(rndi); - mp_clear(rnd); + mp_forcezero(rndi); + mp_forcezero(rnd); } #ifdef WOLFSSL_SMALL_STACK XFREE(rnd, key->heap, DYNAMIC_TYPE_RSA); @@ -4201,7 +4208,7 @@ static int wc_CompareDiffPQ(mp_int* p, mp_int* q, int size) #ifdef WOLFSSL_SMALL_STACK if (d != NULL) { - mp_clear(d); + mp_forcezero(d); XFREE(d, NULL, DYNAMIC_TYPE_WOLF_BIGINT); } if (c != NULL) { @@ -4209,7 +4216,7 @@ static int wc_CompareDiffPQ(mp_int* p, mp_int* q, int size) XFREE(c, NULL, DYNAMIC_TYPE_WOLF_BIGINT); } #else - mp_clear(d); + mp_forcezero(d); mp_clear(c); #endif @@ -4360,7 +4367,7 @@ notOkay: #ifdef WOLFSSL_SMALL_STACK if (tmp1 != NULL) { - mp_clear(tmp1); + mp_forcezero(tmp1); XFREE(tmp1, NULL, DYNAMIC_TYPE_WOLF_BIGINT); } if (tmp2 != NULL) { @@ -4368,7 +4375,7 @@ notOkay: XFREE(tmp2, NULL, DYNAMIC_TYPE_WOLF_BIGINT); } #else - mp_clear(tmp1); + mp_forcezero(tmp1); mp_clear(tmp2); #endif @@ -4438,11 +4445,11 @@ int wc_CheckProbablePrime_ex(const byte* pRaw, word32 pRawSz, #ifdef WOLFSSL_SMALL_STACK if (p != NULL) { - mp_clear(p); + mp_forcezero(p); XFREE(p, NULL, DYNAMIC_TYPE_RSA_BUFFER); } if (q != NULL) { - mp_clear(q); + mp_forcezero(q); XFREE(q, NULL, DYNAMIC_TYPE_RSA_BUFFER); } if (e != NULL) { @@ -4450,8 +4457,8 @@ int wc_CheckProbablePrime_ex(const byte* pRaw, word32 pRawSz, XFREE(e, NULL, DYNAMIC_TYPE_RSA_BUFFER); } #else - mp_clear(p); - mp_clear(q); + mp_forcezero(p); + mp_forcezero(q); mp_clear(e); #endif @@ -4749,7 +4756,7 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) if (err == MP_OKAY) err = mp_sub_d(p, 2, tmp3); if (err == MP_OKAY) /* key->u = 1/q mod p = q^p-2 mod p */ - err = mp_exptmod(q, tmp3 , p, &key->u); + err = mp_exptmod(q, tmp3, p, &key->u); #endif if (err == MP_OKAY) err = mp_copy(p, &key->p); @@ -4781,11 +4788,14 @@ int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) RESTORE_VECTOR_REGISTERS(); - mp_clear(tmp1); - mp_clear(tmp2); - mp_clear(tmp3); - mp_clear(p); - mp_clear(q); + /* Last value p - 1. */ + mp_forcezero(tmp1); + /* Last value q - 1. */ + mp_forcezero(tmp2); + /* Last value p - 2. */ + mp_forcezero(tmp3); + mp_forcezero(p); + mp_forcezero(q); #ifndef WOLFSSL_NO_RSA_KEY_CHECK /* Perform the pair-wise consistency test on the new key. */ diff --git a/wolfcrypt/src/sp_int.c b/wolfcrypt/src/sp_int.c index b9980fdcc..e1231d5be 100644 --- a/wolfcrypt/src/sp_int.c +++ b/wolfcrypt/src/sp_int.c @@ -4517,7 +4517,8 @@ void sp_clear(sp_int* a) */ void sp_forcezero(sp_int* a) { - ForceZero(a->dp, a->used * sizeof(sp_int_digit)); + /* Ensure all data zeroized - data not zeroed when used decreases. */ + ForceZero(a->dp, a->size * sizeof(sp_int_digit)); _sp_zero(a); #ifdef HAVE_WOLF_BIGINT wc_bigint_zero(&a->raw); diff --git a/wolfcrypt/src/wc_encrypt.c b/wolfcrypt/src/wc_encrypt.c index d64920880..fa0ddd6eb 100644 --- a/wolfcrypt/src/wc_encrypt.c +++ b/wolfcrypt/src/wc_encrypt.c @@ -297,6 +297,7 @@ int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz, info->iv); #endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */ + ForceZero(key, WC_MAX_SYM_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); #endif @@ -354,6 +355,7 @@ int wc_BufferKeyEncrypt(EncryptedInfo* info, byte* der, word32 derSz, info->iv); #endif /* !NO_AES && HAVE_AES_CBC */ + ForceZero(key, WC_MAX_SYM_KEY_SIZE); #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); #endif diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 8cbd36c15..a4349b86a 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -7804,6 +7804,7 @@ static int aes_key_size_test(void) ret = 0; /* success */ out: + wc_AesFree(aes); #ifdef WOLFSSL_SMALL_STACK XFREE(aes, HEAP_HINT, DYNAMIC_TYPE_AES); #endif