PKCS#7: Fix NULL dereference with missing EncryptedContent.
[openssl.git] / crypto / pkcs7 / pk7_doit.c
index f77326b883d5d4423c857cd203542f24d8a3b79f..cc2f3be5543e3d5395efae6bb28115beb3061e72 100644 (file)
@@ -57,7 +57,7 @@
  */
 
 #include <stdio.h>
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include <openssl/rand.h>
 #include <openssl/objects.h>
 #include <openssl/x509.h>
@@ -128,8 +128,7 @@ static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg)
     return 1;
 
  err:
-    if (btmp)
-        BIO_free(btmp);
+    BIO_free(btmp);
     return 0;
 
 }
@@ -180,12 +179,9 @@ static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri,
     ret = 1;
 
  err:
-    if (pkey)
-        EVP_PKEY_free(pkey);
-    if (pctx)
-        EVP_PKEY_CTX_free(pctx);
-    if (ek)
-        OPENSSL_free(ek);
+    EVP_PKEY_free(pkey);
+    EVP_PKEY_CTX_free(pctx);
+    OPENSSL_free(ek);
     return ret;
 
 }
@@ -232,18 +228,13 @@ static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen,
 
     ret = 1;
 
-    if (*pek) {
-        OPENSSL_cleanse(*pek, *peklen);
-        OPENSSL_free(*pek);
-    }
-
+    OPENSSL_clear_free(*pek, *peklen);
     *pek = ek;
     *peklen = eklen;
 
  err:
-    if (pctx)
-        EVP_PKEY_CTX_free(pctx);
-    if (!ret && ek)
+    EVP_PKEY_CTX_free(pctx);
+    if (!ret)
         OPENSSL_free(ek);
 
     return ret;
@@ -390,16 +381,12 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
         BIO_push(out, bio);
     else
         out = bio;
-    bio = NULL;
-    if (0) {
+    return out;
+
  err:
-        if (out != NULL)
-            BIO_free_all(out);
-        if (btmp != NULL)
-            BIO_free_all(btmp);
-        out = NULL;
-    }
-    return (out);
+    BIO_free_all(out);
+    BIO_free_all(btmp);
+    return NULL;
 }
 
 static int pkcs7_cmp_ri(PKCS7_RECIP_INFO *ri, X509 *pcert)
@@ -445,6 +432,12 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
 
     switch (i) {
     case NID_pkcs7_signed:
+        /*
+         * p7->d.sign->contents is a PKCS7 structure consisting of a contentType
+         * field and optional content.
+         * data_body is NULL if that structure has no (=detached) content
+         * or if the contentType is wrong (i.e., not "data").
+         */
         data_body = PKCS7_get_octet_string(p7->d.sign->contents);
         if (!PKCS7_is_detached(p7) && data_body == NULL) {
             PKCS7err(PKCS7_F_PKCS7_DATADECODE,
@@ -456,6 +449,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
     case NID_pkcs7_signedAndEnveloped:
         rsk = p7->d.signed_and_enveloped->recipientinfo;
         md_sk = p7->d.signed_and_enveloped->md_algs;
+        /* data_body is NULL if the optional EncryptedContent is missing. */
         data_body = p7->d.signed_and_enveloped->enc_data->enc_data;
         enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm;
         evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
@@ -468,6 +462,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
     case NID_pkcs7_enveloped:
         rsk = p7->d.enveloped->recipientinfo;
         enc_alg = p7->d.enveloped->enc_data->algorithm;
+        /* data_body is NULL if the optional EncryptedContent is missing. */
         data_body = p7->d.enveloped->enc_data->enc_data;
         evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm);
         if (evp_cipher == NULL) {
@@ -481,6 +476,12 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
         goto err;
     }
 
+    /* Detached content must be supplied via in_bio instead. */
+    if (data_body == NULL && in_bio == NULL) {
+        PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT);
+        goto err;
+    }
+
     /* We will be checking the signature */
     if (md_sk != NULL) {
         for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) {
@@ -584,8 +585,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
              */
             if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) {
                 /* Use random key as MMA defence */
-                OPENSSL_cleanse(ek, eklen);
-                OPENSSL_free(ek);
+                OPENSSL_clear_free(ek, eklen);
                 ek = tkey;
                 eklen = tkeylen;
                 tkey = NULL;
@@ -596,16 +596,10 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
         if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0)
             goto err;
 
-        if (ek) {
-            OPENSSL_cleanse(ek, eklen);
-            OPENSSL_free(ek);
-            ek = NULL;
-        }
-        if (tkey) {
-            OPENSSL_cleanse(tkey, tkeylen);
-            OPENSSL_free(tkey);
-            tkey = NULL;
-        }
+        OPENSSL_clear_free(ek, eklen);
+        ek = NULL;
+        OPENSSL_clear_free(tkey, tkeylen);
+        tkey = NULL;
 
         if (out == NULL)
             out = etmp;
@@ -613,7 +607,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
             BIO_push(out, etmp);
         etmp = NULL;
     }
