diff --git a/CHANGES b/CHANGES index 9946a95785..a070705730 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,11 @@ [23-Dec-1998] down below; but in later versions, these hyphens are gone.] + *) Reorganise the PKCS#7 library and get rid of some of the more obvious + problems: find RecipientInfo structure that matches recipient certificate + and initialise the ASN1 structures properly based on passed cipher. + [Steve Henson] + *) Belatedly make the BN tests actually check the results. [Ben Laurie] diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index ac21717057..39f48610ed 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -624,7 +624,7 @@ int EVP_PKEY_missing_parameters(EVP_PKEY *pkey); int EVP_PKEY_save_parameters(EVP_PKEY *pkey,int mode); int EVP_PKEY_cmp_parameters(EVP_PKEY *a,EVP_PKEY *b); -int EVP_CIPHER_type(EVP_CIPHER *ctx); +int EVP_CIPHER_type(const EVP_CIPHER *ctx); /* calls methods */ int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type); diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index 6a60ca4bcc..63ce3ae17d 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -71,7 +71,7 @@ static ERR_STRING_DATA EVP_str_functs[]= {ERR_PACK(0,EVP_F_EVP_OPENINIT,0), "EVP_OpenInit"}, {ERR_PACK(0,EVP_F_EVP_PBE_ALGOR_CIPHERINIT,0), "EVP_PBE_ALGOR_CipherInit"}, {ERR_PACK(0,EVP_F_EVP_PBE_ALG_ADD,0), "EVP_PBE_alg_add"}, -{ERR_PACK(0,EVP_F_EVP_PBE_CIPHERINIT,0), "EVP_PBE_CIPHERINIT"}, +{ERR_PACK(0,EVP_F_EVP_PBE_CIPHERINIT,0), "EVP_PBE_CipherInit"}, {ERR_PACK(0,EVP_F_EVP_PKCS82PKEY,0), "EVP_PKCS82PKEY"}, {ERR_PACK(0,EVP_F_EVP_PKCS8_SET_BROKEN,0), "EVP_PKCS8_SET_BROKEN"}, {ERR_PACK(0,EVP_F_EVP_PKEY2PKCS8,0), "EVP_PKEY2PKCS8"}, diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index d49ae90c77..3f9bf55828 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -112,7 +112,7 @@ int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) } /* Convert the various cipher NIDs and dummies to a proper OID NID */ -int EVP_CIPHER_type(EVP_CIPHER *ctx) +int EVP_CIPHER_type(const EVP_CIPHER *ctx) { int nid; nid = EVP_CIPHER_nid(ctx); diff --git a/crypto/pkcs7/dec.c b/crypto/pkcs7/dec.c index c485d39d1d..7063037bb1 100644 --- a/crypto/pkcs7/dec.c +++ b/crypto/pkcs7/dec.c @@ -144,7 +144,7 @@ again: /* We need to process the data */ /* We cannot support detached encryption */ - p7bio=PKCS7_dataDecode(p7,pkey,detached,cert_store); + p7bio=PKCS7_dataDecode(p7,pkey,detached,x509); if (p7bio == NULL) { diff --git a/crypto/pkcs7/pk7_doit.c b/crypto/pkcs7/pk7_doit.c index 030bc92eeb..7a537eeb4e 100644 --- a/crypto/pkcs7/pk7_doit.c +++ b/crypto/pkcs7/pk7_doit.c @@ -88,23 +88,25 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; - evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(p7->d.signed_and_enveloped->enc_data->algorithm->algorithm))); + xalg=p7->d.signed_and_enveloped->enc_data->algorithm; + evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher; if (evp_cipher == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + PKCS7err(PKCS7_F_PKCS7_DATAINIT, + PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } - xalg=p7->d.signed_and_enveloped->enc_data->algorithm; break; case NID_pkcs7_enveloped: rsk=p7->d.enveloped->recipientinfo; - evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(p7->d.enveloped->enc_data->algorithm->algorithm))); + xalg=p7->d.enveloped->enc_data->algorithm; + evp_cipher=p7->d.enveloped->enc_data->cipher; if (evp_cipher == NULL) { - PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + PKCS7err(PKCS7_F_PKCS7_DATAINIT, + PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } - xalg=p7->d.enveloped->enc_data->algorithm; break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); @@ -146,24 +148,28 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) int keylen,ivlen; int jj,max; unsigned char *tmp; + EVP_CIPHER_CTX *ctx; if ((btmp=BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); goto err; } + BIO_get_cipher_ctx(btmp, &ctx); keylen=EVP_CIPHER_key_length(evp_cipher); ivlen=EVP_CIPHER_iv_length(evp_cipher); + RAND_bytes(key,keylen); + EVP_CipherInit(ctx, evp_cipher, key, iv, 1); + memset(key, 0, keylen); + xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); if (ivlen > 0) { - EVP_CIPHER_CTX *ctx; - BIO_get_cipher_ctx(btmp, &ctx); + RAND_bytes(iv,ivlen); if (xalg->parameter == NULL) xalg->parameter=ASN1_TYPE_new(); if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) goto err; } - RAND_bytes(key,keylen); /* Lets do the pub key stuff :-) */ max=0; @@ -201,8 +207,6 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) } Free(tmp); - BIO_set_cipher(btmp,evp_cipher,key,iv,1); - if (out == NULL) out=btmp; else @@ -249,8 +253,7 @@ err: } /* int */ -BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, - X509_STORE *xs) +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; @@ -286,7 +289,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm))); if (evp_cipher == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } xalg=p7->d.signed_and_enveloped->enc_data->algorithm; @@ -298,13 +301,13 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm))); if (evp_cipher == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } xalg=p7->d.enveloped->enc_data->algorithm; break; default: - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } @@ -316,7 +319,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, xa=(X509_ALGOR *)sk_value(md_sk,i); if ((btmp=BIO_new(BIO_f_md())) == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } @@ -324,7 +327,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, evp_md=EVP_get_digestbyname(OBJ_nid2sn(j)); if (evp_md == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_UNKNOWN_DIGEST_TYPE); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); goto err; } @@ -351,50 +354,36 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, if ((etmp=BIO_new(BIO_f_cipher())) == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_BIO_LIB); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } /* It was encrypted, we need to decrypt the secret key * with the private key */ - /* We need to find a private key for one of the people in the - * recipentinfo list */ - if (rsk == NULL) - return(NULL); - - /* FIXME: this assumes that the passed private key - * corresponds to the first RecipientInfo. This in - * general is not true + /* Find the recipientInfo which matches the passed certificate + * (if any) */ - ri=(PKCS7_RECIP_INFO *)sk_value(rsk,0); -#if 0 - X509_STORE_CTX_init(&s_ctx,xs,NULL,NULL); - for (i=0; iissuer_and_serial->issuer, - ri->issuer_and_serial->serial, - &ret)) - break; + if(!X509_NAME_cmp(ri->issuer_and_serial->issuer, + pcert->cert_info->issuer) && + !ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, + ri->issuer_and_serial->serial)) break; ri=NULL; - } - if (ri == NULL) return(NULL); - pkey=ret.data.pkey; -#endif - if (pkey == NULL) - { + } + if (ri == NULL) { + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); return(NULL); - } + } jj=EVP_PKEY_size(pkey); tmp=Malloc(jj+10); if (tmp == NULL) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_MALLOC_FAILURE); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE); goto err; } @@ -404,7 +393,7 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, pkey); if (jj <= 0) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,ERR_R_EVP_LIB); + PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB); goto err; } @@ -416,7 +405,8 @@ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { - PKCS7err(PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); + PKCS7err(PKCS7_F_PKCS7_DATADECODE, + PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); goto err; } EVP_CipherInit(evp_ctx,NULL,(unsigned char *)tmp,NULL,0); diff --git a/crypto/pkcs7/pk7_lib.c b/crypto/pkcs7/pk7_lib.c index ea3a5a2c76..b931ac7e08 100644 --- a/crypto/pkcs7/pk7_lib.c +++ b/crypto/pkcs7/pk7_lib.c @@ -422,7 +422,7 @@ X509 *PKCS7_cert_from_signer_info(PKCS7 *p7, PKCS7_SIGNER_INFO *si) return(NULL); } -int PKCS7_set_cipher(PKCS7 *p7, EVP_CIPHER *cipher) +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher) { int i; PKCS7_ENC_CONTENT *ec; @@ -441,7 +441,9 @@ int PKCS7_set_cipher(PKCS7 *p7, EVP_CIPHER *cipher) return(0); } - ec->algorithm->algorithm=OBJ_nid2obj(EVP_CIPHER_type(cipher)); - return(ec->algorithm->algorithm != NULL); + /* Setup cipher OID */ + + ec->cipher = cipher; + return 1; } diff --git a/crypto/pkcs7/pkcs7.h b/crypto/pkcs7/pkcs7.h index 4afde8274b..5d3215ed0b 100644 --- a/crypto/pkcs7/pkcs7.h +++ b/crypto/pkcs7/pkcs7.h @@ -120,6 +120,7 @@ typedef struct pkcs7_enc_content_st ASN1_OBJECT *content_type; X509_ALGOR *algorithm; ASN1_OCTET_STRING *enc_data; /* [ 0 ] */ + const EVP_CIPHER *cipher; } PKCS7_ENC_CONTENT; typedef struct pkcs7_enveloped_st @@ -128,7 +129,7 @@ typedef struct pkcs7_enveloped_st STACK /* PKCS7_RECIP_INFO */ *recipientinfo; PKCS7_ENC_CONTENT *enc_data; } PKCS7_ENVELOPE; - + typedef struct pkcs7_signedandenveloped_st { ASN1_INTEGER *version; /* version 1 */ @@ -324,7 +325,7 @@ int PKCS7_dataVerify(X509_STORE *cert_store, X509_STORE_CTX *ctx, BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio); int PKCS7_dataFinal(PKCS7 *p7, BIO *bio); -BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509_STORE *xs); +BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert); PKCS7_SIGNER_INFO *PKCS7_add_signature(PKCS7 *p7, X509 *x509, @@ -335,7 +336,7 @@ STACK *PKCS7_get_signer_info(PKCS7 *p7); PKCS7_RECIP_INFO *PKCS7_add_recipient(PKCS7 *p7, X509 *x509); int PKCS7_add_recipient_info(PKCS7 *p7, PKCS7_RECIP_INFO *ri); int PKCS7_RECIP_INFO_set(PKCS7_RECIP_INFO *p7i, X509 *x509); -int PKCS7_set_cipher(PKCS7 *p7, EVP_CIPHER *cipher); +int PKCS7_set_cipher(PKCS7 *p7, const EVP_CIPHER *cipher); PKCS7_ISSUER_AND_SERIAL *PKCS7_get_issuer_and_serial(PKCS7 *p7, int idx); ASN1_OCTET_STRING *PKCS7_digest_from_attributes(STACK *sk); @@ -363,19 +364,21 @@ int PKCS7_set_attributes(PKCS7_SIGNER_INFO *p7si, STACK *sk); #define PKCS7_F_PKCS7_ADD_RECIPIENT_INFO 102 #define PKCS7_F_PKCS7_ADD_SIGNER 103 #define PKCS7_F_PKCS7_CTRL 104 +#define PKCS7_F_PKCS7_DATADECODE 112 #define PKCS7_F_PKCS7_DATAINIT 105 #define PKCS7_F_PKCS7_DATASIGN 106 #define PKCS7_F_PKCS7_DATAVERIFY 107 #define PKCS7_F_PKCS7_SET_CIPHER 108 #define PKCS7_F_PKCS7_SET_CONTENT 109 #define PKCS7_F_PKCS7_SET_TYPE 110 -#define PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT 111 /* Reason codes. */ +#define PKCS7_R_CIPHER_NOT_INITIALIZED 116 #define PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH 100 #define PKCS7_R_DIGEST_FAILURE 101 #define PKCS7_R_INTERNAL_ERROR 102 #define PKCS7_R_MISSING_CERIPEND_INFO 103 +#define PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE 115 #define PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE 104 #define PKCS7_R_SIGNATURE_FAILURE 105 #define PKCS7_R_UNABLE_TO_FIND_CERTIFICATE 106 diff --git a/crypto/pkcs7/pkcs7err.c b/crypto/pkcs7/pkcs7err.c index d0cc96c58a..99e4a44623 100644 --- a/crypto/pkcs7/pkcs7err.c +++ b/crypto/pkcs7/pkcs7err.c @@ -70,22 +70,24 @@ static ERR_STRING_DATA PKCS7_str_functs[]= {ERR_PACK(0,PKCS7_F_PKCS7_ADD_RECIPIENT_INFO,0), "PKCS7_add_recipient_info"}, {ERR_PACK(0,PKCS7_F_PKCS7_ADD_SIGNER,0), "PKCS7_add_signer"}, {ERR_PACK(0,PKCS7_F_PKCS7_CTRL,0), "PKCS7_ctrl"}, +{ERR_PACK(0,PKCS7_F_PKCS7_DATADECODE,0), "PKCS7_dataDecode"}, {ERR_PACK(0,PKCS7_F_PKCS7_DATAINIT,0), "PKCS7_dataInit"}, {ERR_PACK(0,PKCS7_F_PKCS7_DATASIGN,0), "PKCS7_DATASIGN"}, {ERR_PACK(0,PKCS7_F_PKCS7_DATAVERIFY,0), "PKCS7_dataVerify"}, {ERR_PACK(0,PKCS7_F_PKCS7_SET_CIPHER,0), "PKCS7_set_cipher"}, {ERR_PACK(0,PKCS7_F_PKCS7_SET_CONTENT,0), "PKCS7_set_content"}, {ERR_PACK(0,PKCS7_F_PKCS7_SET_TYPE,0), "PKCS7_set_type"}, -{ERR_PACK(0,PKCS7_F_PKCS7_SIGNENVELOPEDECRYPT,0), "PKCS7_SIGNENVELOPEDECRYPT"}, {0,NULL} }; static ERR_STRING_DATA PKCS7_str_reasons[]= { +{PKCS7_R_CIPHER_NOT_INITIALIZED ,"cipher not initialized"}, {PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH ,"decrypted key is wrong length"}, {PKCS7_R_DIGEST_FAILURE ,"digest failure"}, {PKCS7_R_INTERNAL_ERROR ,"internal error"}, {PKCS7_R_MISSING_CERIPEND_INFO ,"missing ceripend info"}, +{PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE,"no recipient matches certificate"}, {PKCS7_R_OPERATION_NOT_SUPPORTED_ON_THIS_TYPE,"operation not supported on this type"}, {PKCS7_R_SIGNATURE_FAILURE ,"signature failure"}, {PKCS7_R_UNABLE_TO_FIND_CERTIFICATE ,"unable to find certificate"},