Index: openssl/crypto/asn1/p5_pbev2.c |
=================================================================== |
--- openssl/crypto/asn1/p5_pbev2.c (revision 105093) |
+++ openssl/crypto/asn1/p5_pbev2.c (working copy) |
@@ -82,10 +82,13 @@ |
/* Return an algorithm identifier for a PKCS#5 v2.0 PBE algorithm: |
* yes I know this is horrible! |
+ * |
+ * Extended version to allow application supplied PRF NID and IV. |
*/ |
-X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, |
- unsigned char *salt, int saltlen) |
+X509_ALGOR *PKCS5_pbe2_set_iv(const EVP_CIPHER *cipher, int iter, |
+ unsigned char *salt, int saltlen, |
+ unsigned char *aiv, int prf_nid) |
{ |
X509_ALGOR *scheme = NULL, *kalg = NULL, *ret = NULL; |
int alg_nid; |
@@ -98,7 +101,7 @@ |
alg_nid = EVP_CIPHER_type(cipher); |
if(alg_nid == NID_undef) { |
- ASN1err(ASN1_F_PKCS5_PBE2_SET, |
+ ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, |
ASN1_R_CIPHER_HAS_NO_OBJECT_IDENTIFIER); |
goto err; |
} |
@@ -113,20 +116,33 @@ |
if(!(scheme->parameter = ASN1_TYPE_new())) goto merr; |
/* Create random IV */ |
- if (EVP_CIPHER_iv_length(cipher) && |
- RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) |
- goto err; |
+ if (EVP_CIPHER_iv_length(cipher)) |
+ { |
+ if (aiv) |
+ memcpy(iv, aiv, EVP_CIPHER_iv_length(cipher)); |
+ else if (RAND_pseudo_bytes(iv, EVP_CIPHER_iv_length(cipher)) < 0) |
+ goto err; |
+ } |
EVP_CIPHER_CTX_init(&ctx); |
- /* Dummy cipherinit to just setup the IV */ |
+ /* Dummy cipherinit to just setup the IV, and PRF */ |
EVP_CipherInit_ex(&ctx, cipher, NULL, NULL, iv, 0); |
if(EVP_CIPHER_param_to_asn1(&ctx, scheme->parameter) < 0) { |
- ASN1err(ASN1_F_PKCS5_PBE2_SET, |
+ ASN1err(ASN1_F_PKCS5_PBE2_SET_IV, |
ASN1_R_ERROR_SETTING_CIPHER_PARAMS); |
EVP_CIPHER_CTX_cleanup(&ctx); |
goto err; |
} |
+ /* If prf NID unspecified see if cipher has a preference. |
+ * An error is OK here: just means use default PRF. |
+ */ |
+ if ((prf_nid == -1) && |
+ EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_PBE_PRF_NID, 0, &prf_nid) <= 0) |
+ { |
+ ERR_clear_error(); |
+ prf_nid = NID_hmacWithSHA1; |
+ } |
EVP_CIPHER_CTX_cleanup(&ctx); |
if(!(kdf = PBKDF2PARAM_new())) goto merr; |
@@ -154,7 +170,15 @@ |
EVP_CIPHER_key_length(cipher))) goto merr; |
} |
- /* prf can stay NULL because we are using hmacWithSHA1 */ |
+ /* prf can stay NULL if we are using hmacWithSHA1 */ |
+ if (prf_nid != NID_hmacWithSHA1) |
+ { |
+ kdf->prf = X509_ALGOR_new(); |
+ if (!kdf->prf) |
+ goto merr; |
+ X509_ALGOR_set0(kdf->prf, OBJ_nid2obj(prf_nid), |
+ V_ASN1_NULL, NULL); |
+ } |
/* Now setup the PBE2PARAM keyfunc structure */ |
@@ -164,7 +188,7 @@ |
if(!(pbe2->keyfunc->parameter = ASN1_TYPE_new())) goto merr; |
- if(!ASN1_pack_string_of(PBKDF2PARAM, kdf, i2d_PBKDF2PARAM, |
+ if(!ASN1_item_pack(kdf, ASN1_ITEM_rptr(PBKDF2PARAM), |
&pbe2->keyfunc->parameter->value.sequence)) goto merr; |
pbe2->keyfunc->parameter->type = V_ASN1_SEQUENCE; |
@@ -180,7 +204,7 @@ |
/* Encode PBE2PARAM into parameter */ |
- if(!ASN1_pack_string_of(PBE2PARAM, pbe2, i2d_PBE2PARAM, |
+ if(!ASN1_item_pack(pbe2, ASN1_ITEM_rptr(PBE2PARAM), |
&ret->parameter->value.sequence)) goto merr; |
ret->parameter->type = V_ASN1_SEQUENCE; |
@@ -190,7 +214,7 @@ |
return ret; |
merr: |
- ASN1err(ASN1_F_PKCS5_PBE2_SET,ERR_R_MALLOC_FAILURE); |
+ ASN1err(ASN1_F_PKCS5_PBE2_SET_IV,ERR_R_MALLOC_FAILURE); |
err: |
PBE2PARAM_free(pbe2); |
@@ -203,3 +227,9 @@ |
return NULL; |
} |
+ |
+X509_ALGOR *PKCS5_pbe2_set(const EVP_CIPHER *cipher, int iter, |
+ unsigned char *salt, int saltlen) |
+ { |
+ return PKCS5_pbe2_set_iv(cipher, iter, salt, saltlen, NULL, -1); |
+ } |