Commit 399a6f0b authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Update PKCS#7 enveloped data to new API.

parent 3d479299
Loading
Loading
Loading
Loading
+8 −1
Original line number Original line Diff line number Diff line
@@ -2,7 +2,14 @@
 OpenSSL CHANGES
 OpenSSL CHANGES
 _______________
 _______________


 Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]
 Changes between 0.9.8b and 0.9.9  [xx XXX xxxx]

  *) Update PKCS#7 enveloped data routines to use new API. This is now
     supported by any public key method supporting the encrypt operation. A
     ctrl is added to allow the public key algorithm to examine or modify
     the PKCS#7 RecipientInfo structure if it needs to: for RSA this is
     a no op.
     [Steve Henson]


  *) Add a ctrl to asn1 method to allow a public key algorithm to express
  *) Add a ctrl to asn1 method to allow a public key algorithm to express
     a default digest type to use. In most cases this will be SHA1 but some
     a default digest type to use. In most cases this will be SHA1 but some
+1 −0
Original line number Original line Diff line number Diff line
@@ -765,6 +765,7 @@ int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b);
  /* Since this is used to store all sorts of things, via macros, for now, make
  /* Since this is used to store all sorts of things, via macros, for now, make
     its data void * */
     its data void * */
int 		ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
int 		ASN1_STRING_set(ASN1_STRING *str, const void *data, int len);
void		ASN1_STRING_set0(ASN1_STRING *str, void *data, int len);
int ASN1_STRING_length(const ASN1_STRING *x);
int ASN1_STRING_length(const ASN1_STRING *x);
void ASN1_STRING_length_set(ASN1_STRING *x, int n);
void ASN1_STRING_length_set(ASN1_STRING *x, int n);
int ASN1_STRING_type(ASN1_STRING *x);
int ASN1_STRING_type(ASN1_STRING *x);
+8 −0
Original line number Original line Diff line number Diff line
@@ -393,6 +393,14 @@ int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
	return(1);
	return(1);
	}
	}


void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
	{
	if (str->data)
		OPENSSL_free(str->data);
	str->data = data;
	str->length = len;
	}

ASN1_STRING *ASN1_STRING_new(void)
ASN1_STRING *ASN1_STRING_new(void)
	{
	{
	return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
	return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
+4 −1
Original line number Original line Diff line number Diff line
@@ -884,6 +884,9 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
#define EVP_PKEY_CTRL_MD		1
#define EVP_PKEY_CTRL_MD		1
#define EVP_PKEY_CTRL_PEER_KEY		2	
#define EVP_PKEY_CTRL_PEER_KEY		2	


#define EVP_PKEY_CTRL_PKCS7_ENCRYPT	3	
#define EVP_PKEY_CTRL_PKCS7_DECRYPT	4	

#define EVP_PKEY_ALG_CTRL		0x1000
#define EVP_PKEY_ALG_CTRL		0x1000


#define EVP_PKEY_FLAG_AUTOARGLEN	2
#define EVP_PKEY_FLAG_AUTOARGLEN	2
+61 −38
Original line number Original line Diff line number Diff line
@@ -138,6 +138,66 @@ 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;
	int 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;

	}



BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
	{
	{
	int i;
	int i;
@@ -148,7 +208,6 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
	X509_ALGOR *xalg=NULL;
	X509_ALGOR *xalg=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
	PKCS7_RECIP_INFO *ri=NULL;
	EVP_PKEY *pkey;
	ASN1_OCTET_STRING *os=NULL;
	ASN1_OCTET_STRING *os=NULL;


	i=OBJ_obj2nid(p7->type);
	i=OBJ_obj2nid(p7->type);
@@ -204,8 +263,6 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char key[EVP_MAX_KEY_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		unsigned char iv[EVP_MAX_IV_LENGTH];
		int keylen,ivlen;
		int keylen,ivlen;
		int jj,max;
		unsigned char *tmp;
		EVP_CIPHER_CTX *ctx;
		EVP_CIPHER_CTX *ctx;


		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
		if ((btmp=BIO_new(BIO_f_cipher())) == NULL)
@@ -233,46 +290,12 @@ BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio)
		}
		}


		/* Lets do the pub key stuff :-) */
		/* Lets do the pub key stuff :-) */
		max=0;
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
			{
			{
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			if (ri->cert == NULL)
			if (pkcs7_encode_rinfo(ri, key, keylen) <= 0)
				{
				PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO);
				goto err;
				}
			pkey=X509_get_pubkey(ri->cert);
			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;
				goto err;
			}
			}
		for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++)
			{
			ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
			pkey=X509_get_pubkey(ri->cert);
			jj=EVP_PKEY_encrypt_old(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);
				goto err;
				}
			}
		OPENSSL_free(tmp);
		OPENSSL_cleanse(key, keylen);
		OPENSSL_cleanse(key, keylen);


		if (out == NULL)
		if (out == NULL)
Loading