The branch master has been updated via 70f39a487d3f7d976a01e0ee7ae98a82ceeea7a0 (commit) via b30b45b7247d056b569e2b5139f8b503d36e646c (commit) via 80ce874a093087b919e1c722427df30f81f5dad5 (commit) from d5f9166bacfb3757dfd6117310ad54ab749b11f9 (commit)
- Log ----------------------------------------------------------------- commit 70f39a487d3f7d976a01e0ee7ae98a82ceeea7a0 Author: Pauli <pa...@openssl.org> Date: Thu Jan 27 13:33:36 2022 +1100 evp enc: cache cipher key length Instead of doing a heavy params based query every time a context is asked for its key length, this value is cached in the context and only queried if it could have been modified. Fixes #17064 Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17543) commit b30b45b7247d056b569e2b5139f8b503d36e646c Author: Pauli <pa...@openssl.org> Date: Wed Jan 26 15:04:51 2022 +1100 evp enc: cache cipher IV length Instead of doing a heavy params based query every time a context is asked for its IV length, this value is cached in the context and only queried if it could have been modified. Fixes #17064 Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17543) commit 80ce874a093087b919e1c722427df30f81f5dad5 Author: Pauli <pa...@openssl.org> Date: Thu Jan 27 12:51:13 2022 +1100 aes: avoid accessing key length field directly Reviewed-by: Tomas Mraz <to...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17543) ----------------------------------------------------------------------- Summary of changes: crypto/evp/e_aes.c | 305 +++++++++++++++++++++++++++------------ crypto/evp/e_aes_cbc_hmac_sha1.c | 23 ++- crypto/evp/evp_enc.c | 38 ++++- crypto/evp/evp_lib.c | 68 ++++++--- crypto/evp/evp_local.h | 1 + 5 files changed, 303 insertions(+), 132 deletions(-) diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 445a28445a..7915d327fa 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -146,20 +146,21 @@ static int aesni_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { int ret, mode; EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } mode = EVP_CIPHER_CTX_get_mode(ctx); if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { - ret = aesni_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = aesni_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) aesni_decrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) aesni_cbc_encrypt : NULL; } else { - ret = aesni_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = aesni_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) aesni_encrypt; if (mode == EVP_CIPH_CBC_MODE) dat->stream.cbc = (cbc128_f) aesni_cbc_encrypt; @@ -223,12 +224,19 @@ static int aesni_ctr_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, static int aesni_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { - EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); - if (!iv && !key) + EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX, ctx); + + if (iv == NULL && key == NULL) return 1; + if (key) { - aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &gctx->ks.ks); + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + aesni_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aesni_encrypt); gctx->ctr = (ctr128_f) aesni_ctr32_encrypt_blocks; /* @@ -262,14 +270,19 @@ static int aesni_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); - if (!iv && !key) + if (iv == NULL && key == NULL) return 1; if (key) { /* The key is two half length keys in reality */ - const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int bytes = keylen / 2; const int bits = bytes * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } /* * Verify that the two keys are different. * @@ -315,11 +328,18 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { - aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + aesni_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) aesni_encrypt); cctx->str = enc ? (ccm128_f) aesni_ccm64_encrypt_blocks : @@ -342,19 +362,25 @@ static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { /* * We set both the encrypt and decrypt key here because decrypt * needs both. We could possibly optimise to remove setting the * decrypt for an encryption operation. */ - aesni_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - aesni_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + aesni_set_encrypt_key(key, keylen, &octx->ksenc.ks); + aesni_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) aesni_encrypt, @@ -452,6 +478,10 @@ static int aes_t4_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, mode = EVP_CIPHER_CTX_get_mode(ctx); bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + if (bits <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { ret = 0; @@ -547,10 +577,16 @@ static int aes_t4_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; if (key) { - int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + const int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (bits <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } aes_t4_set_encrypt_key(key, bits, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) aes_t4_encrypt); @@ -603,9 +639,14 @@ static int aes_t4_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, if (key) { /* The key is two half length keys in reality */ - const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int bytes = keylen / 2; const int bits = bytes * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } /* * Verify that the two keys are different. * @@ -670,10 +711,17 @@ static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { - int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (key != NULL) { + const int bits = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (bits <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } aes_t4_set_encrypt_key(key, bits, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) aes_t4_encrypt); @@ -696,19 +744,25 @@ static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { /* * We set both the encrypt and decrypt key here because decrypt * needs both. We could possibly optimise to remove setting the * decrypt for an encryption operation. */ - aes_t4_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - aes_t4_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + aes_t4_set_encrypt_key(key, keylen, &octx->ksenc.ks); + aes_t4_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) aes_t4_encrypt, @@ -973,6 +1027,10 @@ static int s390x_aes_ecb_init_key(EVP_CIPHER_CTX *ctx, S390X_AES_ECB_CTX *cctx = EVP_C_DATA(S390X_AES_ECB_CTX, ctx); const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } cctx->fc = S390X_AES_FC(keylen); if (!enc) cctx->fc |= S390X_DECRYPT; @@ -999,6 +1057,14 @@ static int s390x_aes_ofb_init_key(EVP_CIPHER_CTX *ctx, const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } memcpy(cctx->kmo.param.cv, iv, ivlen); memcpy(cctx->kmo.param.k, key, keylen); cctx->fc = S390X_AES_FC(keylen); @@ -1058,6 +1124,14 @@ static int s390x_aes_cfb_init_key(EVP_CIPHER_CTX *ctx, const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } cctx->fc = S390X_AES_FC(keylen); cctx->fc |= 16 << 24; /* 16 bytes cipher feedback */ if (!enc) @@ -1081,6 +1155,14 @@ static int s390x_aes_cfb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, int rem; unsigned char tmp; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } memcpy(cctx->kmf.param.cv, iv, ivlen); while (n && len) { tmp = *in; @@ -1128,6 +1210,14 @@ static int s390x_aes_cfb8_init_key(EVP_CIPHER_CTX *ctx, const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); const int ivlen = EVP_CIPHER_CTX_get_iv_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + if (ivlen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_IV_LENGTH); + return 0; + } cctx->fc = S390X_AES_FC(keylen); cctx->fc |= 1 << 24; /* 1 byte cipher feedback */ if (!enc) @@ -1533,6 +1623,11 @@ static int s390x_aes_gcm_init_key(EVP_CIPHER_CTX *ctx, if (key != NULL) { keylen = EVP_CIPHER_CTX_get_key_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + memcpy(&gctx->kma.param.k, key, keylen); gctx->fc = S390X_AES_FC(keylen); @@ -1939,6 +2034,11 @@ static int s390x_aes_ccm_init_key(EVP_CIPHER_CTX *ctx, if (key != NULL) { keylen = EVP_CIPHER_CTX_get_key_length(ctx); + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } + cctx->aes.ccm.fc = S390X_AES_FC(keylen); memcpy(cctx->aes.ccm.kmac_param.k, key, keylen); @@ -2315,15 +2415,19 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { int ret, mode; EVP_AES_KEY *dat = EVP_C_DATA(EVP_AES_KEY,ctx); + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } mode = EVP_CIPHER_CTX_get_mode(ctx); if ((mode == EVP_CIPH_ECB_MODE || mode == EVP_CIPH_CBC_MODE) && !enc) { #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - ret = HWAES_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = HWAES_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) HWAES_decrypt; dat->stream.cbc = NULL; # ifdef HWAES_cbc_encrypt @@ -2334,27 +2438,21 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef BSAES_CAPABLE if (BSAES_CAPABLE && mode == EVP_CIPH_CBC_MODE) { - ret = AES_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_decrypt; dat->stream.cbc = (cbc128_f) ossl_bsaes_cbc_encrypt; } else #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - ret = vpaes_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = vpaes_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) vpaes_decrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) vpaes_cbc_encrypt : NULL; } else #endif { - ret = AES_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_decrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_decrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) AES_cbc_encrypt : NULL; @@ -2362,9 +2460,7 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, } else #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - ret = HWAES_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = HWAES_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) HWAES_encrypt; dat->stream.cbc = NULL; # ifdef HWAES_cbc_encrypt @@ -2382,25 +2478,21 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef BSAES_CAPABLE if (BSAES_CAPABLE && mode == EVP_CIPH_CTR_MODE) { - ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_encrypt; dat->stream.ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks; } else #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - ret = vpaes_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = vpaes_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) vpaes_encrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) vpaes_cbc_encrypt : NULL; } else #endif { - ret = AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &dat->ks.ks); + ret = AES_set_encrypt_key(key, keylen, &dat->ks.ks); dat->block = (block128_f) AES_encrypt; dat->stream.cbc = mode == EVP_CIPH_CBC_MODE ? (cbc128_f) AES_cbc_encrypt : NULL; @@ -2711,13 +2803,21 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_GCM_CTX *gctx = EVP_C_DATA(EVP_AES_GCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - HWAES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + HWAES_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) HWAES_encrypt); # ifdef HWAES_ctr32_encrypt_blocks @@ -2730,7 +2830,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef BSAES_CAPABLE if (BSAES_CAPABLE) { - AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + AES_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) AES_encrypt); gctx->ctr = (ctr128_f) ossl_bsaes_ctr32_encrypt_blocks; @@ -2739,7 +2839,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - vpaes_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + vpaes_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) vpaes_encrypt); gctx->ctr = NULL; @@ -2748,7 +2848,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif (void)0; /* terminate potentially open 'else' */ - AES_set_encrypt_key(key, ctx->key_len * 8, &gctx->ks.ks); + AES_set_encrypt_key(key, keylen, &gctx->ks.ks); CRYPTO_gcm128_init(&gctx->gcm, &gctx->ks, (block128_f) AES_encrypt); #ifdef AES_CTR_ASM @@ -3128,15 +3228,20 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, { EVP_AES_XTS_CTX *xctx = EVP_C_DATA(EVP_AES_XTS_CTX,ctx); - if (!iv && !key) + if (iv == NULL && key == NULL) return 1; - if (key) { + if (key != NULL) { do { /* The key is two half length keys in reality */ - const int bytes = EVP_CIPHER_CTX_get_key_length(ctx) / 2; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + const int bytes = keylen / 2; const int bits = bytes * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } /* * Verify that the two keys are different. * @@ -3382,15 +3487,21 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_CCM_CTX *cctx = EVP_C_DATA(EVP_AES_CCM_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { #ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - HWAES_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + HWAES_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) HWAES_encrypt); @@ -3401,9 +3512,7 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, #endif #ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - vpaes_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + vpaes_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) vpaes_encrypt); cctx->str = NULL; @@ -3411,14 +3520,14 @@ static int aes_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, break; } #endif - AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &cctx->ks.ks); + AES_set_encrypt_key(key, keylen, &cctx->ks.ks); CRYPTO_ccm128_init(&cctx->ccm, cctx->M, cctx->L, &cctx->ks, (block128_f) AES_encrypt); cctx->str = NULL; cctx->key_set = 1; } while (0); - if (iv) { + } + if (iv != NULL) { memcpy(ctx->iv, iv, 15 - cctx->L); cctx->iv_set = 1; } @@ -3573,12 +3682,16 @@ static int aes_wrap_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, if (iv == NULL && key == NULL) return 1; if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } if (EVP_CIPHER_CTX_is_encrypting(ctx)) - AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &wctx->ks.ks); + AES_set_encrypt_key(key, keylen, &wctx->ks.ks); else - AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &wctx->ks.ks); + AES_set_decrypt_key(key, keylen, &wctx->ks.ks); if (iv == NULL) wctx->iv = NULL; } @@ -3806,9 +3919,17 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, const unsigned char *iv, int enc) { EVP_AES_OCB_CTX *octx = EVP_C_DATA(EVP_AES_OCB_CTX,ctx); - if (!iv && !key) + + if (iv == NULL && key == NULL) return 1; - if (key) { + + if (key != NULL) { + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } do { /* * We set both the encrypt and decrypt key here because decrypt @@ -3817,10 +3938,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, */ # ifdef HWAES_CAPABLE if (HWAES_CAPABLE) { - HWAES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - HWAES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + HWAES_set_encrypt_key(key, keylen, &octx->ksenc.ks); + HWAES_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) HWAES_encrypt, @@ -3833,12 +3952,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, # endif # ifdef VPAES_CAPABLE if (VPAES_CAPABLE) { - vpaes_set_encrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - vpaes_set_decrypt_key(key, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + vpaes_set_encrypt_key(key, keylen, &octx->ksenc.ks); + vpaes_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) vpaes_encrypt, @@ -3848,10 +3963,8 @@ static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key, break; } # endif - AES_set_encrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksenc.ks); - AES_set_decrypt_key(key, EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &octx->ksdec.ks); + AES_set_encrypt_key(key, keylen, &octx->ksenc.ks); + AES_set_decrypt_key(key, keylen, &octx->ksdec.ks); if (!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc.ks, &octx->ksdec.ks, (block128_f) AES_encrypt, diff --git a/crypto/evp/e_aes_cbc_hmac_sha1.c b/crypto/evp/e_aes_cbc_hmac_sha1.c index 4941f98e64..5f25cda0ec 100644 --- a/crypto/evp/e_aes_cbc_hmac_sha1.c +++ b/crypto/evp/e_aes_cbc_hmac_sha1.c @@ -72,15 +72,16 @@ static int aesni_cbc_hmac_sha1_init_key(EVP_CIPHER_CTX *ctx, { EVP_AES_HMAC_SHA1 *key = data(ctx); int ret; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx) * 8; + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } if (enc) - ret = aesni_set_encrypt_key(inkey, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &key->ks); + ret = aesni_set_encrypt_key(inkey, keylen, &key->ks); else - ret = aesni_set_decrypt_key(inkey, - EVP_CIPHER_CTX_get_key_length(ctx) * 8, - &key->ks); + ret = aesni_set_decrypt_key(inkey, keylen, &key->ks); SHA1_Init(&key->head); /* handy when benchmarking */ key->tail = key->head; @@ -496,6 +497,12 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, # if defined(STITCHED_DECRYPT_CALL) unsigned char tail_iv[AES_BLOCK_SIZE]; int stitch = 0; + const int keylen = EVP_CIPHER_CTX_get_key_length(ctx); + + if (keylen <= 0) { + ERR_raise(ERR_LIB_EVP, EVP_R_INVALID_KEY_LENGTH); + return 0; + } # endif if ((key->aux.tls_aad[plen - 4] << 8 | key->aux.tls_aad[plen - 3]) @@ -513,7 +520,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return 0; # if defined(STITCHED_DECRYPT_CALL) - if (len >= 1024 && ctx->key_len == 32) { + if (len >= 1024 && keylen == 32) { /* decrypt last block */ memcpy(tail_iv, in + len - 2 * AES_BLOCK_SIZE, AES_BLOCK_SIZE); @@ -734,7 +741,7 @@ static int aesni_cbc_hmac_sha1_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, return ret; } else { # if defined(STITCHED_DECRYPT_CALL) - if (len >= 1024 && ctx->key_len == 32) { + if (len >= 1024 && keylen == 32) { if (sha_off %= SHA_CBLOCK) blocks = (len - 3 * SHA_CBLOCK) / SHA_CBLOCK; else diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 1c02cafa16..7ae92df98b 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -43,6 +43,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) if (ctx->fetched_cipher != NULL) EVP_CIPHER_free(ctx->fetched_cipher); memset(ctx, 0, sizeof(*ctx)); + ctx->iv_len = -1; return 1; @@ -61,6 +62,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) ENGINE_finish(ctx->engine); #endif memset(ctx, 0, sizeof(*ctx)); + ctx->iv_len = 0; return 1; } @@ -87,6 +89,9 @@ static int evp_cipher_init_internal(EVP_CIPHER_CTX *ctx, #if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODULE) ENGINE *tmpimpl = NULL; #endif + + ctx->iv_len = -1; + /* * enc == 1 means we are encrypting. * enc == 0 means we are decrypting. @@ -979,7 +984,7 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) if (c->cipher->prov != NULL) { int ok; OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; - size_t len = keylen; + size_t len; if (EVP_CIPHER_CTX_get_key_length(c) == keylen) return 1; @@ -992,9 +997,13 @@ int EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *c, int keylen) } params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len); + if (!OSSL_PARAM_set_int(params, keylen)) + return 0; ok = evp_do_ciph_ctx_setparams(c->cipher, c->algctx, params); - - return ok > 0 ? 1 : 0; + if (ok <= 0) + return 0; + c->key_len = keylen; + return 1; } /* Code below to be removed when legacy support is dropped. */ @@ -1055,6 +1064,7 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) switch (type) { case EVP_CTRL_SET_KEY_LENGTH: params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &sz); + ctx->key_len = -1; break; case EVP_CTRL_RAND_KEY: /* Used by DES */ set_params = 0; @@ -1079,12 +1089,14 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) if (arg < 0) return 0; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz); + ctx->iv_len = -1; break; case EVP_CTRL_CCM_SET_L: if (arg < 2 || arg > 8) return 0; sz = 15 - arg; params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &sz); + ctx->iv_len = -1; break; case EVP_CTRL_AEAD_SET_IV_FIXED: params[0] = OSSL_PARAM_construct_octet_string( @@ -1248,9 +1260,23 @@ int EVP_CIPHER_get_params(EVP_CIPHER *cipher, OSSL_PARAM params[]) int EVP_CIPHER_CTX_set_params(EVP_CIPHER_CTX *ctx, const OSSL_PARAM params[]) { - if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) - return ctx->cipher->set_ctx_params(ctx->algctx, params); - return 0; + int r = 0; + const OSSL_PARAM *p; + + if (ctx->cipher != NULL && ctx->cipher->set_ctx_params != NULL) { + r = ctx->cipher->set_ctx_params(ctx->algctx, params); + if (r > 0) { + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_KEYLEN); + if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->key_len)) + r = 0; + } + if (r > 0) { + p = OSSL_PARAM_locate_const(params, OSSL_CIPHER_PARAM_IVLEN); + if (p != NULL && !OSSL_PARAM_get_int(p, &ctx->iv_len)) + r = 0; + } + } + return r; } int EVP_CIPHER_CTX_get_params(EVP_CIPHER_CTX *ctx, OSSL_PARAM params[]) diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 3d261c282f..7e03d03bf6 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -504,23 +504,33 @@ int EVP_CIPHER_get_iv_length(const EVP_CIPHER *cipher) int EVP_CIPHER_CTX_get_iv_length(const EVP_CIPHER_CTX *ctx) { - int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher); - size_t v = len; - OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; - - params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &v); - rv = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); - if (rv == EVP_CTRL_RET_UNSUPPORTED) - goto legacy; - return rv != 0 ? (int)v : -1; - /* Code below to be removed when legacy support is dropped. */ -legacy: - if ((EVP_CIPHER_get_flags(ctx->cipher) & EVP_CIPH_CUSTOM_IV_LENGTH) != 0) { - rv = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN, - 0, &len); - return (rv == 1) ? len : -1; + if (ctx->iv_len < 0) { + int rv, len = EVP_CIPHER_get_iv_length(ctx->cipher); + size_t v = len; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_IVLEN, &v); + rv = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); + if (rv != EVP_CTRL_RET_UNSUPPORTED) { + if (rv <= 0) + return -1; + len = (int)v; + } + /* Code below to be removed when legacy support is dropped. */ + else if ((EVP_CIPHER_get_flags(ctx->cipher) + & EVP_CIPH_CUSTOM_IV_LENGTH) != 0) { + rv = EVP_CIPHER_CTX_ctrl((EVP_CIPHER_CTX *)ctx, EVP_CTRL_GET_IVLEN, + 0, &len); + if (rv <= 0) + return -1; + } + /*- + * Casting away the const is annoying but required here. We need to + * cache the result for performance reasons. + */ + ((EVP_CIPHER_CTX *)ctx)->iv_len = len; } - return len; + return ctx->iv_len; } int EVP_CIPHER_CTX_get_tag_length(const EVP_CIPHER_CTX *ctx) @@ -637,14 +647,28 @@ int EVP_CIPHER_get_key_length(const EVP_CIPHER *cipher) int EVP_CIPHER_CTX_get_key_length(const EVP_CIPHER_CTX *ctx) { - int ok; - size_t v = ctx->key_len; - OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + if (ctx->key_len <= 0 && ctx->cipher->prov != NULL) { + int ok; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + size_t len; - params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &v); - ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); + params[0] = OSSL_PARAM_construct_size_t(OSSL_CIPHER_PARAM_KEYLEN, &len); + ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->algctx, params); + if (ok <= 0) + return EVP_CTRL_RET_UNSUPPORTED; - return ok != 0 ? (int)v : EVP_CTRL_RET_UNSUPPORTED; + /*- + * The if branch should never be taken since EVP_MAX_KEY_LENGTH is + * less than INT_MAX but best to be safe. + * + * Casting away the const is annoying but required here. We need to + * cache the result for performance reasons. + */ + if (!OSSL_PARAM_get_int(params, &((EVP_CIPHER_CTX *)ctx)->key_len)) + return -1; + ((EVP_CIPHER_CTX *)ctx)->key_len = (int)len; + } + return ctx->key_len; } int EVP_CIPHER_get_nid(const EVP_CIPHER *cipher) diff --git a/crypto/evp/evp_local.h b/crypto/evp/evp_local.h index d9e1ca997e..8b114d362d 100644 --- a/crypto/evp/evp_local.h +++ b/crypto/evp/evp_local.h @@ -46,6 +46,7 @@ struct evp_cipher_ctx_st { /* FIXME: Should this even exist? It appears unused */ void *app_data; /* application stuff */ int key_len; /* May change for variable length cipher */ + int iv_len; /* IV length */ unsigned long flags; /* Various flags */ void *cipher_data; /* per EVP data */ int final_used;