]> git.ipfire.org Git - thirdparty/openssl.git/blame - providers/implementations/signature/dsa.c
PROV: Ensure the AlgorithmIdentifier registers in DSA signature impl
[thirdparty/openssl.git] / providers / implementations / signature / dsa.c
CommitLineData
4889dadc
MC
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
505b41fc
RL
10#include <string.h>
11
4889dadc
MC
12#include <openssl/crypto.h>
13#include <openssl/core_numbers.h>
14#include <openssl/core_names.h>
505b41fc 15#include <openssl/err.h>
4889dadc
MC
16#include <openssl/dsa.h>
17#include <openssl/params.h>
45a845e4 18#include <openssl/evp.h>
8bee6512 19#include <openssl/err.h>
505b41fc 20#include "internal/nelem.h"
c24937d5 21#include "internal/sizes.h"
505b41fc 22#include "prov/providercommonerr.h"
af3e7e1b 23#include "prov/implementations.h"
8bee6512 24#include "prov/providercommonerr.h"
ddd21319 25#include "prov/provider_ctx.h"
e683582b 26#include "crypto/dsa.h"
4889dadc
MC
27
28static OSSL_OP_signature_newctx_fn dsa_newctx;
390acbeb
MC
29static OSSL_OP_signature_sign_init_fn dsa_signature_init;
30static OSSL_OP_signature_verify_init_fn dsa_signature_init;
4889dadc 31static OSSL_OP_signature_sign_fn dsa_sign;
45a845e4
MC
32static OSSL_OP_signature_verify_fn dsa_verify;
33static OSSL_OP_signature_digest_sign_init_fn dsa_digest_signverify_init;
34static OSSL_OP_signature_digest_sign_update_fn dsa_digest_signverify_update;
35static OSSL_OP_signature_digest_sign_final_fn dsa_digest_sign_final;
36static OSSL_OP_signature_digest_verify_init_fn dsa_digest_signverify_init;
37static OSSL_OP_signature_digest_verify_update_fn dsa_digest_signverify_update;
38static OSSL_OP_signature_digest_verify_final_fn dsa_digest_verify_final;
4889dadc
MC
39static OSSL_OP_signature_freectx_fn dsa_freectx;
40static OSSL_OP_signature_dupctx_fn dsa_dupctx;
9c45222d
MC
41static OSSL_OP_signature_get_ctx_params_fn dsa_get_ctx_params;
42static OSSL_OP_signature_gettable_ctx_params_fn dsa_gettable_ctx_params;
43static OSSL_OP_signature_set_ctx_params_fn dsa_set_ctx_params;
44static OSSL_OP_signature_settable_ctx_params_fn dsa_settable_ctx_params;
45a845e4
MC
45static OSSL_OP_signature_get_ctx_md_params_fn dsa_get_ctx_md_params;
46static OSSL_OP_signature_gettable_ctx_md_params_fn dsa_gettable_ctx_md_params;
47static OSSL_OP_signature_set_ctx_md_params_fn dsa_set_ctx_md_params;
48static OSSL_OP_signature_settable_ctx_md_params_fn dsa_settable_ctx_md_params;
4889dadc
MC
49
50/*
51 * What's passed as an actual key is defined by the KEYMGMT interface.
52 * We happen to know that our KEYMGMT simply passes DSA structures, so
53 * we use that here too.
54 */
55
56typedef struct {
45a845e4 57 OPENSSL_CTX *libctx;
4889dadc 58 DSA *dsa;
8bee6512
RL
59
60 /*
61 * Flag to determine if the hash function can be changed (1) or not (0)
62 * Because it's dangerous to change during a DigestSign or DigestVerify
63 * operation, this flag is cleared by their Init function, and set again
64 * by their Final function.
65 */
66 unsigned int flag_allow_md : 1;
67
c24937d5 68 char mdname[OSSL_MAX_NAME_SIZE];
505b41fc
RL
69
70 /* The Algorithm Identifier of the combined signature agorithm */
71 unsigned char aid[OSSL_MAX_ALGORITHM_ID_SIZE];
72 size_t aid_len;
73
74 /* main digest */
45a845e4
MC
75 EVP_MD *md;
76 EVP_MD_CTX *mdctx;
8bee6512 77 size_t mdsize;
4889dadc
MC
78} PROV_DSA_CTX;
79
8bee6512
RL
80static size_t dsa_get_md_size(const PROV_DSA_CTX *pdsactx)
81{
82 if (pdsactx->md != NULL)
83 return EVP_MD_size(pdsactx->md);
84 return 0;
85}
86
87static int dsa_get_md_nid(const EVP_MD *md)
88{
89 /*
90 * Because the DSA library deals with NIDs, we need to translate.
91 * We do so using EVP_MD_is_a(), and therefore need a name to NID
92 * map.
93 */
94 static const OSSL_ITEM name_to_nid[] = {
95 { NID_sha1, OSSL_DIGEST_NAME_SHA1 },
96 { NID_sha224, OSSL_DIGEST_NAME_SHA2_224 },
97 { NID_sha256, OSSL_DIGEST_NAME_SHA2_256 },
98 { NID_sha384, OSSL_DIGEST_NAME_SHA2_384 },
99 { NID_sha512, OSSL_DIGEST_NAME_SHA2_512 },
100 { NID_sha3_224, OSSL_DIGEST_NAME_SHA3_224 },
101 { NID_sha3_256, OSSL_DIGEST_NAME_SHA3_256 },
102 { NID_sha3_384, OSSL_DIGEST_NAME_SHA3_384 },
103 { NID_sha3_512, OSSL_DIGEST_NAME_SHA3_512 },
104 };
105 size_t i;
106 int mdnid = NID_undef;
107
108 if (md == NULL)
109 goto end;
110
111 for (i = 0; i < OSSL_NELEM(name_to_nid); i++) {
112 if (EVP_MD_is_a(md, name_to_nid[i].ptr)) {
113 mdnid = (int)name_to_nid[i].id;
114 break;
115 }
116 }
117
118 if (mdnid == NID_undef)
119 ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST);
120
121 end:
122 return mdnid;
123}
124
4889dadc
MC
125static void *dsa_newctx(void *provctx)
126{
45a845e4
MC
127 PROV_DSA_CTX *pdsactx = OPENSSL_zalloc(sizeof(PROV_DSA_CTX));
128
129 if (pdsactx == NULL)
130 return NULL;
131
132 pdsactx->libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
8bee6512 133 pdsactx->flag_allow_md = 1;
45a845e4 134 return pdsactx;
4889dadc
MC
135}
136
8bee6512
RL
137static int dsa_setup_md(PROV_DSA_CTX *ctx,
138 const char *mdname, const char *mdprops)
139{
140 if (mdname != NULL) {
141 EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
142 int md_nid = dsa_get_md_nid(md);
143 size_t algorithmidentifier_len = 0;
144 const unsigned char *algorithmidentifier;
145
146 EVP_MD_free(ctx->md);
147 ctx->md = NULL;
148 ctx->mdname[0] = '\0';
149
150 algorithmidentifier =
151 dsa_algorithmidentifier_encoding(md_nid, &algorithmidentifier_len);
152
153 if (algorithmidentifier == NULL) {
154 EVP_MD_free(md);
155 return 0;
156 }
157
158 ctx->md = md;
159 OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
b0593c08
RL
160 memcpy(ctx->aid, algorithmidentifier, algorithmidentifier_len);
161 ctx->aid_len = algorithmidentifier_len;
8bee6512
RL
162 }
163 return 1;
164}
165
390acbeb 166static int dsa_signature_init(void *vpdsactx, void *vdsa)
4889dadc
MC
167{
168 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
169
170 if (pdsactx == NULL || vdsa == NULL || !DSA_up_ref(vdsa))
171 return 0;
172 DSA_free(pdsactx->dsa);
173 pdsactx->dsa = vdsa;
174 return 1;
175}
176
177static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen,
178 size_t sigsize, const unsigned char *tbs, size_t tbslen)
179{
180 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
181 int ret;
182 unsigned int sltmp;
183 size_t dsasize = DSA_size(pdsactx->dsa);
8bee6512 184 size_t mdsize = dsa_get_md_size(pdsactx);
4889dadc
MC
185
186 if (sig == NULL) {
187 *siglen = dsasize;
188 return 1;
189 }
190
191 if (sigsize < (size_t)dsasize)
192 return 0;
193
8bee6512 194 if (mdsize != 0 && tbslen != mdsize)
4889dadc
MC
195 return 0;
196
e683582b
SL
197 ret = dsa_sign_int(pdsactx->libctx, 0, tbs, tbslen, sig, &sltmp,
198 pdsactx->dsa);
4889dadc
MC
199 if (ret <= 0)
200 return 0;
201
202 *siglen = sltmp;
203 return 1;
204}
205
390acbeb
MC
206static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen,
207 const unsigned char *tbs, size_t tbslen)
208{
209 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
8bee6512 210 size_t mdsize = dsa_get_md_size(pdsactx);
390acbeb 211
8bee6512 212 if (mdsize != 0 && tbslen != mdsize)
390acbeb
MC
213 return 0;
214
215 return DSA_verify(0, tbs, tbslen, sig, siglen, pdsactx->dsa);
216}
217
45a845e4
MC
218static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname,
219 const char *props, void *vdsa)
220{
221 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
45a845e4 222
8bee6512 223 pdsactx->flag_allow_md = 0;
45a845e4
MC
224 if (!dsa_signature_init(vpdsactx, vdsa))
225 return 0;
226
8bee6512
RL
227 if (!dsa_setup_md(pdsactx, mdname, props))
228 return 0;
505b41fc 229
45a845e4
MC
230 pdsactx->mdctx = EVP_MD_CTX_new();
231 if (pdsactx->mdctx == NULL)
505b41fc 232 goto error;
45a845e4 233
505b41fc
RL
234 if (!EVP_DigestInit_ex(pdsactx->mdctx, pdsactx->md, NULL))
235 goto error;
45a845e4
MC
236
237 return 1;
505b41fc
RL
238
239 error:
240 EVP_MD_CTX_free(pdsactx->mdctx);
241 EVP_MD_free(pdsactx->md);
242 pdsactx->mdctx = NULL;
505b41fc
RL
243 pdsactx->md = NULL;
244 return 0;
45a845e4
MC
245}
246
247int dsa_digest_signverify_update(void *vpdsactx, const unsigned char *data,
248 size_t datalen)
249{
250 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
251
252 if (pdsactx == NULL || pdsactx->mdctx == NULL)
253 return 0;
254
255 return EVP_DigestUpdate(pdsactx->mdctx, data, datalen);
256}
257
258int dsa_digest_sign_final(void *vpdsactx, unsigned char *sig, size_t *siglen,
259 size_t sigsize)
260{
261 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
262 unsigned char digest[EVP_MAX_MD_SIZE];
263 unsigned int dlen = 0;
264
265 if (pdsactx == NULL || pdsactx->mdctx == NULL)
266 return 0;
267
268 /*
269 * If sig is NULL then we're just finding out the sig size. Other fields
270 * are ignored. Defer to dsa_sign.
271 */
272 if (sig != NULL) {
273 /*
274 * TODO(3.0): There is the possibility that some externally provided
275 * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
276 * but that problem is much larger than just in DSA.
277 */
278 if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen))
279 return 0;
280 }
281
8bee6512
RL
282 pdsactx->flag_allow_md = 1;
283
45a845e4
MC
284 return dsa_sign(vpdsactx, sig, siglen, sigsize, digest, (size_t)dlen);
285}
286
287
288int dsa_digest_verify_final(void *vpdsactx, const unsigned char *sig,
289 size_t siglen)
290{
291 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
292 unsigned char digest[EVP_MAX_MD_SIZE];
293 unsigned int dlen = 0;
294
295 if (pdsactx == NULL || pdsactx->mdctx == NULL)
296 return 0;
297
298 /*
299 * TODO(3.0): There is the possibility that some externally provided
300 * digests exceed EVP_MAX_MD_SIZE. We should probably handle that somehow -
301 * but that problem is much larger than just in DSA.
302 */
303 if (!EVP_DigestFinal_ex(pdsactx->mdctx, digest, &dlen))
304 return 0;
305
8bee6512
RL
306 pdsactx->flag_allow_md = 1;
307
45a845e4
MC
308 return dsa_verify(vpdsactx, sig, siglen, digest, (size_t)dlen);
309}
390acbeb 310
4889dadc
MC
311static void dsa_freectx(void *vpdsactx)
312{
313 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
314
315 DSA_free(pdsactx->dsa);
45a845e4
MC
316 EVP_MD_CTX_free(pdsactx->mdctx);
317 EVP_MD_free(pdsactx->md);
4889dadc
MC
318
319 OPENSSL_free(pdsactx);
320}
321
322static void *dsa_dupctx(void *vpdsactx)
323{
324 PROV_DSA_CTX *srcctx = (PROV_DSA_CTX *)vpdsactx;
325 PROV_DSA_CTX *dstctx;
326
327 dstctx = OPENSSL_zalloc(sizeof(*srcctx));
328 if (dstctx == NULL)
329 return NULL;
330
331 *dstctx = *srcctx;
45a845e4
MC
332 dstctx->dsa = NULL;
333 dstctx->md = NULL;
334 dstctx->mdctx = NULL;
335
336 if (srcctx->dsa != NULL && !DSA_up_ref(srcctx->dsa))
337 goto err;
338 dstctx->dsa = srcctx->dsa;
339
340 if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
341 goto err;
342 dstctx->md = srcctx->md;
343
344 if (srcctx->mdctx != NULL) {
345 dstctx->mdctx = EVP_MD_CTX_new();
346 if (dstctx->mdctx == NULL
347 || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
348 goto err;
4889dadc
MC
349 }
350
351 return dstctx;
45a845e4
MC
352 err:
353 dsa_freectx(dstctx);
354 return NULL;
4889dadc
MC
355}
356
9c45222d
MC
357static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params)
358{
359 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
360 OSSL_PARAM *p;
361
362 if (pdsactx == NULL || params == NULL)
363 return 0;
364
505b41fc
RL
365 p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
366 if (p != NULL
367 && !OSSL_PARAM_set_octet_string(p, pdsactx->aid, pdsactx->aid_len))
368 return 0;
369
9c45222d 370 p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
8bee6512 371 if (p != NULL && !OSSL_PARAM_set_utf8_string(p, pdsactx->mdname))
9c45222d
MC
372 return 0;
373
374 return 1;
375}
376
377static const OSSL_PARAM known_gettable_ctx_params[] = {
505b41fc 378 OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
9c45222d
MC
379 OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
380 OSSL_PARAM_END
381};
382
383static const OSSL_PARAM *dsa_gettable_ctx_params(void)
384{
385 return known_gettable_ctx_params;
386}
387
388static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[])
4889dadc
MC
389{
390 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
391 const OSSL_PARAM *p;
4889dadc
MC
392
393 if (pdsactx == NULL || params == NULL)
394 return 0;
395
9c45222d 396 p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
8bee6512
RL
397 /* Not allowed during certain operations */
398 if (p != NULL && !pdsactx->flag_allow_md)
9c45222d 399 return 0;
8bee6512
RL
400 if (p != NULL) {
401 char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
402 char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
403 const OSSL_PARAM *propsp =
404 OSSL_PARAM_locate_const(params,
405 OSSL_SIGNATURE_PARAM_PROPERTIES);
406
407 if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
408 return 0;
409 if (propsp != NULL
410 && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
411 return 0;
412 if (!dsa_setup_md(pdsactx, mdname, mdprops))
413 return 0;
414 }
4889dadc
MC
415
416 return 1;
417}
418
9c45222d 419static const OSSL_PARAM known_settable_ctx_params[] = {
9c45222d
MC
420 OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
421 OSSL_PARAM_END
422};
423
424static const OSSL_PARAM *dsa_settable_ctx_params(void)
425{
45a845e4
MC
426 /*
427 * TODO(3.0): Should this function return a different set of settable ctx
428 * params if the ctx is being used for a DigestSign/DigestVerify? In that
429 * case it is not allowed to set the digest size/digest name because the
430 * digest is explicitly set as part of the init.
431 */
9c45222d
MC
432 return known_settable_ctx_params;
433}
434
45a845e4
MC
435static int dsa_get_ctx_md_params(void *vpdsactx, OSSL_PARAM *params)
436{
437 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
438
439 if (pdsactx->mdctx == NULL)
440 return 0;
441
442 return EVP_MD_CTX_get_params(pdsactx->mdctx, params);
443}
444
445static const OSSL_PARAM *dsa_gettable_ctx_md_params(void *vpdsactx)
446{
447 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
448
449 if (pdsactx->md == NULL)
450 return 0;
451
452 return EVP_MD_gettable_ctx_params(pdsactx->md);
453}
454
455static int dsa_set_ctx_md_params(void *vpdsactx, const OSSL_PARAM params[])
456{
457 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
458
459 if (pdsactx->mdctx == NULL)
460 return 0;
461
462 return EVP_MD_CTX_set_params(pdsactx->mdctx, params);
463}
464
465static const OSSL_PARAM *dsa_settable_ctx_md_params(void *vpdsactx)
466{
467 PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx;
468
469 if (pdsactx->md == NULL)
470 return 0;
471
472 return EVP_MD_settable_ctx_params(pdsactx->md);
473}
474
4889dadc
MC
475const OSSL_DISPATCH dsa_signature_functions[] = {
476 { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))dsa_newctx },
390acbeb 477 { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))dsa_signature_init },
4889dadc 478 { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))dsa_sign },
390acbeb
MC
479 { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))dsa_signature_init },
480 { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))dsa_verify },
45a845e4
MC
481 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
482 (void (*)(void))dsa_digest_signverify_init },
483 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
484 (void (*)(void))dsa_digest_signverify_update },
485 { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
486 (void (*)(void))dsa_digest_sign_final },
487 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
488 (void (*)(void))dsa_digest_signverify_init },
489 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
490 (void (*)(void))dsa_digest_signverify_update },
491 { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
492 (void (*)(void))dsa_digest_verify_final },
4889dadc
MC
493 { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))dsa_freectx },
494 { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))dsa_dupctx },
9c45222d
MC
495 { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))dsa_get_ctx_params },
496 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
497 (void (*)(void))dsa_gettable_ctx_params },
498 { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))dsa_set_ctx_params },
499 { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
500 (void (*)(void))dsa_settable_ctx_params },
45a845e4
MC
501 { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
502 (void (*)(void))dsa_get_ctx_md_params },
503 { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
504 (void (*)(void))dsa_gettable_ctx_md_params },
505 { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
506 (void (*)(void))dsa_set_ctx_md_params },
507 { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
508 (void (*)(void))dsa_settable_ctx_md_params },
4889dadc
MC
509 { 0, NULL }
510};