diff --git a/CHANGES b/CHANGES index 0c6d47cfda342ae4f67bdd64a3340a639e7986d2..93a7739a9ea053e2a385ddc5511b079ecae2b91a 100644 --- a/CHANGES +++ b/CHANGES @@ -5,6 +5,17 @@ Changes between 0.9.3a and 0.9.4 + *) Rewrite the way password based encryption (PBE) is handled. It used to + assume that the ASN1 AlgorithmIdentifier parameter was a PBEParameter + structure. This was true for the PKCS#5 v1.5 and PKCS#12 PBE algorithms + but doesn't apply to PKCS#5 v2.0 where it can be something else. Now + the 'parameter' field of the AlgorithmIdentifier is passed to the + underlying key generation function so it must do its own ASN1 parsing. + This has also changed the EVP_PBE_CipherInit() function which now has a + 'parameter' argument instead of literal salt and iteration count values + and the function EVP_PBE_ALGOR_CipherInit() has been deleted. + [Steve Henson] + *) Support for PKCS#5 v1.5 compatible password based encryption algorithms and PKCS#8 functionality. New 'pkcs8' application linked to openssl. Needed to change the PEM_STRING_EVP_PKEY value which was just "PRIVATE diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 3d5b27f389a3ac5670765eef60e3d7c2ac63e2a9..5e12b21f9c5e901115e8c22ce996d17a53e13420 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -396,7 +396,7 @@ typedef struct evp_Encode_Ctx_st /* Password based encryption function */ typedef int (EVP_PBE_KEYGEN)(const char *pass, int passlen, - unsigned char *salt, int saltlen, int iter, EVP_CIPHER *cipher, + ASN1_TYPE *param, EVP_CIPHER *cipher, EVP_MD *md, unsigned char *key, unsigned char *iv); #define EVP_PKEY_assign_RSA(pkey,rsa) EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\ @@ -635,12 +635,18 @@ int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type); int EVP_CIPHER_get_asn1_iv(EVP_CIPHER_CTX *c,ASN1_TYPE *type); /* PKCS5 password based encryption */ -int PKCS5_PBE_keyivgen(const char *pass, int passlen, unsigned char *salt, - int saltlen, int iter, EVP_CIPHER *cipher, EVP_MD *md, +int PKCS5_PBE_keyivgen(const char *pass, int passlen, ASN1_TYPE *param, + EVP_CIPHER *cipher, EVP_MD *md, unsigned char *key, unsigned char *iv); void PKCS5_PBE_add(void); +int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de); +int EVP_PBE_alg_add(int nid, EVP_CIPHER *cipher, EVP_MD *md, + EVP_PBE_KEYGEN *keygen); +void EVP_PBE_cleanup(void); + /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. @@ -653,9 +659,9 @@ void PKCS5_PBE_add(void); #define EVP_F_EVP_DECRYPTFINAL 101 #define EVP_F_EVP_MD_CTX_COPY 110 #define EVP_F_EVP_OPENINIT 102 -#define EVP_F_EVP_PBE_ALGOR_CIPHERINIT 114 #define EVP_F_EVP_PBE_ALG_ADD 115 #define EVP_F_EVP_PBE_CIPHERINIT 116 +#define EVP_F_EVP_PKCS5_PBE_KEYIVGEN 117 #define EVP_F_EVP_PKCS82PKEY 111 #define EVP_F_EVP_PKCS8_SET_BROKEN 112 #define EVP_F_EVP_PKEY2PKCS8 113 diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c index 63ce3ae17d3c7fdfd41bd4c0ee937a87ee0d1e61..cd00af8b77da458a221e47dee2a418bc4c2a4e59 100644 --- a/crypto/evp/evp_err.c +++ b/crypto/evp/evp_err.c @@ -69,9 +69,9 @@ static ERR_STRING_DATA EVP_str_functs[]= {ERR_PACK(0,EVP_F_EVP_DECRYPTFINAL,0), "EVP_DecryptFinal"}, {ERR_PACK(0,EVP_F_EVP_MD_CTX_COPY,0), "EVP_MD_CTX_copy"}, {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_PKCS5_PBE_KEYIVGEN,0), "EVP_PKCS5_PBE_KEYIVGEN"}, {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_pbe.c b/crypto/evp/evp_pbe.c index 848edddd8c9257e7393fac30ba838162ca94a5d4..abc4d0683c1e70f38010c8200d7074966fede6de 100644 --- a/crypto/evp/evp_pbe.c +++ b/crypto/evp/evp_pbe.c @@ -75,8 +75,7 @@ EVP_PBE_KEYGEN *keygen; } EVP_PBE_CTL; int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, - unsigned char *salt, int saltlen, int iter, EVP_CIPHER_CTX *ctx, - int en_de) + ASN1_TYPE *param, EVP_CIPHER_CTX *ctx, int en_de) { EVP_PBE_CTL *pbetmp, pbelu; @@ -96,8 +95,8 @@ int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, } if (passlen == -1) passlen = strlen(pass); pbetmp = (EVP_PBE_CTL *)sk_value (pbe_algs, i); - i = (*pbetmp->keygen)(pass, passlen, salt, saltlen, iter, - pbetmp->cipher, pbetmp->md, key, iv); + i = (*pbetmp->keygen)(pass, passlen, param, pbetmp->cipher, + pbetmp->md, key, iv); if (!i) { EVPerr(EVP_F_EVP_PBE_CIPHERINIT,EVP_R_KEYGEN_FAILURE); return 0; @@ -106,39 +105,6 @@ int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, return 1; } -/* Setup a PBE algorithm but take most parameters from AlgorithmIdentifier */ - -int EVP_PBE_ALGOR_CipherInit (X509_ALGOR *algor, const char *pass, - int passlen, EVP_CIPHER_CTX *ctx, int en_de) -{ - PBEPARAM *pbe; - int saltlen, iter; - unsigned char *salt, *pbuf; - - /* Extract useful info from algor */ - pbuf = algor->parameter->value.sequence->data; - if (!(pbe = d2i_PBEPARAM (NULL, &pbuf, - algor->parameter->value.sequence->length))) { - EVPerr(EVP_F_EVP_PBE_ALGOR_CIPHERINIT,EVP_R_DECODE_ERROR); - return 0; - } - - if (!pbe->iter) iter = 1; - else iter = ASN1_INTEGER_get (pbe->iter); - salt = pbe->salt->data; - saltlen = pbe->salt->length; - - if (!(EVP_PBE_CipherInit (algor->algorithm, pass, passlen, salt, - saltlen, iter, ctx, en_de))) { - EVPerr(EVP_F_EVP_PBE_ALGOR_CIPHERINIT,EVP_R_EVP_PBE_CIPHERINIT_ERROR); - PBEPARAM_free(pbe); - return 0; - } - PBEPARAM_free(pbe); - return 1; -} - - static int pbe_cmp (EVP_PBE_CTL **pbe1, EVP_PBE_CTL **pbe2) { return ((*pbe1)->pbe_nid - (*pbe2)->pbe_nid); diff --git a/crypto/evp/p5_crpt.c b/crypto/evp/p5_crpt.c index 11bf88b96d84e64bb23e7622ef6dda4855748b63..857835bc74358ce5b2c7413a21509a9003223b7e 100644 --- a/crypto/evp/p5_crpt.c +++ b/crypto/evp/p5_crpt.c @@ -85,16 +85,34 @@ EVP_PBE_alg_add(NID_pbeWithSHA1AndRC2_CBC, EVP_rc2_64_cbc(), EVP_sha1(), #endif } -int PKCS5_PBE_keyivgen(const char *pass, int passlen, unsigned char *salt, - int saltlen, int iter, EVP_CIPHER *cipher, EVP_MD *md, +int PKCS5_PBE_keyivgen(const char *pass, int passlen, ASN1_TYPE *param, + EVP_CIPHER *cipher, EVP_MD *md, unsigned char *key, unsigned char *iv) { EVP_MD_CTX ctx; unsigned char md_tmp[EVP_MAX_MD_SIZE]; int i; + PBEPARAM *pbe; + int saltlen, iter; + unsigned char *salt, *pbuf; + + /* Extract useful info from parameter */ + pbuf = param->value.sequence->data; + if (!(pbe = d2i_PBEPARAM (NULL, &pbuf, + param->value.sequence->length))) { + EVPerr(EVP_F_EVP_PKCS5_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) iter = 1; + else iter = ASN1_INTEGER_get (pbe->iter); + salt = pbe->salt->data; + saltlen = pbe->salt->length; + EVP_DigestInit (&ctx, md); EVP_DigestUpdate (&ctx, pass, passlen); EVP_DigestUpdate (&ctx, salt, saltlen); + PBEPARAM_free(pbe); EVP_DigestFinal (&ctx, md_tmp, NULL); for (i = 1; i < iter; i++) { EVP_DigestInit(&ctx, md); diff --git a/crypto/pkcs12/p12_crpt.c b/crypto/pkcs12/p12_crpt.c index 9e37436c925e02e29c0f275abce9101f70947e0d..cb65c4200079b2263369d027df2b7e6e1a8c4982 100644 --- a/crypto/pkcs12/p12_crpt.c +++ b/crypto/pkcs12/p12_crpt.c @@ -82,19 +82,38 @@ EVP_PBE_alg_add(NID_pbe_WithSHA1And40BitRC2_CBC, EVP_rc2_40_cbc(), #endif } -int PKCS12_PBE_keyivgen (const char *pass, int passlen, unsigned char *salt, - int saltlen, int iter, EVP_CIPHER *cipher, EVP_MD *md, +int PKCS12_PBE_keyivgen (const char *pass, int passlen, ASN1_TYPE *param, + EVP_CIPHER *cipher, EVP_MD *md, unsigned char *key, unsigned char *iv) { + PBEPARAM *pbe; + int saltlen, iter; + unsigned char *salt, *pbuf; + + /* Extract useful info from parameter */ + pbuf = param->value.sequence->data; + if (!(pbe = d2i_PBEPARAM (NULL, &pbuf, + param->value.sequence->length))) { + EVPerr(PKCS12_F_PKCS12_PBE_KEYIVGEN,EVP_R_DECODE_ERROR); + return 0; + } + + if (!pbe->iter) iter = 1; + else iter = ASN1_INTEGER_get (pbe->iter); + salt = pbe->salt->data; + saltlen = pbe->salt->length; if (!PKCS12_key_gen (pass, passlen, salt, saltlen, PKCS12_KEY_ID, iter, EVP_CIPHER_key_length(cipher), key, md)) { PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN,PKCS12_R_KEY_GEN_ERROR); + PBEPARAM_free(pbe); return 0; } if (!PKCS12_key_gen (pass, passlen, salt, saltlen, PKCS12_IV_ID, iter, EVP_CIPHER_iv_length(cipher), iv, md)) { PKCS12err(PKCS12_F_PKCS12_PBE_KEYIVGEN,PKCS12_R_IV_GEN_ERROR); + PBEPARAM_free(pbe); return 0; } + PBEPARAM_free(pbe); return 1; } diff --git a/crypto/pkcs12/p12_decr.c b/crypto/pkcs12/p12_decr.c index 53fb8aad0fe7940bf2b920b4eff2b63cd7af4eba..8f502fae7fe6c1df3435be72bb83e4dde3fec9ba 100644 --- a/crypto/pkcs12/p12_decr.c +++ b/crypto/pkcs12/p12_decr.c @@ -82,7 +82,8 @@ unsigned char * PKCS12_pbe_crypt (X509_ALGOR *algor, const char *pass, } /* Decrypt data */ - if (!EVP_PBE_ALGOR_CipherInit (algor, pass, passlen, &ctx, en_de)) { + if (!EVP_PBE_CipherInit (algor->algorithm, pass, passlen, + algor->parameter, &ctx, en_de)) { PKCS12err(PKCS12_F_PKCS12_PBE_CRYPT,PKCS12_R_PKCS12_ALGOR_CIPHERINIT_ERROR); return NULL; } diff --git a/crypto/pkcs12/pkcs12.h b/crypto/pkcs12/pkcs12.h index 459962c1a35f725cee585f3189a5a8ff86174bae..12ef0e5146b572590cc4ab9186f5fa1372ce3ff3 100644 --- a/crypto/pkcs12/pkcs12.h +++ b/crypto/pkcs12/pkcs12.h @@ -230,13 +230,17 @@ int PKCS12_key_gen_asc(const char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type); int PKCS12_key_gen_uni(unsigned char *pass, int passlen, unsigned char *salt, int saltlen, int id, int iter, int n, unsigned char *out, const EVP_MD *md_type); -int PKCS12_PBE_keyivgen(const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, EVP_CIPHER *cipher, EVP_MD *md_type, unsigned char *key, unsigned char *iv); -int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *mac, unsigned int *maclen); +int PKCS12_PBE_keyivgen(const char *pass, int passlen, ASN1_TYPE *param, + EVP_CIPHER *cipher, EVP_MD *md_type, + unsigned char *key, unsigned char *iv); +int PKCS12_gen_mac(PKCS12 *p12, const char *pass, int passlen, + unsigned char *mac, unsigned int *maclen); int PKCS12_verify_mac(PKCS12 *p12, const char *pass, int passlen); int PKCS12_set_mac(PKCS12 *p12, const char *pass, int passlen, unsigned char *salt, int saltlen, int iter, EVP_MD *md_type); -int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, int saltlen, EVP_MD *md_type); +int PKCS12_setup_mac(PKCS12 *p12, int iter, unsigned char *salt, + int saltlen, EVP_MD *md_type); unsigned char *asc2uni(const char *asc, unsigned char **uni, int *unilen); char *uni2asc(unsigned char *uni, int unilen); int i2d_PKCS12_BAGS(PKCS12_BAGS *a, unsigned char **pp); @@ -249,17 +253,21 @@ PKCS12 *PKCS12_new(void); void PKCS12_free(PKCS12 *a); int i2d_PKCS12_MAC_DATA(PKCS12_MAC_DATA *a, unsigned char **pp); PKCS12_MAC_DATA *PKCS12_MAC_DATA_new(void); -PKCS12_MAC_DATA *d2i_PKCS12_MAC_DATA(PKCS12_MAC_DATA **a, unsigned char **pp, long length); +PKCS12_MAC_DATA *d2i_PKCS12_MAC_DATA(PKCS12_MAC_DATA **a, unsigned char **pp, + long length); void PKCS12_MAC_DATA_free(PKCS12_MAC_DATA *a); int i2d_PKCS12_SAFEBAG(PKCS12_SAFEBAG *a, unsigned char **pp); PKCS12_SAFEBAG *PKCS12_SAFEBAG_new(void); -PKCS12_SAFEBAG *d2i_PKCS12_SAFEBAG(PKCS12_SAFEBAG **a, unsigned char **pp, long length); +PKCS12_SAFEBAG *d2i_PKCS12_SAFEBAG(PKCS12_SAFEBAG **a, unsigned char **pp, + long length); void PKCS12_SAFEBAG_free(PKCS12_SAFEBAG *a); void ERR_load_PKCS12_strings(void); void PKCS12_PBE_add(void); int PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert, STACK **ca); -PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, STACK *ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype); +PKCS12 *PKCS12_create(char *pass, char *name, EVP_PKEY *pkey, X509 *cert, + STACK *ca, int nid_key, int nid_cert, int iter, + int mac_iter, int keytype); int i2d_PKCS12_bio(BIO *bp, PKCS12 *p12); int i2d_PKCS12_fp(FILE *fp, PKCS12 *p12); PKCS12 *d2i_PKCS12_bio(BIO *bp, PKCS12 **p12); diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index 0ed0494d21d94c5cb21b1085003e71832767db3b..5106f2e5921d68153293454f571d04f51bdf10ab 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -929,17 +929,6 @@ EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8); PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey); PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken); -/* Password based encryption routines */ - -int EVP_PBE_CipherInit (ASN1_OBJECT *pbe_obj, const char *pass, int passlen, - unsigned char *salt, int saltlen, int iter, EVP_CIPHER_CTX *ctx, - int en_de); -int EVP_PBE_ALGOR_CipherInit(X509_ALGOR *algor, const char *pass, - int passlen, EVP_CIPHER_CTX *ctx, int en_de); -int EVP_PBE_alg_add(int nid, EVP_CIPHER *cipher, EVP_MD *md, - EVP_PBE_KEYGEN *keygen); -void EVP_PBE_cleanup(void); - /* BEGIN ERROR CODES */ /* The following lines are auto generated by the script mkerr.pl. Any changes * made after this point may be overwritten when the script is next run. diff --git a/util/libeay.num b/util/libeay.num index 3a2dd41a17ea2219847d9c5b2eead248895b1002..f3aaa2dc13fea4c368532e8ff56aa3ead4835529 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -1747,3 +1747,21 @@ sk_X509_LOOKUP_delete_ptr 1771 sk_X509_LOOKUP_set 1772 sk_PKCS7_RECIP_INFO_find 1773 sk_PKCS7_RECIP_INFO_delete 1774 +PKCS5_PBE_add 1775 +PEM_write_bio_PKCS8 1776 +i2d_PKCS8_fp 1777 +PEM_read_bio_PKCS8_PRIV_KEY_INFO 1778 +d2i_PKCS8_bio 1779 +d2i_PKCS8_PRIV_KEY_INFO_fp 1780 +PEM_write_bio_PKCS8_PRIV_KEY_INFO 1781 +PEM_read_PKCS8 1782 +d2i_PKCS8_PRIV_KEY_INFO_bio 1783 +d2i_PKCS8_fp 1784 +PEM_write_PKCS8 1785 +PEM_read_PKCS8_PRIV_KEY_INFO 1786 +PEM_read_bio_PKCS8 1787 +PEM_write_PKCS8_PRIV_KEY_INFO 1788 +PKCS5_PBE_keyivgen 1789 +i2d_PKCS8_bio 1790 +i2d_PKCS8_PRIV_KEY_INFO_fp 1791 +i2d_PKCS8_PRIV_KEY_INFO_bio 1792