summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2019-09-06 17:59:24 +0000
committerjsing <jsing@openbsd.org>2019-09-06 17:59:24 +0000
commit658ab8b571f217d6b69db54c00381c3914cd6436 (patch)
tree409ee00df651573414f4717a29560be143f9ab85
parentHandle CMS PEM headers. (diff)
downloadwireguard-openbsd-658ab8b571f217d6b69db54c00381c3914cd6436.tar.xz
wireguard-openbsd-658ab8b571f217d6b69db54c00381c3914cd6436.zip
Add various macros and controls for EC_PKEY_CTX.
These are needed for the upcoming EC CMS support (nothing else appears to use them). This largely syncs our ec_pmeth.c with OpenSSL 1.1.1b. With input from inoguchi@ and tb@. ok inoguchi@ tb@
-rw-r--r--lib/libcrypto/Makefile3
-rw-r--r--lib/libcrypto/ec/ec.h100
-rw-r--r--lib/libcrypto/ec/ec_err.c6
-rw-r--r--lib/libcrypto/ec/ec_pmeth.c235
4 files changed, 316 insertions, 28 deletions
diff --git a/lib/libcrypto/Makefile b/lib/libcrypto/Makefile
index fe9e3774f8a..3f86b2d0a14 100644
--- a/lib/libcrypto/Makefile
+++ b/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.34 2019/09/05 16:16:05 jsing Exp $
+# $OpenBSD: Makefile,v 1.35 2019/09/06 17:59:24 jsing Exp $
LIB= crypto
LIBREBUILD=y
@@ -34,6 +34,7 @@ CFLAGS+= -I${LCRYPTO_SRC}/modes
# XXX FIXME ecdsa and ec should be merged
CFLAGS+= -I${LCRYPTO_SRC}/ecdsa
CFLAGS+= -I${LCRYPTO_SRC}/ec
+CFLAGS+= -I${LCRYPTO_SRC}/ecdh
VERSION_SCRIPT= Symbols.map
SYMBOL_LIST= ${.CURDIR}/Symbols.list
diff --git a/lib/libcrypto/ec/ec.h b/lib/libcrypto/ec/ec.h
index 1c5641eca0d..d0e36736755 100644
--- a/lib/libcrypto/ec/ec.h
+++ b/lib/libcrypto/ec/ec.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ec.h,v 1.16 2019/01/19 01:17:41 tb Exp $ */
+/* $OpenBSD: ec.h,v 1.17 2019/09/06 17:59:25 jsing Exp $ */
/*
* Originally written by Bodo Moeller for the OpenSSL project.
*/
@@ -97,7 +97,7 @@ extern "C" {
#ifndef OPENSSL_ECC_MAX_FIELD_BITS
-# define OPENSSL_ECC_MAX_FIELD_BITS 661
+#define OPENSSL_ECC_MAX_FIELD_BITS 661
#endif
/** Enum for the point conversion form as defined in X9.62 (ECDSA)
@@ -714,6 +714,7 @@ typedef struct ec_key_method_st EC_KEY_METHOD;
/* some values for the flags field */
#define EC_FLAG_NON_FIPS_ALLOW 0x1
#define EC_FLAG_FIPS_CHECKED 0x2
+#define EC_FLAG_COFACTOR_ECDH 0x1000
/** Creates a new EC_KEY object.
* \return EC_KEY object or NULL if an error occurred.
@@ -995,11 +996,96 @@ EC_KEY *ECParameters_dup(EC_KEY *key);
#endif
#define EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid) \
- EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, EVP_PKEY_OP_PARAMGEN, \
- EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
-
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
+ EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID, nid, NULL)
+
+#define EVP_PKEY_CTX_set_ec_param_enc(ctx, flag) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN, \
+ EVP_PKEY_CTRL_EC_PARAM_ENC, flag, NULL)
+
+#define EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, flag) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_EC_ECDH_COFACTOR, flag, NULL)
+
+#define EVP_PKEY_CTX_get_ecdh_cofactor_mode(ctx) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL)
+
+#define EVP_PKEY_CTX_set_ecdh_kdf_type(ctx, kdf) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL)
+
+#define EVP_PKEY_CTX_get_ecdh_kdf_type(ctx) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL)
+
+#define EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md))
+
+#define EVP_PKEY_CTX_get_ecdh_kdf_md(ctx, pmd) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd))
+
+#define EVP_PKEY_CTX_set_ecdh_kdf_outlen(ctx, len) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_EC_KDF_OUTLEN, len, NULL)
+
+#define EVP_PKEY_CTX_get_ecdh_kdf_outlen(ctx, plen) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0, \
+ (void *)(plen))
+
+#define EVP_PKEY_CTX_set0_ecdh_kdf_ukm(ctx, p, plen) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_EC_KDF_UKM, plen, (void *)(p))
+
+#define EVP_PKEY_CTX_get0_ecdh_kdf_ukm(ctx, p) \
+ EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC, \
+ EVP_PKEY_OP_DERIVE, \
+ EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0, (void *)(p))
+
+/* SM2 will skip the operation check so no need to pass operation here */
+#define EVP_PKEY_CTX_set1_id(ctx, id, id_len) \
+ EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
+ EVP_PKEY_CTRL_SET1_ID, (int)id_len, (void*)(id))
+
+#define EVP_PKEY_CTX_get1_id(ctx, id) \
+ EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
+ EVP_PKEY_CTRL_GET1_ID, 0, (void*)(id))
+
+#define EVP_PKEY_CTX_get1_id_len(ctx, id_len) \
+ EVP_PKEY_CTX_ctrl(ctx, -1, -1, \
+ EVP_PKEY_CTRL_GET1_ID_LEN, 0, (void*)(id_len))
#define EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID (EVP_PKEY_ALG_CTRL + 1)
+#define EVP_PKEY_CTRL_EC_PARAM_ENC (EVP_PKEY_ALG_CTRL + 2)
+#define EVP_PKEY_CTRL_EC_ECDH_COFACTOR (EVP_PKEY_ALG_CTRL + 3)
+#define EVP_PKEY_CTRL_EC_KDF_TYPE (EVP_PKEY_ALG_CTRL + 4)
+#define EVP_PKEY_CTRL_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 5)
+#define EVP_PKEY_CTRL_GET_EC_KDF_MD (EVP_PKEY_ALG_CTRL + 6)
+#define EVP_PKEY_CTRL_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 7)
+#define EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN (EVP_PKEY_ALG_CTRL + 8)
+#define EVP_PKEY_CTRL_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 9)
+#define EVP_PKEY_CTRL_GET_EC_KDF_UKM (EVP_PKEY_ALG_CTRL + 10)
+#define EVP_PKEY_CTRL_SET1_ID (EVP_PKEY_ALG_CTRL + 11)
+#define EVP_PKEY_CTRL_GET1_ID (EVP_PKEY_ALG_CTRL + 12)
+#define EVP_PKEY_CTRL_GET1_ID_LEN (EVP_PKEY_ALG_CTRL + 13)
+
+/* KDF types */
+#define EVP_PKEY_ECDH_KDF_NONE 1
+#define EVP_PKEY_ECDH_KDF_X9_63 2
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
@@ -1172,6 +1258,7 @@ void ERR_load_EC_strings(void);
#define EC_R_INVALID_COMPRESSED_POINT 110
#define EC_R_INVALID_COMPRESSION_BIT 109
#define EC_R_INVALID_CURVE 141
+#define EC_R_INVALID_DIGEST 151
#define EC_R_INVALID_DIGEST_TYPE 138
#define EC_R_INVALID_ENCODING 102
#define EC_R_INVALID_FIELD 103
@@ -1180,6 +1267,7 @@ void ERR_load_EC_strings(void);
#define EC_R_INVALID_PENTANOMIAL_BASIS 132
#define EC_R_INVALID_PRIVATE_KEY 123
#define EC_R_INVALID_TRINOMIAL_BASIS 137
+#define EC_R_KDF_PARAMETER_ERROR 148
#define EC_R_KEYS_NOT_SET 140
#define EC_R_MISSING_PARAMETERS 124
#define EC_R_MISSING_PRIVATE_KEY 125
@@ -1190,9 +1278,11 @@ void ERR_load_EC_strings(void);
#define EC_R_NO_FIELD_MOD 133
#define EC_R_NO_PARAMETERS_SET 139
#define EC_R_PASSED_NULL_PARAMETER 134
+#define EC_R_PEER_KEY_ERROR 149
#define EC_R_PKPARAMETERS2GROUP_FAILURE 127
#define EC_R_POINT_AT_INFINITY 106
#define EC_R_POINT_IS_NOT_ON_CURVE 107
+#define EC_R_SHARED_INFO_ERROR 150
#define EC_R_SLOT_FULL 108
#define EC_R_UNDEFINED_GENERATOR 113
#define EC_R_UNDEFINED_ORDER 128
diff --git a/lib/libcrypto/ec/ec_err.c b/lib/libcrypto/ec/ec_err.c
index fa5deceda5d..7c426188819 100644
--- a/lib/libcrypto/ec/ec_err.c
+++ b/lib/libcrypto/ec/ec_err.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ec_err.c,v 1.10 2017/01/29 17:49:23 beck Exp $ */
+/* $OpenBSD: ec_err.c,v 1.11 2019/09/06 17:59:25 jsing Exp $ */
/* ====================================================================
* Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
*
@@ -96,6 +96,7 @@ static ERR_STRING_DATA EC_str_reasons[] =
{ERR_REASON(EC_R_INVALID_COMPRESSED_POINT), "invalid compressed point"},
{ERR_REASON(EC_R_INVALID_COMPRESSION_BIT), "invalid compression bit"},
{ERR_REASON(EC_R_INVALID_CURVE), "invalid curve"},
+ {ERR_REASON(EC_R_INVALID_DIGEST), "invalid digest"},
{ERR_REASON(EC_R_INVALID_DIGEST_TYPE), "invalid digest type"},
{ERR_REASON(EC_R_INVALID_ENCODING), "invalid encoding"},
{ERR_REASON(EC_R_INVALID_FIELD), "invalid field"},
@@ -104,6 +105,7 @@ static ERR_STRING_DATA EC_str_reasons[] =
{ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"},
{ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
{ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"},
+ {ERR_REASON(EC_R_KDF_PARAMETER_ERROR), "kdf parameter error"},
{ERR_REASON(EC_R_KEYS_NOT_SET), "keys not set"},
{ERR_REASON(EC_R_MISSING_PARAMETERS), "missing parameters"},
{ERR_REASON(EC_R_MISSING_PRIVATE_KEY), "missing private key"},
@@ -114,9 +116,11 @@ static ERR_STRING_DATA EC_str_reasons[] =
{ERR_REASON(EC_R_NO_FIELD_MOD), "no field mod"},
{ERR_REASON(EC_R_NO_PARAMETERS_SET), "no parameters set"},
{ERR_REASON(EC_R_PASSED_NULL_PARAMETER), "passed null parameter"},
+ {ERR_REASON(EC_R_PEER_KEY_ERROR), "peer key error"},
{ERR_REASON(EC_R_PKPARAMETERS2GROUP_FAILURE), "pkparameters2group failure"},
{ERR_REASON(EC_R_POINT_AT_INFINITY), "point at infinity"},
{ERR_REASON(EC_R_POINT_IS_NOT_ON_CURVE), "point is not on curve"},
+ {ERR_REASON(EC_R_SHARED_INFO_ERROR), "shared info error"},
{ERR_REASON(EC_R_SLOT_FULL), "slot full"},
{ERR_REASON(EC_R_UNDEFINED_GENERATOR), "undefined generator"},
{ERR_REASON(EC_R_UNDEFINED_ORDER), "undefined order"},
diff --git a/lib/libcrypto/ec/ec_pmeth.c b/lib/libcrypto/ec/ec_pmeth.c
index 08172fe0c67..08050df2929 100644
--- a/lib/libcrypto/ec/ec_pmeth.c
+++ b/lib/libcrypto/ec/ec_pmeth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ec_pmeth.c,v 1.10 2017/01/29 17:49:23 beck Exp $ */
+/* $OpenBSD: ec_pmeth.c,v 1.11 2019/09/06 17:59:25 jsing Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2006.
*/
@@ -66,6 +66,8 @@
#include <openssl/evp.h>
#include <openssl/x509.h>
+#include "ec_lcl.h"
+#include "ech_locl.h"
#include "evp_locl.h"
/* EC pkey context structure */
@@ -75,17 +77,33 @@ typedef struct {
EC_GROUP *gen_group;
/* message digest */
const EVP_MD *md;
+ /* Duplicate key if custom cofactor needed */
+ EC_KEY *co_key;
+ /* Cofactor mode */
+ signed char cofactor_mode;
+ /* KDF (if any) to use for ECDH */
+ char kdf_type;
+ /* Message digest to use for key derivation */
+ const EVP_MD *kdf_md;
+ /* User key material */
+ unsigned char *kdf_ukm;
+ size_t kdf_ukmlen;
+ /* KDF output length */
+ size_t kdf_outlen;
} EC_PKEY_CTX;
static int
pkey_ec_init(EVP_PKEY_CTX * ctx)
{
EC_PKEY_CTX *dctx;
- dctx = malloc(sizeof(EC_PKEY_CTX));
- if (!dctx)
+
+ if ((dctx = calloc(1, sizeof(EC_PKEY_CTX))) == NULL) {
+ ECerror(ERR_R_MALLOC_FAILURE);
return 0;
- dctx->gen_group = NULL;
- dctx->md = NULL;
+ }
+
+ dctx->cofactor_mode = -1;
+ dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
ctx->data = dctx;
@@ -106,6 +124,24 @@ pkey_ec_copy(EVP_PKEY_CTX * dst, EVP_PKEY_CTX * src)
return 0;
}
dctx->md = sctx->md;
+
+ if (sctx->co_key) {
+ dctx->co_key = EC_KEY_dup(sctx->co_key);
+ if (!dctx->co_key)
+ return 0;
+ }
+ dctx->kdf_type = sctx->kdf_type;
+ dctx->kdf_md = sctx->kdf_md;
+ dctx->kdf_outlen = sctx->kdf_outlen;
+ if (sctx->kdf_ukm) {
+ if ((dctx->kdf_ukm = calloc(1, sctx->kdf_ukmlen)) == NULL)
+ return 0;
+ memcpy(dctx->kdf_ukm, sctx->kdf_ukm, sctx->kdf_ukmlen);
+ } else
+ dctx->kdf_ukm = NULL;
+
+ dctx->kdf_ukmlen = sctx->kdf_ukmlen;
+
return 1;
}
@@ -113,9 +149,13 @@ static void
pkey_ec_cleanup(EVP_PKEY_CTX * ctx)
{
EC_PKEY_CTX *dctx = ctx->data;
- if (dctx) {
+
+ if (dctx != NULL) {
EC_GROUP_free(dctx->gen_group);
+ EC_KEY_free(dctx->co_key);
+ free(dctx->kdf_ukm);
free(dctx);
+ ctx->data = NULL;
}
}
@@ -140,9 +180,7 @@ pkey_ec_sign(EVP_PKEY_CTX * ctx, unsigned char *sig, size_t * siglen,
else
type = NID_sha1;
-
ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
-
if (ret <= 0)
return ret;
*siglen = (size_t) sltmp;
@@ -174,13 +212,18 @@ pkey_ec_derive(EVP_PKEY_CTX * ctx, unsigned char *key, size_t * keylen)
int ret;
size_t outlen;
const EC_POINT *pubkey = NULL;
+ EC_KEY *eckey;
+ EC_PKEY_CTX *dctx = ctx->data;
+
if (!ctx->pkey || !ctx->peerkey) {
ECerror(EC_R_KEYS_NOT_SET);
return 0;
}
+
+ eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
if (!key) {
const EC_GROUP *group;
- group = EC_KEY_get0_group(ctx->pkey->pkey.ec);
+ group = EC_KEY_get0_group(eckey);
*keylen = (EC_GROUP_get_degree(group) + 7) / 8;
return 1;
}
@@ -193,18 +236,58 @@ pkey_ec_derive(EVP_PKEY_CTX * ctx, unsigned char *key, size_t * keylen)
outlen = *keylen;
- ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0);
- if (ret < 0)
- return ret;
+ ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
+ if (ret <= 0)
+ return 0;
+
*keylen = ret;
+
return 1;
}
+static int
+pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
+{
+ EC_PKEY_CTX *dctx = ctx->data;
+ unsigned char *ktmp = NULL;
+ size_t ktmplen;
+ int rv = 0;
+
+ if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
+ return pkey_ec_derive(ctx, key, keylen);
+
+ if (!key) {
+ *keylen = dctx->kdf_outlen;
+ return 1;
+ }
+ if (*keylen != dctx->kdf_outlen)
+ return 0;
+ if (!pkey_ec_derive(ctx, NULL, &ktmplen))
+ return 0;
+ if ((ktmp = calloc(1, ktmplen)) == NULL) {
+ ECerror(ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+ if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
+ goto err;
+ /* Do KDF stuff */
+ if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm,
+ dctx->kdf_ukmlen, dctx->kdf_md))
+ goto err;
+ rv = 1;
+
+ err:
+ freezero(ktmp, ktmplen);
+
+ return rv;
+}
+
static int
pkey_ec_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2)
{
EC_PKEY_CTX *dctx = ctx->data;
EC_GROUP *group;
+
switch (type) {
case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
group = EC_GROUP_new_by_curve_name(p1);
@@ -216,6 +299,86 @@ pkey_ec_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2)
dctx->gen_group = group;
return 1;
+ case EVP_PKEY_CTRL_EC_PARAM_ENC:
+ if (!dctx->gen_group) {
+ ECerror(EC_R_NO_PARAMETERS_SET);
+ return 0;
+ }
+ EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
+ return 1;
+
+ case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
+ if (p1 == -2) {
+ if (dctx->cofactor_mode != -1)
+ return dctx->cofactor_mode;
+ else {
+ EC_KEY *ec_key = ctx->pkey->pkey.ec;
+ return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
+ }
+ } else if (p1 < -1 || p1 > 1)
+ return -2;
+ dctx->cofactor_mode = p1;
+ if (p1 != -1) {
+ EC_KEY *ec_key = ctx->pkey->pkey.ec;
+ if (!ec_key->group)
+ return -2;
+ /* If cofactor is 1 cofactor mode does nothing */
+ if (BN_is_one(&ec_key->group->cofactor))
+ return 1;
+ if (!dctx->co_key) {
+ dctx->co_key = EC_KEY_dup(ec_key);
+ if (!dctx->co_key)
+ return 0;
+ }
+ if (p1)
+ EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
+ else
+ EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
+ } else {
+ EC_KEY_free(dctx->co_key);
+ dctx->co_key = NULL;
+ }
+ return 1;
+
+ case EVP_PKEY_CTRL_EC_KDF_TYPE:
+ if (p1 == -2)
+ return dctx->kdf_type;
+ if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
+ return -2;
+ dctx->kdf_type = p1;
+ return 1;
+
+ case EVP_PKEY_CTRL_EC_KDF_MD:
+ dctx->kdf_md = p2;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET_EC_KDF_MD:
+ *(const EVP_MD **)p2 = dctx->kdf_md;
+ return 1;
+
+ case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
+ if (p1 <= 0)
+ return -2;
+ dctx->kdf_outlen = (size_t)p1;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
+ *(int *)p2 = dctx->kdf_outlen;
+ return 1;
+
+ case EVP_PKEY_CTRL_EC_KDF_UKM:
+ free(dctx->kdf_ukm);
+ dctx->kdf_ukm = p2;
+ if (p2)
+ dctx->kdf_ukmlen = p1;
+ else
+ dctx->kdf_ukmlen = 0;
+ return 1;
+
+ case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
+ *(unsigned char **)p2 = dctx->kdf_ukm;
+ return dctx->kdf_ukmlen;
+
case EVP_PKEY_CTRL_MD:
if (EVP_MD_type((const EVP_MD *) p2) != NID_sha1 &&
EVP_MD_type((const EVP_MD *) p2) != NID_ecdsa_with_SHA1 &&
@@ -243,8 +406,7 @@ pkey_ec_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2)
}
static int
-pkey_ec_ctrl_str(EVP_PKEY_CTX * ctx,
- const char *type, const char *value)
+pkey_ec_ctrl_str(EVP_PKEY_CTX * ctx, const char *type, const char *value)
{
if (!strcmp(type, "ec_paramgen_curve")) {
int nid;
@@ -258,6 +420,26 @@ pkey_ec_ctrl_str(EVP_PKEY_CTX * ctx,
return 0;
}
return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
+ } else if (strcmp(type, "ec_param_enc") == 0) {
+ int param_enc;
+ if (strcmp(value, "explicit") == 0)
+ param_enc = 0;
+ else if (strcmp(value, "named_curve") == 0)
+ param_enc = OPENSSL_EC_NAMED_CURVE;
+ else
+ return -2;
+ return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
+ } else if (strcmp(type, "ecdh_kdf_md") == 0) {
+ const EVP_MD *md;
+ if ((md = EVP_get_digestbyname(value)) == NULL) {
+ ECerror(EC_R_INVALID_DIGEST);
+ return 0;
+ }
+ return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
+ } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
+ int co_mode;
+ co_mode = atoi(value);
+ return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
}
return -2;
}
@@ -287,18 +469,29 @@ static int
pkey_ec_keygen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey)
{
EC_KEY *ec = NULL;
- if (ctx->pkey == NULL) {
+ EC_PKEY_CTX *dctx = ctx->data;
+
+ if (ctx->pkey == NULL && dctx->gen_group == NULL) {
ECerror(EC_R_NO_PARAMETERS_SET);
return 0;
}
ec = EC_KEY_new();
- if (!ec)
+ if (ec == NULL)
return 0;
- EVP_PKEY_assign_EC_KEY(pkey, ec);
- /* Note: if error return, pkey is freed by parent routine */
- if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
+ EC_KEY_free(ec);
return 0;
- return EC_KEY_generate_key(pkey->pkey.ec);
+ }
+ /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
+ if (ctx->pkey != NULL) {
+ if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
+ return 0;
+ } else {
+ if (!EC_KEY_set_group(ec, dctx->gen_group))
+ return 0;
+ }
+
+ return EC_KEY_generate_key(ec);
}
const EVP_PKEY_METHOD ec_pkey_meth = {
@@ -316,7 +509,7 @@ const EVP_PKEY_METHOD ec_pkey_meth = {
.verify = pkey_ec_verify,
- .derive = pkey_ec_derive,
+ .derive = pkey_ec_kdf_derive,
.ctrl = pkey_ec_ctrl,
.ctrl_str = pkey_ec_ctrl_str