CMS, PKCS7, and CRMF: simplify use of EVP_PKEY_decrypt() by helper function
authorDr. David von Oheimb <David.von.Oheimb@siemens.com>
Sat, 25 Dec 2021 12:38:23 +0000 (13:38 +0100)
committerDr. David von Oheimb <dev@ddvo.net>
Tue, 30 May 2023 20:02:10 +0000 (22:02 +0200)
Also remove needless constant_time_* and ERR_clear_error() calls
from OSSL_CRMF_ENCRYPTEDVALUE_get1_encCert().

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com>
(Merged from https://github.com/openssl/openssl/pull/17354)

crypto/cms/cms_env.c
crypto/crmf/crmf_lib.c
crypto/evp/asymcipher.c
crypto/pkcs7/pk7_doit.c
include/crypto/evp.h

index c55511011f6aefc708b32b84de0a768511fcc803..2b06da468e2de952e5d00ce6e0ef66b5206aefaa 100644 (file)
@@ -615,24 +615,11 @@ static int cms_RecipientInfo_ktri_decrypt(CMS_ContentInfo *cms,
          * disable implicit rejection for RSA keys */
         EVP_PKEY_CTX_ctrl_str(ktri->pctx, "rsa_pkcs1_implicit_rejection", "0");
 
-    if (EVP_PKEY_decrypt(ktri->pctx, NULL, &eklen,
-                         ktri->encryptedKey->data,
-                         ktri->encryptedKey->length) <= 0)
+    if (evp_pkey_decrypt_alloc(ktri->pctx, &ek, &eklen, fixlen,
+                               ktri->encryptedKey->data,
+                               ktri->encryptedKey->length) <= 0)
         goto err;
 
-    ek = OPENSSL_malloc(eklen);
-    if (ek == NULL)
-        goto err;
-
-    if (EVP_PKEY_decrypt(ktri->pctx, ek, &eklen,
-                         ktri->encryptedKey->data,
-                         ktri->encryptedKey->length) <= 0
-            || eklen == 0
-            || (fixlen != 0 && eklen != fixlen)) {
-        ERR_raise(ERR_LIB_CMS, CMS_R_CMS_LIB);
-        goto err;
-    }
-
     ret = 1;
 
     OPENSSL_clear_free(ec->key, ec->keylen);
index 6fc7c9109560d39831608f6a4bca8aff6eed0254..12939b9920c8320956e4446e183e4d34a8884c9d 100644 (file)
@@ -29,8 +29,8 @@
 #include <openssl/asn1t.h>
 
 #include "crmf_local.h"
-#include "internal/constant_time.h"
 #include "internal/sizes.h"
+#include "crypto/evp.h"
 #include "crypto/x509.h"
 
 /* explicit #includes not strictly needed since implied by the above: */
@@ -661,28 +661,12 @@ X509
     cikeysize = EVP_CIPHER_get_key_length(cipher);
     /* first the symmetric key needs to be decrypted */
     pkctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, propq);
-    if (pkctx != NULL && EVP_PKEY_decrypt_init(pkctx) > 0) {
-        ASN1_BIT_STRING *encKey = ecert->encSymmKey;
-        size_t failure;
-        int retval;
-
-        if (EVP_PKEY_decrypt(pkctx, NULL, &eksize,
-                             encKey->data, encKey->length) <= 0
-                || (ek = OPENSSL_malloc(eksize)) == NULL)
-            goto end;
-        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) {
-            ERR_raise(ERR_LIB_CRMF, CRMF_R_ERROR_DECRYPTING_SYMMETRIC_KEY);
-            goto end;
-        }
-    } else {
+    if (pkctx == NULL || EVP_PKEY_decrypt_init(pkctx) <= 0
+        || evp_pkey_decrypt_alloc(pkctx, &ek, &eksize, (size_t)cikeysize,
+                                  ecert->encSymmKey->data,
+                                  ecert->encSymmKey->length) <= 0)
         goto end;
-    }
+
     if ((iv = OPENSSL_malloc(EVP_CIPHER_get_iv_length(cipher))) == NULL)
         goto end;
     if (ASN1_TYPE_get_octetstring(ecert->symmAlg->parameter, iv,
index 3acf4d1dfdbcd34d12c3ed3bf8de5addcafc3e43..ca2a8ebdf27e551ad64e36e62a47622d5af9bab8 100644 (file)
@@ -298,6 +298,24 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
         return ctx->pmeth->decrypt(ctx, out, outlen, in, inlen);
 }
 
+/* decrypt to new buffer of dynamic size, checking any pre-determined size */
+int evp_pkey_decrypt_alloc(EVP_PKEY_CTX *ctx, unsigned char **outp,
+                           size_t *outlenp, size_t expected_outlen,
+                           const unsigned char *in, size_t inlen)
+{
+    if (EVP_PKEY_decrypt(ctx, NULL, outlenp, in, inlen) <= 0
+            || (*outp = OPENSSL_malloc(*outlenp)) == NULL)
+        return -1;
+    if (EVP_PKEY_decrypt(ctx, *outp, outlenp, in, inlen) <= 0
+            || *outlenp == 0
+            || (expected_outlen != 0 && *outlenp != expected_outlen)) {
+        ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
+        OPENSSL_clear_free(*outp, *outlenp);
+        *outp = NULL;
+        return 0;
+    }
+    return 1;
+}
 
 static EVP_ASYM_CIPHER *evp_asym_cipher_new(OSSL_PROVIDER *prov)
 {
index e39821a205df84fad25f5c722afc8590f059387f..d3f65adb66d6aac0f1c2e6e0680e8f6bea038e1e 100644 (file)
@@ -15,6 +15,7 @@
 #include <openssl/err.h>
 #include "internal/cryptlib.h"
 #include "internal/sizes.h"
+#include "crypto/evp.h"
 #include "pk7_local.h"
 
 static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
@@ -174,23 +175,11 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
          * disable implicit rejection for RSA keys */
         EVP_PKEY_CTX_ctrl_str(pctx, "rsa_pkcs1_implicit_rejection", "0");
 
-    if (EVP_PKEY_decrypt(pctx, NULL, &eklen,
-                         ri->enc_key->data, ri->enc_key->length) <= 0)
+    ret = evp_pkey_decrypt_alloc(pctx, &ek, &eklen, fixlen,
+                                 ri->enc_key->data, ri->enc_key->length);
+    if (ret <= 0)
         goto err;
 
-    ek = OPENSSL_malloc(eklen);
-    if (ek == NULL)
-        goto err;
-
-    if (EVP_PKEY_decrypt(pctx, ek, &eklen,
-                         ri->enc_key->data, ri->enc_key->length) <= 0
-            || eklen == 0
-            || (fixlen != 0 && eklen != fixlen)) {
-        ret = 0;
-        ERR_raise(ERR_LIB_PKCS7, ERR_R_EVP_LIB);
-        goto err;
-    }
-
     ret = 1;
 
     OPENSSL_clear_free(*pek, *peklen);
index 4f7f0c6eeaa8fdc114cfce8241976f74960d7c74..4e9cf7bb6da4db6dcd9ce7fa84d75e62f9c4cdb0 100644 (file)
@@ -952,4 +952,8 @@ int evp_md_get_number(const EVP_MD *md);
 int evp_rand_get_number(const EVP_RAND *rand);
 int evp_signature_get_number(const EVP_SIGNATURE *signature);
 
+int evp_pkey_decrypt_alloc(EVP_PKEY_CTX *ctx, unsigned char **outp,
+                           size_t *outlenp, size_t expected_outlen,
+                           const unsigned char *in, size_t inlen);
+
 #endif /* OSSL_CRYPTO_EVP_H */