[PROV][KMGMT][KEXCH][EC] Implement EC keymgtm and ECDH
[openssl.git] / providers / implementations / keymgmt / ec_kmgmt.c
1 /*
2  * Copyright 2019 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/ECDSA low level APIs are deprecated for public use, but still ok for
12  * internal use.
13  */
14 #include "internal/deprecated.h"
15
16 #include <openssl/core_numbers.h>
17 #include <openssl/core_names.h>
18 #include <openssl/bn.h>
19 #include <openssl/ec.h>
20 #include <openssl/objects.h>
21 #include <openssl/params.h>
22 #include "internal/param_build.h"
23 #include "prov/implementations.h"
24 #include "prov/providercommon.h"
25
26 static OSSL_OP_keymgmt_new_fn ec_newdata;
27 static OSSL_OP_keymgmt_free_fn ec_freedata;
28 static OSSL_OP_keymgmt_get_params_fn ec_get_params;
29 static OSSL_OP_keymgmt_gettable_params_fn ec_gettable_params;
30 static OSSL_OP_keymgmt_set_params_fn ec_set_params;
31 static OSSL_OP_keymgmt_settable_params_fn ec_settable_params;
32 static OSSL_OP_keymgmt_has_fn ec_has;
33 static OSSL_OP_keymgmt_import_fn ec_import;
34 static OSSL_OP_keymgmt_import_types_fn ec_import_types;
35 static OSSL_OP_keymgmt_export_fn ec_export;
36 static OSSL_OP_keymgmt_export_types_fn ec_export_types;
37 static OSSL_OP_keymgmt_query_operation_name_fn ec_query_operation_name;
38
39 #define EC_POSSIBLE_SELECTIONS                 \
40     (OSSL_KEYMGMT_SELECT_KEYPAIR | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS )
41
42 static
43 const char *ec_query_operation_name(int operation_id)
44 {
45     switch (operation_id) {
46     case OSSL_OP_KEYEXCH:
47         return "ECDH";
48 #if 0
49     case OSSL_OP_SIGNATURE:
50         return deflt_signature;
51 #endif
52     }
53     return NULL;
54 }
55
56 static ossl_inline
57 int params_to_domparams(EC_KEY *ec, const OSSL_PARAM params[])
58 {
59     const OSSL_PARAM *param_ec_name;
60     EC_GROUP *ecg = NULL;
61     char *curve_name = NULL;
62     int ok = 0;
63
64     if (ec == NULL)
65         return 0;
66
67     param_ec_name = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_EC_NAME);
68     if (param_ec_name == NULL) {
69         /* explicit parameters */
70
71         /*
72          * TODO(3.0): should we support explicit parameters curves?
73          */
74         return 0;
75     } else {
76         /* named curve */
77         int curve_nid;
78
79         if (!OSSL_PARAM_get_utf8_string(param_ec_name, &curve_name, 0)
80                 || curve_name == NULL
81                 || (curve_nid = OBJ_sn2nid(curve_name)) == NID_undef)
82             goto err;
83
84         if ((ecg = EC_GROUP_new_by_curve_name(curve_nid)) == NULL)
85             goto err;
86     }
87
88     if (!EC_KEY_set_group(ec, ecg))
89         goto err;
90
91     /*
92      * TODO(3.0): if the group has changed, should we invalidate the private and
93      * public key?
94      */
95
96     ok = 1;
97
98  err:
99     OPENSSL_free(curve_name);
100     EC_GROUP_free(ecg);
101     return ok;
102 }
103
104 static ossl_inline
105 int domparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
106 {
107     const EC_GROUP *ecg;
108     int curve_nid;
109
110     if (ec == NULL)
111         return 0;
112
113     ecg = EC_KEY_get0_group(ec);
114     if (ecg == NULL)
115         return 0;
116
117     curve_nid = EC_GROUP_get_curve_name(ecg);
118
119     if (curve_nid == NID_undef) {
120         /* explicit parameters */
121
122         /*
123          * TODO(3.0): should we support explicit parameters curves?
124          */
125         return 0;
126     } else {
127         /* named curve */
128         const char *curve_name = NULL;
129
130         if ((curve_name = OBJ_nid2sn(curve_nid)) == NULL)
131             return 0;
132
133         if (!ossl_param_bld_push_utf8_string(tmpl, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0))
134             return 0;
135     }
136
137     return 1;
138 }
139
140 /*
141  * Callers of params_to_key MUST make sure that params_to_domparams has been
142  * called before!
143  *
144  * This function only imports the bare keypair, domain parameters and other
145  * parameters are imported separately, and domain parameters are required to
146  * define a keypair.
147  */
148 static ossl_inline
149 int params_to_key(EC_KEY *ec, const OSSL_PARAM params[], int include_private)
150 {
151     const OSSL_PARAM *param_priv_key, *param_pub_key;
152     BIGNUM *priv_key = NULL;
153     unsigned char *pub_key = NULL;
154     size_t pub_key_len;
155     const EC_GROUP *ecg = NULL;
156     EC_POINT *pub_point = NULL;
157     int ok = 0;
158
159     ecg = EC_KEY_get0_group(ec);
160     if (ecg == NULL)
161         return 0;
162
163     param_priv_key =
164         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY);
165     param_pub_key =
166         OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY);
167
168     /*
169      * We want to have at least a public key either way, so we end up
170      * requiring it unconditionally.
171      */
172     if (param_pub_key == NULL
173             || !OSSL_PARAM_get_octet_string(param_pub_key,
174                                             (void **)&pub_key, 0, &pub_key_len)
175             || (pub_point = EC_POINT_new(ecg)) == NULL
176             || !EC_POINT_oct2point(ecg, pub_point,
177                                    pub_key, pub_key_len, NULL))
178         goto err;
179
180     if (param_priv_key != NULL && include_private
181             && !OSSL_PARAM_get_BN(param_priv_key, &priv_key))
182         goto err;
183
184     if (priv_key != NULL
185             && !EC_KEY_set_private_key(ec, priv_key))
186         goto err;
187
188     if (!EC_KEY_set_public_key(ec, pub_point))
189         goto err;
190
191     ok = 1;
192
193  err:
194     BN_clear_free(priv_key);
195     OPENSSL_free(pub_key);
196     EC_POINT_free(pub_point);
197     return ok;
198 }
199
200 /*
201  * Callers of key_to_params MUST make sure that domparams_to_params is also
202  * called!
203  *
204  * This function only exports the bare keypair, domain parameters and other
205  * parameters are exported separately.
206  */
207 static ossl_inline
208 int key_to_params(const EC_KEY *eckey, OSSL_PARAM_BLD *tmpl, int include_private)
209 {
210     const BIGNUM *priv_key = NULL;
211     const EC_POINT *pub_point = NULL;
212     const EC_GROUP *ecg = NULL;
213     unsigned char *pub_key = NULL;
214     size_t pub_key_len = 0;
215     int ret = 0;
216
217     if (eckey == NULL)
218         return 0;
219
220     ecg = EC_KEY_get0_group(eckey);
221     priv_key = EC_KEY_get0_private_key(eckey);
222     pub_point = EC_KEY_get0_public_key(eckey);
223
224     /* group and public_key must be present, priv_key is optional */
225     if (ecg == NULL || pub_point == NULL)
226         return 0;
227     if ((pub_key_len = EC_POINT_point2buf(ecg, pub_point,
228                                           POINT_CONVERSION_COMPRESSED,
229                                           &pub_key, NULL)) == 0)
230         return 0;
231
232     if (!ossl_param_bld_push_octet_string(tmpl,
233                                           OSSL_PKEY_PARAM_PUB_KEY,
234                                           pub_key, pub_key_len))
235         goto err;
236
237     if (priv_key != NULL && include_private
238             && !ossl_param_bld_push_BN(tmpl,
239                                        OSSL_PKEY_PARAM_PRIV_KEY,
240                                        priv_key))
241         goto err;
242
243     ret = 1;
244
245  err:
246     OPENSSL_free(pub_key);
247     return ret;
248 }
249
250 static ossl_inline
251 int ec_set_param_ecdh_cofactor_mode(EC_KEY *ec, const OSSL_PARAM *p)
252 {
253     const EC_GROUP *ecg = EC_KEY_get0_group(ec);
254     const BIGNUM *cofactor;
255     int mode;
256
257     if (!OSSL_PARAM_get_int(p, &mode))
258         return 0;
259
260     /*
261      * mode can be only 0 for disable, or 1 for enable here.
262      *
263      * This is in contrast with the same parameter on an ECDH EVP_PKEY_CTX that
264      * also supports mode == -1 with the meaning of "reset to the default for
265      * the associated key".
266      */
267     if (mode < 0 || mode > 1)
268         return 0;
269
270     if ((cofactor = EC_GROUP_get0_cofactor(ecg)) == NULL )
271         return 0;
272
273     /* ECDH cofactor mode has no effect if cofactor is 1 */
274     if (BN_is_one(cofactor))
275         return 1;
276
277     if (mode == 1)
278         EC_KEY_set_flags(ec, EC_FLAG_COFACTOR_ECDH);
279     else if (mode == 0)
280         EC_KEY_clear_flags(ec, EC_FLAG_COFACTOR_ECDH);
281
282     return 1;
283 }
284
285 static ossl_inline
286 int params_to_otherparams(EC_KEY *ec, const OSSL_PARAM params[])
287 {
288     const OSSL_PARAM *p;
289
290     if (ec == NULL)
291         return 0;
292
293     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
294     if (p != NULL && !ec_set_param_ecdh_cofactor_mode(ec, p))
295         return 0;
296
297     return 1;
298 }
299
300 static ossl_inline
301 int otherparams_to_params(const EC_KEY *ec, OSSL_PARAM_BLD *tmpl)
302 {
303     int ecdh_cofactor_mode = 0;
304
305     if (ec == NULL)
306         return 0;
307
308     ecdh_cofactor_mode =
309         (EC_KEY_get_flags(ec) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
310     if (!ossl_param_bld_push_int(tmpl,
311                 OSSL_PKEY_PARAM_USE_COFACTOR_ECDH,
312                 ecdh_cofactor_mode))
313         return 0;
314
315     return 1;
316 }
317
318 static
319 void *ec_newdata(void *provctx)
320 {
321     return EC_KEY_new();
322 }
323
324 static
325 void ec_freedata(void *keydata)
326 {
327     EC_KEY_free(keydata);
328 }
329
330 static
331 int ec_has(void *keydata, int selection)
332 {
333     EC_KEY *ec = keydata;
334     int ok = 0;
335
336     if ((selection & EC_POSSIBLE_SELECTIONS) != 0)
337         ok = 1;
338
339     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
340         ok = ok && (EC_KEY_get0_public_key(ec) != NULL);
341     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
342         ok = ok && (EC_KEY_get0_private_key(ec) != NULL);
343     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
344         ok = ok && (EC_KEY_get0_group(ec) != NULL);
345     /*
346      * We consider OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS to always be available,
347      * so no extra check is needed other than the previous one against
348      * EC_POSSIBLE_SELECTIONS.
349      */
350
351     return ok;
352 }
353
354 static
355 int ec_import(void *keydata, int selection, const OSSL_PARAM params[])
356 {
357     EC_KEY *ec = keydata;
358     int ok = 0;
359
360     if (ec == NULL)
361         return 0;
362
363     /*
364      * In this implementation, we can export/import only keydata in the
365      * following combinations:
366      *   - domain parameters only
367      *   - public key with associated domain parameters (+optional other params)
368      *   - private key with associated public key and domain parameters
369      *         (+optional other params)
370      *
371      * This means:
372      *   - domain parameters must always be requested
373      *   - private key must be requested alongside public key
374      *   - other parameters must be requested only alongside a key
375      */
376     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
377         return 0;
378     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
379             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
380         return 0;
381     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
382             && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
383         return 0;
384
385     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
386         ok = ok && params_to_domparams(ec, params);
387     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
388         int include_private =
389             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
390
391         ok = ok && params_to_key(ec, params, include_private);
392     }
393     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
394         ok = ok && params_to_otherparams(ec, params);
395
396     return ok;
397 }
398
399 static
400 int ec_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
401               void *cbarg)
402 {
403     EC_KEY *ec = keydata;
404     OSSL_PARAM_BLD tmpl;
405     OSSL_PARAM *params = NULL;
406     int ok = 1;
407
408     if (ec == NULL)
409         return 0;
410
411     /*
412      * In this implementation, we can export/import only keydata in the
413      * following combinations:
414      *   - domain parameters only
415      *   - public key with associated domain parameters (+optional other params)
416      *   - private key with associated public key and domain parameters
417      *         (+optional other params)
418      *
419      * This means:
420      *   - domain parameters must always be requested
421      *   - private key must be requested alongside public key
422      *   - other parameters must be requested only alongside a key
423      */
424     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) == 0)
425         return 0;
426     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
427             && (selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) == 0)
428         return 0;
429     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0
430             && (selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
431         return 0;
432
433     ossl_param_bld_init(&tmpl);
434
435     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
436         ok = ok && domparams_to_params(ec, &tmpl);
437     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
438         int include_private =
439             selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
440
441         ok = ok && key_to_params(ec, &tmpl, include_private);
442     }
443     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
444         ok = ok && otherparams_to_params(ec, &tmpl);
445
446     if (!ok
447         || (params = ossl_param_bld_to_param(&tmpl)) == NULL)
448         return 0;
449
450     ok = param_cb(params, cbarg);
451     ossl_param_bld_free(params);
452     return ok;
453 }
454
455 /* IMEXPORT = IMPORT + EXPORT */
456
457 # define EC_IMEXPORTABLE_DOM_PARAMETERS                          \
458     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_EC_NAME, NULL, 0)
459 # define EC_IMEXPORTABLE_PUBLIC_KEY                              \
460     OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0)
461 # define EC_IMEXPORTABLE_PRIVATE_KEY                             \
462     OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
463 # define EC_IMEXPORTABLE_OTHER_PARAMETERS                        \
464     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL)
465
466 /*
467  * Include all the possible combinations of OSSL_PARAM arrays for
468  * ec_imexport_types().
469  *
470  * They are in a separate file as it is ~100 lines of unreadable and
471  * uninteresting machine generated stuff.
472  *
473  * TODO(3.0): the generated list looks quite ugly, as to cover all possible
474  * combinations of the bits in `selection`, it also includes combinations that
475  * are not really useful: we might want to consider alternatives to this
476  * solution.
477  */
478 #include "ec_kmgmt_imexport.inc"
479
480 static ossl_inline
481 const OSSL_PARAM *ec_imexport_types(int selection)
482 {
483     int type_select = 0;
484
485     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
486         type_select += 1;
487     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
488         type_select += 2;
489     if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
490         type_select += 4;
491     if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0)
492         type_select += 8;
493     return ec_types[type_select];
494 }
495
496 static
497 const OSSL_PARAM *ec_import_types(int selection)
498 {
499     return ec_imexport_types(selection);
500 }
501
502 static
503 const OSSL_PARAM *ec_export_types(int selection)
504 {
505     return ec_imexport_types(selection);
506 }
507
508 static
509 int ec_get_params(void *key, OSSL_PARAM params[])
510 {
511     EC_KEY *eck = key;
512     const EC_GROUP *ecg = NULL;
513     OSSL_PARAM *p;
514
515     ecg = EC_KEY_get0_group(eck);
516     if (ecg == NULL)
517         return 0;
518
519     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
520         && !OSSL_PARAM_set_int(p, ECDSA_size(eck)))
521         return 0;
522     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
523         && !OSSL_PARAM_set_int(p, EC_GROUP_order_bits(ecg)))
524         return 0;
525     if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL) {
526         int ecbits, sec_bits;
527
528         ecbits = EC_GROUP_order_bits(ecg);
529
530         /*
531          * The following estimates are based on the values published
532          * in Table 2 of "NIST Special Publication 800-57 Part 1 Revision 4"
533          * at http://dx.doi.org/10.6028/NIST.SP.800-57pt1r4 .
534          *
535          * Note that the above reference explicitly categorizes algorithms in a
536          * discrete set of values {80, 112, 128, 192, 256}, and that it is
537          * relevant only for NIST approved Elliptic Curves, while OpenSSL
538          * applies the same logic also to other curves.
539          *
540          * Classifications produced by other standardazing bodies might differ,
541          * so the results provided for "bits of security" by this provider are
542          * to be considered merely indicative, and it is the users'
543          * responsibility to compare these values against the normative
544          * references that may be relevant for their intent and purposes.
545          */
546         if (ecbits >= 512)
547             sec_bits = 256;
548         else if (ecbits >= 384)
549             sec_bits = 192;
550         else if (ecbits >= 256)
551             sec_bits = 128;
552         else if (ecbits >= 224)
553             sec_bits = 112;
554         else if (ecbits >= 160)
555             sec_bits = 80;
556         else
557             sec_bits = ecbits / 2;
558
559         if (!OSSL_PARAM_set_int(p, sec_bits))
560             return 0;
561     }
562
563     p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
564     if (p != NULL) {
565         int ecdh_cofactor_mode = 0;
566
567         ecdh_cofactor_mode =
568             (EC_KEY_get_flags(eck) & EC_FLAG_COFACTOR_ECDH) ? 1 : 0;
569
570         if (!OSSL_PARAM_set_int(p, ecdh_cofactor_mode))
571             return 0;
572     }
573
574     return 1;
575 }
576
577 static const OSSL_PARAM ec_known_gettable_params[] = {
578     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
579     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
580     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
581     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
582     OSSL_PARAM_END
583 };
584
585 static
586 const OSSL_PARAM *ec_gettable_params(void)
587 {
588     return ec_known_gettable_params;
589 }
590
591 static const OSSL_PARAM ec_known_settable_params[] = {
592     OSSL_PARAM_int(OSSL_PKEY_PARAM_USE_COFACTOR_ECDH, NULL),
593     OSSL_PARAM_END
594 };
595
596 static
597 const OSSL_PARAM *ec_settable_params(void)
598 {
599     return ec_known_settable_params;
600 }
601
602 static
603 int ec_set_params(void *key, const OSSL_PARAM params[])
604 {
605     EC_KEY *eck = key;
606     const OSSL_PARAM *p;
607
608     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_USE_COFACTOR_ECDH);
609     if (p != NULL && !ec_set_param_ecdh_cofactor_mode(eck, p))
610         return 0;
611
612     return 1;
613 }
614
615 const OSSL_DISPATCH ec_keymgmt_functions[] = {
616     { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))ec_newdata },
617     { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ec_freedata },
618     { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))ec_get_params },
619     { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))ec_gettable_params },
620     { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))ec_set_params },
621     { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))ec_settable_params },
622     { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ec_has },
623     { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ec_import },
624     { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ec_import_types },
625     { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ec_export },
626     { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ec_export_types },
627     { OSSL_FUNC_KEYMGMT_QUERY_OPERATION_NAME,
628         (void (*)(void))ec_query_operation_name },
629     { 0, NULL }
630 };