-    if (PKCS7_is_detached(p7) || (in_bio != NULL)) {
+    if (in_bio != NULL) {
         bio = in_bio;
     } else {
         if (data_body->length > 0)
@@ -627,27 +621,16 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
     }
     BIO_push(out, bio);
     bio = NULL;
-    if (0) {
+    return out;
+
  err:
-        if (ek) {
-            OPENSSL_cleanse(ek, eklen);
-            OPENSSL_free(ek);
-        }
-        if (tkey) {
-            OPENSSL_cleanse(tkey, tkeylen);
-            OPENSSL_free(tkey);
-        }
-        if (out != NULL)
-            BIO_free_all(out);
-        if (btmp != NULL)
-            BIO_free_all(btmp);
-        if (etmp != NULL)
-            BIO_free_all(etmp);
-        if (bio != NULL)
-            BIO_free_all(bio);
-        out = NULL;
-    }
-    return (out);
+    OPENSSL_clear_free(ek, eklen);
+    OPENSSL_clear_free(tkey, tkeylen);
+    BIO_free_all(out);
+    BIO_free_all(btmp);
+    BIO_free_all(etmp);
+    BIO_free_all(bio);
+    return  NULL;
 }
 
 static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid)
@@ -920,8 +903,7 @@ int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si)
     return 1;
 
  err:
-    if (abuf)
-        OPENSSL_free(abuf);
+    OPENSSL_free(abuf);
     EVP_MD_CTX_cleanup(&mctx);
     return 0;
 
@@ -1086,8 +1068,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
         PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE);
         ret = -1;
         goto err;
-    } else
-        ret = 1;
+    }
+    ret = 1;
  err:
     EVP_MD_CTX_cleanup(&mdc_tmp);
     return (ret);
@@ -1136,7 +1118,7 @@ static ASN1_TYPE *get_attribute(STACK_OF(X509_ATTRIBUTE) *sk, int nid)
 ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK_OF(X509_ATTRIBUTE) *sk)
 {
     ASN1_TYPE *astype;
-    if (!(astype = get_attribute(sk, NID_pkcs9_messageDigest)))
+    if ((astype = get_attribute(sk, NID_pkcs9_messageDigest)) == NULL)
         return NULL;
     return astype->value.octet_string;
 }
@@ -1146,8 +1128,7 @@ int PKCS7_set_signed_attributes(PKCS7_SIGNER_INFO *p7si,
 {
     int i;
 
-    if (p7si->auth_attr != NULL)
-        sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free);
+    sk_X509_ATTRIBUTE_pop_free(p7si->auth_attr, X509_ATTRIBUTE_free);
     p7si->auth_attr = sk_X509_ATTRIBUTE_dup(sk);
     if (p7si->auth_attr == NULL)
         return 0;
@@ -1166,8 +1147,7 @@ int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,
 {
     int i;
 
-    if (p7si->unauth_attr != NULL)
-        sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free);
+    sk_X509_ATTRIBUTE_pop_free(p7si->unauth_attr, X509_ATTRIBUTE_free);
     p7si->unauth_attr = sk_X509_ATTRIBUTE_dup(sk);
     if (p7si->unauth_attr == NULL)
         return 0;
@@ -1199,11 +1179,10 @@ static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype,
     X509_ATTRIBUTE *attr = NULL;
 
     if (*sk == NULL) {
-        *sk = sk_X509_ATTRIBUTE_new_null();
-        if (*sk == NULL)
+        if ((*sk = sk_X509_ATTRIBUTE_new_null()) == NULL)
             return 0;
  new_attrib:
-        if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value)))
+        if ((attr = X509_ATTRIBUTE_create(nid, atrtype, value)) == NULL)
             return 0;
         if (!sk_X509_ATTRIBUTE_push(*sk, attr)) {
             X509_ATTRIBUTE_free(attr);