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

Complete key derivation support.

parent 3be34589
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -4,6 +4,10 @@

 Changes between 0.9.8a and 0.9.9  [xx XXX xxxx]

  *) Add support for key derivation (agreement) in the API, DH method and
     pkeyutl.
     [Steve Henson]

  *) Add DSA pkey method and DH pkey methods, extend DH ASN1 method to support
     public and private key formats. As a side effect these add additional 
     command line functionality not previously available: DSA signatures can be
+93 −32
Original line number Diff line number Diff line
@@ -74,7 +74,10 @@ static void usage(void);

static EVP_PKEY_CTX *init_ctx(int *pkeysize,
				char *keyfile, int keyform, int key_type,
				char *passargin, int pkey_op, char *engine);
				char *passargin, int pkey_op, ENGINE *e);

static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
							const char *file);

int MAIN(int argc, char **);

@@ -82,9 +85,9 @@ int MAIN(int argc, char **argv)
{
	BIO *in = NULL, *out = NULL;
	char *infile = NULL, *outfile = NULL, *sigfile = NULL;
	char *engine = NULL;
	ENGINE *e = NULL;
	int pkey_op = EVP_PKEY_OP_SIGN, key_type = KEY_PRIVKEY;
	int keyform = FORMAT_PEM;
	int keyform = FORMAT_PEM, peerform = FORMAT_PEM;
	char badarg = 0, rev = 0;
	char hexdump = 0, asn1parse = 0;
	EVP_PKEY_CTX *ctx = NULL;
@@ -131,7 +134,7 @@ int MAIN(int argc, char **argv)
				{
				ctx = init_ctx(&keysize,
						*(++argv), keyform, key_type,
						passargin, pkey_op, engine);
						passargin, pkey_op, e);
				if (!ctx)
					{
					BIO_puts(bio_err,
@@ -141,11 +144,23 @@ int MAIN(int argc, char **argv)
					}
				}
			}
		else if (!strcmp(*argv,"-peerkey"))
			{
			if (--argc < 1)
				badarg = 1;
			else if (!setup_peer(bio_err, ctx, peerform, *(++argv)))
				badarg = 1;
			}
		else if (!strcmp(*argv,"-passin"))
			{
			if (--argc < 1) badarg = 1;
			passargin= *(++argv);
			}
		else if (strcmp(*argv,"-peerform") == 0)
			{
			if (--argc < 1) badarg = 1;
			peerform=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-keyform") == 0)
			{
			if (--argc < 1) badarg = 1;
@@ -157,7 +172,7 @@ int MAIN(int argc, char **argv)
			if (--argc < 1)
				badarg = 1;
			else
				engine = *(++argv);
				e = setup_engine(bio_err, *(++argv), 0);
			}
#endif
		else if(!strcmp(*argv, "-pubin"))
@@ -180,14 +195,16 @@ int MAIN(int argc, char **argv)
			pkey_op = EVP_PKEY_OP_ENCRYPT;
		else if(!strcmp(*argv, "-decrypt"))
			pkey_op = EVP_PKEY_OP_DECRYPT;
		else if(!strcmp(*argv, "-derive"))
			pkey_op = EVP_PKEY_OP_DERIVE;
		else if (strcmp(*argv,"-pkeyopt") == 0)
			{
			if (--argc < 1)
				badarg = 1;
			if (!ctx)
			else if (!ctx)
				{
				BIO_puts(bio_err,
					"-param command before -inkey\n");
					"-pkeyopt command before -inkey\n");
				badarg = 1;
				}
			else if (pkey_ctrl_string(ctx, *(++argv)) <= 0)
@@ -228,17 +245,21 @@ int MAIN(int argc, char **argv)
/* FIXME: seed PRNG only if needed */
	app_RAND_load_file(NULL, bio_err, 0);

	if (pkey_op != EVP_PKEY_OP_DERIVE)
		{
		if(infile)
			{
			if(!(in = BIO_new_file(infile, "rb")))
				{
			BIO_printf(bio_err, "Error Reading Input File\n");
				BIO_puts(bio_err,
					"Error Opening Input File\n");
				ERR_print_errors(bio_err);	
				goto end;
				}
			}
		else
			in = BIO_new_fp(stdin, BIO_NOCLOSE);
		}

	if(outfile)
		{
@@ -280,6 +301,8 @@ int MAIN(int argc, char **argv)
	
	buf_out = OPENSSL_malloc(keysize);

	if (in)
		{
		/* Read the input data */
		buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
		if(buf_inlen <= 0)
@@ -298,6 +321,8 @@ int MAIN(int argc, char **argv)
				buf_in[buf_inlen - 1 - i] = ctmp;
				}
			}
		}

	switch(pkey_op)
		{
		case EVP_PKEY_OP_VERIFYRECOVER:
@@ -330,6 +355,10 @@ int MAIN(int argc, char **argv)
			goto end;
		break; 

		case EVP_PKEY_OP_DERIVE:
		rv  = EVP_PKEY_derive(ctx, buf_out, &buf_outlen);
		break;

		}

	if(rv <= 0)
@@ -387,15 +416,15 @@ static void usage()

