summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ec_pmeth.c
diff options
context:
space:
mode:
authorjsing <>2019-09-06 17:59:25 +0000
committerjsing <>2019-09-06 17:59:25 +0000
commit11474dfb0e4a1fb55d042fbfb4e2c68602f61508 (patch)
tree41fcc6b250b4f518c93bc01711ee02ee90e03002 /src/lib/libcrypto/ec/ec_pmeth.c
parentad62fd73e219aceeb5b13e772228acd3f93d6b23 (diff)
downloadopenbsd-11474dfb0e4a1fb55d042fbfb4e2c68602f61508.tar.gz
openbsd-11474dfb0e4a1fb55d042fbfb4e2c68602f61508.tar.bz2
openbsd-11474dfb0e4a1fb55d042fbfb4e2c68602f61508.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@
Diffstat (limited to '')
-rw-r--r--src/lib/libcrypto/ec/ec_pmeth.c235
1 files changed, 214 insertions, 21 deletions
diff --git a/src/lib/libcrypto/ec/ec_pmeth.c b/src/lib/libcrypto/ec/ec_pmeth.c
index 08172fe0c6..08050df292 100644
--- a/src/lib/libcrypto/ec/ec_pmeth.c
+++ b/src/lib/libcrypto/ec/ec_pmeth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_pmeth.c,v 1.10 2017/01/29 17:49:23 beck Exp $ */ 1/* $OpenBSD: ec_pmeth.c,v 1.11 2019/09/06 17:59:25 jsing Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -66,6 +66,8 @@
66#include <openssl/evp.h> 66#include <openssl/evp.h>
67#include <openssl/x509.h> 67#include <openssl/x509.h>
68 68
69#include "ec_lcl.h"
70#include "ech_locl.h"
69#include "evp_locl.h" 71#include "evp_locl.h"
70 72
71/* EC pkey context structure */ 73/* EC pkey context structure */
@@ -75,17 +77,33 @@ typedef struct {
75 EC_GROUP *gen_group; 77 EC_GROUP *gen_group;
76 /* message digest */ 78 /* message digest */
77 const EVP_MD *md; 79 const EVP_MD *md;
80 /* Duplicate key if custom cofactor needed */
81 EC_KEY *co_key;
82 /* Cofactor mode */
83 signed char cofactor_mode;
84 /* KDF (if any) to use for ECDH */
85 char kdf_type;
86 /* Message digest to use for key derivation */
87 const EVP_MD *kdf_md;
88 /* User key material */
89 unsigned char *kdf_ukm;
90 size_t kdf_ukmlen;
91 /* KDF output length */
92 size_t kdf_outlen;
78} EC_PKEY_CTX; 93} EC_PKEY_CTX;
79 94
80static int 95static int
81pkey_ec_init(EVP_PKEY_CTX * ctx) 96pkey_ec_init(EVP_PKEY_CTX * ctx)
82{ 97{
83 EC_PKEY_CTX *dctx; 98 EC_PKEY_CTX *dctx;
84 dctx = malloc(sizeof(EC_PKEY_CTX)); 99
85 if (!dctx) 100 if ((dctx = calloc(1, sizeof(EC_PKEY_CTX))) == NULL) {
101 ECerror(ERR_R_MALLOC_FAILURE);
86 return 0; 102 return 0;
87 dctx->gen_group = NULL; 103 }
88 dctx->md = NULL; 104
105 dctx->cofactor_mode = -1;
106 dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
89 107
90 ctx->data = dctx; 108 ctx->data = dctx;
91 109
@@ -106,6 +124,24 @@ pkey_ec_copy(EVP_PKEY_CTX * dst, EVP_PKEY_CTX * src)
106 return 0; 124 return 0;
107 } 125 }
108 dctx->md = sctx->md; 126 dctx->md = sctx->md;
127
128 if (sctx->co_key) {
129 dctx->co_key = EC_KEY_dup(sctx->co_key);
130 if (!dctx->co_key)
131 return 0;
132 }
133 dctx->kdf_type = sctx->kdf_type;
134 dctx->kdf_md = sctx->kdf_md;
135 dctx->kdf_outlen = sctx->kdf_outlen;
136 if (sctx->kdf_ukm) {
137 if ((dctx->kdf_ukm = calloc(1, sctx->kdf_ukmlen)) == NULL)
138 return 0;
139 memcpy(dctx->kdf_ukm, sctx->kdf_ukm, sctx->kdf_ukmlen);
140 } else
141 dctx->kdf_ukm = NULL;
142
143 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
144
109 return 1; 145 return 1;
110} 146}
111 147
@@ -113,9 +149,13 @@ static void
113pkey_ec_cleanup(EVP_PKEY_CTX * ctx) 149pkey_ec_cleanup(EVP_PKEY_CTX * ctx)
114{ 150{
115 EC_PKEY_CTX *dctx = ctx->data; 151 EC_PKEY_CTX *dctx = ctx->data;
116 if (dctx) { 152
153 if (dctx != NULL) {
117 EC_GROUP_free(dctx->gen_group); 154 EC_GROUP_free(dctx->gen_group);
155 EC_KEY_free(dctx->co_key);
156 free(dctx->kdf_ukm);
118 free(dctx); 157 free(dctx);
158 ctx->data = NULL;
119 } 159 }
120} 160}
121 161
@@ -140,9 +180,7 @@ pkey_ec_sign(EVP_PKEY_CTX * ctx, unsigned char *sig, size_t * siglen,
140 else 180 else
141 type = NID_sha1; 181 type = NID_sha1;
142 182
143
144 ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec); 183 ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
145
146 if (ret <= 0) 184 if (ret <= 0)
147 return ret; 185 return ret;
148 *siglen = (size_t) sltmp; 186 *siglen = (size_t) sltmp;
@@ -174,13 +212,18 @@ pkey_ec_derive(EVP_PKEY_CTX * ctx, unsigned char *key, size_t * keylen)
174 int ret; 212 int ret;
175 size_t outlen; 213 size_t outlen;
176 const EC_POINT *pubkey = NULL; 214 const EC_POINT *pubkey = NULL;
215 EC_KEY *eckey;
216 EC_PKEY_CTX *dctx = ctx->data;
217
177 if (!ctx->pkey || !ctx->peerkey) { 218 if (!ctx->pkey || !ctx->peerkey) {
178 ECerror(EC_R_KEYS_NOT_SET); 219 ECerror(EC_R_KEYS_NOT_SET);
179 return 0; 220 return 0;
180 } 221 }
222
223 eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
181 if (!key) { 224 if (!key) {
182 const EC_GROUP *group; 225 const EC_GROUP *group;
183 group = EC_KEY_get0_group(ctx->pkey->pkey.ec); 226 group = EC_KEY_get0_group(eckey);
184 *keylen = (EC_GROUP_get_degree(group) + 7) / 8; 227 *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
185 return 1; 228 return 1;
186 } 229 }
@@ -193,18 +236,58 @@ pkey_ec_derive(EVP_PKEY_CTX * ctx, unsigned char *key, size_t * keylen)
193 236
194 outlen = *keylen; 237 outlen = *keylen;
195 238
196 ret = ECDH_compute_key(key, outlen, pubkey, ctx->pkey->pkey.ec, 0); 239 ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
197 if (ret < 0) 240 if (ret <= 0)
198 return ret; 241 return 0;
242
199 *keylen = ret; 243 *keylen = ret;
244
200 return 1; 245 return 1;
201} 246}
202 247
248static int
249pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
250{
251 EC_PKEY_CTX *dctx = ctx->data;
252 unsigned char *ktmp = NULL;
253 size_t ktmplen;
254 int rv = 0;
255
256 if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
257 return pkey_ec_derive(ctx, key, keylen);
258
259 if (!key) {
260 *keylen = dctx->kdf_outlen;
261 return 1;
262 }
263 if (*keylen != dctx->kdf_outlen)
264 return 0;
265 if (!pkey_ec_derive(ctx, NULL, &ktmplen))
266 return 0;
267 if ((ktmp = calloc(1, ktmplen)) == NULL) {
268 ECerror(ERR_R_MALLOC_FAILURE);
269 return 0;
270 }
271 if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
272 goto err;
273 /* Do KDF stuff */
274 if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm,
275 dctx->kdf_ukmlen, dctx->kdf_md))
276 goto err;
277 rv = 1;
278
279 err:
280 freezero(ktmp, ktmplen);
281
282 return rv;
283}
284
203static int 285static int
204pkey_ec_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2) 286pkey_ec_ctrl(EVP_PKEY_CTX * ctx, int type, int p1, void *p2)
205{ 287{
206 EC_PKEY_CTX *dctx = ctx->data; 288 EC_PKEY_CTX *dctx = ctx->data;
207 EC_GROUP *group; 289 EC_GROUP *group;
290
208 switch (type) { 291 switch (type) {
209 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID: 292 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
210 group = EC_GROUP_new_by_curve_name(p1); 293 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)
216 dctx->gen_group = group; 299 dctx->gen_group = group;
217 return 1; 300 return 1;
218 301
302 case EVP_PKEY_CTRL_EC_PARAM_ENC:
303 if (!dctx->gen_group) {
304 ECerror(EC_R_NO_PARAMETERS_SET);
305 return 0;
306 }
307 EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
308 return 1;
309
310 case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
311 if (p1 == -2) {
312 if (dctx->cofactor_mode != -1)
313 return dctx->cofactor_mode;
314 else {
315 EC_KEY *ec_key = ctx->pkey->pkey.ec;
316 return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
317 }
318 } else if (p1 < -1 || p1 > 1)
319 return -2;
320 dctx->cofactor_mode = p1;
321 if (p1 != -1) {
322 EC_KEY *ec_key = ctx->pkey->pkey.ec;
323 if (!ec_key->group)
324 return -2;
325 /* If cofactor is 1 cofactor mode does nothing */
326 if (BN_is_one(&ec_key->group->cofactor))
327 return 1;
328 if (!dctx->co_key) {
329 dctx->co_key = EC_KEY_dup(ec_key);
330 if (!dctx->co_key)
331 return 0;
332 }
333 if (p1)
334 EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
335 else
336 EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
337 } else {
338 EC_KEY_free(dctx->co_key);
339 dctx->co_key = NULL;
340 }
341 return 1;
342
343 case EVP_PKEY_CTRL_EC_KDF_TYPE:
344 if (p1 == -2)
345 return dctx->kdf_type;
346 if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
347 return -2;
348 dctx->kdf_type = p1;
349 return 1;
350
351 case EVP_PKEY_CTRL_EC_KDF_MD:
352 dctx->kdf_md = p2;
353 return 1;
354
355 case EVP_PKEY_CTRL_GET_EC_KDF_MD:
356 *(const EVP_MD **)p2 = dctx->kdf_md;
357 return 1;
358
359 case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
360 if (p1 <= 0)
361 return -2;
362 dctx->kdf_outlen = (size_t)p1;
363 return 1;
364
365 case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
366 *(int *)p2 = dctx->kdf_outlen;
367 return 1;
368
369 case EVP_PKEY_CTRL_EC_KDF_UKM:
370 free(dctx->kdf_ukm);
371 dctx->kdf_ukm = p2;
372 if (p2)
373 dctx->kdf_ukmlen = p1;
374 else
375 dctx->kdf_ukmlen = 0;
376 return 1;
377
378 case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
379 *(unsigned char **)p2 = dctx->kdf_ukm;
380 return dctx->kdf_ukmlen;
381
219 case EVP_PKEY_CTRL_MD: 382 case EVP_PKEY_CTRL_MD:
220 if (EVP_MD_type((const EVP_MD *) p2) != NID_sha1 && 383 if (EVP_MD_type((const EVP_MD *) p2) != NID_sha1 &&
221 EVP_MD_type((const EVP_MD *) p2) != NID_ecdsa_with_SHA1 && 384 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)
243} 406}
244 407
245static int 408static int
246pkey_ec_ctrl_str(EVP_PKEY_CTX * ctx, 409pkey_ec_ctrl_str(EVP_PKEY_CTX * ctx, const char *type, const char *value)
247 const char *type, const char *value)
248{ 410{
249 if (!strcmp(type, "ec_paramgen_curve")) { 411 if (!strcmp(type, "ec_paramgen_curve")) {
250 int nid; 412 int nid;
@@ -258,6 +420,26 @@ pkey_ec_ctrl_str(EVP_PKEY_CTX * ctx,
258 return 0; 420 return 0;
259 } 421 }
260 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid); 422 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
423 } else if (strcmp(type, "ec_param_enc") == 0) {
424 int param_enc;
425 if (strcmp(value, "explicit") == 0)
426 param_enc = 0;
427 else if (strcmp(value, "named_curve") == 0)
428 param_enc = OPENSSL_EC_NAMED_CURVE;
429 else
430 return -2;
431 return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
432 } else if (strcmp(type, "ecdh_kdf_md") == 0) {
433 const EVP_MD *md;
434 if ((md = EVP_get_digestbyname(value)) == NULL) {
435 ECerror(EC_R_INVALID_DIGEST);
436 return 0;
437 }
438 return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
439 } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
440 int co_mode;
441 co_mode = atoi(value);
442 return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
261 } 443 }
262 return -2; 444 return -2;
263} 445}
@@ -287,18 +469,29 @@ static int
287pkey_ec_keygen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey) 469pkey_ec_keygen(EVP_PKEY_CTX * ctx, EVP_PKEY * pkey)
288{ 470{
289 EC_KEY *ec = NULL; 471 EC_KEY *ec = NULL;
290 if (ctx->pkey == NULL) { 472 EC_PKEY_CTX *dctx = ctx->data;
473
474 if (ctx->pkey == NULL && dctx->gen_group == NULL) {
291 ECerror(EC_R_NO_PARAMETERS_SET); 475 ECerror(EC_R_NO_PARAMETERS_SET);
292 return 0; 476 return 0;
293 } 477 }
294 ec = EC_KEY_new(); 478 ec = EC_KEY_new();
295 if (!ec) 479 if (ec == NULL)
296 return 0; 480 return 0;
297 EVP_PKEY_assign_EC_KEY(pkey, ec); 481 if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
298 /* Note: if error return, pkey is freed by parent routine */ 482 EC_KEY_free(ec);
299 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
300 return 0; 483 return 0;
301 return EC_KEY_generate_key(pkey->pkey.ec); 484 }
485 /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
486 if (ctx->pkey != NULL) {
487 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
488 return 0;
489 } else {
490 if (!EC_KEY_set_group(ec, dctx->gen_group))
491 return 0;
492 }
493
494 return EC_KEY_generate_key(ec);
302} 495}
303 496
304const EVP_PKEY_METHOD ec_pkey_meth = { 497const EVP_PKEY_METHOD ec_pkey_meth = {
@@ -316,7 +509,7 @@ const EVP_PKEY_METHOD ec_pkey_meth = {
316 509
317 .verify = pkey_ec_verify, 510 .verify = pkey_ec_verify,
318 511
319 .derive = pkey_ec_derive, 512 .derive = pkey_ec_kdf_derive,
320 513
321 .ctrl = pkey_ec_ctrl, 514 .ctrl = pkey_ec_ctrl,
322 .ctrl_str = pkey_ec_ctrl_str 515 .ctrl_str = pkey_ec_ctrl_str