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);
smime.p7s
Description: S/MIME Cryptographic Signature