9e12b9a15954ccf2e86ddea4980f8e79ade9bd18
[openssl.git] / crypto / ec / ec_ctrl.c
1 /*
2  * Copyright 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 <string.h>
11
12 #include <openssl/err.h>
13 #include <openssl/opensslv.h>
14
15 #include <openssl/core_names.h>
16 #include "crypto/evp.h"
17
18 #include "ec_local.h"
19
20 /*
21  * This file is meant to contain functions to provide EVP_PKEY support for EC
22  * keys.
23  */
24
25 static ossl_inline
26 int evp_pkey_ctx_getset_ecdh_param_checks(const EVP_PKEY_CTX *ctx)
27 {
28     if (ctx == NULL || !EVP_PKEY_CTX_IS_DERIVE_OP(ctx)) {
29         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
30         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
31         return -2;
32     }
33
34     /* If key type not EC return error */
35     if (ctx->pmeth != NULL && ctx->pmeth->pkey_id != EVP_PKEY_EC)
36         return -1;
37
38     return 1;
39 }
40
41 int EVP_PKEY_CTX_set_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx, int cofactor_mode)
42 {
43     int ret;
44     OSSL_PARAM params[2], *p = params;
45
46     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
47     if (ret != 1)
48         return ret;
49
50     /*
51      * Valid input values are:
52      *  * 0 for disable
53      *  * 1 for enable
54      *  * -1 for reset to default for associated priv key
55      */
56     if (cofactor_mode < -1 || cofactor_mode > 1) {
57         /* Uses the same return value of pkey_ec_ctrl() */
58         return -2;
59     }
60
61     /* TODO(3.0): Remove this eventually when no more legacy */
62     if (ctx->op.kex.exchprovctx == NULL)
63         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
64                                  EVP_PKEY_OP_DERIVE,
65                                  EVP_PKEY_CTRL_EC_ECDH_COFACTOR,
66                                  cofactor_mode, NULL);
67
68     *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
69                                     &cofactor_mode);
70     *p++ = OSSL_PARAM_construct_end();
71
72     ret = evp_pkey_ctx_set_params_strict(ctx, params);
73     if (ret == -2) {
74         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
75         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
76         return -2;
77     }
78
79     return ret;
80 }
81
82 int EVP_PKEY_CTX_get_ecdh_cofactor_mode(EVP_PKEY_CTX *ctx)
83 {
84     int ret, mode;
85     OSSL_PARAM params[2], *p = params;
86
87     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
88     if (ret != 1)
89         return ret;
90
91     /* TODO(3.0): Remove this eventually when no more legacy */
92     if (ctx->op.kex.exchprovctx == NULL)
93         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
94                                  EVP_PKEY_OP_DERIVE,
95                                  EVP_PKEY_CTRL_EC_ECDH_COFACTOR, -2, NULL);
96
97     *p++ = OSSL_PARAM_construct_int(OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE,
98                                     &mode);
99     *p++ = OSSL_PARAM_construct_end();
100
101     ret = evp_pkey_ctx_get_params_strict(ctx, params);
102     if (ret == -2) {
103         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
104         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
105         return -2;
106     } else if (ret != 1) {
107         return -1;
108     }
109
110     if (mode < 0 || mode > 1) {
111         /*
112          * The provider should return either 0 or 1, any other value is a
113          * provider error.
114          */
115         return -1;
116     }
117
118     return mode;
119 }
120
121 int EVP_PKEY_CTX_set_ecdh_kdf_type(EVP_PKEY_CTX *ctx, int kdf)
122 {
123     int ret;
124     const char *kdf_type;
125     OSSL_PARAM params[2], *p = params;
126
127     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
128     if (ret != 1)
129         return ret;
130
131     switch (kdf) {
132         case EVP_PKEY_ECDH_KDF_NONE:
133             kdf_type = "";
134             break;
135         case EVP_PKEY_ECDH_KDF_X9_63:
136             kdf_type = OSSL_KDF_NAME_X963KDF;
137             break;
138         default:
139             return -2;
140     }
141
142     /* TODO(3.0): Remove this eventually when no more legacy */
143     if (ctx->op.kex.exchprovctx == NULL)
144         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
145                                  EVP_PKEY_OP_DERIVE,
146                                  EVP_PKEY_CTRL_EC_KDF_TYPE, kdf, NULL);
147
148     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
149                                             /*
150                                              * Cast away the const. This is read
151                                              * only so should be safe
152                                              */
153                                             (char *)kdf_type, 0);
154     *p++ = OSSL_PARAM_construct_end();
155
156     ret = evp_pkey_ctx_set_params_strict(ctx, params);
157     if (ret == -2) {
158         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
159         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
160         return -2;
161     }
162
163     return ret;
164 }
165
166 int EVP_PKEY_CTX_get_ecdh_kdf_type(EVP_PKEY_CTX *ctx)
167 {
168     int ret;
169     /* 80 should be big enough */
170     char kdf_type[80];
171     OSSL_PARAM params[2], *p = params;
172
173     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
174     if (ret != 1)
175         return ret;
176
177     /* TODO(3.0): Remove this eventually when no more legacy */
178     if (ctx->op.kex.exchprovctx == NULL)
179         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
180                                  EVP_PKEY_OP_DERIVE,
181                                  EVP_PKEY_CTRL_EC_KDF_TYPE, -2, NULL);
182
183     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_TYPE,
184                                             kdf_type, sizeof(kdf_type));
185     *p++ = OSSL_PARAM_construct_end();
186
187     ret = evp_pkey_ctx_get_params_strict(ctx, params);
188     if (ret == -2) {
189         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
190         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
191         return -2;
192     } else if (ret != 1) {
193         return -1;
194     }
195
196     if (kdf_type[0] == '\0')
197         return EVP_PKEY_ECDH_KDF_NONE;
198     else if (strcmp(kdf_type, OSSL_KDF_NAME_X963KDF) == 0)
199         return EVP_PKEY_ECDH_KDF_X9_63;
200
201     return -1;
202 }
203
204 int EVP_PKEY_CTX_set_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD *md)
205 {
206     int ret;
207     OSSL_PARAM params[2], *p = params;
208     const char *md_name = NULL;
209
210     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
211     if (ret != 1)
212         return ret;
213
214     /* TODO(3.0): Remove this eventually when no more legacy */
215     if (ctx->op.kex.exchprovctx == NULL)
216         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
217                                  EVP_PKEY_OP_DERIVE,
218                                  EVP_PKEY_CTRL_EC_KDF_MD, 0, (void *)(md));
219
220     md_name = (md == NULL) ? "" : EVP_MD_name(md);
221
222     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
223                                             /*
224                                              * Cast away the const. This is read
225                                              * only so should be safe
226                                              */
227                                             (char *)md_name, 0);
228     *p++ = OSSL_PARAM_construct_end();
229
230     ret = evp_pkey_ctx_set_params_strict(ctx, params);
231     if (ret == -2) {
232         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
233         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
234         return -2;
235     }
236     return ret;
237 }
238
239 int EVP_PKEY_CTX_get_ecdh_kdf_md(EVP_PKEY_CTX *ctx, const EVP_MD **pmd)
240 {
241     /* 80 should be big enough */
242     char name[80] = "";
243     int ret;
244     OSSL_PARAM params[2], *p = params;
245
246     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
247     if (ret != 1)
248         return ret;
249
250     /* TODO(3.0): Remove this eventually when no more legacy */
251     if (ctx->op.kex.exchprovctx == NULL)
252         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
253                                  EVP_PKEY_OP_DERIVE,
254                                  EVP_PKEY_CTRL_GET_EC_KDF_MD, 0, (void *)(pmd));
255
256     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST,
257                                             name, sizeof(name));
258     *p++ = OSSL_PARAM_construct_end();
259
260     ret = evp_pkey_ctx_get_params_strict(ctx, params);
261     if (ret == -2) {
262         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
263         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
264         return -2;
265     } else if (ret != 1) {
266         return -1;
267     }
268
269     /* May be NULL meaning "unknown" */
270     *pmd = EVP_get_digestbyname(name);
271
272     return 1;
273 }
274
275 int EVP_PKEY_CTX_set_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int in)
276 {
277     int ret;
278     size_t len = in;
279     OSSL_PARAM params[2], *p = params;
280
281     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
282     if (ret != 1)
283         return ret;
284
285     /* TODO(3.0): Remove this eventually when no more legacy */
286     if (ctx->op.kex.exchprovctx == NULL)
287         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
288                                  EVP_PKEY_OP_DERIVE,
289                                  EVP_PKEY_CTRL_EC_KDF_OUTLEN, in, NULL);
290
291     if (in <= 0) {
292         /*
293          * This would ideally be -1 or 0, but we have to retain compatibility
294          * with legacy behaviour of EVP_PKEY_CTX_ctrl() which returned -2 if
295          * in <= 0
296          */
297         return -2;
298     }
299
300     *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
301                                        &len);
302     *p++ = OSSL_PARAM_construct_end();
303
304     ret = evp_pkey_ctx_set_params_strict(ctx, params);
305     if (ret == -2) {
306         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
307         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
308         return -2;
309     }
310     return ret;
311 }
312
313 int EVP_PKEY_CTX_get_ecdh_kdf_outlen(EVP_PKEY_CTX *ctx, int *plen)
314 {
315     size_t len = UINT_MAX;
316     int ret;
317     OSSL_PARAM params[2], *p = params;
318
319     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
320     if (ret != 1)
321         return ret;
322
323     /* TODO(3.0): Remove this eventually when no more legacy */
324     if (ctx->op.kex.exchprovctx == NULL)
325         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
326                                  EVP_PKEY_OP_DERIVE,
327                                  EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN, 0,
328                                  (void *)(plen));
329
330     *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN,
331                                        &len);
332     *p++ = OSSL_PARAM_construct_end();
333
334     ret = evp_pkey_ctx_get_params_strict(ctx, params);
335     if (ret == -2) {
336         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
337         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
338         return -2;
339     } else if (ret != 1) {
340         return -1;
341     }
342
343     if (len > INT_MAX)
344         return -1;
345
346     *plen = (int)len;
347
348     return 1;
349 }
350
351 int EVP_PKEY_CTX_set0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char *ukm, int len)
352 {
353     int ret;
354     OSSL_PARAM params[2], *p = params;
355
356     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
357     if (ret != 1)
358         return ret;
359
360     /* TODO(3.0): Remove this eventually when no more legacy */
361     if (ctx->op.kex.exchprovctx == NULL)
362         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
363                                  EVP_PKEY_OP_DERIVE,
364                                  EVP_PKEY_CTRL_EC_KDF_UKM, len, (void *)(ukm));
365
366     *p++ = OSSL_PARAM_construct_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM,
367                                             /*
368                                              * Cast away the const. This is read
369                                              * only so should be safe
370                                              */
371                                             (void *)ukm,
372                                             (size_t)len);
373     *p++ = OSSL_PARAM_construct_end();
374
375     ret = evp_pkey_ctx_set_params_strict(ctx, params);
376     if (ret == -2) {
377         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
378         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
379         return -2;
380     }
381     if (ret == 1)
382         OPENSSL_free(ukm);
383     return ret;
384 }
385
386 int EVP_PKEY_CTX_get0_ecdh_kdf_ukm(EVP_PKEY_CTX *ctx, unsigned char **pukm)
387 {
388     size_t ukmlen;
389     int ret;
390     OSSL_PARAM params[3], *p = params;
391
392     ret = evp_pkey_ctx_getset_ecdh_param_checks(ctx);
393     if (ret != 1)
394         return ret;
395
396     /* TODO(3.0): Remove this eventually when no more legacy */
397     if (ctx->op.kex.exchprovctx == NULL)
398         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
399                                  EVP_PKEY_OP_DERIVE,
400                                  EVP_PKEY_CTRL_GET_EC_KDF_UKM, 0,
401                                  (void *)(pukm));
402
403     *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_EXCHANGE_PARAM_KDF_UKM,
404                                           (void **)pukm, 0);
405     *p++ = OSSL_PARAM_construct_size_t(OSSL_EXCHANGE_PARAM_KDF_UKM_LEN,
406                                        &ukmlen);
407     *p++ = OSSL_PARAM_construct_end();
408
409     ret = evp_pkey_ctx_get_params_strict(ctx, params);
410     if (ret == -2) {
411         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
412         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
413         return -2;
414     } else if (ret != 1) {
415         return -1;
416     }
417
418     if (ukmlen > INT_MAX)
419         return -1;
420
421     return (int)ukmlen;
422 }
423
424 int EVP_PKEY_CTX_set_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
425                                             const char *name)
426 {
427     OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
428     OSSL_PARAM *p = params;
429
430     if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
431         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
432         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
433         return -2;
434     }
435
436     if (name == NULL)
437         return -1;
438
439     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
440                                             (char *)name, 0);
441     return EVP_PKEY_CTX_set_params(ctx, params);
442 }
443
444 int EVP_PKEY_CTX_get_ec_paramgen_curve_name(EVP_PKEY_CTX *ctx,
445                                             char *name, size_t namelen)
446 {
447     OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
448     OSSL_PARAM *p = params;
449
450     if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
451         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
452         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
453         return -2;
454     }
455
456     if (name == NULL)
457         return -1;
458
459     *p++ = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_EC_NAME,
460                                             name, namelen);
461     if (!EVP_PKEY_CTX_get_params(ctx, params))
462         return -1;
463     return 1;
464 }
465
466 #ifndef FIPS_MODULE
467 int EVP_PKEY_CTX_set_ec_paramgen_curve_nid(EVP_PKEY_CTX *ctx, int nid)
468 {
469     if (ctx == NULL || !EVP_PKEY_CTX_IS_GEN_OP(ctx)) {
470         ERR_raise(ERR_LIB_EVP, EVP_R_COMMAND_NOT_SUPPORTED);
471         /* Uses the same return values as EVP_PKEY_CTX_ctrl */
472         return -2;
473     }
474
475     /* Legacy: if key type not EC return error */
476     if (ctx->pmeth != NULL
477         && EVP_PKEY_type(ctx->pmeth->pkey_id) != EVP_PKEY_EC)
478         return -1;
479
480     if (ctx->op.keymgmt.genctx == NULL)
481         return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_EC,
482                                  EVP_PKEY_OP_PARAMGEN|EVP_PKEY_OP_KEYGEN,
483                                  EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID,
484                                  nid, NULL);
485
486     return EVP_PKEY_CTX_set_ec_paramgen_curve_name(ctx, OBJ_nid2sn(nid));
487 }
488 #endif