Retrieve correct content to sign when the
[openssl.git] / crypto / pkcs7 / pk7_doit.c
index 0119272d751c386511754cafaa41fc0f17c1d82d..e7bc3b2bf1c876f51098eceb386e5be3d09f50b9 100644 (file)
@@ -91,12 +91,14 @@ static int PKCS7_type_is_other(PKCS7* p7)
 
        }
 
-static int PKCS7_type_is_octet_string(PKCS7* p7)
+static ASN1_OCTET_STRING *PKCS7_get_octet_string(PKCS7 *p7)
        {
-       if ( 0==PKCS7_type_is_other(p7) )
-               return 0;
-
-       return (V_ASN1_OCTET_STRING==p7->d.other->type) ? 1 : 0;
+       if ( PKCS7_type_is_data(p7))
+               return p7->d.data;
+       if ( PKCS7_type_is_other(p7) && p7->d.other
+               && (p7->d.other->type == V_ASN1_OCTET_STRING))
+               return p7->d.other->value.octet_string;
+       return NULL;
        }
 
 BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
@@ -241,7 +243,7 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
                        M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj);
                        }
                OPENSSL_free(tmp);
-               memset(key, 0, keylen);
+               OPENSSL_cleanse(key, keylen);
 
                if (out == NULL)
                        out=btmp;
@@ -250,29 +252,22 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
                btmp=NULL;
                }
 
-       if (bio == NULL) {
+       if (bio == NULL)
+               {
                if (PKCS7_is_detached(p7))
                        bio=BIO_new(BIO_s_null());
-               else {
-                       if (PKCS7_type_is_signed(p7) ) { 
-                               if ( PKCS7_type_is_data(p7->d.sign->contents)) {
-                                       ASN1_OCTET_STRING *os;
-                                       os=p7->d.sign->contents->d.data;
-                                       if (os->length > 0)
-                                               bio = BIO_new_mem_buf(os->data, os->length);
-                               }
-                               else if ( PKCS7_type_is_octet_string(p7->d.sign->contents) ) {
-                                       ASN1_OCTET_STRING *os;
-                                       os=p7->d.sign->contents->d.other->value.octet_string;
-                                       if (os->length > 0)
-                                               bio = BIO_new_mem_buf(os->data, os->length);
-                               }
-                       }
-                       if(bio == NULL) {
+               else
+                       {
+                       ASN1_OCTET_STRING *os;
+                       os = PKCS7_get_octet_string(p7->d.sign->contents);
+                       if (os && os->length > 0)
+                               bio = BIO_new_mem_buf(os->data, os->length);
+                       if(bio == NULL)
+                               {
                                bio=BIO_new(BIO_s_mem());
                                BIO_set_mem_eof_return(bio,0);
+                               }
                        }
-               }
        }
        BIO_push(out,bio);
        bio=NULL;
@@ -311,7 +306,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
        switch (i)
                {
        case NID_pkcs7_signed:
-               data_body=p7->d.sign->contents->d.data;
+               data_body=PKCS7_get_octet_string(p7->d.sign->contents);
                md_sk=p7->d.sign->md_algs;
                break;
        case NID_pkcs7_signedAndEnveloped:
@@ -448,7 +443,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert)
                } 
                EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0);
 
-               memset(tmp,0,jj);
+               OPENSSL_cleanse(tmp,jj);
 
                if (out == NULL)
                        out=etmp;
@@ -512,6 +507,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
        STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
        ASN1_OCTET_STRING *os=NULL;
 
+       EVP_MD_CTX_init(&ctx_tmp);
        i=OBJ_obj2nid(p7->type);
        p7->state=PKCS7_S_HEADER;
 
@@ -530,9 +526,9 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
                break;
        case NID_pkcs7_signed:
                si_sk=p7->d.sign->signer_info;
-               os=p7->d.sign->contents->d.data;
+               os=PKCS7_get_octet_string(p7->d.sign->contents);
                /* If detached data then the content is excluded */
-               if(p7->detached) {
+               if(PKCS7_type_is_data(p7->d.sign->contents) && p7->detached) {
                        M_ASN1_OCTET_STRING_free(os);
                        p7->d.sign->contents->d.data = NULL;
                }
@@ -576,9 +572,8 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
                        
                        /* We now have the EVP_MD_CTX, lets do the
                         * signing. */
-                       EVP_MD_CTX_init(&ctx_tmp);
                        EVP_MD_CTX_copy_ex(&ctx_tmp,mdc);
-                       if (!BUF_MEM_grow(buf,EVP_PKEY_size(si->pkey)))
+                       if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey)))
                                {
                                PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
                                goto err;
@@ -629,7 +624,7 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio)
                                ctx_tmp.digest=EVP_dss1();
 #endif
 #ifndef OPENSSL_NO_ECDSA
-                       if (si->pkey->type == EVP_PKEY_ECDSA)
+                       if (si->pkey->type == EVP_PKEY_EC)
                                ctx_tmp.digest=EVP_ecdsa();
 #endif
 
@@ -771,6 +766,11 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si,
                        }
                if (EVP_MD_CTX_type(mdc) == md_type)
                        break;
+               /* Workaround for some broken clients that put the signature
+                * OID instead of the digest OID in digest_alg->algorithm
+                */
+               if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type)
+                       break;
                btmp=BIO_next(btmp);
                }
 
@@ -830,7 +830,7 @@ for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n");
        if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1();
 #endif
 #ifndef OPENSSL_NO_ECDSA
-       if (pkey->type == EVP_PKEY_ECDSA) mdc_tmp.digest=EVP_ecdsa();
+       if (pkey->type == EVP_PKEY_EC) mdc_tmp.digest=EVP_ecdsa();
 #endif
 
        i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey);