From 089cb623be76b88a1eea6fcd135101037661bbc3 Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Tue, 8 Oct 2019 09:19:10 +1000 Subject: [PATCH] Move cipher ctx 'original iv' parameter into the provider Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/10026) --- crypto/evp/evp_enc.c | 13 ---------- crypto/evp/evp_lib.c | 15 ++++++++++-- providers/common/ciphers/cipher_aes_ccm.c | 1 - providers/common/ciphers/cipher_aes_gcm.c | 1 - providers/common/ciphers/cipher_aes_wrp.c | 10 +++----- providers/common/ciphers/cipher_aes_xts.c | 8 ++----- providers/common/ciphers/cipher_aes_xts.h | 1 - providers/common/ciphers/cipher_ccm.c | 5 ---- providers/common/ciphers/cipher_common.c | 24 +++++++++++++------ providers/common/ciphers/cipher_gcm.c | 7 +----- providers/common/ciphers/cipher_tdes.c | 7 ++---- .../include/internal/ciphers/cipher_ccm.h | 1 - .../include/internal/ciphers/cipher_gcm.h | 1 - .../include/internal/ciphers/ciphercommon.h | 14 +++++++---- providers/default/ciphers/cipher_aes_ocb.c | 6 ++--- providers/default/ciphers/cipher_aria_ccm.c | 1 - providers/default/ciphers/cipher_aria_gcm.c | 1 - providers/default/ciphers/cipher_des.c | 7 ++---- 18 files changed, 53 insertions(+), 70 deletions(-) diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index 046a9f60af..2a22336a36 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -341,19 +341,6 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, return 0; } - switch (EVP_CIPHER_mode(ctx->cipher)) { - case EVP_CIPH_CFB_MODE: - case EVP_CIPH_OFB_MODE: - case EVP_CIPH_CBC_MODE: - /* For these modes we remember the original IV for later use */ - if (!ossl_assert(EVP_CIPHER_CTX_iv_length(ctx) <= (int)sizeof(ctx->oiv))) { - EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); - return 0; - } - if (iv != NULL) - memcpy(ctx->oiv, iv, EVP_CIPHER_CTX_iv_length(ctx)); - } - if (enc) { if (ctx->cipher->einit == NULL) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 3abea33d19..3a3eec615f 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -194,11 +194,13 @@ int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { int i = 0; unsigned int j; + unsigned char *oiv = NULL; if (type != NULL) { + oiv = (unsigned char *)EVP_CIPHER_CTX_original_iv(c); j = EVP_CIPHER_CTX_iv_length(c); OPENSSL_assert(j <= sizeof(c->iv)); - i = ASN1_TYPE_set_octetstring(type, c->oiv, j); + i = ASN1_TYPE_set_octetstring(type, oiv, j); } return i; } @@ -403,7 +405,16 @@ int EVP_CIPHER_CTX_tag_length(const EVP_CIPHER_CTX *ctx) const unsigned char *EVP_CIPHER_CTX_original_iv(const EVP_CIPHER_CTX *ctx) { - return ctx->oiv; + int ok; + const unsigned char *v = ctx->oiv; + OSSL_PARAM params[2] = { OSSL_PARAM_END, OSSL_PARAM_END }; + + params[0] = + OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_IV, + (void **)&v, sizeof(ctx->oiv)); + ok = evp_do_ciph_ctx_getparams(ctx->cipher, ctx->provctx, params); + + return ok != 0 ? v : NULL; } /* diff --git a/providers/common/ciphers/cipher_aes_ccm.c b/providers/common/ciphers/cipher_aes_ccm.c index c8015898dd..cffca06c80 100644 --- a/providers/common/ciphers/cipher_aes_ccm.c +++ b/providers/common/ciphers/cipher_aes_ccm.c @@ -27,7 +27,6 @@ static void aes_ccm_freectx(void *vctx) { PROV_AES_CCM_CTX *ctx = (PROV_AES_CCM_CTX *)vctx; - ccm_finalctx((PROV_CCM_CTX *)ctx); OPENSSL_clear_free(ctx, sizeof(*ctx)); } diff --git a/providers/common/ciphers/cipher_aes_gcm.c b/providers/common/ciphers/cipher_aes_gcm.c index ba03bed590..ef015bff21 100644 --- a/providers/common/ciphers/cipher_aes_gcm.c +++ b/providers/common/ciphers/cipher_aes_gcm.c @@ -27,7 +27,6 @@ static void aes_gcm_freectx(void *vctx) { PROV_AES_GCM_CTX *ctx = (PROV_AES_GCM_CTX *)vctx; - gcm_deinitctx((PROV_GCM_CTX *)ctx); OPENSSL_clear_free(ctx, sizeof(*ctx)); } diff --git a/providers/common/ciphers/cipher_aes_wrp.c b/providers/common/ciphers/cipher_aes_wrp.c index 70f387f515..1bf4c1793a 100644 --- a/providers/common/ciphers/cipher_aes_wrp.c +++ b/providers/common/ciphers/cipher_aes_wrp.c @@ -36,7 +36,6 @@ typedef struct prov_aes_wrap_ctx_st { OSSL_UNION_ALIGN; AES_KEY ks; } ks; - unsigned int iv_set : 1; aeswrap_fn wrapfn; } PROV_AES_WRAP_CTX; @@ -59,9 +58,7 @@ static void *aes_wrap_newctx(size_t kbits, size_t blkbits, static void aes_wrap_freectx(void *vctx) { PROV_AES_WRAP_CTX *wctx = (PROV_AES_WRAP_CTX *)vctx; - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; - OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv)); OPENSSL_clear_free(wctx, sizeof(*wctx)); } @@ -80,9 +77,8 @@ static int aes_wrap_init(void *vctx, const unsigned char *key, wctx->wrapfn = enc ? CRYPTO_128_wrap : CRYPTO_128_unwrap; if (iv != NULL) { - ctx->ivlen = ivlen; - memcpy(ctx->iv, iv, ivlen); - wctx->iv_set = 1; + if (!cipher_generic_initiv(ctx, iv, ivlen)) + return 0; } if (key != NULL) { if (keylen != ctx->keylen) { @@ -150,7 +146,7 @@ static int aes_wrap_cipher_internal(void *vctx, unsigned char *out, } } - rv = wctx->wrapfn(&wctx->ks.ks, wctx->iv_set ? ctx->iv : NULL, out, in, + rv = wctx->wrapfn(&wctx->ks.ks, ctx->iv_set ? ctx->iv : NULL, out, in, inlen, ctx->block); return rv ? (int)rv : -1; } diff --git a/providers/common/ciphers/cipher_aes_xts.c b/providers/common/ciphers/cipher_aes_xts.c index f114793ba8..fdda733d24 100644 --- a/providers/common/ciphers/cipher_aes_xts.c +++ b/providers/common/ciphers/cipher_aes_xts.c @@ -76,12 +76,8 @@ static int aes_xts_init(void *vctx, const unsigned char *key, size_t keylen, ctx->enc = enc; if (iv != NULL) { - if (ivlen != ctx->ivlen) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); + if (!cipher_generic_initiv(vctx, iv, ivlen)) return 0; - } - memcpy(ctx->iv, iv, ivlen); - xctx->iv_set = 1; } if (key != NULL) { if (keylen != ctx->keylen) { @@ -155,7 +151,7 @@ static int aes_xts_cipher(void *vctx, unsigned char *out, size_t *outl, if (ctx->xts.key1 == NULL || ctx->xts.key2 == NULL - || !ctx->iv_set + || !ctx->base.iv_set || out == NULL || in == NULL || inl < AES_BLOCK_SIZE) diff --git a/providers/common/ciphers/cipher_aes_xts.h b/providers/common/ciphers/cipher_aes_xts.h index daad274328..4f8a8f874f 100644 --- a/providers/common/ciphers/cipher_aes_xts.h +++ b/providers/common/ciphers/cipher_aes_xts.h @@ -23,7 +23,6 @@ typedef struct prov_aes_xts_ctx_st { } ks1, ks2; /* AES key schedules to use */ XTS128_CONTEXT xts; OSSL_xts_stream_fn stream; - unsigned int iv_set : 1; /* Set if an iv is set */ } PROV_AES_XTS_CTX; const PROV_CIPHER_HW *PROV_CIPHER_HW_aes_xts(size_t keybits); diff --git a/providers/common/ciphers/cipher_ccm.c b/providers/common/ciphers/cipher_ccm.c index cc37b49c60..3fbaef9a46 100644 --- a/providers/common/ciphers/cipher_ccm.c +++ b/providers/common/ciphers/cipher_ccm.c @@ -213,7 +213,6 @@ static int ccm_init(void *vctx, const unsigned char *key, size_t keylen, ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); return 0; } - memcpy(ctx->iv, iv, ivlen); ctx->iv_set = 1; } @@ -420,7 +419,3 @@ void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw) ctx->hw = hw; } -void ccm_finalctx(PROV_CCM_CTX *ctx) -{ - OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv)); -} diff --git a/providers/common/ciphers/cipher_common.c b/providers/common/ciphers/cipher_common.c index bc8776d874..2577d94d7a 100644 --- a/providers/common/ciphers/cipher_common.c +++ b/providers/common/ciphers/cipher_common.c @@ -109,11 +109,8 @@ static int cipher_generic_init_internal(PROV_CIPHER_CTX *ctx, ctx->enc = enc ? 1 : 0; if (iv != NULL && ctx->mode != EVP_CIPH_ECB_MODE) { - if (ivlen != ctx->ivlen) { - ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); + if (!cipher_generic_initiv(ctx, iv, ivlen)) return 0; - } - memcpy(ctx->iv, iv, ctx->ivlen); } if (key != NULL) { if ((ctx->flags & EVP_CIPH_VARIABLE_LENGTH) == 0) { @@ -322,8 +319,8 @@ int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[]) } p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_IV); if (p != NULL - && !OSSL_PARAM_set_octet_ptr(p, &ctx->iv, ctx->ivlen) - && !OSSL_PARAM_set_octet_string(p, &ctx->iv, ctx->ivlen)) { + && !OSSL_PARAM_set_octet_ptr(p, &ctx->oiv, ctx->ivlen) + && !OSSL_PARAM_set_octet_string(p, &ctx->oiv, ctx->ivlen)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); return 0; } @@ -337,7 +334,6 @@ int cipher_generic_get_ctx_params(void *vctx, OSSL_PARAM params[]) ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); return 0; } - return 1; } @@ -379,6 +375,20 @@ int cipher_generic_set_ctx_params(void *vctx, const OSSL_PARAM params[]) return 1; } +int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv, + size_t ivlen) +{ + if (ivlen != ctx->ivlen + || ivlen > sizeof(ctx->iv)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + return 0; + } + ctx->iv_set = 1; + memcpy(ctx->iv, iv, ivlen); + memcpy(ctx->oiv, iv, ivlen); + return 1; +} + void cipher_generic_initkey(void *vctx, size_t kbits, size_t blkbits, size_t ivbits, unsigned int mode, uint64_t flags, const PROV_CIPHER_HW *hw, void *provctx) diff --git a/providers/common/ciphers/cipher_gcm.c b/providers/common/ciphers/cipher_gcm.c index 137ad5029c..59368dc81e 100644 --- a/providers/common/ciphers/cipher_gcm.c +++ b/providers/common/ciphers/cipher_gcm.c @@ -38,11 +38,6 @@ void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits, ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx); } -void gcm_deinitctx(PROV_GCM_CTX *ctx) -{ - OPENSSL_cleanse(ctx->iv, sizeof(ctx->iv)); -} - static int gcm_init(void *vctx, const unsigned char *key, size_t keylen, const unsigned char *iv, size_t ivlen, int enc) { @@ -56,7 +51,7 @@ static int gcm_init(void *vctx, const unsigned char *key, size_t keylen, return 0; } ctx->ivlen = ivlen; - memcpy(ctx->iv, iv, ctx->ivlen); + memcpy(ctx->iv, iv, ivlen); ctx->iv_state = IV_STATE_BUFFERED; } diff --git a/providers/common/ciphers/cipher_tdes.c b/providers/common/ciphers/cipher_tdes.c index 004ebc7269..e5fa16358c 100644 --- a/providers/common/ciphers/cipher_tdes.c +++ b/providers/common/ciphers/cipher_tdes.c @@ -26,7 +26,7 @@ void *tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits, void tdes_freectx(void *vctx) { - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + PROV_TDES_CTX *ctx = (PROV_TDES_CTX *)vctx; OPENSSL_clear_free(ctx, sizeof(*ctx)); } @@ -39,11 +39,8 @@ static int tdes_init(void *vctx, const unsigned char *key, size_t keylen, ctx->enc = enc; if (iv != NULL) { - if (ivlen != TDES_IVLEN) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + if (!cipher_generic_initiv(ctx, iv, ivlen)) return 0; - } - memcpy(ctx->iv, iv, TDES_IVLEN); } if (key != NULL) { diff --git a/providers/common/include/internal/ciphers/cipher_ccm.h b/providers/common/include/internal/ciphers/cipher_ccm.h index 757c22eb53..2214b5fc64 100644 --- a/providers/common/include/internal/ciphers/cipher_ccm.h +++ b/providers/common/include/internal/ciphers/cipher_ccm.h @@ -121,7 +121,6 @@ OSSL_OP_cipher_update_fn ccm_stream_update; OSSL_OP_cipher_final_fn ccm_stream_final; OSSL_OP_cipher_cipher_fn ccm_cipher; void ccm_initctx(PROV_CCM_CTX *ctx, size_t keybits, const PROV_CCM_HW *hw); -void ccm_finalctx(PROV_CCM_CTX *ctx); int ccm_generic_setiv(PROV_CCM_CTX *ctx, const unsigned char *nonce, size_t nlen, size_t mlen); diff --git a/providers/common/include/internal/ciphers/cipher_gcm.h b/providers/common/include/internal/ciphers/cipher_gcm.h index f4e2894fe2..711b40cdd4 100644 --- a/providers/common/include/internal/ciphers/cipher_gcm.h +++ b/providers/common/include/internal/ciphers/cipher_gcm.h @@ -139,7 +139,6 @@ OSSL_OP_cipher_set_ctx_params_fn gcm_set_ctx_params; OSSL_OP_cipher_cipher_fn gcm_cipher; OSSL_OP_cipher_update_fn gcm_stream_update; OSSL_OP_cipher_final_fn gcm_stream_final; -void gcm_deinitctx(PROV_GCM_CTX *ctx); void gcm_initctx(void *provctx, PROV_GCM_CTX *ctx, size_t keybits, const PROV_GCM_HW *hw, size_t ivlen_min); diff --git a/providers/common/include/internal/ciphers/ciphercommon.h b/providers/common/include/internal/ciphers/ciphercommon.h index e30af4dfbf..21511a163c 100644 --- a/providers/common/include/internal/ciphers/ciphercommon.h +++ b/providers/common/include/internal/ciphers/ciphercommon.h @@ -40,12 +40,13 @@ struct prov_cipher_ctx_st { } stream; unsigned int mode; - size_t keylen; /* key size (in bytes) */ + size_t keylen; /* key size (in bytes) */ size_t ivlen; size_t blocksize; - size_t bufsz; /* Number of bytes in buf */ - unsigned int pad : 1; /* Whether padding should be used or not */ - unsigned int enc : 1; /* Set to 1 for encrypt, or 0 otherwise */ + size_t bufsz; /* Number of bytes in buf */ + unsigned int pad : 1; /* Whether padding should be used or not */ + unsigned int enc : 1; /* Set to 1 for encrypt, or 0 otherwise */ + unsigned int iv_set : 1; /* Set when the iv is copied to the iv/oiv buffers */ /* * num contains the number of bytes of |iv| which are valid for modes that @@ -54,6 +55,8 @@ struct prov_cipher_ctx_st { unsigned int num; uint64_t flags; + /* The original value of the iv */ + unsigned char oiv[GENERIC_BLOCK_SIZE]; /* Buffer of partial blocks processed via update calls */ unsigned char buf[GENERIC_BLOCK_SIZE]; unsigned char iv[GENERIC_BLOCK_SIZE]; @@ -254,6 +257,9 @@ const OSSL_PARAM * name##_settable_ctx_params(void) \ return name##_known_settable_ctx_params; \ } +int cipher_generic_initiv(PROV_CIPHER_CTX *ctx, const unsigned char *iv, + size_t ivlen); + size_t fillblock(unsigned char *buf, size_t *buflen, size_t blocksize, const unsigned char **in, size_t *inlen); int trailingdata(unsigned char *buf, size_t *buflen, size_t blocksize, diff --git a/providers/default/ciphers/cipher_aes_ocb.c b/providers/default/ciphers/cipher_aes_ocb.c index 93df4a5dbc..95c0658fee 100644 --- a/providers/default/ciphers/cipher_aes_ocb.c +++ b/providers/default/ciphers/cipher_aes_ocb.c @@ -107,7 +107,8 @@ static int aes_ocb_init(void *vctx, const unsigned char *key, size_t keylen, } ctx->base.ivlen = ivlen; } - memcpy(ctx->base.iv, iv, ivlen); + if (!cipher_generic_initiv(&ctx->base, iv, ivlen)) + return 0; ctx->iv_state = IV_STATE_BUFFERED; } if (key != NULL) { @@ -287,7 +288,6 @@ static void aes_ocb_freectx(void *vctx) if (ctx != NULL) { aes_generic_ocb_cleanup(ctx); - OPENSSL_cleanse(ctx->base.iv, sizeof(ctx->base.iv)); OPENSSL_clear_free(ctx, sizeof(*ctx)); } } @@ -388,7 +388,7 @@ static int aes_ocb_get_ctx_params(void *vctx, OSSL_PARAM params[]) ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IV_LENGTH); return 0; } - if (!OSSL_PARAM_set_octet_string(p, ctx->base.iv, ctx->base.ivlen)) { + if (!OSSL_PARAM_set_octet_string(p, ctx->base.oiv, ctx->base.ivlen)) { ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); return 0; } diff --git a/providers/default/ciphers/cipher_aria_ccm.c b/providers/default/ciphers/cipher_aria_ccm.c index 53b3defa9d..97e8137db8 100644 --- a/providers/default/ciphers/cipher_aria_ccm.c +++ b/providers/default/ciphers/cipher_aria_ccm.c @@ -27,7 +27,6 @@ static void aria_ccm_freectx(void *vctx) { PROV_ARIA_CCM_CTX *ctx = (PROV_ARIA_CCM_CTX *)vctx; - ccm_finalctx((PROV_CCM_CTX *)ctx); OPENSSL_clear_free(ctx, sizeof(*ctx)); } diff --git a/providers/default/ciphers/cipher_aria_gcm.c b/providers/default/ciphers/cipher_aria_gcm.c index 213fc147c8..7c9fa3d211 100644 --- a/providers/default/ciphers/cipher_aria_gcm.c +++ b/providers/default/ciphers/cipher_aria_gcm.c @@ -26,7 +26,6 @@ static void aria_gcm_freectx(void *vctx) { PROV_ARIA_GCM_CTX *ctx = (PROV_ARIA_GCM_CTX *)vctx; - gcm_deinitctx((PROV_GCM_CTX *)ctx); OPENSSL_clear_free(ctx, sizeof(*ctx)); } diff --git a/providers/default/ciphers/cipher_des.c b/providers/default/ciphers/cipher_des.c index c4eb10be15..4530114187 100644 --- a/providers/default/ciphers/cipher_des.c +++ b/providers/default/ciphers/cipher_des.c @@ -36,7 +36,7 @@ static void *des_newctx(void *provctx, size_t kbits, size_t blkbits, static void des_freectx(void *vctx) { - PROV_CIPHER_CTX *ctx = (PROV_CIPHER_CTX *)vctx; + PROV_DES_CTX *ctx = (PROV_DES_CTX *)vctx; OPENSSL_clear_free(ctx, sizeof(*ctx)); } @@ -49,11 +49,8 @@ static int des_init(void *vctx, const unsigned char *key, size_t keylen, ctx->enc = enc; if (iv != NULL) { - if (ivlen != ctx->ivlen) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_IVLEN); + if (!cipher_generic_initiv(ctx, iv, ivlen)) return 0; - } - memcpy(ctx->iv, iv, ivlen); } if (key != NULL) { -- 2.34.1