Add SM2 key management
[openssl.git] / crypto / evp / pmeth_gn.c
1 /*
2  * Copyright 2006-2020 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 #include <stdio.h>
11 #include <stdlib.h>
12 #include <openssl/core.h>
13 #include <openssl/core_names.h>
14 #include "internal/cryptlib.h"
15 #include "internal/core.h"
16 #include <openssl/objects.h>
17 #include <openssl/evp.h>
18 #include "crypto/bn.h"
19 #include "crypto/asn1.h"
20 #include "crypto/evp.h"
21 #include "evp_local.h"
22
23 /* TODO(3.0) remove when provider SM2 key generation is implemented */
24 #ifdef TMP_SM2_HACK
25 # include <openssl/ec.h>
26 # include "internal/sizes.h"
27 #endif
28
29 static int gen_init(EVP_PKEY_CTX *ctx, int operation)
30 {
31     int ret = 0;
32
33     if (ctx == NULL)
34         goto not_supported;
35
36     evp_pkey_ctx_free_old_ops(ctx);
37     ctx->operation = operation;
38
39     if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
40         goto legacy;
41
42 /* TODO remove when provider SM2 key generation is implemented */
43 #ifdef TMP_SM2_HACK
44     if (ctx->pmeth != NULL && ctx->pmeth->pkey_id == EVP_PKEY_SM2)
45         goto legacy;
46 #endif
47
48     switch (operation) {
49     case EVP_PKEY_OP_PARAMGEN:
50         ctx->op.keymgmt.genctx =
51             evp_keymgmt_gen_init(ctx->keymgmt,
52                                  OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
53         break;
54     case EVP_PKEY_OP_KEYGEN:
55         ctx->op.keymgmt.genctx =
56             evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR);
57         break;
58     }
59
60     if (ctx->op.keymgmt.genctx == NULL)
61         ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
62     else
63         ret = 1;
64     goto end;
65
66  legacy:
67 #ifdef FIPS_MODULE
68     goto not_supported;
69 #else
70     if (ctx->pmeth == NULL
71         || (operation == EVP_PKEY_OP_PARAMGEN
72             && ctx->pmeth->paramgen == NULL)
73         || (operation == EVP_PKEY_OP_KEYGEN
74             && ctx->pmeth->keygen == NULL))
75         goto not_supported;
76
77     ret = 1;
78     switch (operation) {
79     case EVP_PKEY_OP_PARAMGEN:
80         if (ctx->pmeth->paramgen_init != NULL)
81             ret = ctx->pmeth->paramgen_init(ctx);
82         break;
83     case EVP_PKEY_OP_KEYGEN:
84         if (ctx->pmeth->keygen_init != NULL)
85             ret = ctx->pmeth->keygen_init(ctx);
86         break;
87     }
88 #endif
89
90  end:
91     if (ret <= 0 && ctx != NULL) {
92         evp_pkey_ctx_free_old_ops(ctx);
93         ctx->operation = EVP_PKEY_OP_UNDEFINED;
94     }
95     return ret;
96
97  not_supported:
98     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
99     ret = -2;
100     goto end;
101 }
102
103 int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
104 {
105     return gen_init(ctx, EVP_PKEY_OP_PARAMGEN);
106 }
107
108 int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
109 {
110     return gen_init(ctx, EVP_PKEY_OP_KEYGEN);
111 }
112
113 static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg)
114 {
115     EVP_PKEY_CTX *ctx = arg;
116     const OSSL_PARAM *param = NULL;
117     int p = -1, n = -1;
118
119     if (ctx->pkey_gencb == NULL)
120         return 1;                /* No callback?  That's fine */
121
122     if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL))
123         == NULL
124         || !OSSL_PARAM_get_int(param, &p))
125         return 0;
126     if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION))
127         == NULL
128         || !OSSL_PARAM_get_int(param, &n))
129         return 0;
130
131     ctx->keygen_info[0] = p;
132     ctx->keygen_info[1] = n;
133
134     return ctx->pkey_gencb(ctx);
135 }
136
137 int EVP_PKEY_gen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
138 {
139     int ret = 0;
140     OSSL_CALLBACK cb;
141     EVP_PKEY *allocated_pkey = NULL;
142     /* Legacy compatible keygen callback info, only used with provider impls */
143     int gentmp[2];
144
145     if (ppkey == NULL)
146         return -1;
147
148     if (ctx == NULL)
149         goto not_supported;
150
151     if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0)
152         goto not_initialized;
153
154     if (*ppkey == NULL)
155         *ppkey = allocated_pkey = EVP_PKEY_new();
156
157     if (*ppkey == NULL) {
158         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
159         return -1;
160     }
161
162     if (ctx->op.keymgmt.genctx == NULL)
163         goto legacy;
164
165     /*
166      * Asssigning gentmp to ctx->keygen_info is something our legacy
167      * implementations do.  Because the provider implementations aren't
168      * allowed to reach into our EVP_PKEY_CTX, we need to provide similar
169      * space for backward compatibility.  It's ok that we attach a local
170      * variable, as it should only be useful in the calls down from here.
171      * This is cleared as soon as it isn't useful any more, i.e. directly
172      * after the evp_keymgmt_util_gen() call.
173      */
174     ctx->keygen_info = gentmp;
175     ctx->keygen_info_count = 2;
176
177     ret = 1;
178     if (ctx->pkey != NULL) {
179         EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt;
180         void *keydata =
181             evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
182                                         &tmp_keymgmt, ctx->propquery);
183
184         if (tmp_keymgmt == NULL)
185             goto not_supported;
186         /*
187          * It's ok if keydata is NULL here.  The backend is expected to deal
188          * with that as it sees fit.
189          */
190         ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
191                                            ctx->op.keymgmt.genctx, keydata);
192     }
193
194     /*
195      * the returned value from evp_keymgmt_util_gen() is cached in *ppkey,
196      * so we so not need to save it, just check it.
197      */
198     ret = ret
199         && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx,
200                                  ossl_callback_to_pkey_gencb, ctx)
201             != NULL);
202
203     ctx->keygen_info = NULL;
204
205 #ifndef FIPS_MODULE
206     /* In case |*ppkey| was originally a legacy key */
207     if (ret)
208         evp_pkey_free_legacy(*ppkey);
209 #endif
210
211     /*
212      * Because we still have legacy keys, and evp_pkey_downgrade()
213      * TODO remove this #legacy internal keys are gone
214      */
215     (*ppkey)->type = ctx->legacy_keytype;
216
217 /* TODO remove when SM2 key have been cleanly separated from EC keys */
218 #ifdef TMP_SM2_HACK
219     /*
220      * Legacy SM2 keys are implemented as EC_KEY with a twist.  The legacy
221      * key generation detects the SM2 curve and "magically" changes the pkey
222      * id accordingly.
223      * Since we don't have SM2 in the provider implementation, we need to
224      * downgrade the generated provider side key to a legacy one under the
225      * same conditions.
226      *
227      * THIS IS AN UGLY BUT TEMPORARY HACK
228      */
229     {
230         char curve_name[OSSL_MAX_NAME_SIZE] = "";
231
232         if (!EVP_PKEY_get_utf8_string_param(*ppkey, OSSL_PKEY_PARAM_GROUP_NAME,
233                                             curve_name, sizeof(curve_name),
234                                             NULL)
235             || strcmp(curve_name, "SM2") != 0)
236             goto end;
237     }
238
239     if (!evp_pkey_downgrade(*ppkey)
240         || !EVP_PKEY_set_alias_type(*ppkey, EVP_PKEY_SM2))
241         ret = 0;
242 #endif
243     goto end;
244
245  legacy:
246 #ifdef FIPS_MODULE
247     goto not_supported;
248 #else
249     if (ctx->pkey && !evp_pkey_downgrade(ctx->pkey))
250         goto not_accessible;
251     switch (ctx->operation) {
252     case EVP_PKEY_OP_PARAMGEN:
253         ret = ctx->pmeth->paramgen(ctx, *ppkey);
254         break;
255     case EVP_PKEY_OP_KEYGEN:
256         ret = ctx->pmeth->keygen(ctx, *ppkey);
257         break;
258     default:
259         goto not_supported;
260     }
261 #endif
262
263  end:
264     if (ret <= 0) {
265         if (allocated_pkey != NULL)
266             *ppkey = NULL;
267         EVP_PKEY_free(allocated_pkey);
268     }
269     return ret;
270
271  not_supported:
272     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
273     ret = -2;
274     goto end;
275  not_initialized:
276     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
277     ret = -1;
278     goto end;
279 #ifndef FIPS_MODULE
280  not_accessible:
281     ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
282     ret = -1;
283     goto end;
284 #endif
285 }
286
287 int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
288 {
289     if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
290         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
291         return -1;
292     }
293     return EVP_PKEY_gen(ctx, ppkey);
294 }
295
296 int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
297 {
298     if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
299         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATON_NOT_INITIALIZED);
300         return -1;
301     }
302     return EVP_PKEY_gen(ctx, ppkey);
303 }
304
305 void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
306 {
307     ctx->pkey_gencb = cb;
308 }
309
310 EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
311 {
312     return ctx->pkey_gencb;
313 }
314
315 /*
316  * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style
317  * callbacks.
318  */
319
320 static int trans_cb(int a, int b, BN_GENCB *gcb)
321 {
322     EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb);
323     ctx->keygen_info[0] = a;
324     ctx->keygen_info[1] = b;
325     return ctx->pkey_gencb(ctx);
326 }
327
328 void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
329 {
330     BN_GENCB_set(cb, trans_cb, ctx);
331 }
332
333 int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
334 {
335     if (idx == -1)
336         return ctx->keygen_info_count;
337     if (idx < 0 || idx > ctx->keygen_info_count)
338         return 0;
339     return ctx->keygen_info[idx];
340 }
341
342 #ifndef FIPS_MODULE
343
344 EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
345                                const unsigned char *key, int keylen)
346 {
347     EVP_PKEY_CTX *mac_ctx = NULL;
348     EVP_PKEY *mac_key = NULL;
349     mac_ctx = EVP_PKEY_CTX_new_id(type, e);
350     if (!mac_ctx)
351         return NULL;
352     if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
353         goto merr;
354     if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0)
355         goto merr;
356     if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
357         goto merr;
358  merr:
359     EVP_PKEY_CTX_free(mac_ctx);
360     return mac_key;
361 }
362
363 #endif /* FIPS_MODULE */
364
365 /*- All methods below can also be used in FIPS_MODULE */
366
367 static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
368 {
369     if (ctx == NULL || ctx->keytype == NULL)
370         goto not_supported;
371
372     evp_pkey_ctx_free_old_ops(ctx);
373     if (ctx->keymgmt == NULL)
374         goto not_supported;
375
376     ctx->operation = operation;
377     return 1;
378
379  not_supported:
380     if (ctx != NULL)
381         ctx->operation = EVP_PKEY_OP_UNDEFINED;
382     ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
383     return -2;
384 }
385
386 int EVP_PKEY_param_fromdata_init(EVP_PKEY_CTX *ctx)
387 {
388     return fromdata_init(ctx, EVP_PKEY_OP_PARAMFROMDATA);
389 }
390
391 int EVP_PKEY_key_fromdata_init(EVP_PKEY_CTX *ctx)
392 {
393     return fromdata_init(ctx, EVP_PKEY_OP_KEYFROMDATA);
394 }
395
396 int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, OSSL_PARAM params[])
397 {
398     void *keydata = NULL;
399     int selection;
400
401     if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_TYPE_FROMDATA) == 0) {
402         ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
403         return -2;
404     }
405
406     if (ppkey == NULL)
407         return -1;
408
409     if (*ppkey == NULL)
410         *ppkey = EVP_PKEY_new();
411
412     if (*ppkey == NULL) {
413         ERR_raise(ERR_LIB_EVP, ERR_R_MALLOC_FAILURE);
414         return -1;
415     }
416
417     if (ctx->operation == EVP_PKEY_OP_PARAMFROMDATA)
418         selection = OSSL_KEYMGMT_SELECT_ALL_PARAMETERS;
419     else
420         selection = OSSL_KEYMGMT_SELECT_ALL;
421     keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection,
422                                         params);
423
424     if (keydata == NULL)
425         return 0;
426     /* keydata is cached in *ppkey, so we need not bother with it further */
427     return 1;
428 }
429
430 /*
431  * TODO(3.0) Re-evaluate the names, it's possible that we find these to be
432  * better:
433  *
434  * EVP_PKEY_param_settable()
435  * EVP_PKEY_param_gettable()
436  */
437 const OSSL_PARAM *EVP_PKEY_param_fromdata_settable(EVP_PKEY_CTX *ctx)
438 {
439     /* We call fromdata_init to get ctx->keymgmt populated */
440     if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
441         return evp_keymgmt_import_types(ctx->keymgmt,
442                                         OSSL_KEYMGMT_SELECT_ALL_PARAMETERS);
443     return NULL;
444 }
445
446 const OSSL_PARAM *EVP_PKEY_key_fromdata_settable(EVP_PKEY_CTX *ctx)
447 {
448     /* We call fromdata_init to get ctx->keymgmt populated */
449     if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED))
450         return evp_keymgmt_import_types(ctx->keymgmt,
451                                         OSSL_KEYMGMT_SELECT_ALL);
452     return NULL;
453 }