Loading CHANGES +13 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,19 @@ Changes between 0.9.6 and 0.9.7 [xx XXX 2000] *) Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN uses the special reorder version of SET OF to sort the attributes and reorder them to match the encoded order. This resolves a long standing problem: a verify on a PKCS7 structure just after signing it used to fail because the attribute order did not match the encoded order. PKCS7_ATTR_VERIFY does not reorder the attributes: it uses the received order. This is necessary to tolerate some broken software that does not order SET OF. This is handled by encoding as a SEQUENCE OF but using implicit tagging (with UNIVERSAL class) to produce the required SET OF. [Steve Henson] *) Have mk1mf.pl generate the macros OPENSSL_BUILD_SHLIBCRYPTO and OPENSSL_BUILD_SHLIBSSL and use them appropriately in the header files to get correct declarations of the ASN.1 item variables. Loading crypto/pkcs7/pk7_asn1.c +23 −2 Original line number Diff line number Diff line Loading @@ -108,8 +108,10 @@ ASN1_SEQUENCE_cb(PKCS7_SIGNER_INFO, si_cb) = { ASN1_SIMPLE(PKCS7_SIGNER_INFO, version, ASN1_INTEGER), ASN1_SIMPLE(PKCS7_SIGNER_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_alg, X509_ALGOR), /* NB this should be a SET OF but we use a SEQUENCE OF so the original order * is retained when the structure is reencoded. /* NB this should be a SET OF but we use a SEQUENCE OF so the * original order * is retained when the structure is reencoded. * Since the attributes are implicitly tagged this will not affect * the encoding. */ ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNER_INFO, auth_attr, X509_ATTRIBUTE, 0), ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_enc_alg, X509_ALGOR), Loading Loading @@ -178,3 +180,22 @@ ASN1_SEQUENCE(PKCS7_DIGEST) = { } ASN1_SEQUENCE_END(PKCS7_DIGEST); IMPLEMENT_ASN1_FUNCTIONS(PKCS7_DIGEST) /* Specials for authenticated attributes */ /* When signing attributes we want to reorder them to match the sorted * encoding. */ ASN1_ITEM_TEMPLATE(PKCS7_ATTR_SIGN) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_SIGN); /* When verifying attributes we need to use the received order. So * we use SEQUENCE OF and tag it to SET OF */ ASN1_ITEM_TEMPLATE(PKCS7_ATTR_VERIFY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL, V_ASN1_SET, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_VERIFY); crypto/pkcs7/pk7_doit.c +16 −35 Original line number Diff line number Diff line Loading @@ -471,8 +471,6 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) EVP_MD_CTX *mdc,ctx_tmp; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; unsigned char *p,*pp=NULL; int x; ASN1_OCTET_STRING *os=NULL; i=OBJ_obj2nid(p7->type); Loading Loading @@ -552,8 +550,8 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) * attribute and only sign the attributes */ if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_data[EVP_MAX_MD_SIZE]; unsigned int md_len; unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *digest; ASN1_UTCTIME *sign_time; const EVP_MD *md_tmp; Loading @@ -573,19 +571,13 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING,digest); /* Now sign the mess */ /* Now sign the attributes */ EVP_SignInit(&ctx_tmp,md_tmp); x=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL, i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET); pp=(unsigned char *)OPENSSL_malloc(x); p=pp; i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p, i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET); EVP_SignUpdate(&ctx_tmp,pp,x); OPENSSL_free(pp); pp=NULL; alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf, &PKCS7_ATTR_SIGN_it); if(!abuf) goto err; EVP_SignUpdate(&ctx_tmp,abuf,alen); OPENSSL_free(abuf); } if (si->pkey->type == EVP_PKEY_DSA) Loading Loading @@ -627,9 +619,6 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) (unsigned char *)buf_mem->data,buf_mem->length); #endif } if (pp != NULL) OPENSSL_free(pp); pp=NULL; ret=1; err: if (buf != NULL) BUF_MEM_free(buf); Loading Loading @@ -691,7 +680,6 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp,*mdc; unsigned char *pp,*p; int ret=0,i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; Loading Loading @@ -736,8 +724,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, sk=si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE]; unsigned int md_len; unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *message_digest; EVP_DigestFinal(&mdc_tmp,md_dat,&md_len); Loading Loading @@ -766,19 +754,12 @@ for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); } EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type)); /* Note: when forming the encoding of the attributes we * shouldn't reorder them or this will break the signature. * This is done by using the IS_SEQUENCE flag. */ i=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); pp=OPENSSL_malloc(i); p=pp; i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); EVP_VerifyUpdate(&mdc_tmp,pp,i); OPENSSL_free(pp); alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, &PKCS7_ATTR_VERIFY_it); EVP_VerifyUpdate(&mdc_tmp, abuf, alen); OPENSSL_free(abuf); } os=si->enc_digest; Loading crypto/pkcs7/pkcs7.h +3 −0 Original line number Diff line number Diff line Loading @@ -295,6 +295,9 @@ DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST) DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT) DECLARE_ASN1_FUNCTIONS(PKCS7) DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN) DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY) void ERR_load_PKCS7_strings(void); Loading Loading
CHANGES +13 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,19 @@ Changes between 0.9.6 and 0.9.7 [xx XXX 2000] *) Fix the PKCS#7 (S/MIME) code to work with new ASN1. Two new ASN1_ITEM structures help with sign and verify. PKCS7_ATTR_SIGN uses the special reorder version of SET OF to sort the attributes and reorder them to match the encoded order. This resolves a long standing problem: a verify on a PKCS7 structure just after signing it used to fail because the attribute order did not match the encoded order. PKCS7_ATTR_VERIFY does not reorder the attributes: it uses the received order. This is necessary to tolerate some broken software that does not order SET OF. This is handled by encoding as a SEQUENCE OF but using implicit tagging (with UNIVERSAL class) to produce the required SET OF. [Steve Henson] *) Have mk1mf.pl generate the macros OPENSSL_BUILD_SHLIBCRYPTO and OPENSSL_BUILD_SHLIBSSL and use them appropriately in the header files to get correct declarations of the ASN.1 item variables. Loading
crypto/pkcs7/pk7_asn1.c +23 −2 Original line number Diff line number Diff line Loading @@ -108,8 +108,10 @@ ASN1_SEQUENCE_cb(PKCS7_SIGNER_INFO, si_cb) = { ASN1_SIMPLE(PKCS7_SIGNER_INFO, version, ASN1_INTEGER), ASN1_SIMPLE(PKCS7_SIGNER_INFO, issuer_and_serial, PKCS7_ISSUER_AND_SERIAL), ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_alg, X509_ALGOR), /* NB this should be a SET OF but we use a SEQUENCE OF so the original order * is retained when the structure is reencoded. /* NB this should be a SET OF but we use a SEQUENCE OF so the * original order * is retained when the structure is reencoded. * Since the attributes are implicitly tagged this will not affect * the encoding. */ ASN1_IMP_SEQUENCE_OF_OPT(PKCS7_SIGNER_INFO, auth_attr, X509_ATTRIBUTE, 0), ASN1_SIMPLE(PKCS7_SIGNER_INFO, digest_enc_alg, X509_ALGOR), Loading Loading @@ -178,3 +180,22 @@ ASN1_SEQUENCE(PKCS7_DIGEST) = { } ASN1_SEQUENCE_END(PKCS7_DIGEST); IMPLEMENT_ASN1_FUNCTIONS(PKCS7_DIGEST) /* Specials for authenticated attributes */ /* When signing attributes we want to reorder them to match the sorted * encoding. */ ASN1_ITEM_TEMPLATE(PKCS7_ATTR_SIGN) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SET_ORDER, 0, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_SIGN); /* When verifying attributes we need to use the received order. So * we use SEQUENCE OF and tag it to SET OF */ ASN1_ITEM_TEMPLATE(PKCS7_ATTR_VERIFY) = ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_IMPTAG | ASN1_TFLG_UNIVERSAL, V_ASN1_SET, PKCS7_ATTRIBUTES, X509_ATTRIBUTE) ASN1_ITEM_TEMPLATE_END(PKCS7_ATTR_VERIFY);
crypto/pkcs7/pk7_doit.c +16 −35 Original line number Diff line number Diff line Loading @@ -471,8 +471,6 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) EVP_MD_CTX *mdc,ctx_tmp; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; unsigned char *p,*pp=NULL; int x; ASN1_OCTET_STRING *os=NULL; i=OBJ_obj2nid(p7->type); Loading Loading @@ -552,8 +550,8 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) * attribute and only sign the attributes */ if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_data[EVP_MAX_MD_SIZE]; unsigned int md_len; unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *digest; ASN1_UTCTIME *sign_time; const EVP_MD *md_tmp; Loading @@ -573,19 +571,13 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING,digest); /* Now sign the mess */ /* Now sign the attributes */ EVP_SignInit(&ctx_tmp,md_tmp); x=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL, i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET); pp=(unsigned char *)OPENSSL_malloc(x); p=pp; i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p, i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL,IS_SET); EVP_SignUpdate(&ctx_tmp,pp,x); OPENSSL_free(pp); pp=NULL; alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf, &PKCS7_ATTR_SIGN_it); if(!abuf) goto err; EVP_SignUpdate(&ctx_tmp,abuf,alen); OPENSSL_free(abuf); } if (si->pkey->type == EVP_PKEY_DSA) Loading Loading @@ -627,9 +619,6 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) (unsigned char *)buf_mem->data,buf_mem->length); #endif } if (pp != NULL) OPENSSL_free(pp); pp=NULL; ret=1; err: if (buf != NULL) BUF_MEM_free(buf); Loading Loading @@ -691,7 +680,6 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp,*mdc; unsigned char *pp,*p; int ret=0,i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; Loading Loading @@ -736,8 +724,8 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, sk=si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE]; unsigned int md_len; unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *message_digest; EVP_DigestFinal(&mdc_tmp,md_dat,&md_len); Loading Loading @@ -766,19 +754,12 @@ for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); } EVP_VerifyInit(&mdc_tmp,EVP_get_digestbynid(md_type)); /* Note: when forming the encoding of the attributes we * shouldn't reorder them or this will break the signature. * This is done by using the IS_SEQUENCE flag. */ i=i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,NULL,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); pp=OPENSSL_malloc(i); p=pp; i2d_ASN1_SET_OF_X509_ATTRIBUTE(sk,&p,i2d_X509_ATTRIBUTE, V_ASN1_SET,V_ASN1_UNIVERSAL, IS_SEQUENCE); EVP_VerifyUpdate(&mdc_tmp,pp,i); OPENSSL_free(pp); alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, &PKCS7_ATTR_VERIFY_it); EVP_VerifyUpdate(&mdc_tmp, abuf, alen); OPENSSL_free(abuf); } os=si->enc_digest; Loading
crypto/pkcs7/pkcs7.h +3 −0 Original line number Diff line number Diff line Loading @@ -295,6 +295,9 @@ DECLARE_ASN1_FUNCTIONS(PKCS7_DIGEST) DECLARE_ASN1_FUNCTIONS(PKCS7_ENCRYPT) DECLARE_ASN1_FUNCTIONS(PKCS7) DECLARE_ASN1_ITEM(PKCS7_ATTR_SIGN) DECLARE_ASN1_ITEM(PKCS7_ATTR_VERIFY) void ERR_load_PKCS7_strings(void); Loading