]> git.ipfire.org Git - thirdparty/openssl.git/blame - providers/implementations/signature/ecdsa.c
Add ECDSA to providers
[thirdparty/openssl.git] / providers / implementations / signature / ecdsa.c
CommitLineData
edd3b7a3
SL
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/*
11 * 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 <string.h> /* memcpy */
17#include <openssl/crypto.h>
18#include <openssl/core_numbers.h>
19#include <openssl/core_names.h>
20#include <openssl/dsa.h>
21#include <openssl/params.h>
22#include <openssl/evp.h>
23#include <openssl/err.h>
24#include "internal/nelem.h"
25#include "internal/sizes.h"
26#include "prov/providercommonerr.h"
27#include "prov/implementations.h"
28#include "prov/provider_ctx.h"
29#include "crypto/ec.h"
30
31static OSSL_OP_signature_newctx_fn ecdsa_newctx;
32static OSSL_OP_signature_sign_init_fn ecdsa_signature_init;
33static OSSL_OP_signature_verify_init_fn ecdsa_signature_init;
34static OSSL_OP_signature_sign_fn ecdsa_sign;
35static OSSL_OP_signature_verify_fn ecdsa_verify;
36static OSSL_OP_signature_digest_sign_init_fn ecdsa_digest_signverify_init;
37static OSSL_OP_signature_digest_sign_update_fn ecdsa_digest_signverify_update;
38static OSSL_OP_signature_digest_sign_final_fn ecdsa_digest_sign_final;
39static OSSL_OP_signature_digest_verify_init_fn ecdsa_digest_signverify_init;
40static OSSL_OP_signature_digest_verify_update_fn ecdsa_digest_signverify_update;
41static OSSL_OP_signature_digest_verify_final_fn ecdsa_digest_verify_final;
42static OSSL_OP_signature_freectx_fn ecdsa_freectx;
43static OSSL_OP_signature_dupctx_fn ecdsa_dupctx;
44static OSSL_OP_signature_get_ctx_params_fn ecdsa_get_ctx_params;
45static OSSL_OP_signature_gettable_ctx_params_fn ecdsa_gettable_ctx_params;
46static OSSL_OP_signature_set_ctx_params_fn ecdsa_set_ctx_params;
47static OSSL_OP_signature_settable_ctx_params_fn ecdsa_settable_ctx_params;
48static OSSL_OP_signature_get_ctx_md_params_fn ecdsa_get_ctx_md_params;
49static OSSL_OP_signature_gettable_ctx_md_params_fn ecdsa_gettable_ctx_md_params;
50static OSSL_OP_signature_set_ctx_md_params_fn ecdsa_set_ctx_md_params;
51static OSSL_OP_signature_settable_ctx_md_params_fn ecdsa_settable_ctx_md_params;
52
53/*
54 * What's passed as an actual key is defined by the KEYMGMT interface.
55 * We happen to know that our KEYMGMT simply passes DSA structures, so
56 * we use that here too.
57 */
58
59typedef struct {
60 OPENSSL_CTX *libctx;
61 EC_KEY *ec;
62 char mdname[OSSL_MAX_NAME_SIZE];
63
64 /* The Algorithm Identifier of the combined signature algorithm */
65 unsigned char aid[OSSL_MAX_ALGORITHM_ID_SIZE];
66 size_t aid_len;
67 size_t mdsize;
68
69 EVP_MD *md;
70 EVP_MD_CTX *mdctx;
71 /*
72 * This indicates that KAT (CAVS) test is running. Externally an app will
73 * override the random callback such that the generated private key and k
74 * are known.
75 * Normal operation will loop to choose a new k if the signature is not
76 * valid - but for this mode of operation it forces a failure instead.
77 */
78 unsigned int kattest;
79 /*
80 * Internally used to cache the results of calling the EC group
81 * sign_setup() methods which are then passed to the sign operation.
82 * This is used by CAVS failure tests to terminate a loop if the signature
83 * is not valid.
84 * This could of also been done with a simple flag.
85 */
86 BIGNUM *kinv;
87 BIGNUM *r;
88} PROV_ECDSA_CTX;
89
90static void *ecdsa_newctx(void *provctx)
91{
92 PROV_ECDSA_CTX *ctx = OPENSSL_zalloc(sizeof(PROV_ECDSA_CTX));
93
94 if (ctx == NULL)
95 return NULL;
96
97 ctx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
98 return ctx;
99}
100
101static int ecdsa_signature_init(void *vctx, void *ec)
102{
103 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
104
105 if (ctx == NULL || ec == NULL || !EC_KEY_up_ref(ec))
106 return 0;
107 EC_KEY_free(ctx->ec);
108 ctx->ec = ec;
109 return 1;
110}
111
112static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen,
113 size_t sigsize, const unsigned char *tbs, size_t tbslen)
114{
115 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
116 int ret;
117 unsigned int sltmp;
118 size_t ecsize = ECDSA_size(ctx->ec);
119
120 if (sig == NULL) {
121 *siglen = ecsize;
122 return 1;
123 }
124
125 if (ctx->kattest && !ECDSA_sign_setup(ctx->ec, NULL, &ctx->kinv, &ctx->r))
126 return 0;
127
128 if (sigsize < (size_t)ecsize)
129 return 0;
130
131 if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
132 return 0;
133
134 ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &sltmp, ctx->kinv, ctx->r, ctx->ec);
135 if (ret <= 0)
136 return 0;
137
138 *siglen = sltmp;
139 return 1;
140}
141
142static int ecdsa_verify(void *vctx, const unsigned char *sig, size_t siglen,
143 const unsigned char *tbs, size_t tbslen)
144{
145 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
146
147 if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
148 return 0;
149
150 return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->ec);
151}
152
153static int get_md_nid(const EVP_MD *md)
154{
155 /*
156 * Because the ECDSA library deals with NIDs, we need to translate.
157 * We do so using EVP_MD_is_a(), and therefore need a name to NID
158 * map.
159 */
160 static const OSSL_ITEM name_to_nid[] = {
161 { NID_sha1, OSSL_DIGEST_NAME_SHA1 },
162 { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
163 { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
164 { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
165 { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
166 { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
167 { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
168 { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
169 { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
170 /* TODO - Add SHAKE OIDS when they are standardized */
171
172 };
173 size_t i;
174 int mdnid = NID_undef;
175
176 if (md == NULL)
177 goto end;
178
179 for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
180 if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
181 mdnid = (int)name_to_nid[i].id;
182 break;
183 }
184 }
185
186 if (mdnid == NID_undef)
187 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
188
189 end:
190 return mdnid;
191}
192
193static void free_md(PROV_ECDSA_CTX *ctx)
194{
195 EVP_MD_CTX_free(ctx->mdctx);
196 EVP_MD_free(ctx->md);
197 ctx->mdctx = NULL;
198 ctx->md = NULL;
199 ctx->mdsize = 0;
200}
201
202static int ecdsa_digest_signverify_init(void *vctx, const char *mdname,
203 const char *props, void *ec)
204{
205 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
206 size_t algorithmidentifier_len = 0;
207 const unsigned char *algorithmidentifier;
208
209 free_md(ctx);
210
211 if (!ecdsa_signature_init(vctx, ec))
212 return 0;
213
214 ctx->md = EVP_MD_fetch(ctx->libctx, mdname, props);
215 algorithmidentifier =
216 ecdsa_algorithmidentifier_encoding(get_md_nid(ctx->md),
217 &algorithmidentifier_len);
218 if (algorithmidentifier == NULL)
219 goto error;
220
221 ctx->mdsize = EVP_MD_size(ctx->md);
222 ctx->mdctx = EVP_MD_CTX_new();
223 if (ctx->mdctx == NULL)
224 goto error;
225
226 memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len);
227 ctx->aid_len = algorithmidentifier_len;
228
229 if (!EVP_DigestInit_ex(ctx->mdctx, ctx->md, NULL))
230 goto error;
231 return 1;
232error:
233 free_md(ctx);
234 return 0;
235}
236
237int ecdsa_digest_signverify_update(void *vctx, const unsigned char *data,
238 size_t datalen)
239{
240 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
241
242 if (ctx == NULL || ctx->mdctx == NULL)
243 return 0;
244
245 return EVP_DigestUpdate(ctx->mdctx, data, datalen);
246}
247
248int ecdsa_digest_sign_final(void *vctx, unsigned char *sig, size_t *siglen,
249 size_t sigsize)
250{
251 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
252 unsigned char digest[EVP_MAX_MD_SIZE];
253 unsigned int dlen = 0;
254
255 if (ctx == NULL || ctx->mdctx == NULL)
256 return 0;
257
258 /*
259 * If sig is NULL then we're just finding out the sig size. Other fields
260 * are ignored. Defer to ecdsa_sign.
261 */
262 if (sig != NULL) {
263 /*
264 * TODO(3.0): There is the possibility that some externally provided
265 * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
266 * but that problem is much larger than just in DSA.
267 */
268 if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
269 return 0;
270 }
271
272 return ecdsa_sign(vctx, sig, siglen, sigsize, digest, (size_t)dlen);
273}
274
275int ecdsa_digest_verify_final(void *vctx, const unsigned char *sig,
276 size_t siglen)
277{
278 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
279 unsigned char digest[EVP_MAX_MD_SIZE];
280 unsigned int dlen = 0;
281
282 if (ctx == NULL || ctx->mdctx == NULL)
283 return 0;
284
285 /*
286 * TODO(3.0): There is the possibility that some externally provided
287 * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
288 * but that problem is much larger than just in DSA.
289 */
290 if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
291 return 0;
292
293 return ecdsa_verify(ctx, sig, siglen, digest, (size_t)dlen);
294}
295
296static void ecdsa_freectx(void *vctx)
297{
298 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
299
300 free_md(ctx);
301 EC_KEY_free(ctx->ec);
302 BN_clear_free(ctx->kinv);
303 BN_clear_free(ctx->r);
304 OPENSSL_free(ctx);
305}
306
307static void *ecdsa_dupctx(void *vctx)
308{
309 PROV_ECDSA_CTX *srcctx = (PROV_ECDSA_CTX *)vctx;
310 PROV_ECDSA_CTX *dstctx;
311
312 dstctx = OPENSSL_zalloc(sizeof(*srcctx));
313 if (dstctx == NULL)
314 return NULL;
315
316 *dstctx = *srcctx;
317 dstctx->ec = NULL;
318 dstctx->md = NULL;
319 dstctx->mdctx = NULL;
320
321 if (srcctx->ec != NULL && !EC_KEY_up_ref(srcctx->ec))
322 goto err;
323 /* Test KATS should not need to be supported */
324 if (srcctx->kinv != NULL || srcctx->r != NULL)
325 goto err;
326 dstctx->ec = srcctx->ec;
327
328 if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
329 goto err;
330 dstctx->md = srcctx->md;
331
332 if (srcctx->mdctx != NULL) {
333 dstctx->mdctx = EVP_MD_CTX_new();
334 if (dstctx->mdctx == NULL
335 || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
336 goto err;
337 }
338
339 return dstctx;
340 err:
341 ecdsa_freectx(dstctx);
342 return NULL;
343}
344
345static int ecdsa_get_ctx_params(void *vctx, OSSL_PARAM *params)
346{
347 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
348 OSSL_PARAM *p;
349
350 if (ctx == NULL || params == NULL)
351 return 0;
352
353 p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
354 if (p != NULL && !OSSL_PARAM_set_octet_string(p, ctx->aid, ctx->aid_len))
355 return 0;
356
357 p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
358 if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->mdsize))
359 return 0;
360
361 p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
362 if (p != NULL && !OSSL_PARAM_set_utf8_string(p, ctx->md == NULL
363 ? ctx->mdname
364 : EVP_MD_name(ctx->md)))
365 return 0;
366
367 return 1;
368}
369
370static const OSSL_PARAM known_gettable_ctx_params[] = {
371 OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
372 OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
373 OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
374 OSSL_PARAM_END
375};
376
377static const OSSL_PARAM *ecdsa_gettable_ctx_params(void)
378{
379 return known_gettable_ctx_params;
380}
381
382static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
383{
384 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
385 const OSSL_PARAM *p;
386 char *mdname;
387
388 if (ctx == NULL || params == NULL)
389 return 0;
390
391 if (ctx->md != NULL) {
392 /*
393 * You cannot set the digest name/size when doing a DigestSign or
394 * DigestVerify.
395 */
396 return 1;
397 }
398
399 p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT);
400 if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->kattest))
401 return 0;
402
403 p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
404 if (p != NULL && !OSSL_PARAM_get_size_t(p, &ctx->mdsize))
405 return 0;
406
407 /*
408 * We never actually use the mdname, but we do support getting it later.
409 * This can be useful for applications that want to know the MD that they
410 * previously set.
411 */
412 p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
413 mdname = ctx->mdname;
414 if (p != NULL
415 && !OSSL_PARAM_get_utf8_string(p, &mdname, sizeof(ctx->mdname)))
416 return 0;
417
418 return 1;
419}
420
421static const OSSL_PARAM known_settable_ctx_params[] = {
422 OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
423 OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
424 OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL),
425 OSSL_PARAM_END
426};
427
428static const OSSL_PARAM *ecdsa_settable_ctx_params(void)
429{
430 /*
431 * TODO(3.0): Should this function return a different set of settable ctx
432 * params if the ctx is being used for a DigestSign/DigestVerify? In that
433 * case it is not allowed to set the digest size/digest name because the
434 * digest is explicitly set as part of the init.
435 */
436 return known_settable_ctx_params;
437}
438
439static int ecdsa_get_ctx_md_params(void *vctx, OSSL_PARAM *params)
440{
441 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
442
443 if (ctx->mdctx == NULL)
444 return 0;
445
446 return EVP_MD_CTX_get_params(ctx->mdctx, params);
447}
448
449static const OSSL_PARAM *ecdsa_gettable_ctx_md_params(void *vctx)
450{
451 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
452
453 if (ctx->md == NULL)
454 return 0;
455
456 return EVP_MD_gettable_ctx_params(ctx->md);
457}
458
459static int ecdsa_set_ctx_md_params(void *vctx, const OSSL_PARAM params[])
460{
461 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
462
463 if (ctx->mdctx == NULL)
464 return 0;
465
466 return EVP_MD_CTX_set_params(ctx->mdctx, params);
467}
468
469static const OSSL_PARAM *ecdsa_settable_ctx_md_params(void *vctx)
470{
471 PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
472
473 if (ctx->md == NULL)
474 return 0;
475
476 return EVP_MD_settable_ctx_params(ctx->md);
477}
478
479const OSSL_DISPATCH ecdsa_signature_functions[] = {
480 { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ecdsa_newctx },
481 { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))ecdsa_signature_init },
482 { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ecdsa_sign },
483 { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))ecdsa_signature_init },
484 { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ecdsa_verify },
485 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
486 (void (*)(void))ecdsa_digest_signverify_init },
487 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
488 (void (*)(void))ecdsa_digest_signverify_update },
489 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
490 (void (*)(void))ecdsa_digest_sign_final },
491 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
492 (void (*)(void))ecdsa_digest_signverify_init },
493 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
494 (void (*)(void))ecdsa_digest_signverify_update },
495 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
496 (void (*)(void))ecdsa_digest_verify_final },
497 { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ecdsa_freectx },
498 { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ecdsa_dupctx },
499 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))ecdsa_get_ctx_params },
500 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
501 (void (*)(void))ecdsa_gettable_ctx_params },
502 { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))ecdsa_set_ctx_params },
503 { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
504 (void (*)(void))ecdsa_settable_ctx_params },
505 { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
506 (void (*)(void))ecdsa_get_ctx_md_params },
507 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
508 (void (*)(void))ecdsa_gettable_ctx_md_params },
509 { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
510 (void (*)(void))ecdsa_set_ctx_md_params },
511 { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
512 (void (*)(void))ecdsa_settable_ctx_md_params },
513 { 0, NULL }
514};