]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_pmeth.c
Update copyright year
[thirdparty/openssl.git] / crypto / ec / ec_pmeth.c
CommitLineData
0f113f3e 1/*
4333b89f 2 * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
9ca7047d 3 *
a7f182b7 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
aa6bb135
RS
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
9ca7047d
DSH
8 */
9
5e3f9aa4
P
10/*
11 * ECDH and ECDSA low level APIs are deprecated for public use, but still ok
12 * for internal use.
13 */
14#include "internal/deprecated.h"
15
9ca7047d 16#include <stdio.h>
b39fc560 17#include "internal/cryptlib.h"
9ca7047d
DSH
18#include <openssl/asn1t.h>
19#include <openssl/x509.h>
20#include <openssl/ec.h>
706457b7 21#include "ec_local.h"
9ca7047d 22#include <openssl/evp.h>
25f2138b 23#include "crypto/evp.h"
9ca7047d
DSH
24
25/* EC pkey context structure */
26
0f113f3e
MC
27typedef struct {
28 /* Key and paramgen group */
29 EC_GROUP *gen_group;
30 /* message digest */
31 const EVP_MD *md;
32 /* Duplicate key if custom cofactor needed */
33 EC_KEY *co_key;
34 /* Cofactor mode */
35 signed char cofactor_mode;
36 /* KDF (if any) to use for ECDH */
37 char kdf_type;
38 /* Message digest to use for key derivation */
39 const EVP_MD *kdf_md;
40 /* User key material */
41 unsigned char *kdf_ukm;
42 size_t kdf_ukmlen;
43 /* KDF output length */
44 size_t kdf_outlen;
45} EC_PKEY_CTX;
9ca7047d
DSH
46
47static int pkey_ec_init(EVP_PKEY_CTX *ctx)
0f113f3e
MC
48{
49 EC_PKEY_CTX *dctx;
b4faea50 50
cdb10bae 51 if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
9311d0c4 52 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
0f113f3e 53 return 0;
cdb10bae 54 }
0f113f3e
MC
55
56 dctx->cofactor_mode = -1;
0f113f3e 57 dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
0f113f3e 58 ctx->data = dctx;
0f113f3e
MC
59 return 1;
60}
9ca7047d 61
9fdcc21f 62static int pkey_ec_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
0f113f3e
MC
63{
64 EC_PKEY_CTX *dctx, *sctx;
65 if (!pkey_ec_init(dst))
66 return 0;
67 sctx = src->data;
68 dctx = dst->data;
69 if (sctx->gen_group) {
70 dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
71 if (!dctx->gen_group)
72 return 0;
73 }
74 dctx->md = sctx->md;
75
76 if (sctx->co_key) {
77 dctx->co_key = EC_KEY_dup(sctx->co_key);
78 if (!dctx->co_key)
79 return 0;
80 }
81 dctx->kdf_type = sctx->kdf_type;
82 dctx->kdf_md = sctx->kdf_md;
83 dctx->kdf_outlen = sctx->kdf_outlen;
84 if (sctx->kdf_ukm) {
7644a9ae 85 dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
0f113f3e
MC
86 if (!dctx->kdf_ukm)
87 return 0;
88 } else
89 dctx->kdf_ukm = NULL;
90 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
91 return 1;
92}
8bdcef40 93
9ca7047d 94static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
0f113f3e
MC
95{
96 EC_PKEY_CTX *dctx = ctx->data;
95a37057 97 if (dctx != NULL) {
8fdc3734
RS
98 EC_GROUP_free(dctx->gen_group);
99 EC_KEY_free(dctx->co_key);
b548a1f1 100 OPENSSL_free(dctx->kdf_ukm);
0f113f3e 101 OPENSSL_free(dctx);
95a37057 102 ctx->data = NULL;
0f113f3e
MC
103 }
104}
9ca7047d 105
eaff5a14 106static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
0f113f3e
MC
107 const unsigned char *tbs, size_t tbslen)
108{
109 int ret, type;
110 unsigned int sltmp;
111 EC_PKEY_CTX *dctx = ctx->data;
112 EC_KEY *ec = ctx->pkey->pkey.ec;
95a37057 113 const int sig_sz = ECDSA_size(ec);
0f113f3e 114
95a37057
AP
115 /* ensure cast to size_t is safe */
116 if (!ossl_assert(sig_sz > 0))
117 return 0;
118
119 if (sig == NULL) {
120 *siglen = (size_t)sig_sz;
0f113f3e 121 return 1;
95a37057
AP
122 }
123
124 if (*siglen < (size_t)sig_sz) {
9311d0c4 125 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
0f113f3e
MC
126 return 0;
127 }
128
95a37057 129 type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1;
0f113f3e 130
ddb634fe 131 ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
0f113f3e
MC
132
133 if (ret <= 0)
134 return ret;
135 *siglen = (size_t)sltmp;
136 return 1;
137}
9ca7047d
DSH
138
139static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
0f113f3e
MC
140 const unsigned char *sig, size_t siglen,
141 const unsigned char *tbs, size_t tbslen)
142{
143 int ret, type;
144 EC_PKEY_CTX *dctx = ctx->data;
145 EC_KEY *ec = ctx->pkey->pkey.ec;
9ca7047d 146
0f113f3e
MC
147 if (dctx->md)
148 type = EVP_MD_type(dctx->md);
149 else
150 type = NID_sha1;
9ca7047d 151
ddb634fe 152 ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
9ca7047d 153
0f113f3e
MC
154 return ret;
155}
9ca7047d 156
10bf4fc2 157#ifndef OPENSSL_NO_EC
dceb99a5 158static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
0f113f3e
MC
159{
160 int ret;
161 size_t outlen;
162 const EC_POINT *pubkey = NULL;
163 EC_KEY *eckey;
164 EC_PKEY_CTX *dctx = ctx->data;
165 if (!ctx->pkey || !ctx->peerkey) {
9311d0c4 166 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
0f113f3e
MC
167 return 0;
168 }
169
170 eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
171
172 if (!key) {
173 const EC_GROUP *group;
174 group = EC_KEY_get0_group(eckey);
82a46200
TM
175
176 if (group == NULL)
177 return 0;
0f113f3e
MC
178 *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
179 return 1;
180 }
181 pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
182
183 /*
184 * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
185 * an error, the result is truncated.
186 */
187
188 outlen = *keylen;
189
190 ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
191 if (ret <= 0)
192 return 0;
193 *keylen = ret;
194 return 1;
195}
9ca7047d 196
25af7a5d 197static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
0f113f3e
MC
198 unsigned char *key, size_t *keylen)
199{
200 EC_PKEY_CTX *dctx = ctx->data;
201 unsigned char *ktmp = NULL;
202 size_t ktmplen;
203 int rv = 0;
204 if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
205 return pkey_ec_derive(ctx, key, keylen);
206 if (!key) {
207 *keylen = dctx->kdf_outlen;
208 return 1;
209 }
210 if (*keylen != dctx->kdf_outlen)
211 return 0;
212 if (!pkey_ec_derive(ctx, NULL, &ktmplen))
213 return 0;
cdb10bae 214 if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) {
9311d0c4 215 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
0f113f3e 216 return 0;
cdb10bae 217 }
0f113f3e
MC
218 if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
219 goto err;
220 /* Do KDF stuff */
ffd89124 221 if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen,
5ccada09
SL
222 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md,
223 ctx->libctx, ctx->propquery))
0f113f3e
MC
224 goto err;
225 rv = 1;
226
227 err:
4b45c6e5 228 OPENSSL_clear_free(ktmp, ktmplen);
0f113f3e
MC
229 return rv;
230}
af6e2d51 231#endif
25af7a5d 232
9ca7047d 233static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
0f113f3e
MC
234{
235 EC_PKEY_CTX *dctx = ctx->data;
236 EC_GROUP *group;
237 switch (type) {
238 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
239 group = EC_GROUP_new_by_curve_name(p1);
240 if (group == NULL) {
9311d0c4 241 ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
0f113f3e
MC
242 return 0;
243 }
8fdc3734 244 EC_GROUP_free(dctx->gen_group);
0f113f3e
MC
245 dctx->gen_group = group;
246 return 1;
247
248 case EVP_PKEY_CTRL_EC_PARAM_ENC:
249 if (!dctx->gen_group) {
9311d0c4 250 ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
0f113f3e
MC
251 return 0;
252 }
253 EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
254 return 1;
24edfa9d 255
10bf4fc2 256#ifndef OPENSSL_NO_EC
0f113f3e
MC
257 case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
258 if (p1 == -2) {
259 if (dctx->cofactor_mode != -1)
260 return dctx->cofactor_mode;
261 else {
262 EC_KEY *ec_key = ctx->pkey->pkey.ec;
dceb99a5 263 return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
0f113f3e
MC
264 }
265 } else if (p1 < -1 || p1 > 1)
266 return -2;
267 dctx->cofactor_mode = p1;
268 if (p1 != -1) {
269 EC_KEY *ec_key = ctx->pkey->pkey.ec;
270 if (!ec_key->group)
271 return -2;
272 /* If cofactor is 1 cofactor mode does nothing */
273 if (BN_is_one(ec_key->group->cofactor))
274 return 1;
275 if (!dctx->co_key) {
276 dctx->co_key = EC_KEY_dup(ec_key);
277 if (!dctx->co_key)
278 return 0;
279 }
280 if (p1)
281 EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
282 else
283 EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
8fdc3734 284 } else {
0f113f3e
MC
285 EC_KEY_free(dctx->co_key);
286 dctx->co_key = NULL;
287 }
288 return 1;
af6e2d51 289#endif
25af7a5d 290
0f113f3e
MC
291 case EVP_PKEY_CTRL_EC_KDF_TYPE:
292 if (p1 == -2)
293 return dctx->kdf_type;
ffd89124 294 if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
0f113f3e
MC
295 return -2;
296 dctx->kdf_type = p1;
297 return 1;
298
299 case EVP_PKEY_CTRL_EC_KDF_MD:
300 dctx->kdf_md = p2;
301 return 1;
302
303 case EVP_PKEY_CTRL_GET_EC_KDF_MD:
304 *(const EVP_MD **)p2 = dctx->kdf_md;
305 return 1;
306
307 case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
308 if (p1 <= 0)
309 return -2;
310 dctx->kdf_outlen = (size_t)p1;
311 return 1;
312
313 case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
314 *(int *)p2 = dctx->kdf_outlen;
315 return 1;
316
317 case EVP_PKEY_CTRL_EC_KDF_UKM:
b548a1f1 318 OPENSSL_free(dctx->kdf_ukm);
0f113f3e
MC
319 dctx->kdf_ukm = p2;
320 if (p2)
321 dctx->kdf_ukmlen = p1;
322 else
323 dctx->kdf_ukmlen = 0;
324 return 1;
325
326 case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
327 *(unsigned char **)p2 = dctx->kdf_ukm;
328 return dctx->kdf_ukmlen;
329
330 case EVP_PKEY_CTRL_MD:
331 if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
332 EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
333 EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
334 EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
335 EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
e8d0678d
PS
336 EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
337 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
338 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
339 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
bc42bd62
PY
340 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512 &&
341 EVP_MD_type((const EVP_MD *)p2) != NID_sm3) {
9311d0c4 342 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
0f113f3e
MC
343 return 0;
344 }
345 dctx->md = p2;
346 return 1;
347
348 case EVP_PKEY_CTRL_GET_MD:
349 *(const EVP_MD **)p2 = dctx->md;
350 return 1;
351
352 case EVP_PKEY_CTRL_PEER_KEY:
353 /* Default behaviour is OK */
354 case EVP_PKEY_CTRL_DIGESTINIT:
355 case EVP_PKEY_CTRL_PKCS7_SIGN:
356 case EVP_PKEY_CTRL_CMS_SIGN:
357 return 1;
358
359 default:
360 return -2;
361
362 }
363}
364
9ca7047d 365static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
0f113f3e
MC
366 const char *type, const char *value)
367{
86885c28 368 if (strcmp(type, "ec_paramgen_curve") == 0) {
0f113f3e
MC
369 int nid;
370 nid = EC_curve_nist2nid(value);
371 if (nid == NID_undef)
372 nid = OBJ_sn2nid(value);
373 if (nid == NID_undef)
374 nid = OBJ_ln2nid(value);
375 if (nid == NID_undef) {
9311d0c4 376 ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
0f113f3e
MC
377 return 0;
378 }
379 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
86885c28 380 } else if (strcmp(type, "ec_param_enc") == 0) {
0f113f3e 381 int param_enc;
86885c28 382 if (strcmp(value, "explicit") == 0)
0f113f3e 383 param_enc = 0;
86885c28 384 else if (strcmp(value, "named_curve") == 0)
0f113f3e
MC
385 param_enc = OPENSSL_EC_NAMED_CURVE;
386 else
387 return -2;
388 return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
86885c28 389 } else if (strcmp(type, "ecdh_kdf_md") == 0) {
0f113f3e 390 const EVP_MD *md;
75ebbd9a 391 if ((md = EVP_get_digestbyname(value)) == NULL) {
9311d0c4 392 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST);
0f113f3e
MC
393 return 0;
394 }
395 return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
86885c28 396 } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
0f113f3e
MC
397 int co_mode;
398 co_mode = atoi(value);
399 return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
400 }
401
402 return -2;
403}
9ca7047d
DSH
404
405static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
406{
407 EC_KEY *ec = NULL;
408 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
409 int ret;
410
0f113f3e 411 if (dctx->gen_group == NULL) {
9311d0c4 412 ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
0f113f3e
MC
413 return 0;
414 }
415 ec = EC_KEY_new();
90945fa3 416 if (ec == NULL)
0f113f3e 417 return 0;
95a37057
AP
418 if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
419 || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
0f113f3e
MC
420 EC_KEY_free(ec);
421 return ret;
422}
9ca7047d
DSH
423
424static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
425{
426 EC_KEY *ec = NULL;
427 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
428 int ret;
429
0f113f3e 430 if (ctx->pkey == NULL && dctx->gen_group == NULL) {
9311d0c4 431 ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
0f113f3e
MC
432 return 0;
433 }
434 ec = EC_KEY_new();
95a37057
AP
435 if (ec == NULL)
436 return 0;
437 if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
438 EC_KEY_free(ec);
0f113f3e 439 return 0;
0f113f3e 440 }
95a37057
AP
441 /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
442 if (ctx->pkey != NULL)
443 ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
444 else
445 ret = EC_KEY_set_group(ec, dctx->gen_group);
446
447 return ret ? EC_KEY_generate_key(ec) : 0;
0f113f3e
MC
448}
449
19bd1fa1 450static const EVP_PKEY_METHOD ec_pkey_meth = {
0f113f3e 451 EVP_PKEY_EC,
4e664750 452 0,
0f113f3e
MC
453 pkey_ec_init,
454 pkey_ec_copy,
455 pkey_ec_cleanup,
456
457 0,
458 pkey_ec_paramgen,
459
460 0,
461 pkey_ec_keygen,
462
463 0,
464 pkey_ec_sign,
465
466 0,
467 pkey_ec_verify,
468
469 0, 0,
470
471 0, 0, 0, 0,
472
dceb99a5 473 0,
ddb634fe 474 0,
0f113f3e 475
dceb99a5 476 0,
ddb634fe 477 0,
0f113f3e
MC
478
479 0,
10bf4fc2 480#ifndef OPENSSL_NO_EC
0f113f3e 481 pkey_ec_kdf_derive,
af6e2d51 482#else
0f113f3e 483 0,
af6e2d51 484#endif
0f113f3e
MC
485 pkey_ec_ctrl,
486 pkey_ec_ctrl_str
487};
19bd1fa1
PS
488
489const EVP_PKEY_METHOD *ec_pkey_method(void)
490{
491 return &ec_pkey_meth;
492}