Various S/MIME fixes.
[openssl.git] / crypto / pkcs7 / pk7_smime.c
index 58bf2d7d288cdd994dba02032fcfa9aeff286ec1..04489380b8f22d0634958ab91ca9fd52f518bcd4 100644 (file)
@@ -115,12 +115,16 @@ PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
                }
 #ifndef NO_DES
                PKCS7_simple_smimecap (smcap, NID_des_ede3_cbc, -1);
-               PKCS7_simple_smimecap (smcap, NID_des_cbc, -1);
 #endif
 #ifndef NO_RC2
-               PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40);
                PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 128);
                PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 64);
+#endif
+#ifndef NO_DES
+               PKCS7_simple_smimecap (smcap, NID_des_cbc, -1);
+#endif
+#ifndef NO_RC2
+               PKCS7_simple_smimecap (smcap, NID_rc2_cbc, 40);
 #endif
                PKCS7_add_attrib_smimecap (si, smcap);
                sk_pop_free(smcap, X509_ALGOR_free);
@@ -144,21 +148,25 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
        X509 *signer;
        STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
        PKCS7_SIGNER_INFO *si;
-       PKCS7_ISSUER_AND_SERIAL *ias;
        X509_STORE_CTX cert_ctx;
        char buf[4096];
        int i, j=0;
        BIO *p7bio;
        BIO *tmpout;
 
-       if(OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
-                               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
+       if(!p7) {
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
+               return 0;
+       }
+
+       if(!PKCS7_type_is_signed(p7)) {
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
                return 0;
        }
 
        /* Check for no data and no content: no data to verify signature */
        if(PKCS7_get_detached(p7) && !indata) {
-                               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
                return 0;
        }
 
@@ -171,39 +179,14 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
        sinfos = PKCS7_get_signer_info(p7);
 
        if(!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
-                               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
-               return 0;
-       }
-
-
-       if(!(signers = sk_X509_new(NULL))) {
-               PKCS7err(PKCS7_F_PKCS7_VERIFY,ERR_R_MALLOC_FAILURE);
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
                return 0;
        }
 
-       /* Collect all the signers together */
-
-       for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
-       {
-           si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
-           ias = si->issuer_and_serial;
-           signer = NULL;
-               /* If any certificates passed they take priority */
-           if (certs) signer = X509_find_by_issuer_and_serial (certs,
-                                               ias->issuer, ias->serial);
-           if (!signer && !(flags & PKCS7_NOINTERN)
-                       && p7->d.sign->cert) signer =
-                             X509_find_by_issuer_and_serial (p7->d.sign->cert,
-                                               ias->issuer, ias->serial);
-           if (!signer) {
-                       PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
-                       sk_X509_free(signers);
-                       return 0;
-           }
 
-           sk_X509_push(signers, signer);
-       }
+       signers = PKCS7_iget_signers(p7, certs, flags);
 
+       if(!signers) return 0;
 
        /* Now verify the certificates */
 
@@ -281,6 +264,62 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
        return 0;
 }
 
+STACK_OF(X509) *PKCS7_iget_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
+{
+       STACK_OF(X509) *signers;
+       STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
+       PKCS7_SIGNER_INFO *si;
+       PKCS7_ISSUER_AND_SERIAL *ias;
+       X509 *signer;
+       int i;
+
+       if(!p7) {
+               PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_INVALID_NULL_POINTER);
+               return NULL;
+       }
+
+       if(!PKCS7_type_is_signed(p7)) {
+               PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
+               return NULL;
+       }
+       if(!(signers = sk_X509_new(NULL))) {
+               PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,ERR_R_MALLOC_FAILURE);
+               return NULL;
+       }
+
+       /* Collect all the signers together */
+
+       sinfos = PKCS7_get_signer_info(p7);
+
+       if(sk_PKCS7_SIGNER_INFO_num(sinfos) <= 0) {
+               PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_NO_SIGNERS);
+               return 0;
+       }
+
+       for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(sinfos); i++)
+       {
+           si = sk_PKCS7_SIGNER_INFO_value(sinfos, i);
+           ias = si->issuer_and_serial;
+           signer = NULL;
+               /* If any certificates passed they take priority */
+           if (certs) signer = X509_find_by_issuer_and_serial (certs,
+                                               ias->issuer, ias->serial);
+           if (!signer && !(flags & PKCS7_NOINTERN)
+                       && p7->d.sign->cert) signer =
+                             X509_find_by_issuer_and_serial (p7->d.sign->cert,
+                                               ias->issuer, ias->serial);
+           if (!signer) {
+                       PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_SIGNER_CERTIFICATE_NOT_FOUND);
+                       sk_X509_free(signers);
+                       return 0;
+           }
+
+           sk_X509_push(signers, signer);
+       }
+       return signers;
+}
+
+
 /* Build a complete PKCS#7 enveloped data */
 
 PKCS7 *PKCS7_encrypt(STACK_OF(X509) *certs, BIO *in, EVP_CIPHER *cipher,
@@ -351,10 +390,17 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
        BIO *tmpmem;
        int ret, i;
        char buf[4096];
+
+       if(!p7) {
+               PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_INVALID_NULL_POINTER);
+               return 0;
+       }
+
        if(!PKCS7_type_is_enveloped(p7)) {
                PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_WRONG_CONTENT_TYPE);
                return 0;
        }
+
        if(!X509_check_private_key(cert, pkey)) {
                PKCS7err(PKCS7_F_PKCS7_DECRYPT,
                                PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);