xref: /freebsd/crypto/openssl/providers/implementations/signature/ecdsa_sig.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1b077aed3SPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2020-2025 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery  *
4b077aed3SPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5b077aed3SPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6b077aed3SPierre Pronchery  * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery  * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery  */
9b077aed3SPierre Pronchery 
10b077aed3SPierre Pronchery /*
11b077aed3SPierre Pronchery  * ECDSA low level APIs are deprecated for public use, but still ok for
12b077aed3SPierre Pronchery  * internal use.
13b077aed3SPierre Pronchery  */
14b077aed3SPierre Pronchery #include "internal/deprecated.h"
15b077aed3SPierre Pronchery 
16b077aed3SPierre Pronchery #include <string.h> /* memcpy */
17b077aed3SPierre Pronchery #include <openssl/crypto.h>
18b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
19b077aed3SPierre Pronchery #include <openssl/core_names.h>
20b077aed3SPierre Pronchery #include <openssl/dsa.h>
21b077aed3SPierre Pronchery #include <openssl/params.h>
22b077aed3SPierre Pronchery #include <openssl/evp.h>
23b077aed3SPierre Pronchery #include <openssl/err.h>
24b077aed3SPierre Pronchery #include <openssl/proverr.h>
25b077aed3SPierre Pronchery #include "internal/nelem.h"
26b077aed3SPierre Pronchery #include "internal/sizes.h"
27b077aed3SPierre Pronchery #include "internal/cryptlib.h"
28*e7be843bSPierre Pronchery #include "internal/deterministic_nonce.h"
29b077aed3SPierre Pronchery #include "prov/providercommon.h"
30b077aed3SPierre Pronchery #include "prov/implementations.h"
31b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
32b077aed3SPierre Pronchery #include "prov/securitycheck.h"
33b077aed3SPierre Pronchery #include "prov/der_ec.h"
34*e7be843bSPierre Pronchery #include "crypto/ec.h"
35b077aed3SPierre Pronchery 
36b077aed3SPierre Pronchery static OSSL_FUNC_signature_newctx_fn ecdsa_newctx;
37b077aed3SPierre Pronchery static OSSL_FUNC_signature_sign_init_fn ecdsa_sign_init;
38b077aed3SPierre Pronchery static OSSL_FUNC_signature_verify_init_fn ecdsa_verify_init;
39b077aed3SPierre Pronchery static OSSL_FUNC_signature_sign_fn ecdsa_sign;
40*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_update_fn ecdsa_signverify_message_update;
41*e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_final_fn ecdsa_sign_message_final;
42b077aed3SPierre Pronchery static OSSL_FUNC_signature_verify_fn ecdsa_verify;
43*e7be843bSPierre Pronchery static OSSL_FUNC_signature_verify_message_update_fn ecdsa_signverify_message_update;
44*e7be843bSPierre Pronchery static OSSL_FUNC_signature_verify_message_final_fn ecdsa_verify_message_final;
45b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_init_fn ecdsa_digest_sign_init;
46b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_update_fn ecdsa_digest_signverify_update;
47b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_sign_final_fn ecdsa_digest_sign_final;
48b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_init_fn ecdsa_digest_verify_init;
49b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_update_fn ecdsa_digest_signverify_update;
50b077aed3SPierre Pronchery static OSSL_FUNC_signature_digest_verify_final_fn ecdsa_digest_verify_final;
51b077aed3SPierre Pronchery static OSSL_FUNC_signature_freectx_fn ecdsa_freectx;
52b077aed3SPierre Pronchery static OSSL_FUNC_signature_dupctx_fn ecdsa_dupctx;
53*e7be843bSPierre Pronchery static OSSL_FUNC_signature_query_key_types_fn ecdsa_sigalg_query_key_types;
54b077aed3SPierre Pronchery static OSSL_FUNC_signature_get_ctx_params_fn ecdsa_get_ctx_params;
55b077aed3SPierre Pronchery static OSSL_FUNC_signature_gettable_ctx_params_fn ecdsa_gettable_ctx_params;
56b077aed3SPierre Pronchery static OSSL_FUNC_signature_set_ctx_params_fn ecdsa_set_ctx_params;
57b077aed3SPierre Pronchery static OSSL_FUNC_signature_settable_ctx_params_fn ecdsa_settable_ctx_params;
58b077aed3SPierre Pronchery static OSSL_FUNC_signature_get_ctx_md_params_fn ecdsa_get_ctx_md_params;
59b077aed3SPierre Pronchery static OSSL_FUNC_signature_gettable_ctx_md_params_fn ecdsa_gettable_ctx_md_params;
60b077aed3SPierre Pronchery static OSSL_FUNC_signature_set_ctx_md_params_fn ecdsa_set_ctx_md_params;
61b077aed3SPierre Pronchery static OSSL_FUNC_signature_settable_ctx_md_params_fn ecdsa_settable_ctx_md_params;
62*e7be843bSPierre Pronchery static OSSL_FUNC_signature_set_ctx_params_fn ecdsa_sigalg_set_ctx_params;
63*e7be843bSPierre Pronchery static OSSL_FUNC_signature_settable_ctx_params_fn ecdsa_sigalg_settable_ctx_params;
64b077aed3SPierre Pronchery 
65b077aed3SPierre Pronchery /*
66b077aed3SPierre Pronchery  * What's passed as an actual key is defined by the KEYMGMT interface.
67b077aed3SPierre Pronchery  * We happen to know that our KEYMGMT simply passes DSA structures, so
68b077aed3SPierre Pronchery  * we use that here too.
69b077aed3SPierre Pronchery  */
70b077aed3SPierre Pronchery 
71b077aed3SPierre Pronchery typedef struct {
72b077aed3SPierre Pronchery     OSSL_LIB_CTX *libctx;
73b077aed3SPierre Pronchery     char *propq;
74b077aed3SPierre Pronchery     EC_KEY *ec;
75*e7be843bSPierre Pronchery     /* |operation| reuses EVP's operation bitfield */
76*e7be843bSPierre Pronchery     int operation;
77b077aed3SPierre Pronchery 
78b077aed3SPierre Pronchery     /*
79*e7be843bSPierre Pronchery      * Flag to determine if a full sigalg is run (1) or if a composable
80*e7be843bSPierre Pronchery      * signature algorithm is run (0).
81*e7be843bSPierre Pronchery      *
82*e7be843bSPierre Pronchery      * When a full sigalg is run (1), this currently affects the following
83*e7be843bSPierre Pronchery      * other flags, which are to remain untouched after their initialization:
84*e7be843bSPierre Pronchery      *
85*e7be843bSPierre Pronchery      * - flag_allow_md (initialized to 0)
86*e7be843bSPierre Pronchery      */
87*e7be843bSPierre Pronchery     unsigned int flag_sigalg : 1;
88*e7be843bSPierre Pronchery     /*
89b077aed3SPierre Pronchery      * Flag to determine if the hash function can be changed (1) or not (0)
90b077aed3SPierre Pronchery      * Because it's dangerous to change during a DigestSign or DigestVerify
91b077aed3SPierre Pronchery      * operation, this flag is cleared by their Init function, and set again
92b077aed3SPierre Pronchery      * by their Final function.
93b077aed3SPierre Pronchery      */
94b077aed3SPierre Pronchery     unsigned int flag_allow_md : 1;
95b077aed3SPierre Pronchery 
96b077aed3SPierre Pronchery     /* The Algorithm Identifier of the combined signature algorithm */
97b077aed3SPierre Pronchery     unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE];
98b077aed3SPierre Pronchery     size_t  aid_len;
99b077aed3SPierre Pronchery 
100*e7be843bSPierre Pronchery     /* main digest */
101*e7be843bSPierre Pronchery     char mdname[OSSL_MAX_NAME_SIZE];
102b077aed3SPierre Pronchery     EVP_MD *md;
103b077aed3SPierre Pronchery     EVP_MD_CTX *mdctx;
104*e7be843bSPierre Pronchery     size_t mdsize;
105*e7be843bSPierre Pronchery 
106*e7be843bSPierre Pronchery     /* Signature, for verification */
107*e7be843bSPierre Pronchery     unsigned char *sig;
108*e7be843bSPierre Pronchery     size_t siglen;
109*e7be843bSPierre Pronchery 
110b077aed3SPierre Pronchery     /*
111b077aed3SPierre Pronchery      * Internally used to cache the results of calling the EC group
112b077aed3SPierre Pronchery      * sign_setup() methods which are then passed to the sign operation.
113b077aed3SPierre Pronchery      * This is used by CAVS failure tests to terminate a loop if the signature
114b077aed3SPierre Pronchery      * is not valid.
115b077aed3SPierre Pronchery      * This could of also been done with a simple flag.
116b077aed3SPierre Pronchery      */
117b077aed3SPierre Pronchery     BIGNUM *kinv;
118b077aed3SPierre Pronchery     BIGNUM *r;
119b077aed3SPierre Pronchery #if !defined(OPENSSL_NO_ACVP_TESTS)
120b077aed3SPierre Pronchery     /*
121b077aed3SPierre Pronchery      * This indicates that KAT (CAVS) test is running. Externally an app will
122b077aed3SPierre Pronchery      * override the random callback such that the generated private key and k
123b077aed3SPierre Pronchery      * are known.
124b077aed3SPierre Pronchery      * Normal operation will loop to choose a new k if the signature is not
125b077aed3SPierre Pronchery      * valid - but for this mode of operation it forces a failure instead.
126b077aed3SPierre Pronchery      */
127b077aed3SPierre Pronchery     unsigned int kattest;
128b077aed3SPierre Pronchery #endif
129*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
130*e7be843bSPierre Pronchery     /*
131*e7be843bSPierre Pronchery      * FIPS 140-3 IG 2.4.B mandates that verification based on a digest of a
132*e7be843bSPierre Pronchery      * message is not permitted.  However, signing based on a digest is still
133*e7be843bSPierre Pronchery      * permitted.
134*e7be843bSPierre Pronchery      */
135*e7be843bSPierre Pronchery     int verify_message;
136*e7be843bSPierre Pronchery #endif
137*e7be843bSPierre Pronchery     /* If this is set then the generated k is not random */
138*e7be843bSPierre Pronchery     unsigned int nonce_type;
139*e7be843bSPierre Pronchery     OSSL_FIPS_IND_DECLARE
140b077aed3SPierre Pronchery } PROV_ECDSA_CTX;
141b077aed3SPierre Pronchery 
142b077aed3SPierre Pronchery static void *ecdsa_newctx(void *provctx, const char *propq)
143b077aed3SPierre Pronchery {
144b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx;
145b077aed3SPierre Pronchery 
146b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
147b077aed3SPierre Pronchery         return NULL;
148b077aed3SPierre Pronchery 
149b077aed3SPierre Pronchery     ctx = OPENSSL_zalloc(sizeof(PROV_ECDSA_CTX));
150b077aed3SPierre Pronchery     if (ctx == NULL)
151b077aed3SPierre Pronchery         return NULL;
152b077aed3SPierre Pronchery 
153*e7be843bSPierre Pronchery     OSSL_FIPS_IND_INIT(ctx)
154b077aed3SPierre Pronchery     ctx->flag_allow_md = 1;
155*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
156*e7be843bSPierre Pronchery     ctx->verify_message = 1;
157*e7be843bSPierre Pronchery #endif
158b077aed3SPierre Pronchery     ctx->libctx = PROV_LIBCTX_OF(provctx);
159b077aed3SPierre Pronchery     if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL) {
160b077aed3SPierre Pronchery         OPENSSL_free(ctx);
161b077aed3SPierre Pronchery         ctx = NULL;
162b077aed3SPierre Pronchery     }
163b077aed3SPierre Pronchery     return ctx;
164b077aed3SPierre Pronchery }
165b077aed3SPierre Pronchery 
166*e7be843bSPierre Pronchery static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx,
167*e7be843bSPierre Pronchery                           const char *mdname, const char *mdprops,
168*e7be843bSPierre Pronchery                           const char *desc)
169b077aed3SPierre Pronchery {
170*e7be843bSPierre Pronchery     EVP_MD *md = NULL;
171*e7be843bSPierre Pronchery     size_t mdname_len;
172*e7be843bSPierre Pronchery     int md_nid, md_size;
173*e7be843bSPierre Pronchery     WPACKET pkt;
174*e7be843bSPierre Pronchery     unsigned char *aid = NULL;
175b077aed3SPierre Pronchery 
176*e7be843bSPierre Pronchery     if (mdname == NULL)
177*e7be843bSPierre Pronchery         return 1;
178*e7be843bSPierre Pronchery 
179*e7be843bSPierre Pronchery     mdname_len = strlen(mdname);
180*e7be843bSPierre Pronchery     if (mdname_len >= sizeof(ctx->mdname)) {
181*e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
182*e7be843bSPierre Pronchery                        "%s exceeds name buffer length", mdname);
183*e7be843bSPierre Pronchery         return 0;
184*e7be843bSPierre Pronchery     }
185*e7be843bSPierre Pronchery     if (mdprops == NULL)
186*e7be843bSPierre Pronchery         mdprops = ctx->propq;
187*e7be843bSPierre Pronchery     md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
188*e7be843bSPierre Pronchery     if (md == NULL) {
189*e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
190*e7be843bSPierre Pronchery                        "%s could not be fetched", mdname);
191*e7be843bSPierre Pronchery         return 0;
192*e7be843bSPierre Pronchery     }
193*e7be843bSPierre Pronchery     md_size = EVP_MD_get_size(md);
194*e7be843bSPierre Pronchery     if (md_size <= 0) {
195*e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
196*e7be843bSPierre Pronchery                        "%s has invalid md size %d", mdname, md_size);
197*e7be843bSPierre Pronchery         goto err;
198*e7be843bSPierre Pronchery     }
199*e7be843bSPierre Pronchery     md_nid = ossl_digest_get_approved_nid(md);
200*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
201*e7be843bSPierre Pronchery     if (md_nid == NID_undef) {
202*e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
203*e7be843bSPierre Pronchery                        "digest=%s", mdname);
204*e7be843bSPierre Pronchery         goto err;
205*e7be843bSPierre Pronchery     }
206*e7be843bSPierre Pronchery #endif
207*e7be843bSPierre Pronchery     /* XOF digests don't work */
208*e7be843bSPierre Pronchery     if (EVP_MD_xof(md)) {
209*e7be843bSPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
210*e7be843bSPierre Pronchery         goto err;
211*e7be843bSPierre Pronchery     }
212*e7be843bSPierre Pronchery 
213*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
214*e7be843bSPierre Pronchery     {
215*e7be843bSPierre Pronchery         int sha1_allowed
216*e7be843bSPierre Pronchery             = ((ctx->operation
217*e7be843bSPierre Pronchery                 & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_SIGNMSG)) == 0);
218*e7be843bSPierre Pronchery 
219*e7be843bSPierre Pronchery         if (!ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND_GET(ctx),
220*e7be843bSPierre Pronchery                                              OSSL_FIPS_IND_SETTABLE1,
221*e7be843bSPierre Pronchery                                              ctx->libctx,
222*e7be843bSPierre Pronchery                                              md_nid, sha1_allowed, desc,
223*e7be843bSPierre Pronchery                                              ossl_fips_config_signature_digest_check))
224*e7be843bSPierre Pronchery             goto err;
225*e7be843bSPierre Pronchery     }
226*e7be843bSPierre Pronchery #endif
227*e7be843bSPierre Pronchery 
228*e7be843bSPierre Pronchery     if (!ctx->flag_allow_md) {
229*e7be843bSPierre Pronchery         if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) {
230*e7be843bSPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
231*e7be843bSPierre Pronchery                            "digest %s != %s", mdname, ctx->mdname);
232*e7be843bSPierre Pronchery             goto err;
233*e7be843bSPierre Pronchery         }
234*e7be843bSPierre Pronchery         EVP_MD_free(md);
235*e7be843bSPierre Pronchery         return 1;
236*e7be843bSPierre Pronchery     }
237*e7be843bSPierre Pronchery 
238*e7be843bSPierre Pronchery     EVP_MD_CTX_free(ctx->mdctx);
239*e7be843bSPierre Pronchery     EVP_MD_free(ctx->md);
240*e7be843bSPierre Pronchery 
241*e7be843bSPierre Pronchery     ctx->aid_len = 0;
242*e7be843bSPierre Pronchery #ifndef FIPS_MODULE
243*e7be843bSPierre Pronchery     if (md_nid != NID_undef) {
244*e7be843bSPierre Pronchery #else
245*e7be843bSPierre Pronchery     {
246*e7be843bSPierre Pronchery #endif
247*e7be843bSPierre Pronchery         if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
248*e7be843bSPierre Pronchery             && ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(&pkt, -1, ctx->ec,
249*e7be843bSPierre Pronchery                                                             md_nid)
250*e7be843bSPierre Pronchery             && WPACKET_finish(&pkt)) {
251*e7be843bSPierre Pronchery             WPACKET_get_total_written(&pkt, &ctx->aid_len);
252*e7be843bSPierre Pronchery             aid = WPACKET_get_curr(&pkt);
253*e7be843bSPierre Pronchery         }
254*e7be843bSPierre Pronchery         WPACKET_cleanup(&pkt);
255*e7be843bSPierre Pronchery         if (aid != NULL && ctx->aid_len != 0)
256*e7be843bSPierre Pronchery             memmove(ctx->aid_buf, aid, ctx->aid_len);
257*e7be843bSPierre Pronchery     }
258*e7be843bSPierre Pronchery 
259*e7be843bSPierre Pronchery     ctx->mdctx = NULL;
260*e7be843bSPierre Pronchery     ctx->md = md;
261*e7be843bSPierre Pronchery     ctx->mdsize = (size_t)md_size;
262*e7be843bSPierre Pronchery     OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
263*e7be843bSPierre Pronchery 
264*e7be843bSPierre Pronchery     return 1;
265*e7be843bSPierre Pronchery  err:
266*e7be843bSPierre Pronchery     EVP_MD_free(md);
267*e7be843bSPierre Pronchery     return 0;
268*e7be843bSPierre Pronchery }
269*e7be843bSPierre Pronchery 
270*e7be843bSPierre Pronchery static int
271*e7be843bSPierre Pronchery ecdsa_signverify_init(PROV_ECDSA_CTX *ctx, void *ec,
272*e7be843bSPierre Pronchery                       OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params,
273*e7be843bSPierre Pronchery                       const OSSL_PARAM params[], int operation,
274*e7be843bSPierre Pronchery                       const char *desc)
275*e7be843bSPierre Pronchery {
276b077aed3SPierre Pronchery     if (!ossl_prov_is_running()
277b077aed3SPierre Pronchery             || ctx == NULL)
278b077aed3SPierre Pronchery         return 0;
279b077aed3SPierre Pronchery 
280b077aed3SPierre Pronchery     if (ec == NULL && ctx->ec == NULL) {
281b077aed3SPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_NO_KEY_SET);
282b077aed3SPierre Pronchery         return 0;
283b077aed3SPierre Pronchery     }
284b077aed3SPierre Pronchery 
285b077aed3SPierre Pronchery     if (ec != NULL) {
286b077aed3SPierre Pronchery         if (!EC_KEY_up_ref(ec))
287b077aed3SPierre Pronchery             return 0;
288b077aed3SPierre Pronchery         EC_KEY_free(ctx->ec);
289b077aed3SPierre Pronchery         ctx->ec = ec;
290b077aed3SPierre Pronchery     }
291b077aed3SPierre Pronchery 
292b077aed3SPierre Pronchery     ctx->operation = operation;
293b077aed3SPierre Pronchery 
294*e7be843bSPierre Pronchery     OSSL_FIPS_IND_SET_APPROVED(ctx)
295*e7be843bSPierre Pronchery     if (!set_ctx_params(ctx, params))
296b077aed3SPierre Pronchery         return 0;
297*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
298*e7be843bSPierre Pronchery     if (!ossl_fips_ind_ec_key_check(OSSL_FIPS_IND_GET(ctx),
299*e7be843bSPierre Pronchery                                     OSSL_FIPS_IND_SETTABLE0, ctx->libctx,
300*e7be843bSPierre Pronchery                                     EC_KEY_get0_group(ctx->ec), desc,
301*e7be843bSPierre Pronchery                                     (operation & (EVP_PKEY_OP_SIGN
302*e7be843bSPierre Pronchery                                                   | EVP_PKEY_OP_SIGNMSG)) != 0))
303*e7be843bSPierre Pronchery         return 0;
304*e7be843bSPierre Pronchery #endif
305b077aed3SPierre Pronchery     return 1;
306b077aed3SPierre Pronchery }
307b077aed3SPierre Pronchery 
308b077aed3SPierre Pronchery static int ecdsa_sign_init(void *vctx, void *ec, const OSSL_PARAM params[])
309b077aed3SPierre Pronchery {
310*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
311*e7be843bSPierre Pronchery 
312*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
313*e7be843bSPierre Pronchery     ctx->verify_message = 1;
314*e7be843bSPierre Pronchery #endif
315*e7be843bSPierre Pronchery     return ecdsa_signverify_init(ctx, ec, ecdsa_set_ctx_params, params,
316*e7be843bSPierre Pronchery                                  EVP_PKEY_OP_SIGN, "ECDSA Sign Init");
317b077aed3SPierre Pronchery }
318b077aed3SPierre Pronchery 
319*e7be843bSPierre Pronchery /*
320*e7be843bSPierre Pronchery  * Sign tbs without digesting it first.  This is suitable for "primitive"
321*e7be843bSPierre Pronchery  * signing and signing the digest of a message.
322*e7be843bSPierre Pronchery  */
323*e7be843bSPierre Pronchery static int ecdsa_sign_directly(void *vctx,
324*e7be843bSPierre Pronchery                                unsigned char *sig, size_t *siglen, size_t sigsize,
325*e7be843bSPierre Pronchery                                const unsigned char *tbs, size_t tbslen)
326b077aed3SPierre Pronchery {
327b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
328b077aed3SPierre Pronchery     int ret;
329b077aed3SPierre Pronchery     unsigned int sltmp;
330b077aed3SPierre Pronchery     size_t ecsize = ECDSA_size(ctx->ec);
331b077aed3SPierre Pronchery 
332b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
333b077aed3SPierre Pronchery         return 0;
334b077aed3SPierre Pronchery 
335b077aed3SPierre Pronchery     if (sig == NULL) {
336b077aed3SPierre Pronchery         *siglen = ecsize;
337b077aed3SPierre Pronchery         return 1;
338b077aed3SPierre Pronchery     }
339b077aed3SPierre Pronchery 
340b077aed3SPierre Pronchery #if !defined(OPENSSL_NO_ACVP_TESTS)
341b077aed3SPierre Pronchery     if (ctx->kattest && !ECDSA_sign_setup(ctx->ec, NULL, &ctx->kinv, &ctx->r))
342b077aed3SPierre Pronchery         return 0;
343b077aed3SPierre Pronchery #endif
344b077aed3SPierre Pronchery 
345b077aed3SPierre Pronchery     if (sigsize < (size_t)ecsize)
346b077aed3SPierre Pronchery         return 0;
347b077aed3SPierre Pronchery 
348b077aed3SPierre Pronchery     if (ctx->mdsize != 0 && tbslen != ctx->mdsize)
349b077aed3SPierre Pronchery         return 0;
350b077aed3SPierre Pronchery 
351*e7be843bSPierre Pronchery     if (ctx->nonce_type != 0) {
352*e7be843bSPierre Pronchery         const char *mdname = NULL;
353*e7be843bSPierre Pronchery 
354*e7be843bSPierre Pronchery         if (ctx->mdname[0] != '\0')
355*e7be843bSPierre Pronchery             mdname = ctx->mdname;
356*e7be843bSPierre Pronchery         ret = ossl_ecdsa_deterministic_sign(tbs, tbslen, sig, &sltmp,
357*e7be843bSPierre Pronchery                                             ctx->ec, ctx->nonce_type,
358*e7be843bSPierre Pronchery                                             mdname,
359*e7be843bSPierre Pronchery                                             ctx->libctx, ctx->propq);
360*e7be843bSPierre Pronchery     } else {
361*e7be843bSPierre Pronchery         ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &sltmp, ctx->kinv, ctx->r,
362*e7be843bSPierre Pronchery                             ctx->ec);
363*e7be843bSPierre Pronchery     }
364b077aed3SPierre Pronchery     if (ret <= 0)
365b077aed3SPierre Pronchery         return 0;
366b077aed3SPierre Pronchery 
367b077aed3SPierre Pronchery     *siglen = sltmp;
368b077aed3SPierre Pronchery     return 1;
369b077aed3SPierre Pronchery }
370b077aed3SPierre Pronchery 
371*e7be843bSPierre Pronchery static int ecdsa_signverify_message_update(void *vctx,
372*e7be843bSPierre Pronchery                                          const unsigned char *data,
373*e7be843bSPierre Pronchery                                          size_t datalen)
374*e7be843bSPierre Pronchery {
375*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
376*e7be843bSPierre Pronchery 
377*e7be843bSPierre Pronchery     if (ctx == NULL)
378*e7be843bSPierre Pronchery         return 0;
379*e7be843bSPierre Pronchery 
380*e7be843bSPierre Pronchery     return EVP_DigestUpdate(ctx->mdctx, data, datalen);
381*e7be843bSPierre Pronchery }
382*e7be843bSPierre Pronchery 
383*e7be843bSPierre Pronchery static int ecdsa_sign_message_final(void *vctx, unsigned char *sig,
384*e7be843bSPierre Pronchery                                   size_t *siglen, size_t sigsize)
385*e7be843bSPierre Pronchery {
386*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
387*e7be843bSPierre Pronchery     unsigned char digest[EVP_MAX_MD_SIZE];
388*e7be843bSPierre Pronchery     unsigned int dlen = 0;
389*e7be843bSPierre Pronchery 
390*e7be843bSPierre Pronchery     if (!ossl_prov_is_running() || ctx == NULL)
391*e7be843bSPierre Pronchery         return 0;
392*e7be843bSPierre Pronchery     if (ctx->mdctx == NULL)
393*e7be843bSPierre Pronchery         return 0;
394*e7be843bSPierre Pronchery     /*
395*e7be843bSPierre Pronchery      * If sig is NULL then we're just finding out the sig size. Other fields
396*e7be843bSPierre Pronchery      * are ignored. Defer to ecdsa_sign.
397*e7be843bSPierre Pronchery      */
398*e7be843bSPierre Pronchery     if (sig != NULL
399*e7be843bSPierre Pronchery         && !EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
400*e7be843bSPierre Pronchery         return 0;
401*e7be843bSPierre Pronchery     return ecdsa_sign_directly(vctx, sig, siglen, sigsize, digest, dlen);
402*e7be843bSPierre Pronchery }
403*e7be843bSPierre Pronchery 
404*e7be843bSPierre Pronchery /*
405*e7be843bSPierre Pronchery  * If signing a message, digest tbs and sign the result.
406*e7be843bSPierre Pronchery  * Otherwise, sign tbs directly.
407*e7be843bSPierre Pronchery  */
408*e7be843bSPierre Pronchery static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen,
409*e7be843bSPierre Pronchery                     size_t sigsize, const unsigned char *tbs, size_t tbslen)
410*e7be843bSPierre Pronchery {
411*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
412*e7be843bSPierre Pronchery 
413*e7be843bSPierre Pronchery     if (ctx->operation == EVP_PKEY_OP_SIGNMSG) {
414*e7be843bSPierre Pronchery         /*
415*e7be843bSPierre Pronchery          * If |sig| is NULL, the caller is only looking for the sig length.
416*e7be843bSPierre Pronchery          * DO NOT update the input in this case.
417*e7be843bSPierre Pronchery          */
418*e7be843bSPierre Pronchery         if (sig == NULL)
419*e7be843bSPierre Pronchery             return ecdsa_sign_message_final(ctx, sig, siglen, sigsize);
420*e7be843bSPierre Pronchery 
421*e7be843bSPierre Pronchery         if (ecdsa_signverify_message_update(ctx, tbs, tbslen) <= 0)
422*e7be843bSPierre Pronchery             return 0;
423*e7be843bSPierre Pronchery         return ecdsa_sign_message_final(ctx, sig, siglen, sigsize);
424*e7be843bSPierre Pronchery     }
425*e7be843bSPierre Pronchery     return ecdsa_sign_directly(ctx, sig, siglen, sigsize, tbs, tbslen);
426*e7be843bSPierre Pronchery }
427*e7be843bSPierre Pronchery 
428*e7be843bSPierre Pronchery static int ecdsa_verify_init(void *vctx, void *ec, const OSSL_PARAM params[])
429*e7be843bSPierre Pronchery {
430*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
431*e7be843bSPierre Pronchery 
432*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
433*e7be843bSPierre Pronchery     ctx->verify_message = 0;
434*e7be843bSPierre Pronchery #endif
435*e7be843bSPierre Pronchery     return ecdsa_signverify_init(ctx, ec, ecdsa_set_ctx_params, params,
436*e7be843bSPierre Pronchery                                  EVP_PKEY_OP_VERIFY, "ECDSA Verify Init");
437*e7be843bSPierre Pronchery }
438*e7be843bSPierre Pronchery 
439*e7be843bSPierre Pronchery static int ecdsa_verify_directly(void *vctx,
440*e7be843bSPierre Pronchery                                  const unsigned char *sig, size_t siglen,
441b077aed3SPierre Pronchery                                  const unsigned char *tbs, size_t tbslen)
442b077aed3SPierre Pronchery {
443b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
444b077aed3SPierre Pronchery 
445b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || (ctx->mdsize != 0 && tbslen != ctx->mdsize))
446b077aed3SPierre Pronchery         return 0;
447b077aed3SPierre Pronchery 
448b077aed3SPierre Pronchery     return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->ec);
449b077aed3SPierre Pronchery }
450b077aed3SPierre Pronchery 
451*e7be843bSPierre Pronchery static int ecdsa_verify_set_sig(void *vctx,
452*e7be843bSPierre Pronchery                                 const unsigned char *sig, size_t siglen)
453b077aed3SPierre Pronchery {
454*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
455*e7be843bSPierre Pronchery     OSSL_PARAM params[2];
456b077aed3SPierre Pronchery 
457*e7be843bSPierre Pronchery     params[0] =
458*e7be843bSPierre Pronchery         OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE,
459*e7be843bSPierre Pronchery                                           (unsigned char *)sig, siglen);
460*e7be843bSPierre Pronchery     params[1] = OSSL_PARAM_construct_end();
461*e7be843bSPierre Pronchery     return ecdsa_sigalg_set_ctx_params(ctx, params);
462*e7be843bSPierre Pronchery }
463b077aed3SPierre Pronchery 
464*e7be843bSPierre Pronchery static int ecdsa_verify_message_final(void *vctx)
465*e7be843bSPierre Pronchery {
466*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
467*e7be843bSPierre Pronchery     unsigned char digest[EVP_MAX_MD_SIZE];
468*e7be843bSPierre Pronchery     unsigned int dlen = 0;
469*e7be843bSPierre Pronchery 
470*e7be843bSPierre Pronchery     if (!ossl_prov_is_running() || ctx == NULL || ctx->mdctx == NULL)
471b077aed3SPierre Pronchery         return 0;
472*e7be843bSPierre Pronchery 
473*e7be843bSPierre Pronchery     /*
474*e7be843bSPierre Pronchery      * The digests used here are all known (see ecdsa_get_md_nid()), so they
475*e7be843bSPierre Pronchery      * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
476*e7be843bSPierre Pronchery      */
477*e7be843bSPierre Pronchery     if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
478b077aed3SPierre Pronchery         return 0;
479*e7be843bSPierre Pronchery 
480*e7be843bSPierre Pronchery     return ecdsa_verify_directly(vctx, ctx->sig, ctx->siglen,
481*e7be843bSPierre Pronchery                                digest, dlen);
482b077aed3SPierre Pronchery }
483*e7be843bSPierre Pronchery 
484*e7be843bSPierre Pronchery /*
485*e7be843bSPierre Pronchery  * If verifying a message, digest tbs and verify the result.
486*e7be843bSPierre Pronchery  * Otherwise, verify tbs directly.
487*e7be843bSPierre Pronchery  */
488*e7be843bSPierre Pronchery static int ecdsa_verify(void *vctx,
489*e7be843bSPierre Pronchery                       const unsigned char *sig, size_t siglen,
490*e7be843bSPierre Pronchery                       const unsigned char *tbs, size_t tbslen)
491*e7be843bSPierre Pronchery {
492*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
493*e7be843bSPierre Pronchery 
494*e7be843bSPierre Pronchery     if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) {
495*e7be843bSPierre Pronchery         if (ecdsa_verify_set_sig(ctx, sig, siglen) <= 0)
496b077aed3SPierre Pronchery             return 0;
497*e7be843bSPierre Pronchery         if (ecdsa_signverify_message_update(ctx, tbs, tbslen) <= 0)
498b077aed3SPierre Pronchery             return 0;
499*e7be843bSPierre Pronchery         return ecdsa_verify_message_final(ctx);
500b077aed3SPierre Pronchery     }
501*e7be843bSPierre Pronchery     return ecdsa_verify_directly(ctx, sig, siglen, tbs, tbslen);
502b077aed3SPierre Pronchery }
503b077aed3SPierre Pronchery 
504*e7be843bSPierre Pronchery /* DigestSign/DigestVerify wrappers */
505b077aed3SPierre Pronchery 
506b077aed3SPierre Pronchery static int ecdsa_digest_signverify_init(void *vctx, const char *mdname,
507b077aed3SPierre Pronchery                                         void *ec, const OSSL_PARAM params[],
508*e7be843bSPierre Pronchery                                         int operation, const char *desc)
509b077aed3SPierre Pronchery {
510b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
511b077aed3SPierre Pronchery 
512b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
513b077aed3SPierre Pronchery         return 0;
514b077aed3SPierre Pronchery 
515*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
516*e7be843bSPierre Pronchery     ctx->verify_message = 1;
517*e7be843bSPierre Pronchery #endif
518*e7be843bSPierre Pronchery     if (!ecdsa_signverify_init(vctx, ec, ecdsa_set_ctx_params, params,
519*e7be843bSPierre Pronchery                                operation, desc))
520*e7be843bSPierre Pronchery         return 0;
521*e7be843bSPierre Pronchery 
522*e7be843bSPierre Pronchery     if (mdname != NULL
523*e7be843bSPierre Pronchery         /* was ecdsa_setup_md already called in ecdsa_signverify_init()? */
524*e7be843bSPierre Pronchery         && (mdname[0] == '\0' || OPENSSL_strcasecmp(ctx->mdname, mdname) != 0)
525*e7be843bSPierre Pronchery         && !ecdsa_setup_md(ctx, mdname, NULL, desc))
526b077aed3SPierre Pronchery         return 0;
527b077aed3SPierre Pronchery 
528b077aed3SPierre Pronchery     ctx->flag_allow_md = 0;
529b077aed3SPierre Pronchery 
530b077aed3SPierre Pronchery     if (ctx->mdctx == NULL) {
531b077aed3SPierre Pronchery         ctx->mdctx = EVP_MD_CTX_new();
532b077aed3SPierre Pronchery         if (ctx->mdctx == NULL)
533b077aed3SPierre Pronchery             goto error;
534b077aed3SPierre Pronchery     }
535b077aed3SPierre Pronchery 
536b077aed3SPierre Pronchery     if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params))
537b077aed3SPierre Pronchery         goto error;
538b077aed3SPierre Pronchery     return 1;
539b077aed3SPierre Pronchery error:
540b077aed3SPierre Pronchery     EVP_MD_CTX_free(ctx->mdctx);
541b077aed3SPierre Pronchery     ctx->mdctx = NULL;
542b077aed3SPierre Pronchery     return 0;
543b077aed3SPierre Pronchery }
544b077aed3SPierre Pronchery 
545b077aed3SPierre Pronchery static int ecdsa_digest_sign_init(void *vctx, const char *mdname, void *ec,
546b077aed3SPierre Pronchery                                   const OSSL_PARAM params[])
547b077aed3SPierre Pronchery {
548b077aed3SPierre Pronchery     return ecdsa_digest_signverify_init(vctx, mdname, ec, params,
549*e7be843bSPierre Pronchery                                         EVP_PKEY_OP_SIGNMSG,
550*e7be843bSPierre Pronchery                                         "ECDSA Digest Sign Init");
551b077aed3SPierre Pronchery }
552b077aed3SPierre Pronchery 
553*e7be843bSPierre Pronchery static int ecdsa_digest_signverify_update(void *vctx, const unsigned char *data,
554b077aed3SPierre Pronchery                                           size_t datalen)
555b077aed3SPierre Pronchery {
556b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
557b077aed3SPierre Pronchery 
558b077aed3SPierre Pronchery     if (ctx == NULL || ctx->mdctx == NULL)
559b077aed3SPierre Pronchery         return 0;
560*e7be843bSPierre Pronchery     /* Sigalg implementations shouldn't do digest_sign */
561*e7be843bSPierre Pronchery     if (ctx->flag_sigalg)
562*e7be843bSPierre Pronchery         return 0;
563b077aed3SPierre Pronchery 
564*e7be843bSPierre Pronchery     return ecdsa_signverify_message_update(vctx, data, datalen);
565b077aed3SPierre Pronchery }
566b077aed3SPierre Pronchery 
567b077aed3SPierre Pronchery int ecdsa_digest_sign_final(void *vctx, unsigned char *sig, size_t *siglen,
568b077aed3SPierre Pronchery                             size_t sigsize)
569b077aed3SPierre Pronchery {
570b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
571*e7be843bSPierre Pronchery     int ok = 0;
572b077aed3SPierre Pronchery 
573*e7be843bSPierre Pronchery     if (ctx == NULL)
574*e7be843bSPierre Pronchery         return 0;
575*e7be843bSPierre Pronchery     /* Sigalg implementations shouldn't do digest_sign */
576*e7be843bSPierre Pronchery     if (ctx->flag_sigalg)
577b077aed3SPierre Pronchery         return 0;
578b077aed3SPierre Pronchery 
579*e7be843bSPierre Pronchery     ok = ecdsa_sign_message_final(ctx, sig, siglen, sigsize);
580*e7be843bSPierre Pronchery 
581b077aed3SPierre Pronchery     ctx->flag_allow_md = 1;
582*e7be843bSPierre Pronchery 
583*e7be843bSPierre Pronchery     return ok;
584*e7be843bSPierre Pronchery }
585*e7be843bSPierre Pronchery 
586*e7be843bSPierre Pronchery static int ecdsa_digest_verify_init(void *vctx, const char *mdname, void *ec,
587*e7be843bSPierre Pronchery                                     const OSSL_PARAM params[])
588*e7be843bSPierre Pronchery {
589*e7be843bSPierre Pronchery     return ecdsa_digest_signverify_init(vctx, mdname, ec, params,
590*e7be843bSPierre Pronchery                                         EVP_PKEY_OP_VERIFYMSG,
591*e7be843bSPierre Pronchery                                         "ECDSA Digest Verify Init");
592b077aed3SPierre Pronchery }
593b077aed3SPierre Pronchery 
594b077aed3SPierre Pronchery int ecdsa_digest_verify_final(void *vctx, const unsigned char *sig,
595b077aed3SPierre Pronchery                               size_t siglen)
596b077aed3SPierre Pronchery {
597b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
598*e7be843bSPierre Pronchery     int ok = 0;
599b077aed3SPierre Pronchery 
600b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || ctx == NULL || ctx->mdctx == NULL)
601b077aed3SPierre Pronchery         return 0;
602b077aed3SPierre Pronchery 
603*e7be843bSPierre Pronchery     /* Sigalg implementations shouldn't do digest_verify */
604*e7be843bSPierre Pronchery     if (ctx->flag_sigalg)
605b077aed3SPierre Pronchery         return 0;
606*e7be843bSPierre Pronchery 
607*e7be843bSPierre Pronchery     if (ecdsa_verify_set_sig(ctx, sig, siglen))
608*e7be843bSPierre Pronchery         ok = ecdsa_verify_message_final(ctx);
609*e7be843bSPierre Pronchery 
610b077aed3SPierre Pronchery     ctx->flag_allow_md = 1;
611*e7be843bSPierre Pronchery 
612*e7be843bSPierre Pronchery     return ok;
613b077aed3SPierre Pronchery }
614b077aed3SPierre Pronchery 
615b077aed3SPierre Pronchery static void ecdsa_freectx(void *vctx)
616b077aed3SPierre Pronchery {
617b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
618b077aed3SPierre Pronchery 
619b077aed3SPierre Pronchery     EVP_MD_CTX_free(ctx->mdctx);
620b077aed3SPierre Pronchery     EVP_MD_free(ctx->md);
621*e7be843bSPierre Pronchery     OPENSSL_free(ctx->propq);
622*e7be843bSPierre Pronchery     OPENSSL_free(ctx->sig);
623b077aed3SPierre Pronchery     EC_KEY_free(ctx->ec);
624b077aed3SPierre Pronchery     BN_clear_free(ctx->kinv);
625b077aed3SPierre Pronchery     BN_clear_free(ctx->r);
626b077aed3SPierre Pronchery     OPENSSL_free(ctx);
627b077aed3SPierre Pronchery }
628b077aed3SPierre Pronchery 
629b077aed3SPierre Pronchery static void *ecdsa_dupctx(void *vctx)
630b077aed3SPierre Pronchery {
631b077aed3SPierre Pronchery     PROV_ECDSA_CTX *srcctx = (PROV_ECDSA_CTX *)vctx;
632b077aed3SPierre Pronchery     PROV_ECDSA_CTX *dstctx;
633b077aed3SPierre Pronchery 
634b077aed3SPierre Pronchery     if (!ossl_prov_is_running())
635b077aed3SPierre Pronchery         return NULL;
636b077aed3SPierre Pronchery 
637b077aed3SPierre Pronchery     dstctx = OPENSSL_zalloc(sizeof(*srcctx));
638b077aed3SPierre Pronchery     if (dstctx == NULL)
639b077aed3SPierre Pronchery         return NULL;
640b077aed3SPierre Pronchery 
641b077aed3SPierre Pronchery     *dstctx = *srcctx;
642b077aed3SPierre Pronchery     dstctx->ec = NULL;
643b077aed3SPierre Pronchery     dstctx->propq = NULL;
644b077aed3SPierre Pronchery 
645b077aed3SPierre Pronchery     if (srcctx->ec != NULL && !EC_KEY_up_ref(srcctx->ec))
646b077aed3SPierre Pronchery         goto err;
647b077aed3SPierre Pronchery     /* Test KATS should not need to be supported */
648b077aed3SPierre Pronchery     if (srcctx->kinv != NULL || srcctx->r != NULL)
649b077aed3SPierre Pronchery         goto err;
650b077aed3SPierre Pronchery     dstctx->ec = srcctx->ec;
651b077aed3SPierre Pronchery 
652b077aed3SPierre Pronchery     if (srcctx->md != NULL && !EVP_MD_up_ref(srcctx->md))
653b077aed3SPierre Pronchery         goto err;
654b077aed3SPierre Pronchery     dstctx->md = srcctx->md;
655b077aed3SPierre Pronchery 
656b077aed3SPierre Pronchery     if (srcctx->mdctx != NULL) {
657b077aed3SPierre Pronchery         dstctx->mdctx = EVP_MD_CTX_new();
658b077aed3SPierre Pronchery         if (dstctx->mdctx == NULL
659b077aed3SPierre Pronchery                 || !EVP_MD_CTX_copy_ex(dstctx->mdctx, srcctx->mdctx))
660b077aed3SPierre Pronchery             goto err;
661b077aed3SPierre Pronchery     }
662b077aed3SPierre Pronchery 
663b077aed3SPierre Pronchery     if (srcctx->propq != NULL) {
664b077aed3SPierre Pronchery         dstctx->propq = OPENSSL_strdup(srcctx->propq);
665b077aed3SPierre Pronchery         if (dstctx->propq == NULL)
666b077aed3SPierre Pronchery             goto err;
667b077aed3SPierre Pronchery     }
668b077aed3SPierre Pronchery 
669b077aed3SPierre Pronchery     return dstctx;
670b077aed3SPierre Pronchery  err:
671b077aed3SPierre Pronchery     ecdsa_freectx(dstctx);
672b077aed3SPierre Pronchery     return NULL;
673b077aed3SPierre Pronchery }
674b077aed3SPierre Pronchery 
675b077aed3SPierre Pronchery static int ecdsa_get_ctx_params(void *vctx, OSSL_PARAM *params)
676b077aed3SPierre Pronchery {
677b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
678b077aed3SPierre Pronchery     OSSL_PARAM *p;
679b077aed3SPierre Pronchery 
680b077aed3SPierre Pronchery     if (ctx == NULL)
681b077aed3SPierre Pronchery         return 0;
682b077aed3SPierre Pronchery 
683b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID);
684*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_octet_string(p,
685*e7be843bSPierre Pronchery                                                   ctx->aid_len == 0 ? NULL : ctx->aid_buf,
686*e7be843bSPierre Pronchery                                                   ctx->aid_len))
687b077aed3SPierre Pronchery         return 0;
688b077aed3SPierre Pronchery 
689b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
690b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_size_t(p, ctx->mdsize))
691b077aed3SPierre Pronchery         return 0;
692b077aed3SPierre Pronchery 
693b077aed3SPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_DIGEST);
694b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_utf8_string(p, ctx->md == NULL
695b077aed3SPierre Pronchery                                                     ? ctx->mdname
696b077aed3SPierre Pronchery                                                     : EVP_MD_get0_name(ctx->md)))
697b077aed3SPierre Pronchery         return 0;
698b077aed3SPierre Pronchery 
699*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE);
700*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->nonce_type))
701*e7be843bSPierre Pronchery         return 0;
702*e7be843bSPierre Pronchery 
703*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
704*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_FIPS_VERIFY_MESSAGE);
705*e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->verify_message))
706*e7be843bSPierre Pronchery         return 0;
707*e7be843bSPierre Pronchery #endif
708*e7be843bSPierre Pronchery 
709*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params))
710*e7be843bSPierre Pronchery         return 0;
711b077aed3SPierre Pronchery     return 1;
712b077aed3SPierre Pronchery }
713b077aed3SPierre Pronchery 
714b077aed3SPierre Pronchery static const OSSL_PARAM known_gettable_ctx_params[] = {
715b077aed3SPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0),
716b077aed3SPierre Pronchery     OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
717b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
718*e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL),
719*e7be843bSPierre Pronchery #ifdef FIPS_MODULE
720*e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_FIPS_VERIFY_MESSAGE, NULL),
721*e7be843bSPierre Pronchery #endif
722*e7be843bSPierre Pronchery     OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
723b077aed3SPierre Pronchery     OSSL_PARAM_END
724b077aed3SPierre Pronchery };
725b077aed3SPierre Pronchery 
726b077aed3SPierre Pronchery static const OSSL_PARAM *ecdsa_gettable_ctx_params(ossl_unused void *vctx,
727b077aed3SPierre Pronchery                                                    ossl_unused void *provctx)
728b077aed3SPierre Pronchery {
729b077aed3SPierre Pronchery     return known_gettable_ctx_params;
730b077aed3SPierre Pronchery }
731b077aed3SPierre Pronchery 
732*e7be843bSPierre Pronchery /**
733*e7be843bSPierre Pronchery  * @brief Set up common params for ecdsa_set_ctx_params and
734*e7be843bSPierre Pronchery  * ecdsa_sigalg_set_ctx_params. The caller is responsible for checking |vctx| is
735*e7be843bSPierre Pronchery  * not NULL and |params| is not empty.
736*e7be843bSPierre Pronchery  */
737*e7be843bSPierre Pronchery static int ecdsa_common_set_ctx_params(void *vctx, const OSSL_PARAM params[])
738b077aed3SPierre Pronchery {
739b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
740b077aed3SPierre Pronchery     const OSSL_PARAM *p;
741b077aed3SPierre Pronchery 
742*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params,
743*e7be843bSPierre Pronchery                                      OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK))
744b077aed3SPierre Pronchery         return 0;
745*e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE1, params,
746*e7be843bSPierre Pronchery                                      OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK))
747*e7be843bSPierre Pronchery         return 0;
748b077aed3SPierre Pronchery 
749b077aed3SPierre Pronchery #if !defined(OPENSSL_NO_ACVP_TESTS)
750b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT);
751b077aed3SPierre Pronchery     if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->kattest))
752b077aed3SPierre Pronchery         return 0;
753b077aed3SPierre Pronchery #endif
754b077aed3SPierre Pronchery 
755*e7be843bSPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE);
756*e7be843bSPierre Pronchery     if (p != NULL
757*e7be843bSPierre Pronchery         && !OSSL_PARAM_get_uint(p, &ctx->nonce_type))
758*e7be843bSPierre Pronchery         return 0;
759*e7be843bSPierre Pronchery     return 1;
760*e7be843bSPierre Pronchery }
761*e7be843bSPierre Pronchery 
762*e7be843bSPierre Pronchery #define ECDSA_COMMON_SETTABLE_CTX_PARAMS                                      \
763*e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL),                          \
764*e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL),                   \
765*e7be843bSPierre Pronchery     OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)     \
766*e7be843bSPierre Pronchery     OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)  \
767*e7be843bSPierre Pronchery     OSSL_PARAM_END
768*e7be843bSPierre Pronchery 
769*e7be843bSPierre Pronchery static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
770*e7be843bSPierre Pronchery {
771*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
772*e7be843bSPierre Pronchery     const OSSL_PARAM *p;
773*e7be843bSPierre Pronchery     size_t mdsize = 0;
774*e7be843bSPierre Pronchery     int ret;
775*e7be843bSPierre Pronchery 
776*e7be843bSPierre Pronchery     if (ctx == NULL)
777*e7be843bSPierre Pronchery         return 0;
778*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
779*e7be843bSPierre Pronchery         return 1;
780*e7be843bSPierre Pronchery 
781*e7be843bSPierre Pronchery     if ((ret = ecdsa_common_set_ctx_params(ctx, params)) <= 0)
782*e7be843bSPierre Pronchery         return ret;
783*e7be843bSPierre Pronchery 
784b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST);
785b077aed3SPierre Pronchery     if (p != NULL) {
786b077aed3SPierre Pronchery         char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname;
787b077aed3SPierre Pronchery         char mdprops[OSSL_MAX_PROPQUERY_SIZE] = "", *pmdprops = mdprops;
788b077aed3SPierre Pronchery         const OSSL_PARAM *propsp =
789b077aed3SPierre Pronchery             OSSL_PARAM_locate_const(params,
790b077aed3SPierre Pronchery                                     OSSL_SIGNATURE_PARAM_PROPERTIES);
791b077aed3SPierre Pronchery 
792b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_utf8_string(p, &pmdname, sizeof(mdname)))
793b077aed3SPierre Pronchery             return 0;
794b077aed3SPierre Pronchery         if (propsp != NULL
795b077aed3SPierre Pronchery             && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops)))
796b077aed3SPierre Pronchery             return 0;
797*e7be843bSPierre Pronchery         if (!ecdsa_setup_md(ctx, mdname, mdprops, "ECDSA Set Ctx"))
798b077aed3SPierre Pronchery             return 0;
799b077aed3SPierre Pronchery     }
800b077aed3SPierre Pronchery 
801b077aed3SPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST_SIZE);
802b077aed3SPierre Pronchery     if (p != NULL) {
803b077aed3SPierre Pronchery         if (!OSSL_PARAM_get_size_t(p, &mdsize)
804b077aed3SPierre Pronchery             || (!ctx->flag_allow_md && mdsize != ctx->mdsize))
805b077aed3SPierre Pronchery             return 0;
806b077aed3SPierre Pronchery         ctx->mdsize = mdsize;
807b077aed3SPierre Pronchery     }
808b077aed3SPierre Pronchery     return 1;
809b077aed3SPierre Pronchery }
810b077aed3SPierre Pronchery 
811b077aed3SPierre Pronchery static const OSSL_PARAM settable_ctx_params[] = {
812b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0),
813b077aed3SPierre Pronchery     OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL),
814b077aed3SPierre Pronchery     OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0),
815*e7be843bSPierre Pronchery     ECDSA_COMMON_SETTABLE_CTX_PARAMS
816b077aed3SPierre Pronchery };
817b077aed3SPierre Pronchery 
818b077aed3SPierre Pronchery static const OSSL_PARAM *ecdsa_settable_ctx_params(void *vctx,
819b077aed3SPierre Pronchery                                                    ossl_unused void *provctx)
820b077aed3SPierre Pronchery {
821b077aed3SPierre Pronchery     return settable_ctx_params;
822b077aed3SPierre Pronchery }
823b077aed3SPierre Pronchery 
824b077aed3SPierre Pronchery static int ecdsa_get_ctx_md_params(void *vctx, OSSL_PARAM *params)
825b077aed3SPierre Pronchery {
826b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
827b077aed3SPierre Pronchery 
828b077aed3SPierre Pronchery     if (ctx->mdctx == NULL)
829b077aed3SPierre Pronchery         return 0;
830b077aed3SPierre Pronchery 
831b077aed3SPierre Pronchery     return EVP_MD_CTX_get_params(ctx->mdctx, params);
832b077aed3SPierre Pronchery }
833b077aed3SPierre Pronchery 
834b077aed3SPierre Pronchery static const OSSL_PARAM *ecdsa_gettable_ctx_md_params(void *vctx)
835b077aed3SPierre Pronchery {
836b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
837b077aed3SPierre Pronchery 
838b077aed3SPierre Pronchery     if (ctx->md == NULL)
839b077aed3SPierre Pronchery         return 0;
840b077aed3SPierre Pronchery 
841b077aed3SPierre Pronchery     return EVP_MD_gettable_ctx_params(ctx->md);
842b077aed3SPierre Pronchery }
843b077aed3SPierre Pronchery 
844b077aed3SPierre Pronchery static int ecdsa_set_ctx_md_params(void *vctx, const OSSL_PARAM params[])
845b077aed3SPierre Pronchery {
846b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
847b077aed3SPierre Pronchery 
848b077aed3SPierre Pronchery     if (ctx->mdctx == NULL)
849b077aed3SPierre Pronchery         return 0;
850b077aed3SPierre Pronchery 
851b077aed3SPierre Pronchery     return EVP_MD_CTX_set_params(ctx->mdctx, params);
852b077aed3SPierre Pronchery }
853b077aed3SPierre Pronchery 
854b077aed3SPierre Pronchery static const OSSL_PARAM *ecdsa_settable_ctx_md_params(void *vctx)
855b077aed3SPierre Pronchery {
856b077aed3SPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
857b077aed3SPierre Pronchery 
858b077aed3SPierre Pronchery     if (ctx->md == NULL)
859b077aed3SPierre Pronchery         return 0;
860b077aed3SPierre Pronchery 
861b077aed3SPierre Pronchery     return EVP_MD_settable_ctx_params(ctx->md);
862b077aed3SPierre Pronchery }
863b077aed3SPierre Pronchery 
864b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_ecdsa_signature_functions[] = {
865b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ecdsa_newctx },
866b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN_INIT, (void (*)(void))ecdsa_sign_init },
867b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ecdsa_sign },
868b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY_INIT, (void (*)(void))ecdsa_verify_init },
869b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_VERIFY, (void (*)(void))ecdsa_verify },
870b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT,
871b077aed3SPierre Pronchery       (void (*)(void))ecdsa_digest_sign_init },
872b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_UPDATE,
873b077aed3SPierre Pronchery       (void (*)(void))ecdsa_digest_signverify_update },
874b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_FINAL,
875b077aed3SPierre Pronchery       (void (*)(void))ecdsa_digest_sign_final },
876b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_INIT,
877b077aed3SPierre Pronchery       (void (*)(void))ecdsa_digest_verify_init },
878b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_UPDATE,
879b077aed3SPierre Pronchery       (void (*)(void))ecdsa_digest_signverify_update },
880b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DIGEST_VERIFY_FINAL,
881b077aed3SPierre Pronchery       (void (*)(void))ecdsa_digest_verify_final },
882b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ecdsa_freectx },
883b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ecdsa_dupctx },
884b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))ecdsa_get_ctx_params },
885b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,
886b077aed3SPierre Pronchery       (void (*)(void))ecdsa_gettable_ctx_params },
887b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS, (void (*)(void))ecdsa_set_ctx_params },
888b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,
889b077aed3SPierre Pronchery       (void (*)(void))ecdsa_settable_ctx_params },
890b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GET_CTX_MD_PARAMS,
891b077aed3SPierre Pronchery       (void (*)(void))ecdsa_get_ctx_md_params },
892b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_MD_PARAMS,
893b077aed3SPierre Pronchery       (void (*)(void))ecdsa_gettable_ctx_md_params },
894b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SET_CTX_MD_PARAMS,
895b077aed3SPierre Pronchery       (void (*)(void))ecdsa_set_ctx_md_params },
896b077aed3SPierre Pronchery     { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_MD_PARAMS,
897b077aed3SPierre Pronchery       (void (*)(void))ecdsa_settable_ctx_md_params },
898*e7be843bSPierre Pronchery     OSSL_DISPATCH_END
899b077aed3SPierre Pronchery };
900*e7be843bSPierre Pronchery 
901*e7be843bSPierre Pronchery /* ------------------------------------------------------------------ */
902*e7be843bSPierre Pronchery 
903*e7be843bSPierre Pronchery /*
904*e7be843bSPierre Pronchery  * So called sigalgs (composite ECDSA+hash) implemented below.  They
905*e7be843bSPierre Pronchery  * are pretty much hard coded.
906*e7be843bSPierre Pronchery  */
907*e7be843bSPierre Pronchery 
908*e7be843bSPierre Pronchery static OSSL_FUNC_signature_query_key_types_fn ecdsa_sigalg_query_key_types;
909*e7be843bSPierre Pronchery static OSSL_FUNC_signature_settable_ctx_params_fn ecdsa_sigalg_settable_ctx_params;
910*e7be843bSPierre Pronchery static OSSL_FUNC_signature_set_ctx_params_fn ecdsa_sigalg_set_ctx_params;
911*e7be843bSPierre Pronchery 
912*e7be843bSPierre Pronchery /*
913*e7be843bSPierre Pronchery  * ecdsa_sigalg_signverify_init() is almost like ecdsa_digest_signverify_init(),
914*e7be843bSPierre Pronchery  * just doesn't allow fetching an MD from whatever the user chooses.
915*e7be843bSPierre Pronchery  */
916*e7be843bSPierre Pronchery static int ecdsa_sigalg_signverify_init(void *vctx, void *vec,
917*e7be843bSPierre Pronchery                                       OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params,
918*e7be843bSPierre Pronchery                                       const OSSL_PARAM params[],
919*e7be843bSPierre Pronchery                                       const char *mdname,
920*e7be843bSPierre Pronchery                                       int operation, const char *desc)
921*e7be843bSPierre Pronchery {
922*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
923*e7be843bSPierre Pronchery 
924*e7be843bSPierre Pronchery     if (!ossl_prov_is_running())
925*e7be843bSPierre Pronchery         return 0;
926*e7be843bSPierre Pronchery 
927*e7be843bSPierre Pronchery     if (!ecdsa_signverify_init(vctx, vec, set_ctx_params, params, operation,
928*e7be843bSPierre Pronchery                                desc))
929*e7be843bSPierre Pronchery         return 0;
930*e7be843bSPierre Pronchery 
931*e7be843bSPierre Pronchery     if (!ecdsa_setup_md(ctx, mdname, NULL, desc))
932*e7be843bSPierre Pronchery         return 0;
933*e7be843bSPierre Pronchery 
934*e7be843bSPierre Pronchery     ctx->flag_sigalg = 1;
935*e7be843bSPierre Pronchery     ctx->flag_allow_md = 0;
936*e7be843bSPierre Pronchery 
937*e7be843bSPierre Pronchery     if (ctx->mdctx == NULL) {
938*e7be843bSPierre Pronchery         ctx->mdctx = EVP_MD_CTX_new();
939*e7be843bSPierre Pronchery         if (ctx->mdctx == NULL)
940*e7be843bSPierre Pronchery             goto error;
941*e7be843bSPierre Pronchery     }
942*e7be843bSPierre Pronchery 
943*e7be843bSPierre Pronchery     if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params))
944*e7be843bSPierre Pronchery         goto error;
945*e7be843bSPierre Pronchery 
946*e7be843bSPierre Pronchery     return 1;
947*e7be843bSPierre Pronchery 
948*e7be843bSPierre Pronchery  error:
949*e7be843bSPierre Pronchery     EVP_MD_CTX_free(ctx->mdctx);
950*e7be843bSPierre Pronchery     ctx->mdctx = NULL;
951*e7be843bSPierre Pronchery     return 0;
952*e7be843bSPierre Pronchery }
953*e7be843bSPierre Pronchery 
954*e7be843bSPierre Pronchery static const char **ecdsa_sigalg_query_key_types(void)
955*e7be843bSPierre Pronchery {
956*e7be843bSPierre Pronchery     static const char *keytypes[] = { "EC", NULL };
957*e7be843bSPierre Pronchery 
958*e7be843bSPierre Pronchery     return keytypes;
959*e7be843bSPierre Pronchery }
960*e7be843bSPierre Pronchery 
961*e7be843bSPierre Pronchery static const OSSL_PARAM settable_sigalg_ctx_params[] = {
962*e7be843bSPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0),
963*e7be843bSPierre Pronchery     ECDSA_COMMON_SETTABLE_CTX_PARAMS
964*e7be843bSPierre Pronchery };
965*e7be843bSPierre Pronchery 
966*e7be843bSPierre Pronchery static const OSSL_PARAM *ecdsa_sigalg_settable_ctx_params(void *vctx,
967*e7be843bSPierre Pronchery                                                         ossl_unused void *provctx)
968*e7be843bSPierre Pronchery {
969*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
970*e7be843bSPierre Pronchery 
971*e7be843bSPierre Pronchery     if (ctx != NULL && ctx->operation == EVP_PKEY_OP_VERIFYMSG)
972*e7be843bSPierre Pronchery         return settable_sigalg_ctx_params;
973*e7be843bSPierre Pronchery     return NULL;
974*e7be843bSPierre Pronchery }
975*e7be843bSPierre Pronchery 
976*e7be843bSPierre Pronchery static int ecdsa_sigalg_set_ctx_params(void *vctx, const OSSL_PARAM params[])
977*e7be843bSPierre Pronchery {
978*e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
979*e7be843bSPierre Pronchery     const OSSL_PARAM *p;
980*e7be843bSPierre Pronchery     int ret;
981*e7be843bSPierre Pronchery 
982*e7be843bSPierre Pronchery     if (ctx == NULL)
983*e7be843bSPierre Pronchery         return 0;
984*e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
985*e7be843bSPierre Pronchery         return 1;
986*e7be843bSPierre Pronchery 
987*e7be843bSPierre Pronchery     if ((ret = ecdsa_common_set_ctx_params(ctx, params)) <= 0)
988*e7be843bSPierre Pronchery         return ret;
989*e7be843bSPierre Pronchery 
990*e7be843bSPierre Pronchery     if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) {
991*e7be843bSPierre Pronchery         p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE);
992*e7be843bSPierre Pronchery         if (p != NULL) {
993*e7be843bSPierre Pronchery             OPENSSL_free(ctx->sig);
994*e7be843bSPierre Pronchery             ctx->sig = NULL;
995*e7be843bSPierre Pronchery             ctx->siglen = 0;
996*e7be843bSPierre Pronchery             if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sig,
997*e7be843bSPierre Pronchery                                              0, &ctx->siglen))
998*e7be843bSPierre Pronchery                 return 0;
999*e7be843bSPierre Pronchery         }
1000*e7be843bSPierre Pronchery     }
1001*e7be843bSPierre Pronchery     return 1;
1002*e7be843bSPierre Pronchery }
1003*e7be843bSPierre Pronchery 
1004*e7be843bSPierre Pronchery #define IMPL_ECDSA_SIGALG(md, MD)                                       \
1005*e7be843bSPierre Pronchery     static OSSL_FUNC_signature_sign_init_fn ecdsa_##md##_sign_init;     \
1006*e7be843bSPierre Pronchery     static OSSL_FUNC_signature_sign_message_init_fn                     \
1007*e7be843bSPierre Pronchery         ecdsa_##md##_sign_message_init;                                 \
1008*e7be843bSPierre Pronchery     static OSSL_FUNC_signature_verify_init_fn ecdsa_##md##_verify_init; \
1009*e7be843bSPierre Pronchery     static OSSL_FUNC_signature_verify_message_init_fn                   \
1010*e7be843bSPierre Pronchery         ecdsa_##md##_verify_message_init;                               \
1011*e7be843bSPierre Pronchery                                                                         \
1012*e7be843bSPierre Pronchery     static int                                                          \
1013*e7be843bSPierre Pronchery     ecdsa_##md##_sign_init(void *vctx, void *vec,                       \
1014*e7be843bSPierre Pronchery                          const OSSL_PARAM params[])                     \
1015*e7be843bSPierre Pronchery     {                                                                   \
1016*e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Sign Init";           \
1017*e7be843bSPierre Pronchery                                                                         \
1018*e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1019*e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1020*e7be843bSPierre Pronchery                                             params, #MD,                \
1021*e7be843bSPierre Pronchery                                             EVP_PKEY_OP_SIGN,           \
1022*e7be843bSPierre Pronchery                                             desc);                      \
1023*e7be843bSPierre Pronchery     }                                                                   \
1024*e7be843bSPierre Pronchery                                                                         \
1025*e7be843bSPierre Pronchery     static int                                                          \
1026*e7be843bSPierre Pronchery     ecdsa_##md##_sign_message_init(void *vctx, void *vec,               \
1027*e7be843bSPierre Pronchery                                    const OSSL_PARAM params[])           \
1028*e7be843bSPierre Pronchery     {                                                                   \
1029*e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Sign Message Init";   \
1030*e7be843bSPierre Pronchery                                                                         \
1031*e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1032*e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1033*e7be843bSPierre Pronchery                                             params, #MD,                \
1034*e7be843bSPierre Pronchery                                             EVP_PKEY_OP_SIGNMSG,        \
1035*e7be843bSPierre Pronchery                                             desc);                      \
1036*e7be843bSPierre Pronchery     }                                                                   \
1037*e7be843bSPierre Pronchery                                                                         \
1038*e7be843bSPierre Pronchery     static int                                                          \
1039*e7be843bSPierre Pronchery     ecdsa_##md##_verify_init(void *vctx, void *vec,                     \
1040*e7be843bSPierre Pronchery                            const OSSL_PARAM params[])                   \
1041*e7be843bSPierre Pronchery     {                                                                   \
1042*e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Verify Init";         \
1043*e7be843bSPierre Pronchery                                                                         \
1044*e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1045*e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1046*e7be843bSPierre Pronchery                                             params, #MD,                \
1047*e7be843bSPierre Pronchery                                             EVP_PKEY_OP_VERIFY,         \
1048*e7be843bSPierre Pronchery                                             desc);                      \
1049*e7be843bSPierre Pronchery     }                                                                   \
1050*e7be843bSPierre Pronchery                                                                         \
1051*e7be843bSPierre Pronchery     static int                                                          \
1052*e7be843bSPierre Pronchery     ecdsa_##md##_verify_message_init(void *vctx, void *vec,             \
1053*e7be843bSPierre Pronchery                                      const OSSL_PARAM params[])         \
1054*e7be843bSPierre Pronchery     {                                                                   \
1055*e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Verify Message Init"; \
1056*e7be843bSPierre Pronchery                                                                         \
1057*e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1058*e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1059*e7be843bSPierre Pronchery                                             params, #MD,                \
1060*e7be843bSPierre Pronchery                                             EVP_PKEY_OP_VERIFYMSG,      \
1061*e7be843bSPierre Pronchery                                             desc);                      \
1062*e7be843bSPierre Pronchery     }                                                                   \
1063*e7be843bSPierre Pronchery                                                                         \
1064*e7be843bSPierre Pronchery     const OSSL_DISPATCH ossl_ecdsa_##md##_signature_functions[] = {     \
1065*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ecdsa_newctx },   \
1066*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_INIT,                                \
1067*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_sign_init },                     \
1068*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ecdsa_sign },       \
1069*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT,                        \
1070*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_sign_message_init },             \
1071*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE,                      \
1072*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_signverify_message_update },            \
1073*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL,                       \
1074*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sign_message_final },                   \
1075*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_INIT,                              \
1076*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_verify_init },                   \
1077*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY,                                   \
1078*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_verify },                               \
1079*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT,                      \
1080*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_verify_message_init },           \
1081*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE,                    \
1082*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_signverify_message_update },            \
1083*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL,                     \
1084*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_verify_message_final },                 \
1085*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ecdsa_freectx }, \
1086*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ecdsa_dupctx },   \
1087*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES,                          \
1088*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sigalg_query_key_types },               \
1089*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS,                           \
1090*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_get_ctx_params },                       \
1091*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,                      \
1092*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_gettable_ctx_params },                  \
1093*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS,                           \
1094*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sigalg_set_ctx_params },                \
1095*e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,                      \
1096*e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sigalg_settable_ctx_params },           \
1097*e7be843bSPierre Pronchery         OSSL_DISPATCH_END                                               \
1098*e7be843bSPierre Pronchery     }
1099*e7be843bSPierre Pronchery 
1100*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha1, SHA1);
1101*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha224, SHA2-224);
1102*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha256, SHA2-256);
1103*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha384, SHA2-384);
1104*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha512, SHA2-512);
1105*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_224, SHA3-224);
1106*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_256, SHA3-256);
1107*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_384, SHA3-384);
1108*e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_512, SHA3-512);
1109