From 67e70d6cb66af86467ac93c11f63e266125f85b8 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Wed, 13 Feb 2019 10:13:14 -0800 Subject: [PATCH] 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) {