Hello folks,

I sent this mail in July but it was dropped (my email address changed...):


PKCS7_sign() has the disadvantage that all signed data must be kept in memory.

My patch addes a PKCS7_signHash() that allows
cereating of a PKCS7 signed object just from the
digest of the data.
Intendet usage:

EVP_MD_CTX    sCTX;
const EVP_MD *pMD = EVP_sha1(); /* or any other alg...) */
char          caDigest[EVP_MAX_MD_SIZE];
int           nDLen = EVP_MAX_MD_SIZE;
[...]
EVP_DigestInit(&sCTX,pMD);
while(data_available())
{
     char caBuffer[buffsize];
     int  nBuffLen = FillBuffWithData(caBuffer,buffsize);
     EVP_DigestUpdate(&sCTX,caBuffer,nBuffLen);
}
EVP_DigestFinal(&sCTX,caDigest,&nDLen);

/* we got the digest of the data,
    now create a PKCS#7 detached signed object... */
p7 = PKCS7_signHash(signer, key, other, pMD, caDigest, flags);

Better would be a real PKCS7_signInit / _signUpdate / SignFinal,
but that requires more work...

Bye

Goetz

--
Goetz Babin-Ebell, software designer,
TC TrustCenter AG, Sonninstr. 24-28, 20097 Hamburg, Germany
Office: +49-(0)40 80 80 26 -0,  Fax: +49-(0)40 80 80 26 -126
www.trustcenter.de www.betrusted.com
diff -ur openssl-SNAP-20040704/crypto/pkcs7/pk7_smime.c 
openssl-SNAP-20040704_changed/crypto/pkcs7/pk7_smime.c
--- openssl-SNAP-20040704/crypto/pkcs7/pk7_smime.c      2004-03-28 00:00:14.000000000 
+0100
+++ openssl-SNAP-20040704_changed/crypto/pkcs7/pk7_smime.c      2004-07-10 
21:36:06.000000000 +0200
@@ -63,8 +63,148 @@
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
-PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
-                 BIO *data, int flags)
+PKCS7 *PKCS7_signHash(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                     const EVP_MD *pMD, const unsigned char *digest,
+                     int flags)
+{
+       PKCS7 *p7;
+       ASN1_OCTET_STRING *os=NULL;
+
+       PKCS7_SIGNER_INFO *si;
+       STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL;
+
+       EVP_MD_CTX ctx_tmp;
+
+       BUF_MEM *buf=NULL;
+       unsigned char *abuf=NULL;
+       unsigned int alen;
+       ASN1_OCTET_STRING *digeststr;
+
+       if (!pMD) return NULL;
+
+#ifndef OPENSSL_NO_DSA
+       if (pkey->type == EVP_PKEY_DSA && pMD != EVP_dss1()) {
+               if (pMD != EVP_sha1()) {
+                       PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_DIGEST_FAILURE);
+                       return NULL;
+               }
+               pMD = EVP_dss1();
+       }
+#endif
+#ifndef OPENSSL_NO_ECDSA
+       if (pkey->type == EVP_PKEY_EC && pMD != EVP_ecdsa()) {
+               if (pMD != EVP_sha1()) {
+                       PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_DIGEST_FAILURE);
+                       return NULL;
+               }
+               pMD = EVP_ecdsa();
+       }
+#endif
+
+       p7 = PKCS7_sign2(signcert, pkey, certs, pMD,
+                        NULL, flags | PKCS7_STREAM );
+       if (!p7) return NULL;
+
+       PKCS7_set_detached(p7, 1);
+       /* detached data -> the content is excluded */
+       os=p7->d.sign->contents->d.data;
+       M_ASN1_OCTET_STRING_free(os);
+       p7->d.sign->contents->d.data = NULL;
+
+       p7->state=PKCS7_S_HEADER;
+
+       si_sk=p7->d.sign->signer_info;
+       if (!si_sk || sk_PKCS7_SIGNER_INFO_num(si_sk) < 1)
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_NO_SIGNERS);
+               PKCS7_free(p7);
+               return NULL;
+       }
+       si=sk_PKCS7_SIGNER_INFO_value(si_sk,0);
+       if (!si || !si->pkey)
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_NO_SIGNERS);
+               PKCS7_free(p7);
+               return NULL;
+       }
+
+       p7->state=PKCS7_S_HEADER;
+       
+       /* Add digest */
+       digeststr=M_ASN1_OCTET_STRING_new();
+       M_ASN1_OCTET_STRING_set(digeststr,digest, EVP_MD_size(pMD));
+       PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest,
+                                  V_ASN1_OCTET_STRING,digeststr);
+
+       /* Add signing time if not already present */
+       if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime))
+       {
+               ASN1_UTCTIME *sign_time=X509_gmtime_adj(NULL,0);
+               PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime,
+                                          V_ASN1_UTCTIME,sign_time);
+       }
+
+       if ((buf=BUF_MEM_new()) == NULL)
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
+               PKCS7_free(p7);
+               return NULL;
+       }
+       if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(pkey)))
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
+               BUF_MEM_free(buf);
+               PKCS7_free(p7);
+               return NULL;
+       }
+
+       if (!si->auth_attr)
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
+               BUF_MEM_free(buf);
+               PKCS7_free(p7);
+               return NULL;
+       }
+
+       /* Now sign the attributes */
+       EVP_SignInit_ex(&ctx_tmp,pMD,NULL);
+       alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr,&abuf,
+                            ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
+       if (alen <= 0 || !abuf)
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB);
+               EVP_MD_CTX_cleanup(&ctx_tmp);
+               BUF_MEM_free(buf);
+               PKCS7_free(p7);
+               return NULL;
+       }
+       EVP_SignUpdate(&ctx_tmp,abuf,alen);
+       OPENSSL_free(abuf);
+
+       if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data,
+                          (unsigned int *)&buf->length,si->pkey))
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB);
+               EVP_MD_CTX_cleanup(&ctx_tmp);
+               BUF_MEM_free(buf);
+               PKCS7_free(p7);
+               return NULL;
+       }
+       EVP_MD_CTX_cleanup(&ctx_tmp);
+       if (!ASN1_STRING_set(si->enc_digest,
+                            (unsigned char *)buf->data,buf->length))
+       {
+               PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB);
+               BUF_MEM_free(buf);
+               PKCS7_free(p7);
+               return NULL;
+       }
+       BUF_MEM_free(buf);
+       return p7;
+}
+
+PKCS7 *PKCS7_sign2(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                  const EVP_MD *pMD, BIO *data, int flags)
 {
        PKCS7 *p7;
        PKCS7_SIGNER_INFO *si;
@@ -86,8 +226,9 @@
 
        PKCS7_content_new(p7, NID_pkcs7_data);
 
-       if (!(si = PKCS7_add_signature(p7,signcert,pkey,EVP_sha1()))) {
+       if (!(si = PKCS7_add_signature(p7,signcert,pkey,pMD))) {
                PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_ADD_SIGNATURE_ERROR);
+               PKCS7_free(p7);
                return NULL;
        }
 
@@ -105,6 +246,7 @@
                {
                if(!(smcap = sk_X509_ALGOR_new_null())) {
                        PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
+                       PKCS7_free(p7);
                        return NULL;
                }
 #ifndef OPENSSL_NO_DES
@@ -130,6 +272,7 @@
 
        if (!(p7bio = PKCS7_dataInit(p7, NULL))) {
                PKCS7err(PKCS7_F_PKCS7_SIGN,ERR_R_MALLOC_FAILURE);
+               PKCS7_free(p7);
                return NULL;
        }
 
@@ -139,10 +282,12 @@
 
         if (!PKCS7_dataFinal(p7,p7bio)) {
                PKCS7err(PKCS7_F_PKCS7_SIGN,PKCS7_R_PKCS7_DATASIGN);
+               PKCS7_free(p7);
+               BIO_free_all(p7bio);
                return NULL;
        }
 
-        BIO_free_all(p7bio);
+       BIO_free_all(p7bio);
        return p7;
 }
 
diff -ur openssl-SNAP-20040704/crypto/pkcs7/pkcs7.h 
openssl-SNAP-20040704_changed/crypto/pkcs7/pkcs7.h
--- openssl-SNAP-20040704/crypto/pkcs7/pkcs7.h  2004-03-28 00:00:14.000000000 +0100
+++ openssl-SNAP-20040704_changed/crypto/pkcs7/pkcs7.h  2004-07-10 21:35:48.000000000 
+0200
@@ -353,8 +353,12 @@
 int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si,STACK_OF(X509_ATTRIBUTE) *sk);
 
 
-PKCS7 *PKCS7_sign(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
-                                                       BIO *data, int flags);
+#define PKCS7_sign(signcert,pkey,certs,data,flags) 
PKCS7_sign2(signcert,pkey,certs,EVP_sha1(),data,flags)
+PKCS7 *PKCS7_sign2(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                  const EVP_MD *pMD, BIO *data, int flags);
+PKCS7 *PKCS7_signHash(X509 *signcert, EVP_PKEY *pkey, STACK_OF(X509) *certs,
+                     const EVP_MD *pMD, const unsigned char *digest,
+                     int flags);
 int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
                                        BIO *indata, BIO *out, int flags);
 STACK_OF(X509) *PKCS7_get0_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags);


Attachment: smime.p7s
Description: S/MIME Cryptographic Signature

Reply via email to