]>
Commit | Line | Data |
---|---|---|
0f113f3e | 1 | /* |
4333b89f | 2 | * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved. |
448be743 | 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 | |
448be743 DSH |
8 | */ |
9 | ||
579422c8 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 | ||
448be743 | 16 | #include <stdio.h> |
b39fc560 | 17 | #include "internal/cryptlib.h" |
448be743 DSH |
18 | #include <openssl/x509.h> |
19 | #include <openssl/ec.h> | |
1e26a8ba | 20 | #include <openssl/bn.h> |
88e20b85 | 21 | #include <openssl/asn1t.h> |
25f2138b DMSP |
22 | #include "crypto/asn1.h" |
23 | #include "crypto/evp.h" | |
22b81444 | 24 | #include "crypto/x509.h" |
4fe54d67 | 25 | #include <openssl/core_names.h> |
110bff61 | 26 | #include "openssl/param_build.h" |
706457b7 | 27 | #include "ec_local.h" |
448be743 | 28 | |
cd701de9 | 29 | static int eckey_param2type(int *pptype, void **ppval, const EC_KEY *ec_key) |
0f113f3e MC |
30 | { |
31 | const EC_GROUP *group; | |
32 | int nid; | |
83156454 | 33 | |
0f113f3e | 34 | if (ec_key == NULL || (group = EC_KEY_get0_group(ec_key)) == NULL) { |
9311d0c4 | 35 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); |
0f113f3e MC |
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 | { | |
e0137ca9 NT |
42 | ASN1_OBJECT *asn1obj = OBJ_nid2obj(nid); |
43 | ||
44 | if (asn1obj == NULL || OBJ_length(asn1obj) == 0) { | |
45 | ASN1_OBJECT_free(asn1obj); | |
9311d0c4 | 46 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_OID); |
e0137ca9 NT |
47 | return 0; |
48 | } | |
49 | *ppval = asn1obj; | |
0f113f3e MC |
50 | *pptype = V_ASN1_OBJECT; |
51 | } else { /* explicit parameters */ | |
52 | ||
53 | ASN1_STRING *pstr = NULL; | |
54 | pstr = ASN1_STRING_new(); | |
90945fa3 | 55 | if (pstr == NULL) |
0f113f3e MC |
56 | return 0; |
57 | pstr->length = i2d_ECParameters(ec_key, &pstr->data); | |
58 | if (pstr->length <= 0) { | |
59 | ASN1_STRING_free(pstr); | |
9311d0c4 | 60 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
0f113f3e MC |
61 | return 0; |
62 | } | |
63 | *ppval = pstr; | |
64 | *pptype = V_ASN1_SEQUENCE; | |
65 | } | |
66 | return 1; | |
67 | } | |
448be743 | 68 | |
6f81892e | 69 | static int eckey_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey) |
0f113f3e | 70 | { |
cd701de9 | 71 | const EC_KEY *ec_key = pkey->pkey.ec; |
0f113f3e MC |
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)) { | |
9311d0c4 | 78 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
0f113f3e MC |
79 | return 0; |
80 | } | |
81 | penclen = i2o_ECPublicKey(ec_key, NULL); | |
82 | if (penclen <= 0) | |
83 | goto err; | |
84 | penc = OPENSSL_malloc(penclen); | |
90945fa3 | 85 | if (penc == NULL) |
0f113f3e MC |
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); | |
b548a1f1 | 99 | OPENSSL_free(penc); |
0f113f3e MC |
100 | return 0; |
101 | } | |
448be743 | 102 | |
7674e923 | 103 | static int eckey_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey) |
0f113f3e MC |
104 | { |
105 | const unsigned char *p = NULL; | |
cf333799 | 106 | int pklen; |
0f113f3e MC |
107 | EC_KEY *eckey = NULL; |
108 | X509_ALGOR *palg; | |
b4250010 | 109 | OSSL_LIB_CTX *libctx = NULL; |
22b81444 | 110 | const char *propq = NULL; |
0f113f3e | 111 | |
4669015d | 112 | if (!ossl_x509_PUBKEY_get0_libctx(&libctx, &propq, pubkey) |
22b81444 | 113 | || !X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey)) |
0f113f3e | 114 | return 0; |
cf333799 | 115 | eckey = ossl_ec_key_param_from_x509_algor(palg, libctx, propq); |
0f113f3e | 116 | |
66066e1b | 117 | if (!eckey) |
0f113f3e | 118 | return 0; |
0f113f3e MC |
119 | |
120 | /* We have parameters now set public key */ | |
121 | if (!o2i_ECPublicKey(&eckey, &p, pklen)) { | |
9311d0c4 | 122 | ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); |
0f113f3e MC |
123 | goto ecerr; |
124 | } | |
125 | ||
126 | EVP_PKEY_assign_EC_KEY(pkey, eckey); | |
127 | return 1; | |
128 | ||
129 | ecerr: | |
8fdc3734 | 130 | EC_KEY_free(eckey); |
0f113f3e MC |
131 | return 0; |
132 | } | |
448be743 | 133 | |
6f81892e | 134 | static int eckey_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b) |
0f113f3e MC |
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); | |
83156454 | 140 | |
978ecbb0 DW |
141 | if (group == NULL || pa == NULL || pb == NULL) |
142 | return -2; | |
0f113f3e MC |
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 | } | |
6f81892e | 150 | |
d8652be0 | 151 | static int eckey_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8, |
b4250010 | 152 | OSSL_LIB_CTX *libctx, const char *propq) |
0f113f3e | 153 | { |
cf333799 RL |
154 | int ret = 0; |
155 | EC_KEY *eckey = ossl_ec_key_from_pkcs8(p8, libctx, propq); | |
0f113f3e | 156 | |
cf333799 RL |
157 | if (eckey != NULL) { |
158 | ret = 1; | |
159 | EVP_PKEY_assign_EC_KEY(pkey, eckey); | |
0f113f3e MC |
160 | } |
161 | ||
cf333799 | 162 | return ret; |
0f113f3e | 163 | } |
448be743 | 164 | |
6f81892e | 165 | static int eckey_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey) |
448be743 | 166 | { |
b8a7bd83 | 167 | EC_KEY ec_key = *(pkey->pkey.ec); |
0f113f3e MC |
168 | unsigned char *ep, *p; |
169 | int eplen, ptype; | |
170 | void *pval; | |
b8a7bd83 | 171 | unsigned int old_flags; |
0f113f3e | 172 | |
b8a7bd83 | 173 | if (!eckey_param2type(&ptype, &pval, &ec_key)) { |
9311d0c4 | 174 | ERR_raise(ERR_LIB_EC, EC_R_DECODE_ERROR); |
0f113f3e MC |
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 | */ | |
b8a7bd83 RL |
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); | |
0f113f3e | 188 | if (!eplen) { |
9311d0c4 | 189 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
0f113f3e MC |
190 | return 0; |
191 | } | |
b196e7d9 | 192 | ep = OPENSSL_malloc(eplen); |
90945fa3 | 193 | if (ep == NULL) { |
9311d0c4 | 194 | ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE); |
0f113f3e MC |
195 | return 0; |
196 | } | |
197 | p = ep; | |
b8a7bd83 | 198 | if (!i2d_ECPrivateKey(&ec_key, &p)) { |
0f113f3e | 199 | OPENSSL_free(ep); |
9311d0c4 | 200 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
0f113f3e MC |
201 | return 0; |
202 | } | |
0f113f3e MC |
203 | |
204 | if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_X9_62_id_ecPublicKey), 0, | |
e0670973 Y |
205 | ptype, pval, ep, eplen)) { |
206 | OPENSSL_free(ep); | |
0f113f3e | 207 | return 0; |
e0670973 | 208 | } |
0f113f3e MC |
209 | |
210 | return 1; | |
448be743 DSH |
211 | } |
212 | ||
6f81892e | 213 | static int int_ec_size(const EVP_PKEY *pkey) |
0f113f3e MC |
214 | { |
215 | return ECDSA_size(pkey->pkey.ec); | |
216 | } | |
6f81892e DSH |
217 | |
218 | static int ec_bits(const EVP_PKEY *pkey) | |
0f113f3e | 219 | { |
be2e334f | 220 | return EC_GROUP_order_bits(EC_KEY_get0_group(pkey->pkey.ec)); |
0f113f3e | 221 | } |
6f81892e | 222 | |
2514fa79 | 223 | static int ec_security_bits(const EVP_PKEY *pkey) |
0f113f3e MC |
224 | { |
225 | int ecbits = ec_bits(pkey); | |
83156454 | 226 | |
0f113f3e MC |
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 | } | |
2514fa79 | 239 | |
6f81892e | 240 | static int ec_missing_parameters(const EVP_PKEY *pkey) |
0f113f3e | 241 | { |
f72f00d4 | 242 | if (pkey->pkey.ec == NULL || EC_KEY_get0_group(pkey->pkey.ec) == NULL) |
0f113f3e MC |
243 | return 1; |
244 | return 0; | |
245 | } | |
6f81892e | 246 | |
930b0c4b | 247 | static int ec_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from) |
0f113f3e MC |
248 | { |
249 | EC_GROUP *group = EC_GROUP_dup(EC_KEY_get0_group(from->pkey.ec)); | |
188a9bd9 | 250 | |
0f113f3e MC |
251 | if (group == NULL) |
252 | return 0; | |
2986ecdc DSH |
253 | if (to->pkey.ec == NULL) { |
254 | to->pkey.ec = EC_KEY_new(); | |
255 | if (to->pkey.ec == NULL) | |
188a9bd9 | 256 | goto err; |
2986ecdc | 257 | } |
0f113f3e | 258 | if (EC_KEY_set_group(to->pkey.ec, group) == 0) |
188a9bd9 | 259 | goto err; |
0f113f3e MC |
260 | EC_GROUP_free(group); |
261 | return 1; | |
188a9bd9 BE |
262 | err: |
263 | EC_GROUP_free(group); | |
264 | return 0; | |
0f113f3e | 265 | } |
6f81892e | 266 | |
930b0c4b | 267 | static int ec_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b) |
0f113f3e MC |
268 | { |
269 | const EC_GROUP *group_a = EC_KEY_get0_group(a->pkey.ec), | |
270 | *group_b = EC_KEY_get0_group(b->pkey.ec); | |
83156454 | 271 | |
978ecbb0 DW |
272 | if (group_a == NULL || group_b == NULL) |
273 | return -2; | |
0f113f3e MC |
274 | if (EC_GROUP_cmp(group_a, group_b, NULL)) |
275 | return 0; | |
276 | else | |
277 | return 1; | |
278 | } | |
6f81892e DSH |
279 | |
280 | static void int_ec_free(EVP_PKEY *pkey) | |
0f113f3e MC |
281 | { |
282 | EC_KEY_free(pkey->pkey.ec); | |
283 | } | |
6f81892e | 284 | |
d6755bb6 DSH |
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) | |
0f113f3e | 292 | { |
0f113f3e | 293 | const char *ecstr; |
7fc7d1a7 DSH |
294 | unsigned char *priv = NULL, *pub = NULL; |
295 | size_t privlen = 0, publen = 0; | |
296 | int ret = 0; | |
0f113f3e | 297 | const EC_GROUP *group; |
0f113f3e MC |
298 | |
299 | if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) { | |
9311d0c4 | 300 | ERR_raise(ERR_LIB_EC, ERR_R_PASSED_NULL_PARAMETER); |
7fc7d1a7 | 301 | return 0; |
0f113f3e MC |
302 | } |
303 | ||
82f52631 | 304 | if (ktype != EC_KEY_PRINT_PARAM && EC_KEY_get0_public_key(x) != NULL) { |
7fc7d1a7 DSH |
305 | publen = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL); |
306 | if (publen == 0) | |
307 | goto err; | |
0f113f3e MC |
308 | } |
309 | ||
d6755bb6 | 310 | if (ktype == EC_KEY_PRINT_PRIVATE && EC_KEY_get0_private_key(x) != NULL) { |
7fc7d1a7 DSH |
311 | privlen = EC_KEY_priv2buf(x, &priv); |
312 | if (privlen == 0) | |
d810700b | 313 | goto err; |
d810700b | 314 | } |
0f113f3e | 315 | |
d6755bb6 | 316 | if (ktype == EC_KEY_PRINT_PRIVATE) |
0f113f3e | 317 | ecstr = "Private-Key"; |
d6755bb6 | 318 | else if (ktype == EC_KEY_PRINT_PUBLIC) |
0f113f3e MC |
319 | ecstr = "Public-Key"; |
320 | else | |
321 | ecstr = "ECDSA-Parameters"; | |
322 | ||
323 | if (!BIO_indent(bp, off, 128)) | |
324 | goto err; | |
be2e334f DSH |
325 | if (BIO_printf(bp, "%s: (%d bit)\n", ecstr, |
326 | EC_GROUP_order_bits(group)) <= 0) | |
0f113f3e MC |
327 | goto err; |
328 | ||
7fc7d1a7 | 329 | if (privlen != 0) { |
d810700b DSH |
330 | if (BIO_printf(bp, "%*spriv:\n", off, "") <= 0) |
331 | goto err; | |
7fc7d1a7 | 332 | if (ASN1_buf_print(bp, priv, privlen, off + 4) == 0) |
d810700b DSH |
333 | goto err; |
334 | } | |
335 | ||
7fc7d1a7 | 336 | if (publen != 0) { |
d810700b DSH |
337 | if (BIO_printf(bp, "%*spub:\n", off, "") <= 0) |
338 | goto err; | |
7fc7d1a7 | 339 | if (ASN1_buf_print(bp, pub, publen, off + 4) == 0) |
d810700b DSH |
340 | goto err; |
341 | } | |
342 | ||
0f113f3e MC |
343 | if (!ECPKParameters_print(bp, group, off)) |
344 | goto err; | |
345 | ret = 1; | |
346 | err: | |
347 | if (!ret) | |
9311d0c4 | 348 | ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB); |
7fc7d1a7 DSH |
349 | OPENSSL_clear_free(priv, privlen); |
350 | OPENSSL_free(pub); | |
d810700b | 351 | return ret; |
0f113f3e | 352 | } |
35208f36 | 353 | |
3e4585c8 | 354 | static int eckey_param_decode(EVP_PKEY *pkey, |
0f113f3e MC |
355 | const unsigned char **pder, int derlen) |
356 | { | |
357 | EC_KEY *eckey; | |
75ebbd9a | 358 | |
29844ea5 | 359 | if ((eckey = d2i_ECParameters(NULL, pder, derlen)) == NULL) |
0f113f3e | 360 | return 0; |
0f113f3e MC |
361 | EVP_PKEY_assign_EC_KEY(pkey, eckey); |
362 | return 1; | |
363 | } | |
3e4585c8 DSH |
364 | |
365 | static int eckey_param_encode(const EVP_PKEY *pkey, unsigned char **pder) | |
0f113f3e MC |
366 | { |
367 | return i2d_ECParameters(pkey->pkey.ec, pder); | |
368 | } | |
3e4585c8 | 369 | |
35208f36 | 370 | static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, |
0f113f3e MC |
371 | ASN1_PCTX *ctx) |
372 | { | |
d6755bb6 | 373 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PARAM); |
0f113f3e | 374 | } |
35208f36 DSH |
375 | |
376 | static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent, | |
0f113f3e MC |
377 | ASN1_PCTX *ctx) |
378 | { | |
d6755bb6 | 379 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PUBLIC); |
0f113f3e | 380 | } |
35208f36 DSH |
381 | |
382 | static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent, | |
0f113f3e MC |
383 | ASN1_PCTX *ctx) |
384 | { | |
d6755bb6 | 385 | return do_EC_KEY_print(bp, pkey->pkey.ec, indent, EC_KEY_PRINT_PRIVATE); |
0f113f3e | 386 | } |
35208f36 | 387 | |
e4263314 | 388 | static int old_ec_priv_decode(EVP_PKEY *pkey, |
0f113f3e MC |
389 | const unsigned char **pder, int derlen) |
390 | { | |
391 | EC_KEY *ec; | |
75ebbd9a | 392 | |
66066e1b | 393 | if ((ec = d2i_ECPrivateKey(NULL, pder, derlen)) == NULL) |
0f113f3e | 394 | return 0; |
0f113f3e MC |
395 | EVP_PKEY_assign_EC_KEY(pkey, ec); |
396 | return 1; | |
397 | } | |
e4263314 DSH |
398 | |
399 | static int old_ec_priv_encode(const EVP_PKEY *pkey, unsigned char **pder) | |
0f113f3e MC |
400 | { |
401 | return i2d_ECPrivateKey(pkey->pkey.ec, pder); | |
402 | } | |
e4263314 | 403 | |
492a9e24 | 404 | static int ec_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) |
0f113f3e MC |
405 | { |
406 | switch (op) { | |
0f113f3e | 407 | case ASN1_PKEY_CTRL_DEFAULT_MD_NID: |
e766f4a0 PY |
408 | if (EVP_PKEY_id(pkey) == EVP_PKEY_SM2) { |
409 | /* For SM2, the only valid digest-alg is SM3 */ | |
410 | *(int *)arg2 = NID_sm3; | |
ef077ba0 | 411 | return 2; /* Make it mandatory */ |
e766f4a0 | 412 | } |
ef077ba0 | 413 | *(int *)arg2 = NID_sha256; |
eb7eb137 | 414 | return 1; |
492a9e24 | 415 | |
3bca6c27 | 416 | case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: |
7bc0fdd3 MC |
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); | |
3bca6c27 DSH |
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 | ||
0f113f3e MC |
426 | default: |
427 | return -2; | |
0f113f3e | 428 | } |
0f113f3e | 429 | } |
6f81892e | 430 | |
2aee35d3 PY |
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) { | |
9311d0c4 | 437 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_PRIVATE_KEY); |
2aee35d3 PY |
438 | return 0; |
439 | } | |
440 | ||
441 | return EC_KEY_check_key(eckey); | |
442 | } | |
443 | ||
b0004708 PY |
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) { | |
9311d0c4 | 466 | ERR_raise(ERR_LIB_EC, EC_R_MISSING_PARAMETERS); |
b0004708 PY |
467 | return 0; |
468 | } | |
469 | ||
470 | return EC_GROUP_check(eckey->group, NULL); | |
471 | } | |
472 | ||
4fe54d67 NT |
473 | static |
474 | size_t ec_pkey_dirty_cnt(const EVP_PKEY *pkey) | |
475 | { | |
476 | return pkey->pkey.ec->dirty_cnt; | |
477 | } | |
478 | ||
4fe54d67 NT |
479 | static |
480 | int ec_pkey_export_to(const EVP_PKEY *from, void *to_keydata, | |
b4250010 | 481 | EVP_KEYMGMT *to_keymgmt, OSSL_LIB_CTX *libctx, |
76e23fc5 | 482 | const char *propq) |
4fe54d67 NT |
483 | { |
484 | const EC_KEY *eckey = NULL; | |
485 | const EC_GROUP *ecg = NULL; | |
c0f39ded | 486 | unsigned char *pub_key_buf = NULL, *gen_buf = NULL; |
4fe54d67 | 487 | size_t pub_key_buflen; |
6d4e6009 | 488 | OSSL_PARAM_BLD *tmpl; |
4fe54d67 NT |
489 | OSSL_PARAM *params = NULL; |
490 | const BIGNUM *priv_key = NULL; | |
491 | const EC_POINT *pub_point = NULL; | |
0996cff9 | 492 | int selection = 0; |
4fe54d67 | 493 | int rv = 0; |
76e23fc5 | 494 | BN_CTX *bnctx = NULL; |
4fe54d67 NT |
495 | |
496 | if (from == NULL | |
497 | || (eckey = from->pkey.ec) == NULL | |
498 | || (ecg = EC_KEY_get0_group(eckey)) == NULL) | |
499 | return 0; | |
500 | ||
df13defd RL |
501 | /* |
502 | * If the EC_KEY method is foreign, then we can't be sure of anything, | |
503 | * and can therefore not export or pretend to export. | |
504 | */ | |
505 | if (EC_KEY_get_method(eckey) != EC_KEY_OpenSSL()) | |
506 | return 0; | |
507 | ||
6d4e6009 P |
508 | tmpl = OSSL_PARAM_BLD_new(); |
509 | if (tmpl == NULL) | |
510 | return 0; | |
4fe54d67 | 511 | |
c0f39ded SL |
512 | /* |
513 | * EC_POINT_point2buf() can generate random numbers in some | |
514 | * implementations so we need to ensure we use the correct libctx. | |
515 | */ | |
516 | bnctx = BN_CTX_new_ex(libctx); | |
517 | if (bnctx == NULL) | |
518 | goto err; | |
519 | BN_CTX_start(bnctx); | |
520 | ||
4fe54d67 | 521 | /* export the domain parameters */ |
32ab57cb | 522 | if (!ossl_ec_group_todata(ecg, tmpl, NULL, libctx, propq, bnctx, &gen_buf)) |
0996cff9 RL |
523 | goto err; |
524 | selection |= OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS; | |
4fe54d67 NT |
525 | |
526 | priv_key = EC_KEY_get0_private_key(eckey); | |
527 | pub_point = EC_KEY_get0_public_key(eckey); | |
528 | ||
0996cff9 RL |
529 | if (pub_point != NULL) { |
530 | /* convert pub_point to a octet string according to the SECG standard */ | |
531 | if ((pub_key_buflen = EC_POINT_point2buf(ecg, pub_point, | |
532 | POINT_CONVERSION_COMPRESSED, | |
76e23fc5 | 533 | &pub_key_buf, bnctx)) == 0 |
6d4e6009 | 534 | || !OSSL_PARAM_BLD_push_octet_string(tmpl, |
0996cff9 RL |
535 | OSSL_PKEY_PARAM_PUB_KEY, |
536 | pub_key_buf, | |
537 | pub_key_buflen)) | |
538 | goto err; | |
539 | selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY; | |
540 | } | |
4fe54d67 NT |
541 | |
542 | if (priv_key != NULL) { | |
a377871d NT |
543 | size_t sz; |
544 | int ecbits; | |
545 | int ecdh_cofactor_mode; | |
546 | ||
547 | /* | |
548 | * Key import/export should never leak the bit length of the secret | |
549 | * scalar in the key. | |
550 | * | |
551 | * For this reason, on export we use padded BIGNUMs with fixed length. | |
552 | * | |
553 | * When importing we also should make sure that, even if short lived, | |
554 | * the newly created BIGNUM is marked with the BN_FLG_CONSTTIME flag as | |
555 | * soon as possible, so that any processing of this BIGNUM might opt for | |
556 | * constant time implementations in the backend. | |
557 | * | |
558 | * Setting the BN_FLG_CONSTTIME flag alone is never enough, we also have | |
559 | * to preallocate the BIGNUM internal buffer to a fixed public size big | |
560 | * enough that operations performed during the processing never trigger | |
561 | * a realloc which would leak the size of the scalar through memory | |
562 | * accesses. | |
563 | * | |
564 | * Fixed Length | |
565 | * ------------ | |
566 | * | |
567 | * The order of the large prime subgroup of the curve is our choice for | |
568 | * a fixed public size, as that is generally the upper bound for | |
569 | * generating a private key in EC cryptosystems and should fit all valid | |
570 | * secret scalars. | |
571 | * | |
572 | * For padding on export we just use the bit length of the order | |
573 | * converted to bytes (rounding up). | |
574 | * | |
575 | * For preallocating the BIGNUM storage we look at the number of "words" | |
576 | * required for the internal representation of the order, and we | |
577 | * preallocate 2 extra "words" in case any of the subsequent processing | |
578 | * might temporarily overflow the order length. | |
579 | */ | |
580 | ecbits = EC_GROUP_order_bits(ecg); | |
581 | if (ecbits <= 0) | |
582 | goto err; | |
583 | ||
584 | sz = (ecbits + 7 ) / 8; | |
6d4e6009 | 585 | if (!OSSL_PARAM_BLD_push_BN_pad(tmpl, |
a377871d NT |
586 | OSSL_PKEY_PARAM_PRIV_KEY, |
587 | priv_key, sz)) | |
588 | goto err; | |
0996cff9 | 589 | selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY; |
a377871d | 590 | |
4fe54d67 NT |
591 | /* |
592 | * The ECDH Cofactor Mode is defined only if the EC_KEY actually | |
593 | * contains a private key, so we check for the flag and export it only | |
594 | * in this case. | |
595 | */ | |
a377871d | 596 | ecdh_cofactor_mode = |
4fe54d67 NT |
597 | (EC_KEY_get_flags(eckey) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0; |
598 | ||
4fe54d67 | 599 | /* Export the ECDH_COFACTOR_MODE parameter */ |
6d4e6009 | 600 | if (!OSSL_PARAM_BLD_push_int(tmpl, |
4fe54d67 NT |
601 | OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, |
602 | ecdh_cofactor_mode)) | |
603 | goto err; | |
0996cff9 | 604 | selection |= OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS; |
4fe54d67 NT |
605 | } |
606 | ||
6d4e6009 | 607 | params = OSSL_PARAM_BLD_to_param(tmpl); |
4fe54d67 NT |
608 | |
609 | /* We export, the provider imports */ | |
0996cff9 | 610 | rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params); |
4fe54d67 NT |
611 | |
612 | err: | |
6d4e6009 P |
613 | OSSL_PARAM_BLD_free(tmpl); |
614 | OSSL_PARAM_BLD_free_params(params); | |
4fe54d67 | 615 | OPENSSL_free(pub_key_buf); |
c0f39ded SL |
616 | OPENSSL_free(gen_buf); |
617 | BN_CTX_end(bnctx); | |
76e23fc5 | 618 | BN_CTX_free(bnctx); |
4fe54d67 NT |
619 | return rv; |
620 | } | |
621 | ||
629c72db | 622 | static int ec_pkey_import_from(const OSSL_PARAM params[], void *vpctx) |
0abae163 | 623 | { |
629c72db MC |
624 | EVP_PKEY_CTX *pctx = vpctx; |
625 | EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx); | |
d8652be0 | 626 | EC_KEY *ec = EC_KEY_new_ex(pctx->libctx, pctx->propquery); |
0abae163 RL |
627 | |
628 | if (ec == NULL) { | |
629 | ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE); | |
630 | return 0; | |
631 | } | |
632 | ||
32ab57cb SL |
633 | if (!ossl_ec_group_fromdata(ec, params) |
634 | || !ossl_ec_key_otherparams_fromdata(ec, params) | |
635 | || !ossl_ec_key_fromdata(ec, params, 1) | |
0abae163 RL |
636 | || !EVP_PKEY_assign_EC_KEY(pkey, ec)) { |
637 | EC_KEY_free(ec); | |
638 | return 0; | |
639 | } | |
640 | return 1; | |
641 | } | |
642 | ||
2145ba5e TM |
643 | static int ec_pkey_copy(EVP_PKEY *to, EVP_PKEY *from) |
644 | { | |
645 | EC_KEY *eckey = from->pkey.ec; | |
646 | EC_KEY *dupkey = NULL; | |
647 | int ret; | |
648 | ||
649 | if (eckey != NULL) { | |
650 | dupkey = EC_KEY_dup(eckey); | |
651 | if (dupkey == NULL) | |
652 | return 0; | |
653 | } else { | |
654 | /* necessary to properly copy empty SM2 keys */ | |
655 | return EVP_PKEY_set_type(to, from->type); | |
656 | } | |
657 | ||
658 | ret = EVP_PKEY_assign_EC_KEY(to, dupkey); | |
659 | if (!ret) | |
660 | EC_KEY_free(dupkey); | |
661 | return ret; | |
662 | } | |
663 | ||
adf7e6d1 | 664 | const EVP_PKEY_ASN1_METHOD ossl_eckey_asn1_meth = { |
0f113f3e MC |
665 | EVP_PKEY_EC, |
666 | EVP_PKEY_EC, | |
667 | 0, | |
668 | "EC", | |
669 | "OpenSSL EC algorithm", | |
670 | ||
671 | eckey_pub_decode, | |
672 | eckey_pub_encode, | |
673 | eckey_pub_cmp, | |
674 | eckey_pub_print, | |
675 | ||
febe6bb7 | 676 | NULL, |
0f113f3e MC |
677 | eckey_priv_encode, |
678 | eckey_priv_print, | |
679 | ||
680 | int_ec_size, | |
681 | ec_bits, | |
682 | ec_security_bits, | |
683 | ||
684 | eckey_param_decode, | |
685 | eckey_param_encode, | |
686 | ec_missing_parameters, | |
687 | ec_copy_parameters, | |
688 | ec_cmp_parameters, | |
689 | eckey_param_print, | |
690 | 0, | |
691 | ||
692 | int_ec_free, | |
693 | ec_pkey_ctrl, | |
694 | old_ec_priv_decode, | |
2aee35d3 PY |
695 | old_ec_priv_encode, |
696 | ||
697 | 0, 0, 0, | |
698 | ||
b0004708 PY |
699 | ec_pkey_check, |
700 | ec_pkey_public_check, | |
4fe54d67 NT |
701 | ec_pkey_param_check, |
702 | ||
703 | 0, /* set_priv_key */ | |
704 | 0, /* set_pub_key */ | |
705 | 0, /* get_priv_key */ | |
706 | 0, /* get_pub_key */ | |
707 | ||
708 | ec_pkey_dirty_cnt, | |
0abae163 | 709 | ec_pkey_export_to, |
febe6bb7 | 710 | ec_pkey_import_from, |
2145ba5e | 711 | ec_pkey_copy, |
d8652be0 | 712 | eckey_priv_decode_ex |
0f113f3e | 713 | }; |
88e20b85 | 714 | |
ddb634fe | 715 | #if !defined(OPENSSL_NO_SM2) |
adf7e6d1 | 716 | const EVP_PKEY_ASN1_METHOD ossl_sm2_asn1_meth = { |
ddb634fe JL |
717 | EVP_PKEY_SM2, |
718 | EVP_PKEY_EC, | |
719 | ASN1_PKEY_ALIAS | |
720 | }; | |
721 | #endif | |
722 | ||
dca5eeb4 RS |
723 | int EC_KEY_print(BIO *bp, const EC_KEY *x, int off) |
724 | { | |
725 | int private = EC_KEY_get0_private_key(x) != NULL; | |
726 | ||
727 | return do_EC_KEY_print(bp, x, off, | |
a66069db | 728 | private ? EC_KEY_PRINT_PRIVATE : EC_KEY_PRINT_PUBLIC); |
dca5eeb4 RS |
729 | } |
730 | ||
731 | int ECParameters_print(BIO *bp, const EC_KEY *x) | |
732 | { | |
733 | return do_EC_KEY_print(bp, x, 4, EC_KEY_PRINT_PARAM); | |
734 | } |