Commit 69cbf468 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Rewrite PBE handling read to support PKCS#5 v2.0 and update the function

list for Win32.
parent 095ce353
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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
+10 −4
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -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"},
+3 −37
Original line number Diff line number Diff line
@@ -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);
+20 −2
Original line number Diff line number Diff line
@@ -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);
Loading