summaryrefslogtreecommitdiff
path: root/Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c
diff options
context:
space:
mode:
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c')
-rw-r--r--Cryptlib/OpenSSL/crypto/pkcs7/pk7_doit.c550
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)))