From f3f3318a25e62f471a69e1e8dd117bf30191da20 Mon Sep 17 00:00:00 2001 From: Andreas Kretschmer Date: Thu, 5 Sep 2019 13:21:03 +0200 Subject: [PATCH] fix CRMF symmetric key handling Reviewed-by: Bernd Edlinger Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/9774) --- crypto/crmf/crmf_lib.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/crypto/crmf/crmf_lib.c b/crypto/crmf/crmf_lib.c index e519c50677..2974341446 100644 --- a/crypto/crmf/crmf_lib.c +++ b/crypto/crmf/crmf_lib.c @@ -29,6 +29,7 @@ #include #include "crmf_int.h" +#include "internal/constant_time_locl.h" /* explicit #includes not strictly needed since implied by the above: */ #include @@ -654,7 +655,9 @@ X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert, X509 *cert = NULL; /* decrypted certificate */ EVP_CIPHER_CTX *evp_ctx = NULL; /* context for symmetric encryption */ unsigned char *ek = NULL; /* decrypted symmetric encryption key */ + size_t eksize = 0; /* size of decrypted symmetric encryption key */ const EVP_CIPHER *cipher = NULL; /* used cipher */ + int cikeysize = 0; /* key size from cipher */ unsigned char *iv = NULL; /* initial vector for symmetric encryption */ unsigned char *outbuf = NULL; /* decryption output buffer */ const unsigned char *p = NULL; /* needed for decoding ASN1 */ @@ -673,18 +676,31 @@ X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert, CRMF_R_UNSUPPORTED_CIPHER); return NULL; } - + /* select symmetric cipher based on algorithm given in message */ + if ((cipher = EVP_get_cipherbynid(symmAlg)) == NULL) { + CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT, + CRMF_R_UNSUPPORTED_CIPHER); + goto end; + } + cikeysize = EVP_CIPHER_key_length(cipher); /* first the symmetric key needs to be decrypted */ pkctx = EVP_PKEY_CTX_new(pkey, NULL); if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx)) { ASN1_BIT_STRING *encKey = ecert->encSymmKey; - size_t eksize = 0; + size_t failure; + int retval; - if (EVP_PKEY_decrypt(pkctx, NULL, &eksize, encKey->data, encKey->length) - <= 0 - || (ek = OPENSSL_malloc(eksize)) == NULL - || EVP_PKEY_decrypt(pkctx, ek, &eksize, encKey->data, - encKey->length) <= 0) { + if (EVP_PKEY_decrypt(pkctx, NULL, &eksize, + encKey->data, encKey->length) <= 0 + || (ek = OPENSSL_malloc(eksize)) == NULL) + goto oom; + retval = EVP_PKEY_decrypt(pkctx, ek, &eksize, + encKey->data, encKey->length); + ERR_clear_error(); /* error state may have sensitive information */ + failure = ~constant_time_is_zero_s(constant_time_msb(retval) + | constant_time_is_zero(retval)); + failure |= ~constant_time_eq_s(eksize, (size_t)cikeysize); + if (failure) { CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY); goto end; @@ -692,13 +708,6 @@ X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert, } else { goto oom; } - - /* select symmetric cipher based on algorithm given in message */ - if ((cipher = EVP_get_cipherbynid(symmAlg)) == NULL) { - CRMFerr(CRMF_F_OSSL_CRMF_ENCRYPTEDVALUE_GET1_ENCCERT, - CRMF_R_UNSUPPORTED_CIPHER); - goto end; - } if ((iv = OPENSSL_malloc(EVP_CIPHER_iv_length(cipher))) == NULL) goto oom; if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv, @@ -743,7 +752,7 @@ X509 *OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert(OSSL_CRMF_ENCRYPTEDVALUE *ecert, EVP_PKEY_CTX_free(pkctx); OPENSSL_free(outbuf); EVP_CIPHER_CTX_free(evp_ctx); - OPENSSL_free(ek); + OPENSSL_clear_free(ek, eksize); OPENSSL_free(iv); return cert; } -- 2.25.1