diff options
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c')
| -rw-r--r-- | Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c | 550 |
1 files changed, 338 insertions, 212 deletions
diff --git a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c index db134ddc..c8d7db01 100644 --- a/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c +++ b/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c @@ -134,6 +134,121 @@ static int PKCS7_bio_add_digest(BIO **pbio, X509_ALGOR *alg) } +static int pkcs7_encode_rinfo(PKCS7_RECIP_INFO *ri, + unsigned char *key, int keylen) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_PKEY *pkey = NULL; + unsigned char *ek = NULL; + int ret = 0; + size_t eklen; + + pkey = X509_get_pubkey(ri->cert); + + if (!pkey) + return 0; + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pctx) + return 0; + + if (EVP_PKEY_encrypt_init(pctx) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_ENCRYPT, + EVP_PKEY_CTRL_PKCS7_ENCRYPT, 0, ri) <= 0) { + PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, PKCS7_R_CTRL_ERROR); + goto err; + } + + if (EVP_PKEY_encrypt(pctx, NULL, &eklen, key, keylen) <= 0) + goto err; + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) { + PKCS7err(PKCS7_F_PKCS7_ENCODE_RINFO, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_encrypt(pctx, ek, &eklen, key, keylen) <= 0) + goto err; + + ASN1_STRING_set0(ri->enc_key, ek, eklen); + ek = NULL; + + ret = 1; + + err: + if (pkey) + EVP_PKEY_free(pkey); + if (pctx) + EVP_PKEY_CTX_free(pctx); + if (ek) + OPENSSL_free(ek); + return ret; + +} + +static int pkcs7_decrypt_rinfo(unsigned char **pek, int *peklen, + PKCS7_RECIP_INFO *ri, EVP_PKEY *pkey) +{ + EVP_PKEY_CTX *pctx = NULL; + unsigned char *ek = NULL; + size_t eklen; + + int ret = -1; + + pctx = EVP_PKEY_CTX_new(pkey, NULL); + if (!pctx) + return -1; + + if (EVP_PKEY_decrypt_init(pctx) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_DECRYPT, + EVP_PKEY_CTRL_PKCS7_DECRYPT, 0, ri) <= 0) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, PKCS7_R_CTRL_ERROR); + goto err; + } + + if (EVP_PKEY_decrypt(pctx, NULL, &eklen, + ri->enc_key->data, ri->enc_key->length) <= 0) + goto err; + + ek = OPENSSL_malloc(eklen); + + if (ek == NULL) { + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_MALLOC_FAILURE); + goto err; + } + + if (EVP_PKEY_decrypt(pctx, ek, &eklen, + ri->enc_key->data, ri->enc_key->length) <= 0) { + ret = 0; + PKCS7err(PKCS7_F_PKCS7_DECRYPT_RINFO, ERR_R_EVP_LIB); + goto err; + } + + ret = 1; + + if (*pek) { + OPENSSL_cleanse(*pek, *peklen); + OPENSSL_free(*pek); + } + + *pek = ek; + *peklen = eklen; + + err: + if (pctx) + EVP_PKEY_CTX_free(pctx); + if (!ret && ek) + OPENSSL_free(ek); + + return ret; +} + BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { int i; @@ -144,7 +259,6 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; X509_ALGOR *xalg = NULL; PKCS7_RECIP_INFO *ri = NULL; - EVP_PKEY *pkey; ASN1_OCTET_STRING *os = NULL; if (p7 == NULL) { @@ -197,6 +311,8 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) xa = p7->d.digest->md; os = PKCS7_get_octet_string(p7->d.digest->contents); break; + case NID_pkcs7_data: + break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; @@ -213,8 +329,6 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; int keylen, ivlen; - int jj, max; - unsigned char *tmp; EVP_CIPHER_CTX *ctx; if ((btmp = BIO_new(BIO_f_cipher())) == NULL) { @@ -246,43 +360,11 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) } /* Lets do the pub key stuff :-) */ - max = 0; - for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { - ri = sk_PKCS7_RECIP_INFO_value(rsk, i); - if (ri->cert == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAINIT, - PKCS7_R_MISSING_CERIPEND_INFO); - goto err; - } - if ((pkey = X509_get_pubkey(ri->cert)) == NULL) - goto err; - jj = EVP_PKEY_size(pkey); - EVP_PKEY_free(pkey); - if (max < jj) - max = jj; - } - if ((tmp = (unsigned char *)OPENSSL_malloc(max)) == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_MALLOC_FAILURE); - goto err; - } for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri = sk_PKCS7_RECIP_INFO_value(rsk, i); - if ((pkey = X509_get_pubkey(ri->cert)) == NULL) - goto err; - jj = EVP_PKEY_encrypt(tmp, key, keylen, pkey); - EVP_PKEY_free(pkey); - if (jj <= 0) { - PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_EVP_LIB); - OPENSSL_free(tmp); - goto err; - } - if (!M_ASN1_OCTET_STRING_set(ri->enc_key, tmp, jj)) { - PKCS7err(PKCS7_F_PKCS7_DATAINIT, ERR_R_MALLOC_FAILURE); - OPENSSL_free(tmp); + if (pkcs7_encode_rinfo(ri, key, keylen) <= 0) goto err; - } } - OPENSSL_free(tmp); OPENSSL_cleanse(key, keylen); if (out == NULL) @@ -304,7 +386,10 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) BIO_set_mem_eof_return(bio, 0); } } - BIO_push(out, bio); + if (out) + BIO_push(out, bio); + else + out = bio; bio = NULL; if (0) { err: @@ -333,7 +418,6 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) { int i, j; BIO *out = NULL, *btmp = NULL, *etmp = NULL, *bio = NULL; - unsigned char *tmp = NULL; X509_ALGOR *xa; ASN1_OCTET_STRING *data_body = NULL; const EVP_MD *evp_md; @@ -343,6 +427,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) STACK_OF(X509_ALGOR) *md_sk = NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk = NULL; PKCS7_RECIP_INFO *ri = NULL; + unsigned char *ek = NULL, *tkey = NULL; + int eklen = 0, tkeylen = 0; if (p7 == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_INVALID_NULL_POINTER); @@ -359,12 +445,24 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) switch (i) { case NID_pkcs7_signed: + /* + * p7->d.sign->contents is a PKCS7 structure consisting of a contentType + * field and optional content. + * data_body is NULL if that structure has no (=detached) content + * or if the contentType is wrong (i.e., not "data"). + */ data_body = PKCS7_get_octet_string(p7->d.sign->contents); + if (!PKCS7_is_detached(p7) && data_body == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_INVALID_SIGNED_DATA_TYPE); + goto err; + } md_sk = p7->d.sign->md_algs; break; case NID_pkcs7_signedAndEnveloped: rsk = p7->d.signed_and_enveloped->recipientinfo; md_sk = p7->d.signed_and_enveloped->md_algs; + /* data_body is NULL if the optional EncryptedContent is missing. */ data_body = p7->d.signed_and_enveloped->enc_data->enc_data; enc_alg = p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); @@ -377,6 +475,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) case NID_pkcs7_enveloped: rsk = p7->d.enveloped->recipientinfo; enc_alg = p7->d.enveloped->enc_data->algorithm; + /* data_body is NULL if the optional EncryptedContent is missing. */ data_body = p7->d.enveloped->enc_data->enc_data; evp_cipher = EVP_get_cipherbyobj(enc_alg->algorithm); if (evp_cipher == NULL) { @@ -390,6 +489,12 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) goto err; } + /* Detached content must be supplied via in_bio instead. */ + if (data_body == NULL && in_bio == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_CONTENT); + goto err; + } + /* We will be checking the signature */ if (md_sk != NULL) { for (i = 0; i < sk_X509_ALGOR_num(md_sk); i++) { @@ -425,9 +530,6 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) int max; X509_OBJECT ret; #endif - unsigned char *tkey = NULL; - int tkeylen; - int jj; if ((etmp = BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_BIO_LIB); @@ -458,48 +560,23 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) } } - jj = EVP_PKEY_size(pkey); - tmp = (unsigned char *)OPENSSL_malloc(jj + 10); - if (tmp == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_MALLOC_FAILURE); - goto err; - } - /* If we haven't got a certificate try each ri in turn */ - if (pcert == NULL) { /* - * Temporary storage in case EVP_PKEY_decrypt overwrites output - * buffer on error. - */ - unsigned char *tmp2; - tmp2 = OPENSSL_malloc(jj); - if (!tmp2) - goto err; - jj = -1; - /* - * Always attempt to decrypt all cases to avoid leaking timing - * information about a successful decrypt. + * Always attempt to decrypt all rinfo even after sucess as a + * defence against MMA timing attacks. */ for (i = 0; i < sk_PKCS7_RECIP_INFO_num(rsk); i++) { - int tret; ri = sk_PKCS7_RECIP_INFO_value(rsk, i); - tret = EVP_PKEY_decrypt(tmp2, - M_ASN1_STRING_data(ri->enc_key), - M_ASN1_STRING_length(ri->enc_key), - pkey); - if (tret > 0) { - memcpy(tmp, tmp2, tret); - OPENSSL_cleanse(tmp2, tret); - jj = tret; - } + + if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) + goto err; ERR_clear_error(); } - OPENSSL_free(tmp2); } else { - jj = EVP_PKEY_decrypt(tmp, - M_ASN1_STRING_data(ri->enc_key), - M_ASN1_STRING_length(ri->enc_key), pkey); + /* Only exit on fatal errors, not decrypt failure */ + if (pkcs7_decrypt_rinfo(&ek, &eklen, ri, pkey) < 0) + goto err; ERR_clear_error(); } @@ -509,45 +586,48 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) goto err; if (EVP_CIPHER_asn1_to_param(evp_ctx, enc_alg->parameter) < 0) goto err; - /* Generate random key to counter MMA */ + /* Generate random key as MMA defence */ tkeylen = EVP_CIPHER_CTX_key_length(evp_ctx); tkey = OPENSSL_malloc(tkeylen); if (!tkey) goto err; if (EVP_CIPHER_CTX_rand_key(evp_ctx, tkey) <= 0) goto err; - /* If we have no key use random key */ - if (jj <= 0) { - OPENSSL_free(tmp); - jj = tkeylen; - tmp = tkey; + if (ek == NULL) { + ek = tkey; + eklen = tkeylen; tkey = NULL; } - if (jj != tkeylen) { + if (eklen != EVP_CIPHER_CTX_key_length(evp_ctx)) { /* * Some S/MIME clients don't use the same key and effective key * length. The key length is determined by the size of the * decrypted RSA key. */ - if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) { - /* As MMA defence use random key instead */ - OPENSSL_cleanse(tmp, jj); - OPENSSL_free(tmp); - jj = tkeylen; - tmp = tkey; + if (!EVP_CIPHER_CTX_set_key_length(evp_ctx, eklen)) { + /* Use random key as MMA defence */ + OPENSSL_cleanse(ek, eklen); + OPENSSL_free(ek); + ek = tkey; + eklen = tkeylen; tkey = NULL; } } + /* Clear errors so we don't leak information useful in MMA */ ERR_clear_error(); - if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, tmp, NULL, 0) <= 0) + if (EVP_CipherInit_ex(evp_ctx, NULL, NULL, ek, NULL, 0) <= 0) goto err; - OPENSSL_cleanse(tmp, jj); - + if (ek) { + OPENSSL_cleanse(ek, eklen); + OPENSSL_free(ek); + ek = NULL; + } if (tkey) { OPENSSL_cleanse(tkey, tkeylen); OPENSSL_free(tkey); + tkey = NULL; } if (out == NULL) @@ -557,7 +637,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) etmp = NULL; } #if 1 - if (PKCS7_is_detached(p7) || (in_bio != NULL)) { + if (in_bio != NULL) { bio = in_bio; } else { # if 0 @@ -587,6 +667,14 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) #endif if (0) { err: + if (ek) { + OPENSSL_cleanse(ek, eklen); + OPENSSL_free(ek); + } + if (tkey) { + OPENSSL_cleanse(tkey, tkeylen); + OPENSSL_free(tkey); + } if (out != NULL) BIO_free_all(out); if (btmp != NULL) @@ -597,8 +685,6 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) BIO_free_all(bio); out = NULL; } - if (tmp != NULL) - OPENSSL_free(tmp); return (out); } @@ -623,13 +709,41 @@ static BIO *PKCS7_find_digest(EVP_MD_CTX **pmd, BIO *bio, int nid) return NULL; } +static int do_pkcs7_signed_attrib(PKCS7_SIGNER_INFO *si, EVP_MD_CTX *mctx) +{ + unsigned char md_data[EVP_MAX_MD_SIZE]; + unsigned int md_len; + + /* Add signing time if not already present */ + if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { + if (!PKCS7_add0_attrib_signing_time(si, NULL)) { + PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); + return 0; + } + } + + /* Add digest */ + if (!EVP_DigestFinal_ex(mctx, md_data, &md_len)) { + PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_EVP_LIB); + return 0; + } + if (!PKCS7_add1_attrib_digest(si, md_data, md_len)) { + PKCS7err(PKCS7_F_DO_PKCS7_SIGNED_ATTRIB, ERR_R_MALLOC_FAILURE); + return 0; + } + + /* Now sign the attributes */ + if (!PKCS7_SIGNER_INFO_sign(si)) + return 0; + + return 1; +} + int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) { int ret = 0; int i, j; BIO *btmp; - BUF_MEM *buf_mem = NULL; - BUF_MEM *buf = NULL; PKCS7_SIGNER_INFO *si; EVP_MD_CTX *mdc, ctx_tmp; STACK_OF(X509_ATTRIBUTE) *sk; @@ -651,22 +765,33 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) p7->state = PKCS7_S_HEADER; switch (i) { + case NID_pkcs7_data: + os = p7->d.data; + break; case NID_pkcs7_signedAndEnveloped: /* XXXXXXXXXXXXXXXX */ si_sk = p7->d.signed_and_enveloped->signer_info; - if (!(os = M_ASN1_OCTET_STRING_new())) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); - goto err; + os = p7->d.signed_and_enveloped->enc_data->enc_data; + if (!os) { + os = M_ASN1_OCTET_STRING_new(); + if (!os) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); + goto err; + } + p7->d.signed_and_enveloped->enc_data->enc_data = os; } - p7->d.signed_and_enveloped->enc_data->enc_data = os; break; case NID_pkcs7_enveloped: /* XXXXXXXXXXXXXXXX */ - if (!(os = M_ASN1_OCTET_STRING_new())) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); - goto err; + os = p7->d.enveloped->enc_data->enc_data; + if (!os) { + os = M_ASN1_OCTET_STRING_new(); + if (!os) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); + goto err; + } + p7->d.enveloped->enc_data->enc_data = os; } - p7->d.enveloped->enc_data->enc_data = os; break; case NID_pkcs7_signed: si_sk = p7->d.sign->signer_info; @@ -689,13 +814,12 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) } break; + default: + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + goto err; } if (si_sk != NULL) { - if ((buf = BUF_MEM_new()) == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_BIO_LIB); - goto err; - } for (i = 0; i < sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { si = sk_PKCS7_SIGNER_INFO_value(si_sk, i); if (si->pkey == NULL) @@ -713,11 +837,8 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) /* * We now have the EVP_MD_CTX, lets do the signing. */ - EVP_MD_CTX_copy_ex(&ctx_tmp, mdc); - if (!BUF_MEM_grow_clean(buf, EVP_PKEY_size(si->pkey))) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_BIO_LIB); + if (!EVP_MD_CTX_copy_ex(&ctx_tmp, mdc)) goto err; - } sk = si->auth_attr; @@ -725,76 +846,22 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) * If there are attributes, we add the digest attribute and only * sign the attributes */ - if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { - 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; - - /* Add signing time if not already present */ - if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { - if (!(sign_time = X509_gmtime_adj(NULL, 0))) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, - ERR_R_MALLOC_FAILURE); - goto err; - } - if (!PKCS7_add_signed_attribute(si, - NID_pkcs9_signingTime, - V_ASN1_UTCTIME, - sign_time)) { - M_ASN1_UTCTIME_free(sign_time); - goto err; - } - } - - /* Add digest */ - md_tmp = EVP_MD_CTX_md(&ctx_tmp); - EVP_DigestFinal_ex(&ctx_tmp, md_data, &md_len); - if (!(digest = M_ASN1_OCTET_STRING_new())) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); - goto err; - } - if (!M_ASN1_OCTET_STRING_set(digest, md_data, md_len)) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_MALLOC_FAILURE); - M_ASN1_OCTET_STRING_free(digest); - goto err; - } - if (!PKCS7_add_signed_attribute(si, - NID_pkcs9_messageDigest, - V_ASN1_OCTET_STRING, digest)) - { - M_ASN1_OCTET_STRING_free(digest); + if (sk_X509_ATTRIBUTE_num(sk) > 0) { + if (!do_pkcs7_signed_attrib(si, &ctx_tmp)) goto err; - } - - /* Now sign the attributes */ - EVP_SignInit_ex(&ctx_tmp, md_tmp, NULL); - alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, - ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); + } else { + unsigned char *abuf = NULL; + unsigned int abuflen; + abuflen = EVP_PKEY_size(si->pkey); + abuf = OPENSSL_malloc(abuflen); if (!abuf) goto err; - EVP_SignUpdate(&ctx_tmp, abuf, alen); - OPENSSL_free(abuf); - } -#ifndef OPENSSL_NO_DSA - if (si->pkey->type == EVP_PKEY_DSA) - ctx_tmp.digest = EVP_dss1(); -#endif -#ifndef OPENSSL_NO_ECDSA - if (si->pkey->type == EVP_PKEY_EC) - ctx_tmp.digest = EVP_ecdsa(); -#endif - if (!EVP_SignFinal(&ctx_tmp, (unsigned char *)buf->data, - (unsigned int *)&buf->length, si->pkey)) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); - goto err; - } - if (!ASN1_STRING_set(si->enc_digest, - (unsigned char *)buf->data, buf->length)) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_ASN1_LIB); - goto err; + if (!EVP_SignFinal(&ctx_tmp, abuf, &abuflen, si->pkey)) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, ERR_R_EVP_LIB); + goto err; + } + ASN1_STRING_set0(si->enc_digest, abuf, abuflen); } } } else if (i == NID_pkcs7_digest) { @@ -803,7 +870,8 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) if (!PKCS7_find_digest(&mdc, bio, OBJ_obj2nid(p7->d.digest->md->algorithm))) goto err; - EVP_DigestFinal_ex(mdc, md_data, &md_len); + if (!EVP_DigestFinal_ex(mdc, md_data, &md_len)) + goto err; M_ASN1_OCTET_STRING_set(p7->d.digest->digest, md_data, md_len); } @@ -814,34 +882,89 @@ int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) */ if (os == NULL) goto err; - btmp = BIO_find_type(bio, BIO_TYPE_MEM); - if (btmp == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); - goto err; + if (!(os->flags & ASN1_STRING_FLAG_NDEF)) { + char *cont; + long contlen; + btmp = BIO_find_type(bio, BIO_TYPE_MEM); + if (btmp == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATAFINAL, PKCS7_R_UNABLE_TO_FIND_MEM_BIO); + goto err; + } + contlen = BIO_get_mem_data(btmp, &cont); + /* + * Mark the BIO read only then we can use its copy of the data + * instead of making an extra copy. + */ + BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); + BIO_set_mem_eof_return(btmp, 0); + ASN1_STRING_set0(os, (unsigned char *)cont, contlen); } - BIO_get_mem_ptr(btmp, &buf_mem); - /* - * Mark the BIO read only then we can use its copy of the data - * instead of making an extra copy. - */ - BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); - BIO_set_mem_eof_return(btmp, 0); - os->data = (unsigned char *)buf_mem->data; - os->length = buf_mem->length; -#if 0 - M_ASN1_OCTET_STRING_set(os, - (unsigned char *)buf_mem->data, - buf_mem->length); -#endif } ret = 1; err: EVP_MD_CTX_cleanup(&ctx_tmp); - if (buf != NULL) - BUF_MEM_free(buf); return (ret); } +int PKCS7_SIGNER_INFO_sign(PKCS7_SIGNER_INFO *si) +{ + EVP_MD_CTX mctx; + EVP_PKEY_CTX *pctx; + unsigned char *abuf = NULL; + int alen; + size_t siglen; + const EVP_MD *md = NULL; + + md = EVP_get_digestbyobj(si->digest_alg->algorithm); + if (md == NULL) + return 0; + + EVP_MD_CTX_init(&mctx); + if (EVP_DigestSignInit(&mctx, &pctx, md, NULL, si->pkey) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_PKCS7_SIGN, 0, si) <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); + goto err; + } + + alen = ASN1_item_i2d((ASN1_VALUE *)si->auth_attr, &abuf, + ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); + if (!abuf) + goto err; + if (EVP_DigestSignUpdate(&mctx, abuf, alen) <= 0) + goto err; + OPENSSL_free(abuf); + abuf = NULL; + if (EVP_DigestSignFinal(&mctx, NULL, &siglen) <= 0) + goto err; + abuf = OPENSSL_malloc(siglen); + if (!abuf) + goto err; + if (EVP_DigestSignFinal(&mctx, abuf, &siglen) <= 0) + goto err; + + if (EVP_PKEY_CTX_ctrl(pctx, -1, EVP_PKEY_OP_SIGN, + EVP_PKEY_CTRL_PKCS7_SIGN, 1, si) <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNER_INFO_SIGN, PKCS7_R_CTRL_ERROR); + goto err; + } + + EVP_MD_CTX_cleanup(&mctx); + + ASN1_STRING_set0(si->enc_digest, abuf, siglen); + + return 1; + + err: + if (abuf) + OPENSSL_free(abuf); + EVP_MD_CTX_cleanup(&mctx); + return 0; + +} + int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si) { @@ -947,15 +1070,18 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, * mdc is the digest ctx that we want, unless there are attributes, in * which case the digest is the signed attributes */ - EVP_MD_CTX_copy_ex(&mdc_tmp, mdc); + if (!EVP_MD_CTX_copy_ex(&mdc_tmp, mdc)) + goto err; sk = si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; - unsigned int md_len, alen; + unsigned int md_len; + int alen; ASN1_OCTET_STRING *message_digest; - EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len); + if (!EVP_DigestFinal_ex(&mdc_tmp, md_dat, &md_len)) + goto err; message_digest = PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, @@ -980,11 +1106,18 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, goto err; } - EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL); + if (!EVP_VerifyInit_ex(&mdc_tmp, EVP_get_digestbynid(md_type), NULL)) + goto err; alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); - EVP_VerifyUpdate(&mdc_tmp, abuf, alen); + if (alen <= 0) { + PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_ASN1_LIB); + ret = -1; + goto err; + } + if (!EVP_VerifyUpdate(&mdc_tmp, abuf, alen)) + goto err; OPENSSL_free(abuf); } @@ -995,14 +1128,6 @@ int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, ret = -1; goto err; } -#ifndef OPENSSL_NO_DSA - if (pkey->type == EVP_PKEY_DSA) - mdc_tmp.digest = EVP_dss1(); -#endif -#ifndef OPENSSL_NO_ECDSA - if (pkey->type == EVP_PKEY_EC) - mdc_tmp.digest = EVP_ecdsa(); -#endif i = EVP_VerifyFinal(&mdc_tmp, os->data, os->length, pkey); EVP_PKEY_free(pkey); @@ -1135,7 +1260,8 @@ static int add_attribute(STACK_OF(X509_ATTRIBUTE) **sk, int nid, int atrtype, X509_ATTRIBUTE *attr = NULL; if (*sk == NULL) { - if (!(*sk = sk_X509_ATTRIBUTE_new_null())) + *sk = sk_X509_ATTRIBUTE_new_null(); + if (*sk == NULL) return 0; new_attrib: if (!(attr = X509_ATTRIBUTE_create(nid, atrtype, value))) |
