]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_pmeth.c
Fix no-sm2
[thirdparty/openssl.git] / crypto / ec / ec_pmeth.c
CommitLineData
0f113f3e 1/*
aa6bb135 2 * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
9ca7047d 3 *
aa6bb135
RS
4 * Licensed under the OpenSSL license (the "License"). You may not use
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
10#include <stdio.h>
b39fc560 11#include "internal/cryptlib.h"
9ca7047d
DSH
12#include <openssl/asn1t.h>
13#include <openssl/x509.h>
14#include <openssl/ec.h>
25af7a5d 15#include "ec_lcl.h"
9ca7047d 16#include <openssl/evp.h>
27af42f9 17#include "internal/evp_int.h"
9ca7047d 18
3d328a44 19#if !defined(OPENSSL_NO_SM2)
dceb99a5 20# include <openssl/sm2.h>
3d328a44
JL
21#endif
22
9ca7047d
DSH
23/* EC pkey context structure */
24
0f113f3e
MC
25typedef struct {
26 /* Key and paramgen group */
27 EC_GROUP *gen_group;
28 /* message digest */
29 const EVP_MD *md;
30 /* Duplicate key if custom cofactor needed */
31 EC_KEY *co_key;
32 /* Cofactor mode */
33 signed char cofactor_mode;
34 /* KDF (if any) to use for ECDH */
35 char kdf_type;
36 /* Message digest to use for key derivation */
37 const EVP_MD *kdf_md;
38 /* User key material */
39 unsigned char *kdf_ukm;
40 size_t kdf_ukmlen;
41 /* KDF output length */
42 size_t kdf_outlen;
43} EC_PKEY_CTX;
9ca7047d
DSH
44
45static int pkey_ec_init(EVP_PKEY_CTX *ctx)
0f113f3e
MC
46{
47 EC_PKEY_CTX *dctx;
b4faea50 48
64b25758 49 dctx = OPENSSL_zalloc(sizeof(*dctx));
90945fa3 50 if (dctx == NULL)
0f113f3e 51 return 0;
0f113f3e
MC
52
53 dctx->cofactor_mode = -1;
0f113f3e 54 dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
0f113f3e 55 ctx->data = dctx;
0f113f3e
MC
56 return 1;
57}
9ca7047d 58
8bdcef40 59static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
0f113f3e
MC
60{
61 EC_PKEY_CTX *dctx, *sctx;
62 if (!pkey_ec_init(dst))
63 return 0;
64 sctx = src->data;
65 dctx = dst->data;
66 if (sctx->gen_group) {
67 dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
68 if (!dctx->gen_group)
69 return 0;
70 }
71 dctx->md = sctx->md;
72
73 if (sctx->co_key) {
74 dctx->co_key = EC_KEY_dup(sctx->co_key);
75 if (!dctx->co_key)
76 return 0;
77 }
78 dctx->kdf_type = sctx->kdf_type;
79 dctx->kdf_md = sctx->kdf_md;
80 dctx->kdf_outlen = sctx->kdf_outlen;
81 if (sctx->kdf_ukm) {
7644a9ae 82 dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
0f113f3e
MC
83 if (!dctx->kdf_ukm)
84 return 0;
85 } else
86 dctx->kdf_ukm = NULL;
87 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
88 return 1;
89}
8bdcef40 90
9ca7047d 91static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
0f113f3e
MC
92{
93 EC_PKEY_CTX *dctx = ctx->data;
94 if (dctx) {
8fdc3734
RS
95 EC_GROUP_free(dctx->gen_group);
96 EC_KEY_free(dctx->co_key);
b548a1f1 97 OPENSSL_free(dctx->kdf_ukm);
0f113f3e
MC
98 OPENSSL_free(dctx);
99 }
100}
9ca7047d 101
eaff5a14 102static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
0f113f3e
MC
103 const unsigned char *tbs, size_t tbslen)
104{
105 int ret, type;
106 unsigned int sltmp;
107 EC_PKEY_CTX *dctx = ctx->data;
108 EC_KEY *ec = ctx->pkey->pkey.ec;
3d328a44 109 const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
0f113f3e
MC
110
111 if (!sig) {
112 *siglen = ECDSA_size(ec);
113 return 1;
114 } else if (*siglen < (size_t)ECDSA_size(ec)) {
115 ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
116 return 0;
117 }
118
119 if (dctx->md)
120 type = EVP_MD_type(dctx->md);
121 else
122 type = NID_sha1;
123
3d328a44
JL
124 if (ec_nid == NID_sm2) {
125#if defined(OPENSSL_NO_SM2)
dceb99a5 126 ret = -1;
3d328a44 127#else
dceb99a5 128 ret = SM2_sign(type, tbs, tbslen, sig, &sltmp, ec);
3d328a44 129#endif
dceb99a5
JL
130 } else {
131 ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
3d328a44 132 }
0f113f3e
MC
133
134 if (ret <= 0)
135 return ret;
136 *siglen = (size_t)sltmp;
137 return 1;
138}
9ca7047d
DSH
139
140static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
0f113f3e
MC
141 const unsigned char *sig, size_t siglen,
142 const unsigned char *tbs, size_t tbslen)
143{
144 int ret, type;
145 EC_PKEY_CTX *dctx = ctx->data;
146 EC_KEY *ec = ctx->pkey->pkey.ec;
3d328a44 147 const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
9ca7047d 148
0f113f3e
MC
149 if (dctx->md)
150 type = EVP_MD_type(dctx->md);
151 else
152 type = NID_sha1;
9ca7047d 153
3d328a44
JL
154 if (ec_nid == NID_sm2) {
155#if defined(OPENSSL_NO_SM2)
dceb99a5 156 ret = -1;
3d328a44 157#else
dceb99a5 158 ret = SM2_verify(type, tbs, tbslen, sig, siglen, ec);
3d328a44 159#endif
dceb99a5
JL
160 } else {
161 ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
3d328a44 162 }
9ca7047d 163
0f113f3e
MC
164 return ret;
165}
9ca7047d 166
10bf4fc2 167#ifndef OPENSSL_NO_EC
dceb99a5 168static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
0f113f3e
MC
169{
170 int ret;
171 size_t outlen;
172 const EC_POINT *pubkey = NULL;
173 EC_KEY *eckey;
174 EC_PKEY_CTX *dctx = ctx->data;
175 if (!ctx->pkey || !ctx->peerkey) {
176 ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
177 return 0;
178 }
179
180 eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
181
182 if (!key) {
183 const EC_GROUP *group;
184 group = EC_KEY_get0_group(eckey);
185 *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
186 return 1;
187 }
188 pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
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
dceb99a5
JL
204static int pkey_ecies_encrypt(EVP_PKEY_CTX *ctx,
205 unsigned char *out, size_t *outlen,
206 const unsigned char *in, size_t inlen)
207{
1bf2cc23 208 int ret;
dceb99a5
JL
209 EC_KEY *ec = ctx->pkey->pkey.ec;
210 const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
211
dceb99a5
JL
212 if (ec_nid == NID_sm2) {
213# if defined(OPENSSL_NO_SM2)
214 ret = -1;
215# else
1bf2cc23
MC
216 int md_type;
217 EC_PKEY_CTX *dctx = ctx->data;
218
219 if (dctx->md)
220 md_type = EVP_MD_type(dctx->md);
221 else if (ec_nid == NID_sm2)
222 md_type = NID_sm3;
223 else
224 md_type = NID_sha256;
225
4e664750 226 if (out == NULL) {
1bf2cc23
MC
227 *outlen = SM2_ciphertext_size(ec, EVP_get_digestbynid(md_type),
228 inlen);
4e664750
JL
229 ret = 1;
230 }
231 else {
232 ret = SM2_encrypt(ec, EVP_get_digestbynid(md_type),
233 in, inlen, out, outlen);
234 }
dceb99a5
JL
235# endif
236 } else {
237 /* standard ECIES not implemented */
238 ret = -1;
239 }
240
241 return ret;
242}
243
244static int pkey_ecies_decrypt(EVP_PKEY_CTX *ctx,
245 unsigned char *out, size_t *outlen,
246 const unsigned char *in, size_t inlen)
247{
1bf2cc23 248 int ret;
dceb99a5
JL
249 EC_KEY *ec = ctx->pkey->pkey.ec;
250 const int ec_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
251
dceb99a5
JL
252 if (ec_nid == NID_sm2) {
253# if defined(OPENSSL_NO_SM2)
254 ret = -1;
255# else
1bf2cc23
MC
256 int md_type;
257 EC_PKEY_CTX *dctx = ctx->data;
258
259 if (dctx->md)
260 md_type = EVP_MD_type(dctx->md);
261 else if (ec_nid == NID_sm2)
262 md_type = NID_sm3;
263 else
264 md_type = NID_sha256;
265
4e664750
JL
266 if (out == NULL) {
267 *outlen = SM2_plaintext_size(ec, EVP_get_digestbynid(md_type), inlen);
268 ret = 1;
269 }
270 else {
271 ret = SM2_decrypt(ec, EVP_get_digestbynid(md_type),
272 in, inlen, out, outlen);
273 }
dceb99a5
JL
274# endif
275 } else {
276 /* standard ECIES not implemented */
277 ret = -1;
278 }
279
280 return ret;
281}
282
25af7a5d 283static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
0f113f3e
MC
284 unsigned char *key, size_t *keylen)
285{
286 EC_PKEY_CTX *dctx = ctx->data;
287 unsigned char *ktmp = NULL;
288 size_t ktmplen;
289 int rv = 0;
290 if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
291 return pkey_ec_derive(ctx, key, keylen);
292 if (!key) {
293 *keylen = dctx->kdf_outlen;
294 return 1;
295 }
296 if (*keylen != dctx->kdf_outlen)
297 return 0;
298 if (!pkey_ec_derive(ctx, NULL, &ktmplen))
299 return 0;
300 ktmp = OPENSSL_malloc(ktmplen);
90945fa3 301 if (ktmp == NULL)
0f113f3e
MC
302 return 0;
303 if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
304 goto err;
305 /* Do KDF stuff */
306 if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen,
307 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
308 goto err;
309 rv = 1;
310
311 err:
4b45c6e5 312 OPENSSL_clear_free(ktmp, ktmplen);
0f113f3e
MC
313 return rv;
314}
af6e2d51 315#endif
25af7a5d 316
9ca7047d 317static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
0f113f3e
MC
318{
319 EC_PKEY_CTX *dctx = ctx->data;
320 EC_GROUP *group;
321 switch (type) {
322 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
323 group = EC_GROUP_new_by_curve_name(p1);
324 if (group == NULL) {
325 ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
326 return 0;
327 }
8fdc3734 328 EC_GROUP_free(dctx->gen_group);
0f113f3e
MC
329 dctx->gen_group = group;
330 return 1;
331
332 case EVP_PKEY_CTRL_EC_PARAM_ENC:
333 if (!dctx->gen_group) {
334 ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
335 return 0;
336 }
337 EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
338 return 1;
24edfa9d 339
10bf4fc2 340#ifndef OPENSSL_NO_EC
0f113f3e
MC
341 case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
342 if (p1 == -2) {
343 if (dctx->cofactor_mode != -1)
344 return dctx->cofactor_mode;
345 else {
346 EC_KEY *ec_key = ctx->pkey->pkey.ec;
dceb99a5 347 return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
0f113f3e
MC
348 }
349 } else if (p1 < -1 || p1 > 1)
350 return -2;
351 dctx->cofactor_mode = p1;
352 if (p1 != -1) {
353 EC_KEY *ec_key = ctx->pkey->pkey.ec;
354 if (!ec_key->group)
355 return -2;
356 /* If cofactor is 1 cofactor mode does nothing */
357 if (BN_is_one(ec_key->group->cofactor))
358 return 1;
359 if (!dctx->co_key) {
360 dctx->co_key = EC_KEY_dup(ec_key);
361 if (!dctx->co_key)
362 return 0;
363 }
364 if (p1)
365 EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
366 else
367 EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
8fdc3734 368 } else {
0f113f3e
MC
369 EC_KEY_free(dctx->co_key);
370 dctx->co_key = NULL;
371 }
372 return 1;
af6e2d51 373#endif
25af7a5d 374
0f113f3e
MC
375 case EVP_PKEY_CTRL_EC_KDF_TYPE:
376 if (p1 == -2)
377 return dctx->kdf_type;
378 if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62)
379 return -2;
380 dctx->kdf_type = p1;
381 return 1;
382
383 case EVP_PKEY_CTRL_EC_KDF_MD:
384 dctx->kdf_md = p2;
385 return 1;
386
387 case EVP_PKEY_CTRL_GET_EC_KDF_MD:
388 *(const EVP_MD **)p2 = dctx->kdf_md;
389 return 1;
390
391 case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
392 if (p1 <= 0)
393 return -2;
394 dctx->kdf_outlen = (size_t)p1;
395 return 1;
396
397 case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
398 *(int *)p2 = dctx->kdf_outlen;
399 return 1;
400
401 case EVP_PKEY_CTRL_EC_KDF_UKM:
b548a1f1 402 OPENSSL_free(dctx->kdf_ukm);
0f113f3e
MC
403 dctx->kdf_ukm = p2;
404 if (p2)
405 dctx->kdf_ukmlen = p1;
406 else
407 dctx->kdf_ukmlen = 0;
408 return 1;
409
410 case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
411 *(unsigned char **)p2 = dctx->kdf_ukm;
412 return dctx->kdf_ukmlen;
413
414 case EVP_PKEY_CTRL_MD:
415 if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
416 EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
417 EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
418 EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
419 EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
3d328a44
JL
420 EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
421 EVP_MD_type((const EVP_MD *)p2) != NID_sm3) {
0f113f3e
MC
422 ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
423 return 0;
424 }
425 dctx->md = p2;
426 return 1;
427
428 case EVP_PKEY_CTRL_GET_MD:
429 *(const EVP_MD **)p2 = dctx->md;
430 return 1;
431
432 case EVP_PKEY_CTRL_PEER_KEY:
433 /* Default behaviour is OK */
434 case EVP_PKEY_CTRL_DIGESTINIT:
435 case EVP_PKEY_CTRL_PKCS7_SIGN:
436 case EVP_PKEY_CTRL_CMS_SIGN:
437 return 1;
438
439 default:
440 return -2;
441
442 }
443}
444
9ca7047d 445static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
0f113f3e
MC
446 const char *type, const char *value)
447{
86885c28 448 if (strcmp(type, "ec_paramgen_curve") == 0) {
0f113f3e
MC
449 int nid;
450 nid = EC_curve_nist2nid(value);
451 if (nid == NID_undef)
452 nid = OBJ_sn2nid(value);
453 if (nid == NID_undef)
454 nid = OBJ_ln2nid(value);
455 if (nid == NID_undef) {
456 ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
457 return 0;
458 }
459 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
86885c28 460 } else if (strcmp(type, "ec_param_enc") == 0) {
0f113f3e 461 int param_enc;
86885c28 462 if (strcmp(value, "explicit") == 0)
0f113f3e 463 param_enc = 0;
86885c28 464 else if (strcmp(value, "named_curve") == 0)
0f113f3e
MC
465 param_enc = OPENSSL_EC_NAMED_CURVE;
466 else
467 return -2;
468 return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
86885c28 469 } else if (strcmp(type, "ecdh_kdf_md") == 0) {
0f113f3e 470 const EVP_MD *md;
75ebbd9a 471 if ((md = EVP_get_digestbyname(value)) == NULL) {
0f113f3e
MC
472 ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST);
473 return 0;
474 }
475 return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
86885c28 476 } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
0f113f3e
MC
477 int co_mode;
478 co_mode = atoi(value);
479 return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
480 }
481
482 return -2;
483}
9ca7047d
DSH
484
485static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
486{
487 EC_KEY *ec = NULL;
488 EC_PKEY_CTX *dctx = ctx->data;
489 int ret = 0;
490 if (dctx->gen_group == NULL) {
491 ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
492 return 0;
493 }
494 ec = EC_KEY_new();
90945fa3 495 if (ec == NULL)
0f113f3e
MC
496 return 0;
497 ret = EC_KEY_set_group(ec, dctx->gen_group);
498 if (ret)
499 EVP_PKEY_assign_EC_KEY(pkey, ec);
500 else
501 EC_KEY_free(ec);
502 return ret;
503}
9ca7047d
DSH
504
505static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
506{
507 EC_KEY *ec = NULL;
508 EC_PKEY_CTX *dctx = ctx->data;
509 if (ctx->pkey == NULL && dctx->gen_group == NULL) {
510 ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
511 return 0;
512 }
513 ec = EC_KEY_new();
514 if (!ec)
515 return 0;
516 EVP_PKEY_assign_EC_KEY(pkey, ec);
517 if (ctx->pkey) {
518 /* Note: if error return, pkey is freed by parent routine */
519 if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey))
520 return 0;
521 } else {
522 if (!EC_KEY_set_group(ec, dctx->gen_group))
523 return 0;
524 }
525 return EC_KEY_generate_key(pkey->pkey.ec);
526}
527
528const EVP_PKEY_METHOD ec_pkey_meth = {
529 EVP_PKEY_EC,
4e664750 530 0,
0f113f3e
MC
531 pkey_ec_init,
532 pkey_ec_copy,
533 pkey_ec_cleanup,
534
535 0,
536 pkey_ec_paramgen,
537
538 0,
539 pkey_ec_keygen,
540
541 0,
542 pkey_ec_sign,
543
544 0,
545 pkey_ec_verify,
546
547 0, 0,
548
549 0, 0, 0, 0,
550
dceb99a5
JL
551 0,
552 pkey_ecies_encrypt,
0f113f3e 553
dceb99a5
JL
554 0,
555 pkey_ecies_decrypt,
0f113f3e
MC
556
557 0,
10bf4fc2 558#ifndef OPENSSL_NO_EC
0f113f3e 559 pkey_ec_kdf_derive,
af6e2d51 560#else
0f113f3e 561 0,
af6e2d51 562#endif
0f113f3e
MC
563 pkey_ec_ctrl,
564 pkey_ec_ctrl_str
565};