Add support for some broken PKCS#8 formats.
This commit is contained in:
		
							
								
								
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							@@ -4,6 +4,10 @@
 | 
			
		||||
 | 
			
		||||
 Changes between 0.9.4 and 0.9.5  [xx XXX 2000]
 | 
			
		||||
 | 
			
		||||
  *) Add support for various broken PKCS#8 formats, and command line
 | 
			
		||||
     options to produce them.
 | 
			
		||||
     [Steve Henson]
 | 
			
		||||
 | 
			
		||||
  *) New functions BN_CTX_start(), BN_CTX_get() and BT_CTX_end() to
 | 
			
		||||
     get temporary BIGNUMs from a BN_CTX.
 | 
			
		||||
     [Ulf M<>ller]
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										19
									
								
								apps/pkcs8.c
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								apps/pkcs8.c
									
									
									
									
									
								
							@@ -124,6 +124,8 @@ int MAIN(int argc, char **argv)
 | 
			
		||||
		else if (!strcmp (*args, "-noiter")) iter = 1;
 | 
			
		||||
		else if (!strcmp (*args, "-nocrypt")) nocrypt = 1;
 | 
			
		||||
		else if (!strcmp (*args, "-nooct")) p8_broken = PKCS8_NO_OCTET;
 | 
			
		||||
		else if (!strcmp (*args, "-nsdb")) p8_broken = PKCS8_NS_DB;
 | 
			
		||||
		else if (!strcmp (*args, "-embed")) p8_broken = PKCS8_EMBEDDED_PARAM;
 | 
			
		||||
		else if (!strcmp(*args,"-passin"))
 | 
			
		||||
			{
 | 
			
		||||
			if (!args[1]) goto bad;
 | 
			
		||||
@@ -183,7 +185,9 @@ int MAIN(int argc, char **argv)
 | 
			
		||||
		BIO_printf(bio_err, "-passout arg    input file pass phrase\n");
 | 
			
		||||
		BIO_printf(bio_err, "-envpassout arg environment variable containing input file pass phrase\n");
 | 
			
		||||
		BIO_printf(bio_err, "-topk8     output PKCS8 file\n");
 | 
			
		||||
		BIO_printf(bio_err, "-nooct     use (broken) no octet form\n");
 | 
			
		||||
		BIO_printf(bio_err, "-nooct     use (nonstandard) no octet format\n");
 | 
			
		||||
		BIO_printf(bio_err, "-embed     use (nonstandard) embedded DSA parameters format\n");
 | 
			
		||||
		BIO_printf(bio_err, "-nsdb      use (nonstandard) DSA Netscape DB format\n");
 | 
			
		||||
		BIO_printf(bio_err, "-noiter    use 1 as iteration count\n");
 | 
			
		||||
		BIO_printf(bio_err, "-nocrypt   use or expect unencrypted private key\n");
 | 
			
		||||
		BIO_printf(bio_err, "-v2 alg    use PKCS#5 v2.0 and cipher \"alg\"\n");
 | 
			
		||||
@@ -224,12 +228,11 @@ int MAIN(int argc, char **argv)
 | 
			
		||||
			return (1);
 | 
			
		||||
		}
 | 
			
		||||
		BIO_free(in);
 | 
			
		||||
		if (!(p8inf = EVP_PKEY2PKCS8(pkey))) {
 | 
			
		||||
		if (!(p8inf = EVP_PKEY2PKCS8_broken(pkey, p8_broken))) {
 | 
			
		||||
			BIO_printf(bio_err, "Error converting key\n", outfile);
 | 
			
		||||
			ERR_print_errors(bio_err);
 | 
			
		||||
			return (1);
 | 
			
		||||
		}
 | 
			
		||||
		PKCS8_set_broken(p8inf, p8_broken);
 | 
			
		||||
		if(nocrypt) {
 | 
			
		||||
			if(outformat == FORMAT_PEM) 
 | 
			
		||||
				PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8inf);
 | 
			
		||||
@@ -316,7 +319,15 @@ int MAIN(int argc, char **argv)
 | 
			
		||||
		BIO_printf(bio_err, "Warning: broken key encoding: ");
 | 
			
		||||
		switch (p8inf->broken) {
 | 
			
		||||
			case PKCS8_NO_OCTET:
 | 
			
		||||
			BIO_printf(bio_err, "No Octet String\n");
 | 
			
		||||
			BIO_printf(bio_err, "No Octet String in PrivateKey\n");
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
			case PKCS8_EMBEDDED_PARAM:
 | 
			
		||||
			BIO_printf(bio_err, "DSA parameters included in PrivateKey\n");
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
			case PKCS8_NS_DB:
 | 
			
		||||
			BIO_printf(bio_err, "DSA public key include in PrivateKey\n");
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
			default:
 | 
			
		||||
 
 | 
			
		||||
@@ -109,8 +109,6 @@ PKCS8_PRIV_KEY_INFO *d2i_PKCS8_PRIV_KEY_INFO(PKCS8_PRIV_KEY_INFO **a,
 | 
			
		||||
	M_ASN1_D2I_get_IMP_set_opt_type(X509_ATTRIBUTE, ret->attributes,
 | 
			
		||||
					d2i_X509_ATTRIBUTE,
 | 
			
		||||
					X509_ATTRIBUTE_free, 0);
 | 
			
		||||
	if (ASN1_TYPE_get(ret->pkey) == V_ASN1_SEQUENCE) 
 | 
			
		||||
						ret->broken = PKCS8_NO_OCTET;
 | 
			
		||||
	M_ASN1_D2I_Finish(a, PKCS8_PRIV_KEY_INFO_free, ASN1_F_D2I_PKCS8_PRIV_KEY_INFO);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -62,19 +62,22 @@
 | 
			
		||||
#include <openssl/x509.h>
 | 
			
		||||
#include <openssl/rand.h>
 | 
			
		||||
 | 
			
		||||
static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8inf, EVP_PKEY *pkey);
 | 
			
		||||
 | 
			
		||||
/* Extract a private key from a PKCS8 structure */
 | 
			
		||||
 | 
			
		||||
EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
 | 
			
		||||
{
 | 
			
		||||
	EVP_PKEY *pkey;
 | 
			
		||||
	EVP_PKEY *pkey = NULL;
 | 
			
		||||
#ifndef NO_RSA
 | 
			
		||||
	RSA *rsa;
 | 
			
		||||
	RSA *rsa = NULL;
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef NO_DSA
 | 
			
		||||
	DSA *dsa;
 | 
			
		||||
	ASN1_INTEGER *dsapriv;
 | 
			
		||||
	STACK *ndsa;
 | 
			
		||||
	BN_CTX *ctx;
 | 
			
		||||
	DSA *dsa = NULL;
 | 
			
		||||
	ASN1_INTEGER *privkey;
 | 
			
		||||
	ASN1_TYPE *t1, *t2, *param = NULL;
 | 
			
		||||
	STACK *ndsa = NULL;
 | 
			
		||||
	BN_CTX *ctx = NULL;
 | 
			
		||||
	int plen;
 | 
			
		||||
#endif
 | 
			
		||||
	X509_ALGOR *a;
 | 
			
		||||
@@ -82,21 +85,14 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
 | 
			
		||||
	int pkeylen;
 | 
			
		||||
	char obj_tmp[80];
 | 
			
		||||
 | 
			
		||||
	switch (p8->broken) {
 | 
			
		||||
		case PKCS8_OK:
 | 
			
		||||
	if(p8->pkey->type == V_ASN1_OCTET_STRING) {
 | 
			
		||||
		p8->broken = PKCS8_OK;
 | 
			
		||||
		p = p8->pkey->value.octet_string->data;
 | 
			
		||||
		pkeylen = p8->pkey->value.octet_string->length;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
		case PKCS8_NO_OCTET:
 | 
			
		||||
	} else {
 | 
			
		||||
		p8->broken = PKCS8_NO_OCTET;
 | 
			
		||||
		p = p8->pkey->value.sequence->data;
 | 
			
		||||
		pkeylen = p8->pkey->value.sequence->length;
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
		default:
 | 
			
		||||
		EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_PKCS8_UNKNOWN_BROKEN_TYPE);
 | 
			
		||||
		return NULL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	if (!(pkey = EVP_PKEY_new())) {
 | 
			
		||||
		EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
@@ -121,65 +117,83 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
 | 
			
		||||
		 * be recalculated.
 | 
			
		||||
		 */
 | 
			
		||||
	
 | 
			
		||||
		/* Check for broken Netscape Database DSA PKCS#8, UGH! */
 | 
			
		||||
		/* Check for broken DSA PKCS#8, UGH! */
 | 
			
		||||
		if(*p == (V_ASN1_SEQUENCE|V_ASN1_CONSTRUCTED)) {
 | 
			
		||||
		    if(!(ndsa = ASN1_seq_unpack(p, pkeylen, 
 | 
			
		||||
					(char *(*)())d2i_ASN1_INTEGER,
 | 
			
		||||
							 ASN1_STRING_free))) {
 | 
			
		||||
					(char *(*)())d2i_ASN1_TYPE,
 | 
			
		||||
							 ASN1_TYPE_free))) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		    }
 | 
			
		||||
		    if(sk_num(ndsa) != 2 ) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
 | 
			
		||||
			sk_pop_free(ndsa, ASN1_STRING_free);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		    }
 | 
			
		||||
		    dsapriv = (ASN1_INTEGER *) sk_pop(ndsa);
 | 
			
		||||
		    sk_pop_free(ndsa, ASN1_STRING_free);
 | 
			
		||||
		} else if (!(dsapriv=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) {
 | 
			
		||||
		    /* Handle Two broken types:
 | 
			
		||||
		     * SEQUENCE {parameters, priv_key}
 | 
			
		||||
		     * SEQUENCE {pub_key, priv_key}
 | 
			
		||||
		     */
 | 
			
		||||
                     
 | 
			
		||||
		    t1 = (ASN1_TYPE *)sk_value(ndsa, 0);
 | 
			
		||||
		    t2 = (ASN1_TYPE *)sk_value(ndsa, 1);
 | 
			
		||||
		    if(t1->type == V_ASN1_SEQUENCE) {
 | 
			
		||||
			p8->broken = PKCS8_EMBEDDED_PARAM;
 | 
			
		||||
			param = t1;
 | 
			
		||||
		    } else if(a->parameter->type == V_ASN1_SEQUENCE) {
 | 
			
		||||
			p8->broken = PKCS8_NS_DB;
 | 
			
		||||
			param = a->parameter;
 | 
			
		||||
		    } else {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		    }
 | 
			
		||||
		/* Retrieve parameters */
 | 
			
		||||
		if (a->parameter->type != V_ASN1_SEQUENCE) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_NO_DSA_PARAMETERS);
 | 
			
		||||
			return NULL;
 | 
			
		||||
 | 
			
		||||
		    if(t2->type != V_ASN1_INTEGER) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		    }
 | 
			
		||||
		p = a->parameter->value.sequence->data;
 | 
			
		||||
		plen = a->parameter->value.sequence->length;
 | 
			
		||||
		    privkey = t2->value.integer;
 | 
			
		||||
		} else if (!(privkey=d2i_ASN1_INTEGER (NULL, &p, pkeylen))) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		}
 | 
			
		||||
		p = param->value.sequence->data;
 | 
			
		||||
		plen = param->value.sequence->length;
 | 
			
		||||
		if (!(dsa = d2i_DSAparams (NULL, &p, plen))) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY, EVP_R_DECODE_ERROR);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		}
 | 
			
		||||
		/* We have parameters now set private key */
 | 
			
		||||
		if (!(dsa->priv_key = ASN1_INTEGER_to_BN(dsapriv, NULL))) {
 | 
			
		||||
		if (!(dsa->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_DECODE_ERROR);
 | 
			
		||||
			DSA_free (dsa);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		}
 | 
			
		||||
		/* Calculate public key (ouch!) */
 | 
			
		||||
		if (!(dsa->pub_key = BN_new())) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
			DSA_free (dsa);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		}
 | 
			
		||||
		if (!(ctx = BN_CTX_new())) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
			DSA_free (dsa);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		}
 | 
			
		||||
			
 | 
			
		||||
		if (!BN_mod_exp(dsa->pub_key, dsa->g,
 | 
			
		||||
						 dsa->priv_key, dsa->p, ctx)) {
 | 
			
		||||
			
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKCS82PKEY,EVP_R_BN_PUBKEY_ERROR);
 | 
			
		||||
			BN_CTX_free (ctx);
 | 
			
		||||
			DSA_free (dsa);
 | 
			
		||||
			return NULL;
 | 
			
		||||
			goto dsaerr;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		EVP_PKEY_assign_DSA (pkey, dsa);
 | 
			
		||||
		EVP_PKEY_assign_DSA(pkey, dsa);
 | 
			
		||||
		BN_CTX_free (ctx);
 | 
			
		||||
		sk_pop_free(ndsa, ASN1_TYPE_free);
 | 
			
		||||
		break;
 | 
			
		||||
		dsaerr:
 | 
			
		||||
		BN_CTX_free (ctx);
 | 
			
		||||
		sk_pop_free(ndsa, ASN1_TYPE_free);
 | 
			
		||||
		DSA_free(dsa);
 | 
			
		||||
		EVP_PKEY_free(pkey);
 | 
			
		||||
		return NULL;
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
		default:
 | 
			
		||||
