]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_pmeth.c
Rename all getters to use get/get0 in name
[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
ed576acd 129 type = (dctx->md != NULL) ? EVP_MD_get_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 147 if (dctx->md)
ed576acd 148 type = EVP_MD_get_type(dctx->md);
0f113f3e
MC
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;
19ad1e9d 164 const EC_KEY *eckeypub;
0f113f3e 165 EC_PKEY_CTX *dctx = ctx->data;
19ad1e9d
MC
166
167 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
168 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
169 return 0;
170 }
171 eckeypub = EVP_PKEY_get0_EC_KEY(ctx->peerkey);
172 if (eckeypub == NULL) {
9311d0c4 173 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
0f113f3e
MC
174 return 0;
175 }
176
177 eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
178
179 if (!key) {
180 const EC_GROUP *group;
181 group = EC_KEY_get0_group(eckey);
82a46200
TM
182
183 if (group == NULL)
184 return 0;
0f113f3e
MC
185 *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
186 return 1;
187 }
19ad1e9d 188 pubkey = EC_KEY_get0_public_key(eckeypub);
0f113f3e
MC
189
190 /*
191 * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
192 * an error, the result is truncated.
193 */
194
195 outlen = *keylen;
196
197 ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
198 if (ret <= 0)
199 return 0;
200 *keylen = ret;
201 return 1;
202}
9ca7047d 203
25af7a5d 204static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
0f113f3e
MC
205 unsigned char *key, size_t *keylen)
206{
207 EC_PKEY_CTX *dctx = ctx->data;
208 unsigned char *ktmp = NULL;
209 size_t ktmplen;
210 int rv = 0;
211 if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
212 return pkey_ec_derive(ctx, key, keylen);
213 if (!key) {
214 *keylen = dctx->kdf_outlen;
215 return 1;
216 }
217 if (*keylen != dctx->kdf_outlen)
218 return 0;
219 if (!pkey_ec_derive(ctx, NULL, &ktmplen))
220 return 0;
cdb10bae 221 if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) {
9311d0c4 222 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
0f113f3e 223 return 0;
cdb10bae 224 }
0f113f3e
MC
225 if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
226 goto err;
227 /* Do KDF stuff */
32ab57cb
SL
228 if (!ossl_ecdh_kdf_X9_63(key, *keylen, ktmp, ktmplen,
229 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md,
230 ctx->libctx, ctx->propquery))
0f113f3e
MC
231 goto err;
232 rv = 1;
233
234 err:
4b45c6e5 235 OPENSSL_clear_free(ktmp, ktmplen);
0f113f3e
MC
236 return rv;
237}
af6e2d51 238#endif
25af7a5d 239
9ca7047d 240static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
0f113f3e
MC
241{
242 EC_PKEY_CTX *dctx = ctx->data;
243 EC_GROUP *group;
244 switch (type) {
245 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
246 group = EC_GROUP_new_by_curve_name(p1);
247 if (group == NULL) {
9311d0c4 248 ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
0f113f3e
MC
249 return 0;
250 }
8fdc3734 251 EC_GROUP_free(dctx->gen_group);
0f113f3e
MC
252 dctx->gen_group = group;
253 return 1;
254
255 case EVP_PKEY_CTRL_EC_PARAM_ENC:
256 if (!dctx->gen_group) {
9311d0c4 257 ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
0f113f3e
MC
258 return 0;
259 }
260 EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
261 return 1;
24edfa9d 262
10bf4fc2 263#ifndef OPENSSL_NO_EC
0f113f3e
MC
264 case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
265 if (p1 == -2) {
266 if (dctx->cofactor_mode != -1)
267 return dctx->cofactor_mode;
268 else {
269 EC_KEY *ec_key = ctx->pkey->pkey.ec;
dceb99a5 270 return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
0f113f3e
MC
271 }
272 } else if (p1 < -1 || p1 > 1)
273 return -2;
274 dctx->cofactor_mode = p1;
275 if (p1 != -1) {
276 EC_KEY *ec_key = ctx->pkey->pkey.ec;
277 if (!ec_key->group)
278 return -2;
279 /* If cofactor is 1 cofactor mode does nothing */
280 if (BN_is_one(ec_key->group->cofactor))
281 return 1;
282 if (!dctx->co_key) {
283 dctx->co_key = EC_KEY_dup(ec_key);
284 if (!dctx->co_key)
285 return 0;
286 }
287 if (p1)
288 EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
289 else
290 EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
8fdc3734 291 } else {
0f113f3e
MC
292 EC_KEY_free(dctx->co_key);
293 dctx->co_key = NULL;
294 }
295 return 1;
af6e2d51 296#endif
25af7a5d 297
0f113f3e
MC
298 case EVP_PKEY_CTRL_EC_KDF_TYPE:
299 if (p1 == -2)
300 return dctx->kdf_type;
ffd89124 301 if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
0f113f3e
MC
302 return -2;
303 dctx->kdf_type = p1;
304 return 1;
305
306 case EVP_PKEY_CTRL_EC_KDF_MD:
307 dctx->kdf_md = p2;
308 return 1;
309
310 case EVP_PKEY_CTRL_GET_EC_KDF_MD:
311 *(const EVP_MD **)p2 = dctx->kdf_md;
312 return 1;
313
314 case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
315 if (p1 <= 0)
316 return -2;
317 dctx->kdf_outlen = (size_t)p1;
318 return 1;
319
320 case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
321 *(int *)p2 = dctx->kdf_outlen;
322 return 1;
323
324 case EVP_PKEY_CTRL_EC_KDF_UKM:
b548a1f1 325 OPENSSL_free(dctx->kdf_ukm);
0f113f3e
MC
326 dctx->kdf_ukm = p2;
327 if (p2)
328 dctx->kdf_ukmlen = p1;
329 else
330 dctx->kdf_ukmlen = 0;
331 return 1;
332
333 case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
334 *(unsigned char **)p2 = dctx->kdf_ukm;
335 return dctx->kdf_ukmlen;
336
337 case EVP_PKEY_CTRL_MD:
ed576acd
TM
338 if (EVP_MD_get_type((const EVP_MD *)p2) != NID_sha1 &&
339 EVP_MD_get_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
340 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha224 &&
341 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha256 &&
342 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha384 &&
343 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha512 &&
344 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_224 &&
345 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_256 &&
346 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_384 &&
347 EVP_MD_get_type((const EVP_MD *)p2) != NID_sha3_512 &&
348 EVP_MD_get_type((const EVP_MD *)p2) != NID_sm3) {
9311d0c4 349 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
0f113f3e
MC
350 return 0;
351 }
352 dctx->md = p2;
353 return 1;
354
355 case EVP_PKEY_CTRL_GET_MD:
356 *(const EVP_MD **)p2 = dctx->md;
357 return 1;
358
359 case EVP_PKEY_CTRL_PEER_KEY:
360 /* Default behaviour is OK */
361 case EVP_PKEY_CTRL_DIGESTINIT:
362 case EVP_PKEY_CTRL_PKCS7_SIGN:
363 case EVP_PKEY_CTRL_CMS_SIGN:
364 return 1;
365
366 default:
367 return -2;
368
369 }
370}
371
9ca7047d 372static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
0f113f3e
MC
373 const char *type, const char *value)
374{
86885c28 375 if (strcmp(type, "ec_paramgen_curve") == 0) {
0f113f3e
MC
376 int nid;
377 nid = EC_curve_nist2nid(value);
378 if (nid == NID_undef)
379 nid = OBJ_sn2nid(value);
380 if (nid == NID_undef)
381 nid = OBJ_ln2nid(value);
382 if (nid == NID_undef) {
9311d0c4 383 ERR_raise(ERR_LIB_EC, EC_R_INVALID_CURVE);
0f113f3e
MC
384 return 0;
385 }
386 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
86885c28 387 } else if (strcmp(type, "ec_param_enc") == 0) {
0f113f3e 388 int param_enc;
86885c28 389 if (strcmp(value, "explicit") == 0)
0f113f3e 390 param_enc = 0;
86885c28 391 else if (strcmp(value, "named_curve") == 0)
0f113f3e
MC
392 param_enc = OPENSSL_EC_NAMED_CURVE;
393 else
394 return -2;
395 return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
86885c28 396 } else if (strcmp(type, "ecdh_kdf_md") == 0) {
0f113f3e 397 const EVP_MD *md;
75ebbd9a 398 if ((md = EVP_get_digestbyname(value)) == NULL) {
9311d0c4 399 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST);
0f113f3e
MC
400 return 0;
401 }
402 return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
86885c28 403 } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
0f113f3e
MC
404 int co_mode;
405 co_mode = atoi(value);
406 return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
407 }
408
409 return -2;
410}
9ca7047d
DSH
411
412static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
413{
414 EC_KEY *ec = NULL;
415 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
416 int ret;
417
0f113f3e 418 if (dctx->gen_group == NULL) {
9311d0c4 419 ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
0f113f3e
MC
420 return 0;
421 }
422 ec = EC_KEY_new();
90945fa3 423 if (ec == NULL)
0f113f3e 424 return 0;
95a37057
AP
425 if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
426 || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
0f113f3e
MC
427 EC_KEY_free(ec);
428 return ret;
429}
9ca7047d
DSH
430
431static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
432{
433 EC_KEY *ec = NULL;
434 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
435 int ret;
436
0f113f3e 437 if (ctx->pkey == NULL && dctx->gen_group == NULL) {
9311d0c4 438 ERR_raise(ERR_LIB_EC, EC_R_NO_PARAMETERS_SET);
0f113f3e
MC
439 return 0;
440 }
441 ec = EC_KEY_new();
95a37057
AP
442 if (ec == NULL)
443 return 0;
444 if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
445 EC_KEY_free(ec);
0f113f3e 446 return 0;
0f113f3e 447 }
95a37057
AP
448 /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
449 if (ctx->pkey != NULL)
450 ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
451 else
452 ret = EC_KEY_set_group(ec, dctx->gen_group);
453
454 return ret ? EC_KEY_generate_key(ec) : 0;
0f113f3e
MC
455}
456
19bd1fa1 457static const EVP_PKEY_METHOD ec_pkey_meth = {
0f113f3e 458 EVP_PKEY_EC,
4e664750 459 0,
0f113f3e
MC
460 pkey_ec_init,
461 pkey_ec_copy,
462 pkey_ec_cleanup,
463
464 0,
465 pkey_ec_paramgen,
466
467 0,
468 pkey_ec_keygen,
469
470 0,
471 pkey_ec_sign,
472
473 0,
474 pkey_ec_verify,
475
476 0, 0,
477
478 0, 0, 0, 0,
479
dceb99a5 480 0,
ddb634fe 481 0,
0f113f3e 482
dceb99a5 483 0,
ddb634fe 484 0,
0f113f3e
MC
485
486 0,
10bf4fc2 487#ifndef OPENSSL_NO_EC
0f113f3e 488 pkey_ec_kdf_derive,
af6e2d51 489#else
0f113f3e 490 0,
af6e2d51 491#endif
0f113f3e
MC
492 pkey_ec_ctrl,
493 pkey_ec_ctrl_str
494};
19bd1fa1 495
32ab57cb 496const EVP_PKEY_METHOD *ossl_ec_pkey_method(void)
19bd1fa1
PS
497{
498 return &ec_pkey_meth;
499}