1 | /*
|
---|
2 | * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (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
|
---|
8 | */
|
---|
9 |
|
---|
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 |
|
---|
16 | #include <stdio.h>
|
---|
17 | #include "internal/cryptlib.h"
|
---|
18 | #include <openssl/x509.h>
|
---|
19 | #include <openssl/ec.h>
|
---|
20 | #include <openssl/bn.h>
|
---|
21 | #include <openssl/asn1t.h>
|
---|
22 | #include "crypto/asn1.h"
|
---|
23 | #include "crypto/evp.h"
|
---|
24 | #include "crypto/x509.h"
|
---|
25 | #include <openssl/core_names.h>
|
---|
26 | #include <openssl/param_build.h>
|
---|
27 | #include "ec_local.h"
|
---|
28 |
|
---|
29 | static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key)
|
---|
30 | {
|
---|
31 | const EC_GROUP *group;
|
---|
32 | int nid;
|
---|
33 |
|
---|
34 | if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) {
|
---|
35 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
|
---|
36 | return 0;
|
---|
37 | }
|
---|
38 | if (EC_GROUP_get_asn1_flag(group)
|
---|
39 | && (nid = EC_GROUP_get_curve_name(group)))
|
---|
40 | /* we have a 'named curve' => just set the OID */
|
---|
41 | {
|
---|
42 | ASN1_OBJECT *asn1obj = OBJ_nid2obj(nid);
|
---|
43 |
|
---|
44 | if (asn1obj == NULL || OBJ_length(asn1obj) == 0) {
|
---|
45 | ASN1_OBJECT_free(asn1obj);
|
---|
46 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID);
|
---|
47 | return 0;
|
---|
48 | }
|
---|
49 | *ppval = asn1obj;
|
---|
50 | *pptype = V_ASN1_OBJECT;
|
---|
51 | } else { /* explicit parameters */
|
---|
52 |
|
---|
53 | ASN1_STRING *pstr = NULL;
|
---|
54 | pstr = ASN1_STRING_new();
|
---|
55 | if (pstr == NULL)
|
---|
56 | return 0;
|
---|
57 | pstr->length = i2d_ECParameters(ec_key, &pstr->data);
|
---|
58 | if (pstr->length <= 0) {
|
---|
59 | ASN1_STRING_free(pstr);
|
---|
60 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
|
---|
61 | return 0;
|
---|
62 | }
|
---|
63 | *ppval = pstr;
|
---|
64 | *pptype = V_ASN1_SEQUENCE;
|
---|
65 | }
|
---|
66 | return 1;
|
---|
67 | }
|
---|
68 |
|
---|
69 | static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
|
---|
70 | {
|
---|
71 | const EC_KEY *ec_key = pkey->pkey.ec;
|
---|
72 | void *pval = NULL;
|
---|
73 | int ptype;
|
---|
74 | unsigned char *penc = NULL, *p;
|
---|
75 | int penclen;
|
---|
76 |
|
---|
77 | if (!eckey_param2type(&ptype, &pval, ec_key)) {
|
---|
78 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
|
---|
79 | return 0;
|
---|
80 | }
|
---|
81 | penclen = i2o_ECPublicKey(ec_key, NULL);
|
---|
82 | if (penclen <= 0)
|
---|
83 | goto err;
|
---|
84 | penc = OPENSSL_malloc(penclen);
|
---|
85 | if (penc == NULL)
|
---|
86 | goto err;
|
---|
87 | p = penc;
|
---|
88 | penclen = i2o_ECPublicKey(ec_key, &p);
|
---|
89 | if (penclen <= 0)
|
---|
90 | goto err;
|
---|
91 | if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_EC),
|
---|
92 | ptype, pval, penc, penclen))
|
---|
93 | return 1;
|
---|
94 | err:
|
---|
95 | if (ptype == V_ASN1_OBJECT)
|
---|
96 | ASN1_OBJECT_free(pval);
|
---|
97 | else
|
---|
98 | ASN1_STRING_free(pval);
|
---|
99 | OPENSSL_free(penc);
|
---|
100 | return 0;
|
---|
101 | }
|
---|
102 |
|
---|
103 | static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
|
---|
104 | {
|
---|
105 | const unsigned char *p = NULL;
|
---|
106 | int pklen;
|
---|
107 | EC_KEY *eckey = NULL;
|
---|
108 | X509_ALGOR *palg;
|
---|
109 | OSSL_LIB_CTX *libctx = NULL;
|
---|
110 | const char *propq = NULL;
|
---|
111 |
|
---|
112 | if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey)
|
---|
113 | || !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
|
---|
114 | return 0;
|
---|
115 | eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq);
|
---|
116 |
|
---|
117 | if (!eckey)
|
---|
118 | return 0;
|
---|
119 |
|
---|
120 | /* We have parameters now set public key */
|
---|
121 | if (!o2i_ECPublicKey(&eckey, &p, pklen)) {
|
---|
122 | ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
|
---|
123 | goto ecerr;
|
---|
124 | }
|
---|
125 |
|
---|
126 | EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
---|
127 | return 1;
|
---|
128 |
|
---|
129 | ecerr:
|
---|
130 | EC_KEY_free(eckey);
|
---|
131 | return 0;
|
---|
132 | }
|
---|
133 |
|
---|
134 | static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
|
---|
135 | {
|
---|
136 | int r;
|
---|
137 | const EC_GROUP *group = EC_KEY_get0_group(b->pkey.ec);
|
---|
138 | const EC_POINT *pa = EC_KEY_get0_public_key(a->pkey.ec),
|
---|
139 | *pb = EC_KEY_get0_public_key(b->pkey.ec);
|
---|
140 |
|
---|
141 | if (group == NULL || pa == NULL || pb == NULL)
|
---|
142 | return -2;
|
---|
143 | r = EC_POINT_cmp(group, pa, pb, NULL);
|
---|
144 | if (r == 0)
|
---|
145 | return 1;
|
---|
146 | if (r == 1)
|
---|
147 | return 0;
|
---|
148 | return -2;
|
---|
149 | }
|
---|
150 |
|
---|
151 | static int eckey_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
|
---|
152 | OSSL_LIB_CTX *libctx, const char *propq)
|
---|
153 | {
|
---|
154 | int ret = 0;
|
---|
155 | EC_KEY *eckey = ossl_ec_key_from_pkcs8(p8, libctx, propq);
|
---|
156 |
|
---|
157 | if (eckey != NULL) {
|
---|
158 | ret = 1;
|
---|
159 | EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
---|
160 | }
|
---|
161 |
|
---|
162 | return ret;
|
---|
163 | }
|
---|
164 |
|
---|
165 | static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
|
---|
166 | {
|
---|
167 | EC_KEY ec_key = *(pkey->pkey.ec);
|
---|
168 | unsigned char *ep, *p;
|
---|
169 | int eplen, ptype;
|
---|
170 | void *pval;
|
---|
171 | unsigned int old_flags;
|
---|
172 |
|
---|
173 | if (!eckey_param2type(&ptype, &pval, &ec_key)) {
|
---|
174 | ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR);
|
---|
175 | return 0;
|
---|
176 | }
|
---|
177 |
|
---|
178 | /* set the private key */
|
---|
179 |
|
---|
180 | /*
|
---|
181 | * do not include the parameters in the SEC1 private key see PKCS#11
|
---|
182 | * 12.11
|
---|
183 | */
|
---|
184 | old_flags = EC_KEY_get_enc_flags(&ec_key);
|
---|
185 | EC_KEY_set_enc_flags(&ec_key, old_flags | EC_PKEY_NO_PARAMETERS);
|
---|
186 |
|
---|
187 | eplen = i2d_ECPrivateKey(&ec_key, NULL);
|
---|
188 | if (!eplen) {
|
---|
189 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
|
---|
190 | return 0;
|
---|
191 | }
|
---|
192 | ep = OPENSSL_malloc(eplen);
|
---|
193 | if (ep == NULL) {
|
---|
194 | ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
|
---|
195 | return 0;
|
---|
196 | }
|
---|
197 | p = ep;
|
---|
198 | if (!i2d_ECPrivateKey(&ec_key, &p)) {
|
---|
199 | OPENSSL_free(ep);
|
---|
200 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
|
---|
201 | return 0;
|
---|
202 | }
|
---|
203 |
|
---|
204 | if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0,
|
---|
205 | ptype, pval, ep, eplen)) {
|
---|
206 | OPENSSL_free(ep);
|
---|
207 | return 0;
|
---|
208 | }
|
---|
209 |
|
---|
210 | return 1;
|
---|
211 | }
|
---|
212 |
|
---|
213 | static int int_ec_size(const EVP_PKEY *pkey)
|
---|
214 | {
|
---|
215 | return ECDSA_size(pkey->pkey.ec);
|
---|
216 | }
|
---|
217 |
|
---|
218 | static int ec_bits(const EVP_PKEY *pkey)
|
---|
219 | {
|
---|
220 | return EC_GROUP_order_bits(EC_KEY_get0_group(pkey->pkey.ec));
|
---|
221 | }
|
---|
222 |
|
---|
223 | static int ec_security_bits(const EVP_PKEY *pkey)
|
---|
224 | {
|
---|
225 | int ecbits = ec_bits(pkey);
|
---|
226 |
|
---|
227 | if (ecbits >= 512)
|
---|
228 | return 256;
|
---|
229 | if (ecbits >= 384)
|
---|
230 | return 192;
|
---|
231 | if (ecbits >= 256)
|
---|
232 | return 128;
|
---|
233 | if (ecbits >= 224)
|
---|
234 | return 112;
|
---|
235 | if (ecbits >= 160)
|
---|
236 | return 80;
|
---|
237 | return ecbits / 2;
|
---|
238 | }
|
---|
239 |
|
---|
240 | static int ec_missing_parameters(const EVP_PKEY *pkey)
|
---|
241 | {
|
---|
242 | if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL)
|
---|
243 | return 1;
|
---|
244 | return 0;
|
---|
245 | }
|
---|
246 |
|
---|
247 | static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
|
---|
248 | {
|
---|
249 | EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec));
|
---|
250 |
|
---|
251 | if (group == NULL)
|
---|
252 | return 0;
|
---|
253 | if (to->pkey.ec == NULL) {
|
---|
254 | to->pkey.ec = EC_KEY_new();
|
---|
255 | if (to->pkey.ec == NULL)
|
---|
256 | goto err;
|
---|
257 | }
|
---|
258 | if (EC_KEY_set_group(to->pkey.ec, group) == 0)
|
---|
259 | goto err;
|
---|
260 | EC_GROUP_free(group);
|
---|
261 | return 1;
|
---|
262 | err:
|
---|
263 | EC_GROUP_free(group);
|
---|
264 | return 0;
|
---|
265 | }
|
---|
266 |
|
---|
267 | static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
|
---|
268 | {
|
---|
269 | const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec),
|
---|
270 | *group_b = EC_KEY_get0_group(b->pkey.ec);
|
---|
271 |
|
---|
272 | if (group_a == NULL || group_b == NULL)
|
---|
273 | return -2;
|
---|
274 | if (EC_GROUP_cmp(group_a, group_b, NULL))
|
---|
275 | return 0;
|
---|
276 | else
|
---|
277 | return 1;
|
---|
278 | }
|
---|
279 |
|
---|
280 | static void int_ec_free(EVP_PKEY *pkey)
|
---|
281 | {
|
---|
282 | EC_KEY_free(pkey->pkey.ec);
|
---|
283 | }
|
---|
284 |
|
---|
285 | typedef enum {
|
---|
286 | EC_KEY_PRINT_PRIVATE,
|
---|
287 | EC_KEY_PRINT_PUBLIC,
|
---|
288 | EC_KEY_PRINT_PARAM
|
---|
289 | } ec_print_t;
|
---|
290 |
|
---|
291 | static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, ec_print_t ktype)
|
---|
292 | {
|
---|
293 | const char *ecstr;
|
---|
294 | unsigned char *priv = NULL, *pub = NULL;
|
---|
295 | size_t privlen = 0, publen = 0;
|
---|
296 | int ret = 0;
|
---|
297 | const EC_GROUP *group;
|
---|
298 |
|
---|
299 | if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
|
---|
300 | ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER);
|
---|
301 | return 0;
|
---|
302 | }
|
---|
303 |
|
---|
304 | if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) {
|
---|
305 | publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL);
|
---|
306 | if (publen == 0)
|
---|
307 | goto err;
|
---|
308 | }
|
---|
309 |
|
---|
310 | if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) {
|
---|
311 | privlen = EC_KEY_priv2buf(x, &priv);
|
---|
312 | if (privlen == 0)
|
---|
313 | goto err;
|
---|
314 | }
|
---|
315 |
|
---|
316 | if (ktype == EC_KEY_PRINT_PRIVATE)
|
---|
317 | ecstr = "Private-Key";
|
---|
318 | else if (ktype == EC_KEY_PRINT_PUBLIC)
|
---|
319 | ecstr = "Public-Key";
|
---|
320 | else
|
---|
321 | ecstr = "ECDSA-Parameters";
|
---|
322 |
|
---|
323 | if (!BIO_indent(bp, off, 128))
|
---|
324 | goto err;
|
---|
325 | if (BIO_printf(bp, "%s: (%d bit)\n", ecstr,
|
---|
326 | EC_GROUP_order_bits(group)) <= 0)
|
---|
327 | goto err;
|
---|
328 |
|
---|
329 | if (privlen != 0) {
|
---|
330 | if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0)
|
---|
331 | goto err;
|
---|
332 | if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0)
|
---|
333 | goto err;
|
---|
334 | }
|
---|
335 |
|
---|
336 | if (publen != 0) {
|
---|
337 | if (BIO_printf(bp, "%*spub:\n", off, "") <= 0)
|
---|
338 | goto err;
|
---|
339 | if (ASN1_buf_print(bp, pub, publen, off + 4) == 0)
|
---|
340 | goto err;
|
---|
341 | }
|
---|
342 |
|
---|
343 | if (!ECPKParameters_print(bp, group, off))
|
---|
344 | goto err;
|
---|
345 | ret = 1;
|
---|
346 | err:
|
---|
347 | if (!ret)
|
---|
348 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
|
---|
349 | OPENSSL_clear_free(priv, privlen);
|
---|
350 | OPENSSL_free(pub);
|
---|
351 | return ret;
|
---|
352 | }
|
---|
353 |
|
---|
354 | static int eckey_param_decode(EVP_PKEY *pkey,
|
---|
355 | const unsigned char **pder, int derlen)
|
---|
356 | {
|
---|
357 | EC_KEY *eckey;
|
---|
358 |
|
---|
359 | if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL)
|
---|
360 | return 0;
|
---|
361 | EVP_PKEY_assign_EC_KEY(pkey, eckey);
|
---|
362 | return 1;
|
---|
363 | }
|
---|
364 |
|
---|
365 | static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
|
---|
366 | {
|
---|
367 | return i2d_ECParameters(pkey->pkey.ec, pder);
|
---|
368 | }
|
---|
369 |
|
---|
370 | static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
---|
371 | ASN1_PCTX *ctx)
|
---|
372 | {
|
---|
373 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PARAM);
|
---|
374 | }
|
---|
375 |
|
---|
376 | static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
---|
377 | ASN1_PCTX *ctx)
|
---|
378 | {
|
---|
379 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PUBLIC);
|
---|
380 | }
|
---|
381 |
|
---|
382 | static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
|
---|
383 | ASN1_PCTX *ctx)
|
---|
384 | {
|
---|
385 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PRIVATE);
|
---|
386 | }
|
---|
387 |
|
---|
388 | static int old_ec_priv_decode(EVP_PKEY *pkey,
|
---|
389 | const unsigned char **pder, int derlen)
|
---|
390 | {
|
---|
391 | EC_KEY *ec;
|
---|
392 |
|
---|
393 | if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL)
|
---|
394 | return 0;
|
---|
395 | EVP_PKEY_assign_EC_KEY(pkey, ec);
|
---|
396 | return 1;
|
---|
397 | }
|
---|
398 |
|
---|
399 | static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder)
|
---|
400 | {
|
---|
401 | return i2d_ECPrivateKey(pkey->pkey.ec, pder);
|
---|
402 | }
|
---|
403 |
|
---|
404 | static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
|
---|
405 | {
|
---|
406 | switch (op) {
|
---|
407 | case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
|
---|
408 | if (EVP_PKEY_get_id(pkey) == EVP_PKEY_SM2) {
|
---|
409 | /* For SM2, the only valid digest-alg is SM3 */
|
---|
410 | *(int *)arg2 = NID_sm3;
|
---|
411 | return 2; /* Make it mandatory */
|
---|
412 | }
|
---|
413 | *(int *)arg2 = NID_sha256;
|
---|
414 | return 1;
|
---|
415 |
|
---|
416 | case ASN1_PKEY_CTRL_SET1_TLS_ENCPT:
|
---|
417 | /* We should only be here if we have a legacy key */
|
---|
418 | if (!ossl_assert(evp_pkey_is_legacy(pkey)))
|
---|
419 | return 0;
|
---|
420 | return EC_KEY_oct2key(evp_pkey_get0_EC_KEY_int(pkey), arg2, arg1, NULL);
|
---|
421 |
|
---|
422 | case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
|
---|
423 | return EC_KEY_key2buf(EVP_PKEY_get0_EC_KEY(pkey),
|
---|
424 | POINT_CONVERSION_UNCOMPRESSED, arg2, NULL);
|
---|
425 |
|
---|
426 | default:
|
---|
427 | return -2;
|
---|
428 | }
|
---|
429 | }
|
---|
430 |
|
---|
431 | static int ec_pkey_check(const EVP_PKEY *pkey)
|
---|
432 | {
|
---|
433 | EC_KEY *eckey = pkey->pkey.ec;
|
---|
434 |
|
---|
435 | /* stay consistent to what EVP_PKEY_check demands */
|
---|
436 | if (eckey->priv_key == NULL) {
|
---|
437 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY);
|
---|
438 | return 0;
|
---|
439 | }
|
---|
440 |
|
---|
441 | return EC_KEY_check_key(eckey);
|
---|
442 | }
|
---|
443 |
|
---|
444 | static int ec_pkey_public_check(const EVP_PKEY *pkey)
|
---|
445 | {
|
---|
446 | EC_KEY *eckey = pkey->pkey.ec;
|
---|
447 |
|
---|
448 | /*
|
---|
449 | * Note: it unnecessary to check eckey->pub_key here since
|
---|
450 | * it will be checked in EC_KEY_check_key(). In fact, the
|
---|
451 | * EC_KEY_check_key() mainly checks the public key, and checks
|
---|
452 | * the private key optionally (only if there is one). So if
|
---|
453 | * someone passes a whole EC key (public + private), this
|
---|
454 | * will also work...
|
---|
455 | */
|
---|
456 |
|
---|
457 | return EC_KEY_check_key(eckey);
|
---|
458 | }
|
---|
459 |
|
---|
460 | static int ec_pkey_param_check(const EVP_PKEY *pkey)
|
---|
461 | {
|
---|
462 | EC_KEY *eckey = pkey->pkey.ec;
|
---|
463 |
|
---|
464 | /* stay consistent to what EVP_PKEY_check demands */
|
---|
465 | if (eckey->group == NULL) {
|
---|
466 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS);
|
---|
467 | return 0;
|
---|
468 | }
|
---|
469 |
|
---|
470 | return EC_GROUP_check(eckey->group, NULL);
|
---|
471 | }
|
---|
472 |
|
---|
473 | static
|
---|
474 | size_t ec_pkey_dirty_cnt(const EVP_PKEY *pkey)
|
---|
475 | {
|
---|
476 | return pkey->pkey.ec->dirty_cnt;
|
---|
477 | }
|
---|
478 |
|
---|
479 | static
|
---|
480 | int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
|
---|
481 | OSSL_FUNC_keymgmt_import_fn *importer,
|
---|
482 | OSSL_LIB_CTX *libctx, const char *propq)
|
---|
483 | {
|
---|
484 | const EC_KEY *eckey = NULL;
|
---|
485 | const EC_GROUP *ecg = NULL;
|
---|
486 | unsigned char *pub_key_buf = NULL, *gen_buf = NULL;
|
---|
487 | size_t pub_key_buflen;
|
---|
488 | OSSL_PARAM_BLD *tmpl;
|
---|
489 | OSSL_PARAM *params = NULL;
|
---|
490 | const BIGNUM *priv_key = NULL;
|
---|
491 | const EC_POINT *pub_point = NULL;
|
---|
492 | int selection = 0;
|
---|
493 | int rv = 0;
|
---|
494 | BN_CTX *bnctx = NULL;
|
---|
495 |
|
---|
496 | if (from == NULL
|
---|
497 | || (eckey = from->pkey.ec) == NULL
|
---|
498 | || (ecg = EC_KEY_get0_group(eckey)) == NULL)
|
---|
499 | return 0;
|
---|
500 |
|
---|
501 | tmpl = OSSL_PARAM_BLD_new();
|
---|
502 | if (tmpl == NULL)
|
---|
503 | return 0;
|
---|
504 |
|
---|
505 | /*
|
---|
506 | * EC_POINT_point2buf() can generate random numbers in some
|
---|
507 | * implementations so we need to ensure we use the correct libctx.
|
---|
508 | */
|
---|
509 | bnctx = BN_CTX_new_ex(libctx);
|
---|
510 | if (bnctx == NULL)
|
---|
511 | goto err;
|
---|
512 | BN_CTX_start(bnctx);
|
---|
513 |
|
---|
514 | /* export the domain parameters */
|
---|
515 | if (!ossl_ec_group_todata(ecg, tmpl, NULL, libctx, propq, bnctx, &gen_buf))
|
---|
516 | goto err;
|
---|
517 | selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS;
|
---|
518 |
|
---|
519 | priv_key = EC_KEY_get0_private_key(eckey);
|
---|
520 | pub_point = EC_KEY_get0_public_key(eckey);
|
---|
521 |
|
---|
522 | if (pub_point != NULL) {
|
---|
523 | /* convert pub_point to a octet string according to the SECG standard */
|
---|
524 | if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point,
|
---|
525 | POINT_CONVERSION_COMPRESSED,
|
---|
526 | &pub_key_buf, bnctx)) == 0
|
---|
527 | || !OSSL_PARAM_BLD_push_octet_string(tmpl,
|
---|
528 | OSSL_PKEY_PARAM_PUB_KEY,
|
---|
529 | pub_key_buf,
|
---|
530 | pub_key_buflen))
|
---|
531 | goto err;
|
---|
532 | selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
|
---|
533 | }
|
---|
534 |
|
---|
535 | if (priv_key != NULL) {
|
---|
536 | size_t sz;
|
---|
537 | int ecbits;
|
---|
538 | int ecdh_cofactor_mode;
|
---|
539 |
|
---|
540 | /*
|
---|
541 | * Key import/export should never leak the bit length of the secret
|
---|
542 | * scalar in the key.
|
---|
543 | *
|
---|
544 | * For this reason, on export we use padded BIGNUMs with fixed length.
|
---|
545 | *
|
---|
546 | * When importing we also should make sure that, even if short lived,
|
---|
547 | * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as
|
---|
548 | * soon as possible, so that any processing of this BIGNUM might opt for
|
---|
549 | * constant time implementations in the backend.
|
---|
550 | *
|
---|
551 | * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have
|
---|
552 | * to preallocate the BIGNUM internal buffer to a fixed public size big
|
---|
553 | * enough that operations performed during the processing never trigger
|
---|
554 | * a realloc which would leak the size of the scalar through memory
|
---|
555 | * accesses.
|
---|
556 | *
|
---|
557 | * Fixed Length
|
---|
558 | * ------------
|
---|
559 | *
|
---|
560 | * The order of the large prime subgroup of the curve is our choice for
|
---|
561 | * a fixed public size, as that is generally the upper bound for
|
---|
562 | * generating a private key in EC cryptosystems and should fit all valid
|
---|
563 | * secret scalars.
|
---|
564 | *
|
---|
565 | * For padding on export we just use the bit length of the order
|
---|
566 | * converted to bytes (rounding up).
|
---|
567 | *
|
---|
568 | * For preallocating the BIGNUM storage we look at the number of "words"
|
---|
569 | * required for the internal representation of the order, and we
|
---|
570 | * preallocate 2 extra "words" in case any of the subsequent processing
|
---|
571 | * might temporarily overflow the order length.
|
---|
572 | */
|
---|
573 | ecbits = EC_GROUP_order_bits(ecg);
|
---|
574 | if (ecbits <= 0)
|
---|
575 | goto err;
|
---|
576 |
|
---|
577 | sz = (ecbits + 7 ) / 8;
|
---|
578 | if (!OSSL_PARAM_BLD_push_BN_pad(tmpl,
|
---|
579 | OSSL_PKEY_PARAM_PRIV_KEY,
|
---|
580 | priv_key, sz))
|
---|
581 | goto err;
|
---|
582 | selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
|
---|
583 |
|
---|
584 | /*
|
---|
585 | * The ECDH Cofactor Mode is defined only if the EC_KEY actually
|
---|
586 | * contains a private key, so we check for the flag and export it only
|
---|
587 | * in this case.
|
---|
588 | */
|
---|
589 | ecdh_cofactor_mode =
|
---|
590 | (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
|
---|
591 |
|
---|
592 | /* Export the ECDH_COFACTOR_MODE parameter */
|
---|
593 | if (!OSSL_PARAM_BLD_push_int(tmpl,
|
---|
594 | OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
|
---|
595 | ecdh_cofactor_mode))
|
---|
596 | goto err;
|
---|
597 | selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS;
|
---|
598 | }
|
---|
599 |
|
---|
600 | params = OSSL_PARAM_BLD_to_param(tmpl);
|
---|
601 |
|
---|
602 | /* We export, the provider imports */
|
---|
603 | rv = importer(to_keydata, selection, params);
|
---|
604 |
|
---|
605 | err:
|
---|
606 | OSSL_PARAM_BLD_free(tmpl);
|
---|
607 | OSSL_PARAM_free(params);
|
---|
608 | OPENSSL_free(pub_key_buf);
|
---|
609 | OPENSSL_free(gen_buf);
|
---|
610 | BN_CTX_end(bnctx);
|
---|
611 | BN_CTX_free(bnctx);
|
---|
612 | return rv;
|
---|
613 | }
|
---|
614 |
|
---|
615 | static int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx)
|
---|
616 | {
|
---|
617 | EVP_PKEY_CTX *pctx = vpctx;
|
---|
618 | EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
|
---|
619 | EC_KEY *ec = EC_KEY_new_ex(pctx->libctx, pctx->propquery);
|
---|
620 |
|
---|
621 | if (ec == NULL) {
|
---|
622 | ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
|
---|
623 | return 0;
|
---|
624 | }
|
---|
625 |
|
---|
626 | if (!ossl_ec_group_fromdata(ec, params)
|
---|
627 | || !ossl_ec_key_otherparams_fromdata(ec, params)
|
---|
628 | || !ossl_ec_key_fromdata(ec, params, 1)
|
---|
629 | || !EVP_PKEY_assign_EC_KEY(pkey, ec)) {
|
---|
630 | EC_KEY_free(ec);
|
---|
631 | return 0;
|
---|
632 | }
|
---|
633 | return 1;
|
---|
634 | }
|
---|
635 |
|
---|
636 | static int ec_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
|
---|
637 | {
|
---|
638 | EC_KEY *eckey = from->pkey.ec;
|
---|
639 | EC_KEY *dupkey = NULL;
|
---|
640 | int ret;
|
---|
641 |
|
---|
642 | if (eckey != NULL) {
|
---|
643 | dupkey = EC_KEY_dup(eckey);
|
---|
644 | if (dupkey == NULL)
|
---|
645 | return 0;
|
---|
646 | } else {
|
---|
647 | /* necessary to properly copy empty SM2 keys */
|
---|
648 | return EVP_PKEY_set_type(to, from->type);
|
---|
649 | }
|
---|
650 |
|
---|
651 | ret = EVP_PKEY_assign_EC_KEY(to, dupkey);
|
---|
652 | if (!ret)
|
---|
653 | EC_KEY_free(dupkey);
|
---|
654 | return ret;
|
---|
655 | }
|
---|
656 |
|
---|
657 | const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = {
|
---|
658 | EVP_PKEY_EC,
|
---|
659 | EVP_PKEY_EC,
|
---|
660 | 0,
|
---|
661 | "EC",
|
---|
662 | "OpenSSL EC algorithm",
|
---|
663 |
|
---|
664 | eckey_pub_decode,
|
---|
665 | eckey_pub_encode,
|
---|
666 | eckey_pub_cmp,
|
---|
667 | eckey_pub_print,
|
---|
668 |
|
---|
669 | NULL,
|
---|
670 | eckey_priv_encode,
|
---|
671 | eckey_priv_print,
|
---|
672 |
|
---|
673 | int_ec_size,
|
---|
674 | ec_bits,
|
---|
675 | ec_security_bits,
|
---|
676 |
|
---|
677 | eckey_param_decode,
|
---|
678 | eckey_param_encode,
|
---|
679 | ec_missing_parameters,
|
---|
680 | ec_copy_parameters,
|
---|
681 | ec_cmp_parameters,
|
---|
682 | eckey_param_print,
|
---|
683 | 0,
|
---|
684 |
|
---|
685 | int_ec_free,
|
---|
686 | ec_pkey_ctrl,
|
---|
687 | old_ec_priv_decode,
|
---|
688 | old_ec_priv_encode,
|
---|
689 |
|
---|
690 | 0, 0, 0,
|
---|
691 |
|
---|
692 | ec_pkey_check,
|
---|
693 | ec_pkey_public_check,
|
---|
694 | ec_pkey_param_check,
|
---|
695 |
|
---|
696 | 0, /* set_priv_key */
|
---|
697 | 0, /* set_pub_key */
|
---|
698 | 0, /* get_priv_key */
|
---|
699 | 0, /* get_pub_key */
|
---|
700 |
|
---|
701 | ec_pkey_dirty_cnt,
|
---|
702 | ec_pkey_export_to,
|
---|
703 | ec_pkey_import_from,
|
---|
704 | ec_pkey_copy,
|
---|
705 | eckey_priv_decode_ex
|
---|
706 | };
|
---|
707 |
|
---|
708 | #if !defined(OPENSSL_NO_SM2)
|
---|
709 | const EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth = {
|
---|
710 | EVP_PKEY_SM2,
|
---|
711 | EVP_PKEY_EC,
|
---|
712 | ASN1_PKEY_ALIAS
|
---|
713 | };
|
---|
714 | #endif
|
---|
715 |
|
---|
716 | int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
|
---|
717 | {
|
---|
718 | int private = EC_KEY_get0_private_key(x) != NULL;
|
---|
719 |
|
---|
720 | return do_EC_KEY_print(bp, x, off,
|
---|
721 | private ? EC_KEY_PRINT_PRIVATE : EC_KEY_PRINT_PUBLIC);
|
---|
722 | }
|
---|
723 |
|
---|
724 | int ECParameters_print(BIO *bp, const EC_KEY *x)
|
---|
725 | {
|
---|
726 | return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM);
|
---|
727 | }
|
---|