summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2006-04-13 20:16:56 +0000
committerDr. Stephen Henson <steve@openssl.org>2006-04-13 20:16:56 +0000
commitffb1ac674c8294bf519add26fb37d94b7afeceb4 (patch)
tree5348fcd74b5757bd76b6cee7e81d3fe2717a5e9e /crypto
parent3be34589e8d7d164221d393844e8a841dce992a9 (diff)
Complete key derivation support.
Diffstat (limited to 'crypto')
-rw-r--r--crypto/dh/dh.h2
-rw-r--r--crypto/dh/dh_ameth.c21
-rw-r--r--crypto/dh/dh_err.c2
-rw-r--r--crypto/dh/dh_pmeth.c24
-rw-r--r--crypto/evp/evp.h8
-rw-r--r--crypto/evp/evp_err.c3
-rw-r--r--crypto/evp/pmeth_fn.c60
-rw-r--r--crypto/evp/pmeth_lib.c2
8 files changed, 114 insertions, 8 deletions
diff --git a/crypto/dh/dh.h b/crypto/dh/dh.h
index b4b181c4d9..10bf3fe5de 100644
--- a/crypto/dh/dh.h
+++ b/crypto/dh/dh.h
@@ -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
diff --git a/crypto/dh/dh_ameth.c b/crypto/dh/dh_ameth.c
index 6d3125789d..7a83768e2c 100644
--- a/crypto/dh/dh_ameth.c
+++ b/crypto/dh/dh_ameth.c
@@ -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,
diff --git a/crypto/dh/dh_err.c b/crypto/dh/dh_err.c
index 64acfdea11..2fdfc5516e 100644
--- a/crypto/dh/dh_err.c
+++ b/crypto/dh/dh_err.c
@@ -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"},
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index d2e6aaff1e..aaf32804b8 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -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
diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h
index d60781696a..bfffdd562a 100644
--- a/crypto/evp/evp.h
+++ b/crypto/evp/evp.h
@@ -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
diff --git a/crypto/evp/evp_err.c b/crypto/evp/evp_err.c
index 50d5a71276..225564d25e 100644
--- a/crypto/evp/evp_err.c
+++ b/crypto/evp/evp_err.c
@@ -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"},
diff --git a/crypto/evp/pmeth_fn.c b/crypto/evp/pmeth_fn.c
index 0ad8098718..3d09ba245a 100644
--- a/crypto/evp/pmeth_fn.c
+++ b/crypto/evp/pmeth_fn.c
@@ -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)
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index 95b1e4ed3c..97fcf26012 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -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);
}