Add NULL check in i2d_PrivateKey()
[openssl.git] / crypto / pkcs7 / pk7_smime.c
index e659af824badff957f385b119f5a8fe6710aa245..7c2d5c9895cd4e0628c8bf48bc1bb0901e178c28 100644 (file)
@@ -1,4 +1,3 @@
-/* pk7_smime.c */
 /*
  * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
  * project.
 /* Simple PKCS#7 processing functions */
 
 #include <stdio.h>
-#include "cryptlib.h"
+#include "internal/cryptlib.h"
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
+
+#define BUFFERSIZE 4096
+
 static int pkcs7_copy_existing_digest(PKCS7 *p7, PKCS7_SIGNER_INFO *si);
 
 PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
@@ -72,7 +74,7 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
     PKCS7 *p7;
     int i;
 
-    if (!(p7 = PKCS7_new())) {
+    if ((p7 = PKCS7_new()) == NULL) {
         PKCS7err(PKCS7_F_PKCS7_SIGN, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
@@ -113,7 +115,8 @@ int PKCS7_final(PKCS7 *p7, BIO *data, int flags)
 {
     BIO *p7bio;
     int ret = 0;
-    if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
+
+    if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) {
         PKCS7err(PKCS7_F_PKCS7_FINAL, ERR_R_MALLOC_FAILURE);
         return 0;
     }
@@ -164,7 +167,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
         return NULL;
     }
 
-    if (!(si = PKCS7_add_signature(p7, signcert, pkey, md))) {
+    if ((si = PKCS7_add_signature(p7, signcert, pkey, md)) == NULL) {
         PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER,
                  PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
         return NULL;
@@ -180,11 +183,13 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
             goto err;
         /* Add SMIMECapabilities */
         if (!(flags & PKCS7_NOSMIMECAP)) {
-            if (!(smcap = sk_X509_ALGOR_new_null())) {
+            if ((smcap = sk_X509_ALGOR_new_null()) == NULL) {
                 PKCS7err(PKCS7_F_PKCS7_SIGN_ADD_SIGNER, ERR_R_MALLOC_FAILURE);
                 goto err;
             }
             if (!add_cipher_smcap(smcap, NID_aes_256_cbc, -1)
+                || !add_digest_smcap(smcap, NID_id_GostR3411_2012_256, -1)
+                || !add_digest_smcap(smcap, NID_id_GostR3411_2012_512, -1)
                 || !add_digest_smcap(smcap, NID_id_GostR3411_94, -1)
                 || !add_cipher_smcap(smcap, NID_id_Gost28147_89, -1)
                 || !add_cipher_smcap(smcap, NID_aes_192_cbc, -1)
@@ -208,8 +213,7 @@ PKCS7_SIGNER_INFO *PKCS7_sign_add_signer(PKCS7 *p7, X509 *signcert,
     }
     return si;
  err:
-    if (smcap)
-        sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
+    sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free);
     return NULL;
 }
 
@@ -253,11 +257,11 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
     X509 *signer;
     STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
     PKCS7_SIGNER_INFO *si;
-    X509_STORE_CTX cert_ctx;
-    char buf[4096];
+    X509_STORE_CTX *cert_ctx = NULL;
+    char *buf = NULL;
     int i, j = 0, k, ret = 0;
-    BIO *p7bio;
-    BIO *tmpin, *tmpout;
+    BIO *p7bio = NULL;
+    BIO *tmpin = NULL, *tmpout = NULL;
 
     if (!p7) {
         PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_INVALID_NULL_POINTER);
@@ -275,18 +279,19 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
         return 0;
     }
 
-    /*
-     * Very old Netscape illegally included empty content with
-     * a detached signature. To not support that, enable the
-     * following flag.
-     */
-#ifdef OPENSSL_DONT_SUPPORT_OLD_NETSCAPE
-    /* Check for data and content: two sets of data */
-    if (!PKCS7_get_detached(p7) && indata) {
-        PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_CONTENT_AND_DATA_PRESENT);
-        return 0;
+    if (flags & PKCS7_NO_DUAL_CONTENT) {
+        /*
+         * This was originally "#if 0" because we thought that only old broken
+         * Netscape did this.  It turns out that Authenticode uses this kind
+         * of "extended" PKCS7 format, and things like UEFI secure boot and
+         * tools like osslsigncode need it.  In Authenticode the verification
+         * process is different, but the existing PKCs7 verification works.
+         */
+        if (!PKCS7_get_detached(p7) && indata) {
+            PKCS7err(PKCS7_F_PKCS7_VERIFY, PKCS7_R_CONTENT_AND_DATA_PRESENT);
+            return 0;
+        }
     }
-#endif
 
     sinfos = PKCS7_get_signer_info(p7);
 
@@ -296,41 +301,40 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
     }
 
     signers = PKCS7_get0_signers(p7, certs, flags);
-
     if (!signers)
         return 0;
 
     /* Now verify the certificates */
 
+    cert_ctx = X509_STORE_CTX_new();
+    if (cert_ctx == NULL)
+        goto err;
     if (!(flags & PKCS7_NOVERIFY))
         for (k = 0; k < sk_X509_num(signers); k++) {
             signer = sk_X509_value(signers, k);
             if (!(flags & PKCS7_NOCHAIN)) {
-                if (!X509_STORE_CTX_init(&cert_ctx, store, signer,
+                if (!X509_STORE_CTX_init(cert_ctx, store, signer,
                                          p7->d.sign->cert)) {
                     PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
-                    sk_X509_free(signers);
-                    return 0;
+                    goto err;
                 }
-                X509_STORE_CTX_set_default(&cert_ctx, "smime_sign");
-            } else if (!X509_STORE_CTX_init(&cert_ctx, store, signer, NULL)) {
+                X509_STORE_CTX_set_default(cert_ctx, "smime_sign");
+            } else if (!X509_STORE_CTX_init(cert_ctx, store, signer, NULL)) {
                 PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_X509_LIB);
-                sk_X509_free(signers);
-                return 0;
+                goto err;
             }
             if (!(flags & PKCS7_NOCRL))
-                X509_STORE_CTX_set0_crls(&cert_ctx, p7->d.sign->crl);
-            i = X509_verify_cert(&cert_ctx);
+                X509_STORE_CTX_set0_crls(cert_ctx, p7->d.sign->crl);
+            i = X509_verify_cert(cert_ctx);
             if (i <= 0)
-                j = X509_STORE_CTX_get_error(&cert_ctx);
-            X509_STORE_CTX_cleanup(&cert_ctx);
+                j = X509_STORE_CTX_get_error(cert_ctx);
+            X509_STORE_CTX_cleanup(cert_ctx);
             if (i <= 0) {
                 PKCS7err(PKCS7_F_PKCS7_VERIFY,
                          PKCS7_R_CERTIFICATE_VERIFY_ERROR);
                 ERR_add_error_data(2, "Verify error:",
                                    X509_verify_cert_error_string(j));
-                sk_X509_free(signers);
-                return 0;
+                goto err;
             }
             /* Check for revocation status here */
         }
@@ -349,16 +353,16 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
         tmpin = BIO_new_mem_buf(ptr, len);
         if (tmpin == NULL) {
             PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
-            return 0;
+            goto err;
         }
     } else
         tmpin = indata;
 
-    if (!(p7bio = PKCS7_dataInit(p7, tmpin)))
+    if ((p7bio = PKCS7_dataInit(p7, tmpin)) == NULL)
         goto err;
 
     if (flags & PKCS7_TEXT) {
-        if (!(tmpout = BIO_new(BIO_s_mem()))) {
+        if ((tmpout = BIO_new(BIO_s_mem())) == NULL) {
             PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
             goto err;
         }
@@ -367,8 +371,12 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
         tmpout = out;
 
     /* We now have to 'read' from p7bio to calculate digests etc. */
+    if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) {
+        PKCS7err(PKCS7_F_PKCS7_VERIFY, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
     for (;;) {
-        i = BIO_read(p7bio, buf, sizeof(buf));
+        i = BIO_read(p7bio, buf, BUFFERSIZE);
         if (i <= 0)
             break;
         if (tmpout)
@@ -399,15 +407,14 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
     ret = 1;
 
  err:
-
+    X509_STORE_CTX_free(cert_ctx);
+    OPENSSL_free(buf);
     if (tmpin == indata) {
         if (indata)
             BIO_pop(p7bio);
     }
     BIO_free_all(p7bio);
-
     sk_X509_free(signers);
-
     return ret;
 }
 
@@ -440,7 +447,7 @@ STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs,
         return 0;
     }
 
-    if (!(signers = sk_X509_new_null())) {
+    if ((signers = sk_X509_new_null()) == NULL) {
         PKCS7err(PKCS7_F_PKCS7_GET0_SIGNERS, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
@@ -482,7 +489,7 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
     BIO *p7bio = NULL;
     int i;
     X509 *x509;
-    if (!(p7 = PKCS7_new())) {
+    if ((p7 = PKCS7_new()) == NULL) {
         PKCS7err(PKCS7_F_PKCS7_ENCRYPT, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
@@ -519,8 +526,8 @@ PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, const EVP_CIPHER *cipher,
 int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
 {
     BIO *tmpmem;
-    int ret, i;
-    char buf[4096];
+    int ret = 0, i;
+    char *buf = NULL;
 
     if (!p7) {
         PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_INVALID_NULL_POINTER);
@@ -538,7 +545,7 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
         return 0;
     }
 
-    if (!(tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert))) {
+    if ((tmpmem = PKCS7_dataDecode(p7, pkey, NULL, cert)) == NULL) {
         PKCS7err(PKCS7_F_PKCS7_DECRYPT, PKCS7_R_DECRYPT_ERROR);
         return 0;
     }
@@ -546,12 +553,12 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
     if (flags & PKCS7_TEXT) {
         BIO *tmpbuf, *bread;
         /* Encrypt BIOs can't do BIO_gets() so add a buffer BIO */
-        if (!(tmpbuf = BIO_new(BIO_f_buffer()))) {
+        if ((tmpbuf = BIO_new(BIO_f_buffer())) == NULL) {
             PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
             BIO_free_all(tmpmem);
             return 0;
         }
-        if (!(bread = BIO_push(tmpbuf, tmpmem))) {
+        if ((bread = BIO_push(tmpbuf, tmpmem)) == NULL) {
             PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
             BIO_free_all(tmpbuf);
             BIO_free_all(tmpmem);
@@ -564,24 +571,28 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
         }
         BIO_free_all(bread);
         return ret;
-    } else {
-        for (;;) {
-            i = BIO_read(tmpmem, buf, sizeof(buf));
-            if (i <= 0) {
-                ret = 1;
-                if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
-                    if (!BIO_get_cipher_status(tmpmem))
-                        ret = 0;
-                }
-
-                break;
-            }
-            if (BIO_write(data, buf, i) != i) {
-                ret = 0;
-                break;
+    }
+    if ((buf = OPENSSL_malloc(BUFFERSIZE)) == NULL) {
+        PKCS7err(PKCS7_F_PKCS7_DECRYPT, ERR_R_MALLOC_FAILURE);
+        goto err;
+    }
+    for (;;) {
+        i = BIO_read(tmpmem, buf, BUFFERSIZE);
+        if (i <= 0) {
+            ret = 1;
+            if (BIO_method_type(tmpmem) == BIO_TYPE_CIPHER) {
+                if (!BIO_get_cipher_status(tmpmem))
+                    ret = 0;
             }
+
+            break;
+        }
+        if (BIO_write(data, buf, i) != i) {
+            break;
         }
-        BIO_free_all(tmpmem);
-        return ret;
     }
+err:
+    OPENSSL_free(buf);
+    BIO_free_all(tmpmem);
+    return ret;
 }