static EVP_PKEY_CTX *init_ctx(int *pkeysize,
				char *keyfile, int keyform, int key_type,
				char *passargin, int pkey_op, char *engine)
				char *passargin, int pkey_op, ENGINE *e)
	{
	ENGINE *e = NULL;
	EVP_PKEY *pkey = NULL;
	EVP_PKEY_CTX *ctx = NULL;
	char *passin = NULL;
	int rv = -1;
	X509 *x;
	if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT))
	if(((pkey_op == EVP_PKEY_OP_SIGN) || (pkey_op == EVP_PKEY_OP_DECRYPT) 
		|| (pkey_op == EVP_PKEY_OP_DERIVE))
		&& (key_type != KEY_PRIVKEY))
		{
		BIO_printf(bio_err, "A private key is needed for this operation\n");
@@ -435,7 +464,7 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize,
	if (!pkey)
		goto end;

	ctx = EVP_PKEY_CTX_new(pkey, NULL);
	ctx = EVP_PKEY_CTX_new(pkey, e);

	EVP_PKEY_free(pkey);

@@ -463,6 +492,10 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize,
		case EVP_PKEY_OP_DECRYPT:
		rv = EVP_PKEY_decrypt_init(ctx);
		break;

		case EVP_PKEY_OP_DERIVE:
		rv = EVP_PKEY_derive_init(ctx);
		break;
		}

	if (rv <= 0)
@@ -481,3 +514,31 @@ static EVP_PKEY_CTX *init_ctx(int *pkeysize,

	}

static int setup_peer(BIO *err, EVP_PKEY_CTX *ctx, int peerform,
							const char *file)
	{
	EVP_PKEY *peer = NULL;
	int ret;
	if (!ctx)
		{
		BIO_puts(err, "-peerkey command before -inkey\n");
		return 0;
		}
		
	peer = load_pubkey(bio_err, file, peerform, 0, NULL, NULL, "Peer Key");

	if (!peer)
		{
		BIO_printf(bio_err, "Error reading peer key %s\n", file);
		ERR_print_errors(err);
		return 0;
		}

	ret = EVP_PKEY_derive_set_peer(ctx, peer);

	EVP_PKEY_free(peer);
	if (ret <= 0)
		ERR_print_errors(err);
	return ret;
	}
			
+2 −0
Original line number Diff line number Diff line
@@ -234,6 +234,7 @@ void ERR_load_DH_strings(void);
#define DH_F_DH_PUB_ENCODE				 109
#define DH_F_GENERATE_KEY				 103
#define DH_F_GENERATE_PARAMETERS			 104
#define DH_F_PKEY_DH_DERIVE				 112
#define DH_F_PKEY_DH_KEYGEN				 113

/* Reason codes. */
@@ -242,6 +243,7 @@ void ERR_load_DH_strings(void);
#define DH_R_BN_ERROR					 106
#define DH_R_DECODE_ERROR				 104
#define DH_R_INVALID_PUBKEY				 102
#define DH_R_KEYS_NOT_SET				 108
#define DH_R_NO_PARAMETERS_SET				 107
#define DH_R_NO_PRIVATE_VALUE				 100
#define DH_R_PARAMETER_ENCODING_ERROR			 105
+14 −7
Original line number Diff line number Diff line
@@ -397,6 +397,15 @@ static int dh_bits(const EVP_PKEY *pkey)
	return BN_num_bits(pkey->pkey.dh->p);
	}

static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
	{
	if (	BN_cmp(a->pkey.dh->p,b->pkey.dh->p) ||
		BN_cmp(a->pkey.dh->g,b->pkey.dh->g))
		return 0;
	else
		return 1;
	}

static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
	{
	BIGNUM *a;
@@ -409,20 +418,18 @@ static int dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)

	if ((a=BN_dup(from->pkey.dh->g)) == NULL)
		return 0;
	if (to->pkey.dsa->g != NULL)
	if (to->pkey.dh->g != NULL)
		BN_free(to->pkey.dh->g);
	to->pkey.dh->g=a;

	return 1;
	}

static int dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
static int dh_missing_parameters(const EVP_PKEY *a)
	{
	if (	BN_cmp(a->pkey.dh->p,b->pkey.dsa->p) ||
		BN_cmp(a->pkey.dh->g,b->pkey.dsa->g))
		return 0;
	else
	if (!a->pkey.dh->p || !a->pkey.dh->g)
		return 1;
	return 0;
	}

static int dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
@@ -481,7 +488,7 @@ const EVP_PKEY_ASN1_METHOD dh_asn1_meth =

	dh_param_decode,
	dh_param_encode,
	0,
	dh_missing_parameters,
	dh_copy_parameters,
	dh_cmp_parameters,
	dh_param_print,
+2 −0
Original line number Diff line number Diff line
@@ -82,6 +82,7 @@ static ERR_STRING_DATA DH_str_functs[]=
{ERR_FUNC(DH_F_DH_PUB_ENCODE),	"DH_PUB_ENCODE"},
{ERR_FUNC(DH_F_GENERATE_KEY),	"GENERATE_KEY"},
{ERR_FUNC(DH_F_GENERATE_PARAMETERS),	"GENERATE_PARAMETERS"},
{ERR_FUNC(DH_F_PKEY_DH_DERIVE),	"PKEY_DH_DERIVE"},
{ERR_FUNC(DH_F_PKEY_DH_KEYGEN),	"PKEY_DH_KEYGEN"},
{0,NULL}
	};
@@ -93,6 +94,7 @@ static ERR_STRING_DATA DH_str_reasons[]=
{ERR_REASON(DH_R_BN_ERROR)               ,"bn error"},
{ERR_REASON(DH_R_DECODE_ERROR)           ,"decode error"},
{ERR_REASON(DH_R_INVALID_PUBKEY)         ,"invalid public key"},
{ERR_REASON(DH_R_KEYS_NOT_SET)           ,"keys not set"},
{ERR_REASON(DH_R_NO_PARAMETERS_SET)      ,"no parameters set"},
{ERR_REASON(DH_R_NO_PRIVATE_VALUE)       ,"no private value"},
{ERR_REASON(DH_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
Loading