From 67e70d6cb66af86467ac93c11f63e266125f85b8 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 13 Feb 2019 10:13:14 -0800 Subject: [PATCH 1/5] Update TLS to use the new AES-GCM and AES-CCM APIs that output the IV on encrypt rather than take the IV as an input. --- src/internal.c | 44 +++++++++++++++++++++++++------------------- src/keys.c | 32 +++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/internal.c b/src/internal.c index 16b35131b..44c95a8a6 100644 --- a/src/internal.c +++ b/src/internal.c @@ -11468,7 +11468,7 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifndef WOLFSSL_NO_TLS12 -#ifdef HAVE_AEAD +#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA) static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl) { int i; @@ -11825,6 +11825,14 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* HAVE_AEAD */ +/* The following type is used to share code between AES-GCM and AES-CCM. */ +typedef int (*AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + + static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, int asyncOkay) { @@ -11889,7 +11897,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, case wolfssl_aes_gcm: case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */ { - wc_AesAuthEncryptFunc aes_auth_fn; + AesAuthEncryptFunc aes_auth_fn; const byte* additionalSrc; #ifdef WOLFSSL_ASYNC_CRYPT @@ -11902,11 +11910,11 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) - ? wc_AesGcmEncrypt : wc_AesCcmEncrypt; + ? wc_AesGcmEncrypt_ex : wc_AesCcmEncrypt_ex; #elif defined(BUILD_AESGCM) - aes_auth_fn = wc_AesGcmEncrypt; + aes_auth_fn = wc_AesGcmEncrypt_ex; #else - aes_auth_fn = wc_AesCcmEncrypt; + aes_auth_fn = wc_AesCcmEncrypt_ex; #endif additionalSrc = input - 5; @@ -11929,10 +11937,6 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, * IV length minus the authentication tag size. */ c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, ssl->encrypt.additional + AEAD_LEN_OFFSET); - XMEMCPY(ssl->encrypt.nonce, - ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); - XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, - ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); ret = aes_auth_fn(ssl->encrypt.aes, out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, @@ -11945,6 +11949,8 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif + XMEMCPY(out, + ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, AESGCM_EXP_IV_SZ); } break; #endif /* BUILD_AESGCM || HAVE_AESCCM */ @@ -12073,8 +12079,6 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { /* finalize authentication cipher */ - AeadIncrementExpIV(ssl); - if (ssl->encrypt.nonce) ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); @@ -12094,6 +12098,15 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 return ret; } + +/* The following type is used to share code between AES-GCM and AES-CCM. */ +typedef int (*AesAuthDecryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + + static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { @@ -12153,7 +12166,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, case wolfssl_aes_gcm: case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */ { - wc_AesAuthDecryptFunc aes_auth_fn; + AesAuthDecryptFunc aes_auth_fn; #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ @@ -13993,13 +14006,6 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, } - #ifdef HAVE_AEAD - if (ssl->specs.cipher_type == aead) { - if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) - XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); - } - #endif - args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ AddRecordHeader(output, args->size, (byte)type, ssl); diff --git a/src/keys.c b/src/keys.c index 56ab0786c..dfe448739 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2212,11 +2212,13 @@ static int SetPrefix(byte* sha_input, int idx) static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, - int side, void* heap, int devId) + int side, void* heap, int devId, WC_RNG* rng) { + (void)rng; + #ifdef BUILD_ARC4 - word32 sz = specs->key_size; if (specs->bulk_cipher_algorithm == wolfssl_rc4) { + word32 sz = specs->key_size; if (enc && enc->arc4 == NULL) enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); if (enc && enc->arc4 == NULL) @@ -2607,14 +2609,17 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AEAD_MAX_IMP_SZ); + AESGCM_IMP_IV_SZ); + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->client_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AEAD_MAX_IMP_SZ); + AESGCM_IMP_IV_SZ); } } else { @@ -2623,14 +2628,17 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AEAD_MAX_IMP_SZ); + AESGCM_IMP_IV_SZ); + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->server_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AEAD_MAX_IMP_SZ); + AESGCM_IMP_IV_SZ); } } if (enc) @@ -2692,6 +2700,11 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, } XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, AEAD_MAX_IMP_SZ); + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) { + return CcmRet; + } } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key, @@ -2712,6 +2725,11 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, } XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, AEAD_MAX_IMP_SZ); + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) { + return CcmRet; + } } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key, @@ -3006,7 +3024,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #endif ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side, - ssl->heap, ssl->devId); + ssl->heap, ssl->devId, ssl->rng); #ifdef HAVE_SECURE_RENEGOTIATION if (copy) { From cd7f8cc65327b4425a9c4e03ce90b34f66fdaf0b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 13 Feb 2019 11:22:56 -0800 Subject: [PATCH 2/5] Update AES-GCM/CCM use in TLS with a wrapper to select the correct API depending on using old FIPS, or non-FIPS/FIPSv2. --- src/internal.c | 67 ++++++++++++++++++++++++++++++++++++-------------- src/keys.c | 12 +++++++++ 2 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/internal.c b/src/internal.c index 44c95a8a6..3962aa117 100644 --- a/src/internal.c +++ b/src/internal.c @@ -11468,7 +11468,11 @@ static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifndef WOLFSSL_NO_TLS12 -#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA) +#ifdef HAVE_AEAD + +#if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) || \ + (defined(HAVE_POLY1305) && defined(HAVE_CHACHA)) static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl) { int i; @@ -11476,6 +11480,7 @@ static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl) if (++ssl->keys.aead_exp_IV[i]) return; } } +#endif #if defined(HAVE_POLY1305) && defined(HAVE_CHACHA) @@ -11825,12 +11830,22 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* HAVE_AEAD */ +#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) /* The following type is used to share code between AES-GCM and AES-CCM. */ -typedef int (*AesAuthEncryptFunc)(Aes* aes, byte* out, - const byte* in, word32 sz, - byte* iv, word32 ivSz, - byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz); + typedef int (*AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + #define AES_AUTH_ENCRYPT_FUNC AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt_ex + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt_ex +#else + #define AES_AUTH_ENCRYPT_FUNC wc_AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt +#endif static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, @@ -11897,7 +11912,7 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, case wolfssl_aes_gcm: case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */ { - AesAuthEncryptFunc aes_auth_fn; + AES_AUTH_ENCRYPT_FUNC aes_auth_fn; const byte* additionalSrc; #ifdef WOLFSSL_ASYNC_CRYPT @@ -11910,11 +11925,11 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) - ? wc_AesGcmEncrypt_ex : wc_AesCcmEncrypt_ex; + ? AES_GCM_ENCRYPT : AES_CCM_ENCRYPT; #elif defined(BUILD_AESGCM) - aes_auth_fn = wc_AesGcmEncrypt_ex; + aes_auth_fn = AES_GCM_ENCRYPT; #else - aes_auth_fn = wc_AesCcmEncrypt_ex; + aes_auth_fn = AES_CCM_ENCRYPT; #endif additionalSrc = input - 5; @@ -11937,6 +11952,13 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, * IV length minus the authentication tag size. */ c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, ssl->encrypt.additional + AEAD_LEN_OFFSET); +#if (defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + XMEMCPY(ssl->encrypt.nonce, + ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); +#endif ret = aes_auth_fn(ssl->encrypt.aes, out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, @@ -11949,8 +11971,11 @@ static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, ret = wolfSSL_AsyncPush(ssl, asyncDev); } #endif +#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) XMEMCPY(out, ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, AESGCM_EXP_IV_SZ); +#endif } break; #endif /* BUILD_AESGCM || HAVE_AESCCM */ @@ -12079,6 +12104,10 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { /* finalize authentication cipher */ +#if (defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + AeadIncrementExpIV(ssl); +#endif if (ssl->encrypt.nonce) ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); @@ -12099,14 +12128,6 @@ static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 } -/* The following type is used to share code between AES-GCM and AES-CCM. */ -typedef int (*AesAuthDecryptFunc)(Aes* aes, byte* out, - const byte* in, word32 sz, - const byte* iv, word32 ivSz, - const byte* authTag, word32 authTagSz, - const byte* authIn, word32 authInSz); - - static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, word16 sz) { @@ -12166,7 +12187,7 @@ static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, case wolfssl_aes_gcm: case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */ { - AesAuthDecryptFunc aes_auth_fn; + wc_AesAuthDecryptFunc aes_auth_fn; #ifdef WOLFSSL_ASYNC_CRYPT /* initialize event */ @@ -14005,6 +14026,14 @@ int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, goto exit_buildmsg; } +#if (defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \ + defined(HAVE_AEAD) + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + } +#endif args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ AddRecordHeader(output, args->size, (byte)type, ssl); diff --git a/src/keys.c b/src/keys.c index dfe448739..d0678076d 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2610,9 +2610,12 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, AESGCM_IMP_IV_SZ); +#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, keys->client_write_IV, AESGCM_IMP_IV_SZ, rng); if (gcmRet != 0) return gcmRet; +#endif } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key, @@ -2629,9 +2632,12 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, AESGCM_IMP_IV_SZ); +#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, keys->server_write_IV, AESGCM_IMP_IV_SZ, rng); if (gcmRet != 0) return gcmRet; +#endif } if (dec) { gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key, @@ -2700,11 +2706,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, } XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, AEAD_MAX_IMP_SZ); +#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV, AEAD_MAX_IMP_SZ); if (CcmRet != 0) { return CcmRet; } +#endif } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key, @@ -2725,11 +2734,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, } XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, AEAD_MAX_IMP_SZ); +#if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV, AEAD_MAX_IMP_SZ); if (CcmRet != 0) { return CcmRet; } +#endif } if (dec) { CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key, From 3223920fd95b637009ac259c2de1201cf6a048ef Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 13 Feb 2019 12:23:12 -0800 Subject: [PATCH 3/5] Add a guard for AES-GCM and AES-CCM for the change in Encrypt for the AES-AEAD type and macros. --- src/internal.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/internal.c b/src/internal.c index 3962aa117..bc65a2ff7 100644 --- a/src/internal.c +++ b/src/internal.c @@ -11830,6 +11830,8 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, #endif /* HAVE_AEAD */ +#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) /* The following type is used to share code between AES-GCM and AES-CCM. */ @@ -11847,6 +11849,8 @@ static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, #define AES_CCM_ENCRYPT wc_AesCcmEncrypt #endif +#endif + static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, int asyncOkay) From e2d7b402e760c35166d8187fbca7f96dea6b3a05 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 14 Feb 2019 11:52:31 -0800 Subject: [PATCH 4/5] Update so TLSv1.3 will work. Needed to make the implicit IVs full sized when copying. Added a flag to SetKeys() to skip the IV set (used for TLSv1.3). --- src/keys.c | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/keys.c b/src/keys.c index d0678076d..13db002da 100644 --- a/src/keys.c +++ b/src/keys.c @@ -2212,9 +2212,10 @@ static int SetPrefix(byte* sha_input, int idx) static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, - int side, void* heap, int devId, WC_RNG* rng) + int side, void* heap, int devId, WC_RNG* rng, int skipIv) { (void)rng; + (void)skipIv; #ifdef BUILD_ARC4 if (specs->bulk_cipher_algorithm == wolfssl_rc4) { @@ -2609,12 +2610,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) - gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, - keys->client_write_IV, AESGCM_IMP_IV_SZ, rng); - if (gcmRet != 0) return gcmRet; + if (!skipIv) { + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->client_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; + } #endif } if (dec) { @@ -2622,7 +2625,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } else { @@ -2631,12 +2634,14 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) - gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, - keys->server_write_IV, AESGCM_IMP_IV_SZ, rng); - if (gcmRet != 0) return gcmRet; + if (!skipIv) { + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->server_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; + } #endif } if (dec) { @@ -2644,7 +2649,7 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, specs->key_size); if (gcmRet != 0) return gcmRet; XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, - AESGCM_IMP_IV_SZ); + AEAD_MAX_IMP_SZ); } } if (enc) @@ -2708,10 +2713,10 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, AEAD_MAX_IMP_SZ); #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) - CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV, - AEAD_MAX_IMP_SZ); - if (CcmRet != 0) { - return CcmRet; + if (!skipIv) { + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) return CcmRet; } #endif } @@ -2736,10 +2741,10 @@ static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, AEAD_MAX_IMP_SZ); #if (!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) - CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV, - AEAD_MAX_IMP_SZ); - if (CcmRet != 0) { - return CcmRet; + if (!skipIv) { + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) return CcmRet; } #endif } @@ -3036,7 +3041,7 @@ int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) #endif ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side, - ssl->heap, ssl->devId, ssl->rng); + ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3); #ifdef HAVE_SECURE_RENEGOTIATION if (copy) { From c0d1241786cef55e5f73480a338874a90abf883b Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 15 Feb 2019 13:52:23 -0800 Subject: [PATCH 5/5] Modify the TLSv1.3 calls to the AES-GCM and AES-CCM encrypt functions to use the FIPS compatible APIs with external nonce. --- src/tls13.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/tls13.c b/src/tls13.c index fd50831db..b64e40771 100644 --- a/src/tls13.c +++ b/src/tls13.c @@ -1681,9 +1681,13 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, #endif nonceSz = AESGCM_NONCE_SZ; - ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, - dataSz, ssl->encrypt.nonce, nonceSz, - output + dataSz, macSz, aad, aadSz); + ret = wc_AesGcmSetExtIV(ssl->encrypt.aes, + ssl->encrypt.nonce, nonceSz); + if (ret == 0) { + ret = wc_AesGcmEncrypt_ex(ssl->encrypt.aes, output, + input, dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + } break; #endif @@ -1698,9 +1702,13 @@ static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, #endif nonceSz = AESCCM_NONCE_SZ; - ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, - dataSz, ssl->encrypt.nonce, nonceSz, - output + dataSz, macSz, aad, aadSz); + ret = wc_AesCcmSetNonce(ssl->encrypt.aes, + ssl->encrypt.nonce, nonceSz); + if (ret == 0) { + ret = wc_AesCcmEncrypt_ex(ssl->encrypt.aes, output, + input, dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + } break; #endif