@@ -193,30 +207,35 @@ EVP_PKEY *EVP_PKCS82PKEY (PKCS8_PRIV_KEY_INFO *p8)
 | 
			
		||||
	return pkey;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Turn a private key into a PKCS8 structure */
 | 
			
		||||
 | 
			
		||||
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey)
 | 
			
		||||
{
 | 
			
		||||
	return EVP_PKEY2PKCS8_broken(pkey, PKCS8_OK);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Turn a private key into a PKCS8 structure */
 | 
			
		||||
 | 
			
		||||
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken)
 | 
			
		||||
{
 | 
			
		||||
	PKCS8_PRIV_KEY_INFO *p8;
 | 
			
		||||
#ifndef NO_DSA
 | 
			
		||||
	ASN1_INTEGER *dpkey;
 | 
			
		||||
	unsigned char *p, *q;
 | 
			
		||||
	int len;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	if (!(p8 = PKCS8_PRIV_KEY_INFO_new())) {	
 | 
			
		||||
		EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	p8->broken = broken;
 | 
			
		||||
	ASN1_INTEGER_set (p8->version, 0);
 | 
			
		||||
	if (!(p8->pkeyalg->parameter = ASN1_TYPE_new ())) {
 | 
			
		||||
		EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
		PKCS8_PRIV_KEY_INFO_free (p8);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	p8->pkey->type = V_ASN1_OCTET_STRING;
 | 
			
		||||
	switch (EVP_PKEY_type(pkey->type)) {
 | 
			
		||||
#ifndef NO_RSA
 | 
			
		||||
		case EVP_PKEY_RSA:
 | 
			
		||||
 | 
			
		||||
		if(p8->broken == PKCS8_NO_OCTET) p8->pkey->type = V_ASN1_SEQUENCE;
 | 
			
		||||
 | 
			
		||||
		p8->pkeyalg->algorithm = OBJ_nid2obj(NID_rsaEncryption);
 | 
			
		||||
		p8->pkeyalg->parameter->type = V_ASN1_NULL;
 | 
			
		||||
		if (!ASN1_pack_string ((char *)pkey, i2d_PrivateKey,
 | 
			
		||||
@@ -229,36 +248,11 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey)
 | 
			
		||||
#endif
 | 
			
		||||
#ifndef NO_DSA
 | 
			
		||||
		case EVP_PKEY_DSA:
 | 
			
		||||
		p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa);
 | 
			
		||||
 | 
			
		||||
		/* get parameters and place in AlgorithmIdentifier */
 | 
			
		||||
		len = i2d_DSAparams (pkey->pkey.dsa, NULL);
 | 
			
		||||
		if (!(p = Malloc(len))) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
			PKCS8_PRIV_KEY_INFO_free (p8);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		q = p;
 | 
			
		||||
		i2d_DSAparams (pkey->pkey.dsa, &q);
 | 
			
		||||
		p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE;
 | 
			
		||||
		p8->pkeyalg->parameter->value.sequence = ASN1_STRING_new();
 | 
			
		||||
		ASN1_STRING_set(p8->pkeyalg->parameter->value.sequence, p, len);
 | 
			
		||||
		Free(p);
 | 
			
		||||
		/* Get private key into an integer and pack */
 | 
			
		||||
		if (!(dpkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
 | 
			
		||||
		if(!dsa_pkey2pkcs8(p8, pkey)) {
 | 
			
		||||
			PKCS8_PRIV_KEY_INFO_free (p8);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!ASN1_pack_string((char *)dpkey, i2d_ASN1_INTEGER,
 | 
			
		||||
					 &p8->pkey->value.octet_string)) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
			M_ASN1_INTEGER_free (dpkey);
 | 
			
		||||
			PKCS8_PRIV_KEY_INFO_free (p8);
 | 
			
		||||
			return NULL;
 | 
			
		||||
		}
 | 
			
		||||
		M_ASN1_INTEGER_free (dpkey);
 | 
			
		||||
		break;
 | 
			
		||||
#endif
 | 
			
		||||
		default:
 | 
			
		||||
@@ -266,7 +260,6 @@ PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey)
 | 
			
		||||
		PKCS8_PRIV_KEY_INFO_free (p8);
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	p8->pkey->type = V_ASN1_OCTET_STRING;
 | 
			
		||||
	RAND_add(p8->pkey->value.octet_string->data,
 | 
			
		||||
		 p8->pkey->value.octet_string->length, 0);
 | 
			
		||||
	return p8;
 | 
			
		||||
@@ -295,4 +288,112 @@ PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef NO_DSA
 | 
			
		||||
static int dsa_pkey2pkcs8(PKCS8_PRIV_KEY_INFO *p8, EVP_PKEY *pkey)
 | 
			
		||||
{
 | 
			
		||||
	ASN1_STRING *params;
 | 
			
		||||
	ASN1_INTEGER *prkey;
 | 
			
		||||
	ASN1_TYPE *ttmp;
 | 
			
		||||
	STACK *ndsa;
 | 
			
		||||
	unsigned char *p, *q;
 | 
			
		||||
	int len;
 | 
			
		||||
	p8->pkeyalg->algorithm = OBJ_nid2obj(NID_dsa);
 | 
			
		||||
	len = i2d_DSAparams (pkey->pkey.dsa, NULL);
 | 
			
		||||
	if (!(p = Malloc(len))) {
 | 
			
		||||
		EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
		PKCS8_PRIV_KEY_INFO_free (p8);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
	q = p;
 | 
			
		||||
	i2d_DSAparams (pkey->pkey.dsa, &q);
 | 
			
		||||
	params = ASN1_STRING_new();
 | 
			
		||||
	ASN1_STRING_set(params, p, len);
 | 
			
		||||
	Free(p);
 | 
			
		||||
	/* Get private key into integer */
 | 
			
		||||
	if (!(prkey = BN_to_ASN1_INTEGER (pkey->pkey.dsa->priv_key, NULL))) {
 | 
			
		||||
		EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch(p8->broken) {
 | 
			
		||||
 | 
			
		||||
		case PKCS8_OK:
 | 
			
		||||
		case PKCS8_NO_OCTET:
 | 
			
		||||
 | 
			
		||||
		if (!ASN1_pack_string((char *)prkey, i2d_ASN1_INTEGER,
 | 
			
		||||
					 &p8->pkey->value.octet_string)) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
			M_ASN1_INTEGER_free (prkey);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		M_ASN1_INTEGER_free (prkey);
 | 
			
		||||
		p8->pkeyalg->parameter->value.sequence = params;
 | 
			
		||||
		p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE;
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
		case PKCS8_NS_DB:
 | 
			
		||||
 | 
			
		||||
		p8->pkeyalg->parameter->value.sequence = params;
 | 
			
		||||
		p8->pkeyalg->parameter->type = V_ASN1_SEQUENCE;
 | 
			
		||||
		ndsa = sk_new_null();
 | 
			
		||||
		ttmp = ASN1_TYPE_new();
 | 
			
		||||
		if (!(ttmp->value.integer = BN_to_ASN1_INTEGER (pkey->pkey.dsa->pub_key, NULL))) {
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKEY2PKCS8,EVP_R_ENCODE_ERROR);
 | 
			
		||||
			PKCS8_PRIV_KEY_INFO_free(p8);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		ttmp->type = V_ASN1_INTEGER;
 | 
			
		||||
		sk_push(ndsa, (char *)ttmp);
 | 
			
		||||
 | 
			
		||||
		ttmp = ASN1_TYPE_new();
 | 
			
		||||
		ttmp->value.integer = prkey;
 | 
			
		||||
		ttmp->type = V_ASN1_INTEGER;
 | 
			
		||||
		sk_push(ndsa, (char *)ttmp);
 | 
			
		||||
 | 
			
		||||
		p8->pkey->value.octet_string = ASN1_OCTET_STRING_new();
 | 
			
		||||
 | 
			
		||||
		if (!ASN1_seq_pack(ndsa, i2d_ASN1_TYPE,
 | 
			
		||||
					 &p8->pkey->value.octet_string->data,
 | 
			
		||||
					 &p8->pkey->value.octet_string->length)) {
 | 
			
		||||
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
			sk_pop_free(ndsa, ASN1_TYPE_free);
 | 
			
		||||
			M_ASN1_INTEGER_free(prkey);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		sk_pop_free(ndsa, ASN1_TYPE_free);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
		case PKCS8_EMBEDDED_PARAM:
 | 
			
		||||
 | 
			
		||||
		p8->pkeyalg->parameter->type = V_ASN1_NULL;
 | 
			
		||||
		ndsa = sk_new_null();
 | 
			
		||||
		ttmp = ASN1_TYPE_new();
 | 
			
		||||
		ttmp->value.sequence = params;
 | 
			
		||||
		ttmp->type = V_ASN1_SEQUENCE;
 | 
			
		||||
		sk_push(ndsa, (char *)ttmp);
 | 
			
		||||
 | 
			
		||||
		ttmp = ASN1_TYPE_new();
 | 
			
		||||
		ttmp->value.integer = prkey;
 | 
			
		||||
		ttmp->type = V_ASN1_INTEGER;
 | 
			
		||||
		sk_push(ndsa, (char *)ttmp);
 | 
			
		||||
 | 
			
		||||
		p8->pkey->value.octet_string = ASN1_OCTET_STRING_new();
 | 
			
		||||
 | 
			
		||||
		if (!ASN1_seq_pack(ndsa, i2d_ASN1_TYPE,
 | 
			
		||||
					 &p8->pkey->value.octet_string->data,
 | 
			
		||||
					 &p8->pkey->value.octet_string->length)) {
 | 
			
		||||
 | 
			
		||||
			EVPerr(EVP_F_EVP_PKEY2PKCS8,ERR_R_MALLOC_FAILURE);
 | 
			
		||||
			sk_pop_free(ndsa, ASN1_TYPE_free);
 | 
			
		||||
			M_ASN1_INTEGER_free (prkey);
 | 
			
		||||
			return 0;
 | 
			
		||||
		}
 | 
			
		||||
		sk_pop_free(ndsa, ASN1_TYPE_free);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 
 | 
			
		||||
@@ -435,6 +435,8 @@ typedef struct pkcs8_priv_key_info_st
 | 
			
		||||
        int broken;     /* Flag for various broken formats */
 | 
			
		||||
#define PKCS8_OK		0
 | 
			
		||||
#define PKCS8_NO_OCTET		1
 | 
			
		||||
#define PKCS8_EMBEDDED_PARAM	2
 | 
			
		||||
#define PKCS8_NS_DB		3
 | 
			
		||||
        ASN1_INTEGER *version;
 | 
			
		||||
        X509_ALGOR *pkeyalg;
 | 
			
		||||
        ASN1_TYPE *pkey; /* Should be OCTET STRING but some are broken */
 | 
			
		||||
@@ -1105,6 +1107,7 @@ void PKCS8_PRIV_KEY_INFO_free(PKCS8_PRIV_KEY_INFO *a);
 | 
			
		||||
 | 
			
		||||
EVP_PKEY *EVP_PKCS82PKEY(PKCS8_PRIV_KEY_INFO *p8);
 | 
			
		||||
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8(EVP_PKEY *pkey);
 | 
			
		||||
PKCS8_PRIV_KEY_INFO *EVP_PKEY2PKCS8_broken(EVP_PKEY *pkey, int broken);
 | 
			
		||||
PKCS8_PRIV_KEY_INFO *PKCS8_set_broken(PKCS8_PRIV_KEY_INFO *p8, int broken);
 | 
			
		||||
 | 
			
		||||
int X509_check_trust(X509 *x, int id, int flags);
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,8 @@ B<openssl> B<pkcs8>
 | 
			
		||||
[B<-noiter>]
 | 
			
		||||
[B<-nocrypt>]
 | 
			
		||||
[B<-nooct>]
 | 
			
		||||
[B<-embed>]
 | 
			
		||||
[B<-nsdb>]
 | 
			
		||||
[B<-v2 alg>]
 | 
			
		||||
[B<-v1 alg>]
 | 
			
		||||
 | 
			
		||||
@@ -93,11 +95,24 @@ code signing software used unencrypted private keys.
 | 
			
		||||
 | 
			
		||||
=item B<-nooct>
 | 
			
		||||
 | 
			
		||||
This option generates private keys in a broken format that some software
 | 
			
		||||
This option generates RSA private keys in a broken format that some software
 | 
			
		||||
uses. Specifically the private key should be enclosed in a OCTET STRING
 | 
			
		||||
but some software just includes the structure itself without the
 | 
			
		||||
surrounding OCTET STRING.
 | 
			
		||||
 | 
			
		||||
=item B<-embed>
 | 
			
		||||
 | 
			
		||||
This option generates DSA keys in a broken format. The DSA parameters are
 | 
			
		||||
embedded inside the PrivateKey structure. In this form the OCTET STRING
 | 
			
		||||
contains an ASN1 SEQUENCE consisting of two structures: a SEQUENCE containing
 | 
			
		||||
the parameters and an ASN1 INTEGER containing the private key.
 | 
			
		||||
 | 
			
		||||
=item B<-nsdb>
 | 
			
		||||
 | 
			
		||||
This option generates DSA keys in a broken format compatible with Netscape
 | 
			
		||||
private key databases. The PrivateKey contains a SEQUENCE consisting of
 | 
			
		||||
the public and private keys respectively.
 | 
			
		||||
 | 
			
		||||
=item B<-v2 alg>
 | 
			
		||||
 | 
			
		||||
This option enables the use of PKCS#5 v2.0 algorithms. Normally PKCS#8
 | 
			
		||||
@@ -202,11 +217,16 @@ Convert a private key from any PKCS#8 format to traditional format:
 | 
			
		||||
 | 
			
		||||
=head1 STANDARDS
 | 
			
		||||
 | 
			
		||||
Test vectors from this implementation were posted to the pkcs-tng mailing
 | 
			
		||||
list using triple DES, DES and RC2 with high iteration counts, several
 | 
			
		||||
people confirmed that they could decrypt the private keys produced and
 | 
			
		||||
Therefore it can be assumed that the PKCS#5 v2.0 implementation is
 | 
			
		||||
reasonably accurate at least as far as these algorithms are concerned.
 | 
			
		||||
Test vectors from this PKCS#5 v2.0 implementation were posted to the
 | 
			
		||||
pkcs-tng mailing list using triple DES, DES and RC2 with high iteration
 | 
			
		||||
counts, several people confirmed that they could decrypt the private
 | 
			
		||||
keys produced and Therefore it can be assumed that the PKCS#5 v2.0
 | 
			
		||||
implementation is reasonably accurate at least as far as these
 | 
			
		||||
algorithms are concerned.
 | 
			
		||||
 | 
			
		||||
The format of PKCS#8 DSA (and other) private keys is not well documented:
 | 
			
		||||
it is hidden away in PKCS#11 v2.01, section 11.9. OpenSSL's DSA private
 | 
			
		||||
key format complies with this standard.
 | 
			
		||||
 | 
			
		||||
=head1 BUGS
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2216,3 +2216,4 @@ BN_is_prime_fasttest                    2240
 | 
			
		||||
BN_CTX_end                              2241
 | 
			
		||||
BN_CTX_start                            2242
 | 
			
		||||
BN_CTX_get                              2243
 | 
			
		||||
EVP_PKEY2PKCS8_broken                   2244
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user