提交 ffb1ac67 编写于 作者: D Dr. Stephen Henson

Complete key derivation support.

上级 3be34589
......@@ -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
......
......@@ -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(infile)
if (pkey_op != EVP_PKEY_OP_DERIVE)
{
if(!(in = BIO_new_file(infile, "rb")))
if(infile)
{
BIO_printf(bio_err, "Error Reading Input File\n");
ERR_print_errors(bio_err);
goto end;
if(!(in = BIO_new_file(infile, "rb")))
{
BIO_puts(bio_err,
"Error Opening Input File\n");
ERR_print_errors(bio_err);
goto end;
}
}
else
in = BIO_new_fp(stdin, BIO_NOCLOSE);
}
else
in = BIO_new_fp(stdin, BIO_NOCLOSE);
if(outfile)
{
......@@ -280,24 +301,28 @@ int MAIN(int argc, char **argv)
buf_out = OPENSSL_malloc(keysize);
/* Read the input data */
buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
if(buf_inlen <= 0)
if (in)
{
BIO_printf(bio_err, "Error reading input Data\n");
exit(1);
}
if(rev)
{
int i;
unsigned char ctmp;
for(i = 0; i < buf_inlen/2; i++)
/* Read the input data */
buf_inlen = bio_to_mem(&buf_in, keysize * 10, in);
if(buf_inlen <= 0)
{
BIO_printf(bio_err, "Error reading input Data\n");
exit(1);
}
if(rev)
{
ctmp = buf_in[i];
buf_in[i] = buf_in[buf_inlen - 1 - i];
buf_in[buf_inlen - 1 - i] = ctmp;
int i;
unsigned char ctmp;
for(i = 0; i < buf_inlen/2; i++)
{
ctmp = buf_in[i];
buf_in[i] = buf_in[buf_inlen - 1 - i];
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;
}
......@@ -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
......
......@@ -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,
......
......@@ -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"},
......
......@@ -115,11 +115,16 @@ static int pkey_dh_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
dctx->generator = p1;
return 1;
case EVP_PKEY_CTRL_PEER_KEY:
/* Default behaviour is OK */
return 1;
default:
return -2;
}
}
static int pkey_dh_ctrl_str(EVP_PKEY_CTX *ctx,
const char *type, const char *value)
......@@ -182,6 +187,22 @@ static int pkey_dh_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
return DH_generate_key(pkey->pkey.dh);
}
static int pkey_dh_derive(EVP_PKEY_CTX *ctx, unsigned char *key, int *keylen)
{
int ret;
if (!ctx->pkey || !ctx->peerkey)
{
DHerr(DH_F_PKEY_DH_DERIVE, DH_R_KEYS_NOT_SET);
return 0;
}
ret = DH_compute_key(key, ctx->peerkey->pkey.dh->pub_key,
ctx->pkey->pkey.dh);
if (ret < 0)
return ret;
*keylen = ret;
return 1;
}
const EVP_PKEY_METHOD dh_pkey_meth =
{
EVP_PKEY_DH,
......@@ -209,7 +230,8 @@ const EVP_PKEY_METHOD dh_pkey_meth =
0,0,
0,0,
0,
pkey_dh_derive,
pkey_dh_ctrl,
pkey_dh_ctrl_str
......
......@@ -933,6 +933,7 @@ void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
EVP_PKEY_CTRL_MD, 0, (void *)md)
#define EVP_PKEY_CTRL_MD 1
#define EVP_PKEY_CTRL_PEER_KEY 2
#define EVP_PKEY_ALG_CTRL 0x1000
......@@ -972,6 +973,10 @@ int EVP_PKEY_decrypt(EVP_PKEY_CTX *ctx,
unsigned char *out, int *outlen,
const unsigned char *in, int inlen);
int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx);
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer);
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, int *keylen);
typedef int EVP_PKEY_gen_cb(EVP_PKEY_CTX *ctx);
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx);
......@@ -1018,6 +1023,7 @@ void ERR_load_EVP_strings(void);
#define EVP_F_EVP_PKEY_DECRYPT_OLD 151
#define EVP_F_EVP_PKEY_DERIVE 153
#define EVP_F_EVP_PKEY_DERIVE_INIT 154
#define EVP_F_EVP_PKEY_DERIVE_SET_PEER 155
#define EVP_F_EVP_PKEY_ENCRYPT 105
#define EVP_F_EVP_PKEY_ENCRYPT_INIT 139
#define EVP_F_EVP_PKEY_ENCRYPT_OLD 152
......@@ -1061,6 +1067,7 @@ void ERR_load_EVP_strings(void);
#define EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH 138
#define EVP_R_DECODE_ERROR 114
#define EVP_R_DIFFERENT_KEY_TYPES 101
#define EVP_R_DIFFERENT_PARAMETERS 153
#define EVP_R_ENCODE_ERROR 115
#define EVP_R_EVP_PBE_CIPHERINIT_ERROR 119
#define EVP_R_EXPECTING_AN_RSA_KEY 127
......@@ -1080,6 +1087,7 @@ void ERR_load_EVP_strings(void);
#define EVP_R_NO_CIPHER_SET 131
#define EVP_R_NO_DIGEST_SET 139
#define EVP_R_NO_DSA_PARAMETERS 116
#define EVP_R_NO_KEY_SET 154
#define EVP_R_NO_OPERATION_SET 149
#define EVP_R_NO_SIGN_FUNCTION_CONFIGURED 104
#define EVP_R_NO_VERIFY_FUNCTION_CONFIGURED 105
......
......@@ -97,6 +97,7 @@ static ERR_STRING_DATA EVP_str_functs[]=
{ERR_FUNC(EVP_F_EVP_PKEY_DECRYPT_OLD), "EVP_PKEY_decrypt_old"},
{ERR_FUNC(EVP_F_EVP_PKEY_DERIVE), "EVP_PKEY_DERIVE"},
{ERR_FUNC(EVP_F_EVP_PKEY_DERIVE_INIT), "EVP_PKEY_DERIVE_INIT"},
{ERR_FUNC(EVP_F_EVP_PKEY_DERIVE_SET_PEER), "EVP_PKEY_DERIVE_SET_PEER"},
{ERR_FUNC(EVP_F_EVP_PKEY_ENCRYPT), "EVP_PKEY_encrypt"},
{ERR_FUNC(EVP_F_EVP_PKEY_ENCRYPT_INIT), "EVP_PKEY_encrypt_init"},
{ERR_FUNC(EVP_F_EVP_PKEY_ENCRYPT_OLD), "EVP_PKEY_encrypt_old"},
......@@ -143,6 +144,7 @@ static ERR_STRING_DATA EVP_str_reasons[]=
{ERR_REASON(EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH),"data not multiple of block length"},
{ERR_REASON(EVP_R_DECODE_ERROR) ,"decode error"},
{ERR_REASON(EVP_R_DIFFERENT_KEY_TYPES) ,"different key types"},
{ERR_REASON(EVP_R_DIFFERENT_PARAMETERS) ,"different parameters"},
{ERR_REASON(EVP_R_ENCODE_ERROR) ,"encode error"},
{ERR_REASON(EVP_R_EVP_PBE_CIPHERINIT_ERROR),"evp pbe cipherinit error"},
{ERR_REASON(EVP_R_EXPECTING_AN_RSA_KEY) ,"expecting an rsa key"},
......@@ -162,6 +164,7 @@ static ERR_STRING_DATA EVP_str_reasons[]=
{ERR_REASON(EVP_R_NO_CIPHER_SET) ,"no cipher set"},
{ERR_REASON(EVP_R_NO_DIGEST_SET) ,"no digest set"},
{ERR_REASON(EVP_R_NO_DSA_PARAMETERS) ,"no dsa parameters"},
{ERR_REASON(EVP_R_NO_KEY_SET) ,"no key set"},
{ERR_REASON(EVP_R_NO_OPERATION_SET) ,"no operation set"},
{ERR_REASON(EVP_R_NO_SIGN_FUNCTION_CONFIGURED),"no sign function configured"},
{ERR_REASON(EVP_R_NO_VERIFY_FUNCTION_CONFIGURED),"no verify function configured"},
......
......@@ -262,6 +262,66 @@ int EVP_PKEY_derive_init(EVP_PKEY_CTX *ctx)
return ret;
}
int EVP_PKEY_derive_set_peer(EVP_PKEY_CTX *ctx, EVP_PKEY *peer)
{
int ret;
if (!ctx || !ctx->pmeth || !ctx->pmeth->derive || !ctx->pmeth->ctrl)
{
EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
return -2;
}
if (ctx->operation != EVP_PKEY_OP_DERIVE)
{
EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_OPERATON_NOT_INITIALIZED);
return -1;
}
ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 0, peer);
if (ret <= 0)
return ret;
if (ret == 2)
return 1;
if (!ctx->pkey)
{
EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_NO_KEY_SET);
return -1;
}
if (ctx->pkey->type != peer->type)
{
EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_DIFFERENT_KEY_TYPES);
return -1;
}
if (!EVP_PKEY_missing_parameters(peer) &&
!EVP_PKEY_cmp_parameters(ctx->pkey, peer))
{
EVPerr(EVP_F_EVP_PKEY_DERIVE_SET_PEER,
EVP_R_DIFFERENT_PARAMETERS);
return -1;
}
ctx->peerkey = peer;
ret = ctx->pmeth->ctrl(ctx, EVP_PKEY_CTRL_PEER_KEY, 1, peer);
if (ret <= 0)
{
ctx->peerkey = NULL;
return ret;
}
CRYPTO_add(&peer->references,1,CRYPTO_LOCK_EVP_PKEY);
return 1;
}
int EVP_PKEY_derive(EVP_PKEY_CTX *ctx, unsigned char *key, int *pkeylen)
{
if (!ctx || !ctx->pmeth || !ctx->pmeth->derive)
......
......@@ -153,6 +153,8 @@ void EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx)
ctx->pmeth->cleanup(ctx);
if (ctx->pkey)
EVP_PKEY_free(ctx->pkey);
if (ctx->peerkey)
EVP_PKEY_free(ctx->peerkey);
OPENSSL_free(ctx);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册