From 7dddf2fcc50fe6f7fda0f089ed60dd8545df22bb Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Thu, 8 Aug 2019 13:14:05 +1000 Subject: [PATCH] Change EVP_CIPHER_CTX_iv_length() to return current ivlen for some modes Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/9542) --- crypto/evp/e_aes.c | 28 ++++++++++++++++++++++++---- crypto/evp/e_aria.c | 13 +++++++++++-- crypto/evp/e_chacha20_poly1305.c | 7 ++++++- crypto/evp/evp_lib.c | 17 +++++++++++++---- include/openssl/evp.h | 8 ++++++-- 5 files changed, 60 insertions(+), 13 deletions(-) diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index d687a2cac3..a46ac8f92f 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -1334,7 +1334,7 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) switch (type) { case EVP_CTRL_INIT: - ivlen = EVP_CIPHER_CTX_iv_length(c); + ivlen = EVP_CIPHER_iv_length(c->cipher); iv = EVP_CIPHER_CTX_iv_noconst(c); gctx->key_set = 0; gctx->iv_set = 0; @@ -1345,6 +1345,10 @@ static int s390x_aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) gctx->tls_aad_len = -1; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = gctx->ivlen; + return 1; + case EVP_CTRL_AEAD_SET_IVLEN: if (arg <= 0) return 0; @@ -2053,6 +2057,10 @@ static int s390x_aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) cctx->aes.ccm.tls_aad_len = -1; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = 15 - cctx->aes.ccm.l; + return 1; + case EVP_CTRL_AEAD_TLS1_AAD: if (arg != EVP_AEAD_TLS1_AAD_LEN) return 0; @@ -2536,13 +2544,17 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_INIT: gctx->key_set = 0; gctx->iv_set = 0; - gctx->ivlen = c->cipher->iv_len; + gctx->ivlen = EVP_CIPHER_iv_length(c->cipher); gctx->iv = c->iv; gctx->taglen = -1; gctx->iv_gen = 0; gctx->tls_aad_len = -1; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = gctx->ivlen; + return 1; + case EVP_CTRL_AEAD_SET_IVLEN: if (arg <= 0) return 0; @@ -3055,7 +3067,7 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, #define CUSTOM_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ - | EVP_CIPH_CUSTOM_COPY) + | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_CUSTOM_IV_LENGTH) BLOCK_CIPHER_custom(NID_aes, 128, 1, 12, gcm, GCM, EVP_CIPH_FLAG_AEAD_CIPHER | CUSTOM_FLAGS) @@ -3260,6 +3272,10 @@ static int aes_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) cctx->tls_aad_len = -1; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = 15 - cctx->L; + return 1; + case EVP_CTRL_AEAD_TLS1_AAD: /* Save the AAD for later use */ if (arg != EVP_AEAD_TLS1_AAD_LEN) @@ -3708,13 +3724,17 @@ static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_INIT: octx->key_set = 0; octx->iv_set = 0; - octx->ivlen = EVP_CIPHER_CTX_iv_length(c); + octx->ivlen = EVP_CIPHER_iv_length(c->cipher); octx->iv = EVP_CIPHER_CTX_iv_noconst(c); octx->taglen = 16; octx->data_buf_len = 0; octx->aad_buf_len = 0; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = octx->ivlen; + return 1; + case EVP_CTRL_AEAD_SET_IVLEN: /* IV len must be 1 to 15 */ if (arg <= 0 || arg > 15) diff --git a/crypto/evp/e_aria.c b/crypto/evp/e_aria.c index f2588f141a..84b14826cb 100644 --- a/crypto/evp/e_aria.c +++ b/crypto/evp/e_aria.c @@ -252,13 +252,17 @@ static int aria_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) case EVP_CTRL_INIT: gctx->key_set = 0; gctx->iv_set = 0; - gctx->ivlen = EVP_CIPHER_CTX_iv_length(c); + gctx->ivlen = EVP_CIPHER_iv_length(c->cipher); gctx->iv = EVP_CIPHER_CTX_iv_noconst(c); gctx->taglen = -1; gctx->iv_gen = 0; gctx->tls_aad_len = -1; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = gctx->ivlen; + return 1; + case EVP_CTRL_AEAD_SET_IVLEN: if (arg <= 0) return 0; @@ -539,6 +543,10 @@ static int aria_ccm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr) cctx->tls_aad_len = -1; return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = 15 - cctx->L; + return 1; + case EVP_CTRL_AEAD_TLS1_AAD: /* Save the AAD for later use */ if (arg != EVP_AEAD_TLS1_AAD_LEN) @@ -742,7 +750,8 @@ static int aria_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, #define ARIA_AUTH_FLAGS (EVP_CIPH_FLAG_DEFAULT_ASN1 \ | EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \ | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT \ - | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER) + | EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_AEAD_CIPHER \ + | EVP_CIPH_CUSTOM_IV_LENGTH) #define BLOCK_CIPHER_aead(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \ static const EVP_CIPHER aria_##keylen##_##mode = { \ diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c index ccef031b89..570378b1af 100644 --- a/crypto/evp/e_chacha20_poly1305.c +++ b/crypto/evp/e_chacha20_poly1305.c @@ -534,6 +534,10 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, } return 1; + case EVP_CTRL_GET_IVLEN: + *(int *)ptr = actx->nonce_len; + return 1; + case EVP_CTRL_AEAD_SET_IVLEN: if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN) return 0; @@ -613,7 +617,8 @@ static EVP_CIPHER chacha20_poly1305 = { 12, /* iv_len, 96-bit nonce in the context */ EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV | EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT | - EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER, + EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER | + EVP_CIPH_CUSTOM_IV_LENGTH, chacha20_poly1305_init_key, chacha20_poly1305_cipher, chacha20_poly1305_cleanup, diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index d112eaf65a..0d6a7722a7 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -315,13 +315,22 @@ int EVP_CIPHER_iv_length(const EVP_CIPHER *cipher) int EVP_CIPHER_CTX_iv_length(const EVP_CIPHER_CTX *ctx) { - int ok, v = EVP_CIPHER_iv_length(ctx->cipher); + int len, rv, v = EVP_CIPHER_iv_length(ctx->cipher); OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; params[0] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_IVLEN, &v); - ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params); - - return ok != 0 ? v : -1; + rv = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params); + if (rv == EVP_CTRL_RET_UNSUPPORTED) + goto legacy; + return rv != 0 ? v : -1; + /* TODO (3.0) Remove legacy support */ +legacy: + if ((EVP_CIPHER_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; + } + return v; } const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx) diff --git a/include/openssl/evp.h b/include/openssl/evp.h index 8182915430..eab5a53d8a 100644 --- a/include/openssl/evp.h +++ b/include/openssl/evp.h @@ -268,6 +268,8 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, # define EVP_CIPH_RAND_KEY 0x200 /* cipher has its own additional copying logic */ # define EVP_CIPH_CUSTOM_COPY 0x400 +/* Don't use standard iv length function */ +# define EVP_CIPH_CUSTOM_IV_LENGTH 0x800 /* Allow use default ASN1 get/set iv */ # define EVP_CIPH_FLAG_DEFAULT_ASN1 0x1000 /* Buffer length in bits not bytes: CFB1 mode only */ @@ -356,10 +358,12 @@ int (*EVP_CIPHER_meth_get_ctrl(const EVP_CIPHER *cipher))(EVP_CIPHER_CTX *, # define EVP_CTRL_SET_PIPELINE_INPUT_BUFS 0x23 /* Set the input buffer lengths to use for a pipelined operation */ # define EVP_CTRL_SET_PIPELINE_INPUT_LENS 0x24 +/* Get the IV length used by the cipher */ +# define EVP_CTRL_GET_IVLEN 0x25 /* Get the IV used by the cipher */ -# define EVP_CTRL_GET_IV 0x25 +# define EVP_CTRL_GET_IV 0x26 /* Tell the cipher it's doing a speed test (SIV disallows multiple ops) */ -# define EVP_CTRL_SET_SPEED 0x26 +# define EVP_CTRL_SET_SPEED 0x27 /* Padding modes */ #define EVP_PADDING_PKCS7 1 -- 2.25.1