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