xref: /freebsd/crypto/openssl/providers/implementations/signature/ecdsa_sig.c (revision 88b8b7f0c4e9948667a2279e78e975a784049cba)
1b077aed3SPierre Pronchery /*
2e7be843bSPierre 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"
28e7be843bSPierre 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"
34e7be843bSPierre 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;
40e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_update_fn ecdsa_signverify_message_update;
41e7be843bSPierre Pronchery static OSSL_FUNC_signature_sign_message_final_fn ecdsa_sign_message_final;
42b077aed3SPierre Pronchery static OSSL_FUNC_signature_verify_fn ecdsa_verify;
43e7be843bSPierre Pronchery static OSSL_FUNC_signature_verify_message_update_fn ecdsa_signverify_message_update;
44e7be843bSPierre 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;
53e7be843bSPierre 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;
62e7be843bSPierre Pronchery static OSSL_FUNC_signature_set_ctx_params_fn ecdsa_sigalg_set_ctx_params;
63e7be843bSPierre 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;
75e7be843bSPierre Pronchery     /* |operation| reuses EVP's operation bitfield */
76e7be843bSPierre Pronchery     int operation;
77b077aed3SPierre Pronchery 
78b077aed3SPierre Pronchery     /*
79e7be843bSPierre Pronchery      * Flag to determine if a full sigalg is run (1) or if a composable
80e7be843bSPierre Pronchery      * signature algorithm is run (0).
81e7be843bSPierre Pronchery      *
82e7be843bSPierre Pronchery      * When a full sigalg is run (1), this currently affects the following
83e7be843bSPierre Pronchery      * other flags, which are to remain untouched after their initialization:
84e7be843bSPierre Pronchery      *
85e7be843bSPierre Pronchery      * - flag_allow_md (initialized to 0)
86e7be843bSPierre Pronchery      */
87e7be843bSPierre Pronchery     unsigned int flag_sigalg : 1;
88e7be843bSPierre 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 
100e7be843bSPierre Pronchery     /* main digest */
101e7be843bSPierre Pronchery     char mdname[OSSL_MAX_NAME_SIZE];
102b077aed3SPierre Pronchery     EVP_MD *md;
103b077aed3SPierre Pronchery     EVP_MD_CTX *mdctx;
104e7be843bSPierre Pronchery     size_t mdsize;
105e7be843bSPierre Pronchery 
106e7be843bSPierre Pronchery     /* Signature, for verification */
107e7be843bSPierre Pronchery     unsigned char *sig;
108e7be843bSPierre Pronchery     size_t siglen;
109e7be843bSPierre 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
129e7be843bSPierre Pronchery #ifdef FIPS_MODULE
130e7be843bSPierre Pronchery     /*
131e7be843bSPierre Pronchery      * FIPS 140-3 IG 2.4.B mandates that verification based on a digest of a
132e7be843bSPierre Pronchery      * message is not permitted.  However, signing based on a digest is still
133e7be843bSPierre Pronchery      * permitted.
134e7be843bSPierre Pronchery      */
135e7be843bSPierre Pronchery     int verify_message;
136e7be843bSPierre Pronchery #endif
137e7be843bSPierre Pronchery     /* If this is set then the generated k is not random */
138e7be843bSPierre Pronchery     unsigned int nonce_type;
139e7be843bSPierre Pronchery     OSSL_FIPS_IND_DECLARE
140b077aed3SPierre Pronchery } PROV_ECDSA_CTX;
141b077aed3SPierre Pronchery 
ecdsa_newctx(void * provctx,const char * propq)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 
153e7be843bSPierre Pronchery     OSSL_FIPS_IND_INIT(ctx)
154b077aed3SPierre Pronchery     ctx->flag_allow_md = 1;
155e7be843bSPierre Pronchery #ifdef FIPS_MODULE
156e7be843bSPierre Pronchery     ctx->verify_message = 1;
157e7be843bSPierre 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 
ecdsa_setup_md(PROV_ECDSA_CTX * ctx,const char * mdname,const char * mdprops,const char * desc)166e7be843bSPierre Pronchery static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx,
167e7be843bSPierre Pronchery                           const char *mdname, const char *mdprops,
168e7be843bSPierre Pronchery                           const char *desc)
169b077aed3SPierre Pronchery {
170e7be843bSPierre Pronchery     EVP_MD *md = NULL;
171e7be843bSPierre Pronchery     size_t mdname_len;
172e7be843bSPierre Pronchery     int md_nid, md_size;
173e7be843bSPierre Pronchery     WPACKET pkt;
174e7be843bSPierre Pronchery     unsigned char *aid = NULL;
175b077aed3SPierre Pronchery 
176e7be843bSPierre Pronchery     if (mdname == NULL)
177e7be843bSPierre Pronchery         return 1;
178e7be843bSPierre Pronchery 
179e7be843bSPierre Pronchery     mdname_len = strlen(mdname);
180e7be843bSPierre Pronchery     if (mdname_len >= sizeof(ctx->mdname)) {
181e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
182e7be843bSPierre Pronchery                        "%s exceeds name buffer length", mdname);
183e7be843bSPierre Pronchery         return 0;
184e7be843bSPierre Pronchery     }
185e7be843bSPierre Pronchery     if (mdprops == NULL)
186e7be843bSPierre Pronchery         mdprops = ctx->propq;
187e7be843bSPierre Pronchery     md = EVP_MD_fetch(ctx->libctx, mdname, mdprops);
188e7be843bSPierre Pronchery     if (md == NULL) {
189e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
190e7be843bSPierre Pronchery                        "%s could not be fetched", mdname);
191e7be843bSPierre Pronchery         return 0;
192e7be843bSPierre Pronchery     }
193e7be843bSPierre Pronchery     md_size = EVP_MD_get_size(md);
194e7be843bSPierre Pronchery     if (md_size <= 0) {
195e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST,
196e7be843bSPierre Pronchery                        "%s has invalid md size %d", mdname, md_size);
197e7be843bSPierre Pronchery         goto err;
198e7be843bSPierre Pronchery     }
199e7be843bSPierre Pronchery     md_nid = ossl_digest_get_approved_nid(md);
200e7be843bSPierre Pronchery #ifdef FIPS_MODULE
201e7be843bSPierre Pronchery     if (md_nid == NID_undef) {
202e7be843bSPierre Pronchery         ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
203e7be843bSPierre Pronchery                        "digest=%s", mdname);
204e7be843bSPierre Pronchery         goto err;
205e7be843bSPierre Pronchery     }
206e7be843bSPierre Pronchery #endif
207e7be843bSPierre Pronchery     /* XOF digests don't work */
208e7be843bSPierre Pronchery     if (EVP_MD_xof(md)) {
209e7be843bSPierre Pronchery         ERR_raise(ERR_LIB_PROV, PROV_R_XOF_DIGESTS_NOT_ALLOWED);
210e7be843bSPierre Pronchery         goto err;
211e7be843bSPierre Pronchery     }
212e7be843bSPierre Pronchery 
213e7be843bSPierre Pronchery #ifdef FIPS_MODULE
214e7be843bSPierre Pronchery     {
215e7be843bSPierre Pronchery         int sha1_allowed
216e7be843bSPierre Pronchery             = ((ctx->operation
217e7be843bSPierre Pronchery                 & (EVP_PKEY_OP_SIGN | EVP_PKEY_OP_SIGNMSG)) == 0);
218e7be843bSPierre Pronchery 
219e7be843bSPierre Pronchery         if (!ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND_GET(ctx),
220e7be843bSPierre Pronchery                                              OSSL_FIPS_IND_SETTABLE1,
221e7be843bSPierre Pronchery                                              ctx->libctx,
222*88b8b7f0SEnji Cooper                                              md_nid, sha1_allowed, 0, desc,
223e7be843bSPierre Pronchery                                              ossl_fips_config_signature_digest_check))
224e7be843bSPierre Pronchery             goto err;
225e7be843bSPierre Pronchery     }
226e7be843bSPierre Pronchery #endif
227e7be843bSPierre Pronchery 
228e7be843bSPierre Pronchery     if (!ctx->flag_allow_md) {
229e7be843bSPierre Pronchery         if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) {
230e7be843bSPierre Pronchery             ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED,
231e7be843bSPierre Pronchery                            "digest %s != %s", mdname, ctx->mdname);
232e7be843bSPierre Pronchery             goto err;
233e7be843bSPierre Pronchery         }
234e7be843bSPierre Pronchery         EVP_MD_free(md);
235e7be843bSPierre Pronchery         return 1;
236e7be843bSPierre Pronchery     }
237e7be843bSPierre Pronchery 
238e7be843bSPierre Pronchery     EVP_MD_CTX_free(ctx->mdctx);
239e7be843bSPierre Pronchery     EVP_MD_free(ctx->md);
240e7be843bSPierre Pronchery 
241e7be843bSPierre Pronchery     ctx->aid_len = 0;
242e7be843bSPierre Pronchery #ifndef FIPS_MODULE
243e7be843bSPierre Pronchery     if (md_nid != NID_undef) {
244e7be843bSPierre Pronchery #else
245e7be843bSPierre Pronchery     {
246e7be843bSPierre Pronchery #endif
247e7be843bSPierre Pronchery         if (WPACKET_init_der(&pkt, ctx->aid_buf, sizeof(ctx->aid_buf))
248e7be843bSPierre Pronchery             && ossl_DER_w_algorithmIdentifier_ECDSA_with_MD(&pkt, -1, ctx->ec,
249e7be843bSPierre Pronchery                                                             md_nid)
250e7be843bSPierre Pronchery             && WPACKET_finish(&pkt)) {
251e7be843bSPierre Pronchery             WPACKET_get_total_written(&pkt, &ctx->aid_len);
252e7be843bSPierre Pronchery             aid = WPACKET_get_curr(&pkt);
253e7be843bSPierre Pronchery         }
254e7be843bSPierre Pronchery         WPACKET_cleanup(&pkt);
255e7be843bSPierre Pronchery         if (aid != NULL && ctx->aid_len != 0)
256e7be843bSPierre Pronchery             memmove(ctx->aid_buf, aid, ctx->aid_len);
257e7be843bSPierre Pronchery     }
258e7be843bSPierre Pronchery 
259e7be843bSPierre Pronchery     ctx->mdctx = NULL;
260e7be843bSPierre Pronchery     ctx->md = md;
261e7be843bSPierre Pronchery     ctx->mdsize = (size_t)md_size;
262e7be843bSPierre Pronchery     OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname));
263e7be843bSPierre Pronchery 
264e7be843bSPierre Pronchery     return 1;
265e7be843bSPierre Pronchery  err:
266e7be843bSPierre Pronchery     EVP_MD_free(md);
267e7be843bSPierre Pronchery     return 0;
268e7be843bSPierre Pronchery }
269e7be843bSPierre Pronchery 
270e7be843bSPierre Pronchery static int
271e7be843bSPierre Pronchery ecdsa_signverify_init(PROV_ECDSA_CTX *ctx, void *ec,
272e7be843bSPierre Pronchery                       OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params,
273e7be843bSPierre Pronchery                       const OSSL_PARAM params[], int operation,
274e7be843bSPierre Pronchery                       const char *desc)
275e7be843bSPierre 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 
294e7be843bSPierre Pronchery     OSSL_FIPS_IND_SET_APPROVED(ctx)
295e7be843bSPierre Pronchery     if (!set_ctx_params(ctx, params))
296b077aed3SPierre Pronchery         return 0;
297e7be843bSPierre Pronchery #ifdef FIPS_MODULE
298e7be843bSPierre Pronchery     if (!ossl_fips_ind_ec_key_check(OSSL_FIPS_IND_GET(ctx),
299e7be843bSPierre Pronchery                                     OSSL_FIPS_IND_SETTABLE0, ctx->libctx,
300e7be843bSPierre Pronchery                                     EC_KEY_get0_group(ctx->ec), desc,
301e7be843bSPierre Pronchery                                     (operation & (EVP_PKEY_OP_SIGN
302e7be843bSPierre Pronchery                                                   | EVP_PKEY_OP_SIGNMSG)) != 0))
303e7be843bSPierre Pronchery         return 0;
304e7be843bSPierre 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 {
310e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
311e7be843bSPierre Pronchery 
312e7be843bSPierre Pronchery #ifdef FIPS_MODULE
313e7be843bSPierre Pronchery     ctx->verify_message = 1;
314e7be843bSPierre Pronchery #endif
315e7be843bSPierre Pronchery     return ecdsa_signverify_init(ctx, ec, ecdsa_set_ctx_params, params,
316e7be843bSPierre Pronchery                                  EVP_PKEY_OP_SIGN, "ECDSA Sign Init");
317b077aed3SPierre Pronchery }
318b077aed3SPierre Pronchery 
319e7be843bSPierre Pronchery /*
320e7be843bSPierre Pronchery  * Sign tbs without digesting it first.  This is suitable for "primitive"
321e7be843bSPierre Pronchery  * signing and signing the digest of a message.
322e7be843bSPierre Pronchery  */
323e7be843bSPierre Pronchery static int ecdsa_sign_directly(void *vctx,
324e7be843bSPierre Pronchery                                unsigned char *sig, size_t *siglen, size_t sigsize,
325e7be843bSPierre 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 
351e7be843bSPierre Pronchery     if (ctx->nonce_type != 0) {
352e7be843bSPierre Pronchery         const char *mdname = NULL;
353e7be843bSPierre Pronchery 
354e7be843bSPierre Pronchery         if (ctx->mdname[0] != '\0')
355e7be843bSPierre Pronchery             mdname = ctx->mdname;
356e7be843bSPierre Pronchery         ret = ossl_ecdsa_deterministic_sign(tbs, tbslen, sig, &sltmp,
357e7be843bSPierre Pronchery                                             ctx->ec, ctx->nonce_type,
358e7be843bSPierre Pronchery                                             mdname,
359e7be843bSPierre Pronchery                                             ctx->libctx, ctx->propq);
360e7be843bSPierre Pronchery     } else {
361e7be843bSPierre Pronchery         ret = ECDSA_sign_ex(0, tbs, tbslen, sig, &sltmp, ctx->kinv, ctx->r,
362e7be843bSPierre Pronchery                             ctx->ec);
363e7be843bSPierre Pronchery     }
364b077aed3SPierre Pronchery     if (ret <= 0)
365b077aed3SPierre Pronchery         return 0;
366b077aed3SPierre Pronchery 
367b077aed3SPierre Pronchery     *siglen = sltmp;
368b077aed3SPierre Pronchery     return 1;
369b077aed3SPierre Pronchery }
370b077aed3SPierre Pronchery 
371e7be843bSPierre Pronchery static int ecdsa_signverify_message_update(void *vctx,
372e7be843bSPierre Pronchery                                          const unsigned char *data,
373e7be843bSPierre Pronchery                                          size_t datalen)
374e7be843bSPierre Pronchery {
375e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
376e7be843bSPierre Pronchery 
377e7be843bSPierre Pronchery     if (ctx == NULL)
378e7be843bSPierre Pronchery         return 0;
379e7be843bSPierre Pronchery 
380e7be843bSPierre Pronchery     return EVP_DigestUpdate(ctx->mdctx, data, datalen);
381e7be843bSPierre Pronchery }
382e7be843bSPierre Pronchery 
383e7be843bSPierre Pronchery static int ecdsa_sign_message_final(void *vctx, unsigned char *sig,
384e7be843bSPierre Pronchery                                   size_t *siglen, size_t sigsize)
385e7be843bSPierre Pronchery {
386e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
387e7be843bSPierre Pronchery     unsigned char digest[EVP_MAX_MD_SIZE];
388e7be843bSPierre Pronchery     unsigned int dlen = 0;
389e7be843bSPierre Pronchery 
390e7be843bSPierre Pronchery     if (!ossl_prov_is_running() || ctx == NULL)
391e7be843bSPierre Pronchery         return 0;
392e7be843bSPierre Pronchery     if (ctx->mdctx == NULL)
393e7be843bSPierre Pronchery         return 0;
394e7be843bSPierre Pronchery     /*
395e7be843bSPierre Pronchery      * If sig is NULL then we're just finding out the sig size. Other fields
396e7be843bSPierre Pronchery      * are ignored. Defer to ecdsa_sign.
397e7be843bSPierre Pronchery      */
398e7be843bSPierre Pronchery     if (sig != NULL
399e7be843bSPierre Pronchery         && !EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
400e7be843bSPierre Pronchery         return 0;
401e7be843bSPierre Pronchery     return ecdsa_sign_directly(vctx, sig, siglen, sigsize, digest, dlen);
402e7be843bSPierre Pronchery }
403e7be843bSPierre Pronchery 
404e7be843bSPierre Pronchery /*
405e7be843bSPierre Pronchery  * If signing a message, digest tbs and sign the result.
406e7be843bSPierre Pronchery  * Otherwise, sign tbs directly.
407e7be843bSPierre Pronchery  */
408e7be843bSPierre Pronchery static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen,
409e7be843bSPierre Pronchery                     size_t sigsize, const unsigned char *tbs, size_t tbslen)
410e7be843bSPierre Pronchery {
411e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
412e7be843bSPierre Pronchery 
413e7be843bSPierre Pronchery     if (ctx->operation == EVP_PKEY_OP_SIGNMSG) {
414e7be843bSPierre Pronchery         /*
415e7be843bSPierre Pronchery          * If |sig| is NULL, the caller is only looking for the sig length.
416e7be843bSPierre Pronchery          * DO NOT update the input in this case.
417e7be843bSPierre Pronchery          */
418e7be843bSPierre Pronchery         if (sig == NULL)
419e7be843bSPierre Pronchery             return ecdsa_sign_message_final(ctx, sig, siglen, sigsize);
420e7be843bSPierre Pronchery 
421e7be843bSPierre Pronchery         if (ecdsa_signverify_message_update(ctx, tbs, tbslen) <= 0)
422e7be843bSPierre Pronchery             return 0;
423e7be843bSPierre Pronchery         return ecdsa_sign_message_final(ctx, sig, siglen, sigsize);
424e7be843bSPierre Pronchery     }
425e7be843bSPierre Pronchery     return ecdsa_sign_directly(ctx, sig, siglen, sigsize, tbs, tbslen);
426e7be843bSPierre Pronchery }
427e7be843bSPierre Pronchery 
428e7be843bSPierre Pronchery static int ecdsa_verify_init(void *vctx, void *ec, const OSSL_PARAM params[])
429e7be843bSPierre Pronchery {
430e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
431e7be843bSPierre Pronchery 
432e7be843bSPierre Pronchery #ifdef FIPS_MODULE
433e7be843bSPierre Pronchery     ctx->verify_message = 0;
434e7be843bSPierre Pronchery #endif
435e7be843bSPierre Pronchery     return ecdsa_signverify_init(ctx, ec, ecdsa_set_ctx_params, params,
436e7be843bSPierre Pronchery                                  EVP_PKEY_OP_VERIFY, "ECDSA Verify Init");
437e7be843bSPierre Pronchery }
438e7be843bSPierre Pronchery 
439e7be843bSPierre Pronchery static int ecdsa_verify_directly(void *vctx,
440e7be843bSPierre 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 
451e7be843bSPierre Pronchery static int ecdsa_verify_set_sig(void *vctx,
452e7be843bSPierre Pronchery                                 const unsigned char *sig, size_t siglen)
453b077aed3SPierre Pronchery {
454e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
455e7be843bSPierre Pronchery     OSSL_PARAM params[2];
456b077aed3SPierre Pronchery 
457e7be843bSPierre Pronchery     params[0] =
458e7be843bSPierre Pronchery         OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE,
459e7be843bSPierre Pronchery                                           (unsigned char *)sig, siglen);
460e7be843bSPierre Pronchery     params[1] = OSSL_PARAM_construct_end();
461e7be843bSPierre Pronchery     return ecdsa_sigalg_set_ctx_params(ctx, params);
462e7be843bSPierre Pronchery }
463b077aed3SPierre Pronchery 
464e7be843bSPierre Pronchery static int ecdsa_verify_message_final(void *vctx)
465e7be843bSPierre Pronchery {
466e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
467e7be843bSPierre Pronchery     unsigned char digest[EVP_MAX_MD_SIZE];
468e7be843bSPierre Pronchery     unsigned int dlen = 0;
469e7be843bSPierre Pronchery 
470e7be843bSPierre Pronchery     if (!ossl_prov_is_running() || ctx == NULL || ctx->mdctx == NULL)
471b077aed3SPierre Pronchery         return 0;
472e7be843bSPierre Pronchery 
473e7be843bSPierre Pronchery     /*
474e7be843bSPierre Pronchery      * The digests used here are all known (see ecdsa_get_md_nid()), so they
475e7be843bSPierre Pronchery      * should not exceed the internal buffer size of EVP_MAX_MD_SIZE.
476e7be843bSPierre Pronchery      */
477e7be843bSPierre Pronchery     if (!EVP_DigestFinal_ex(ctx->mdctx, digest, &dlen))
478b077aed3SPierre Pronchery         return 0;
479e7be843bSPierre Pronchery 
480e7be843bSPierre Pronchery     return ecdsa_verify_directly(vctx, ctx->sig, ctx->siglen,
481e7be843bSPierre Pronchery                                digest, dlen);
482b077aed3SPierre Pronchery }
483e7be843bSPierre Pronchery 
484e7be843bSPierre Pronchery /*
485e7be843bSPierre Pronchery  * If verifying a message, digest tbs and verify the result.
486e7be843bSPierre Pronchery  * Otherwise, verify tbs directly.
487e7be843bSPierre Pronchery  */
488e7be843bSPierre Pronchery static int ecdsa_verify(void *vctx,
489e7be843bSPierre Pronchery                       const unsigned char *sig, size_t siglen,
490e7be843bSPierre Pronchery                       const unsigned char *tbs, size_t tbslen)
491e7be843bSPierre Pronchery {
492e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
493e7be843bSPierre Pronchery 
494e7be843bSPierre Pronchery     if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) {
495e7be843bSPierre Pronchery         if (ecdsa_verify_set_sig(ctx, sig, siglen) <= 0)
496b077aed3SPierre Pronchery             return 0;
497e7be843bSPierre Pronchery         if (ecdsa_signverify_message_update(ctx, tbs, tbslen) <= 0)
498b077aed3SPierre Pronchery             return 0;
499e7be843bSPierre Pronchery         return ecdsa_verify_message_final(ctx);
500b077aed3SPierre Pronchery     }
501e7be843bSPierre Pronchery     return ecdsa_verify_directly(ctx, sig, siglen, tbs, tbslen);
502b077aed3SPierre Pronchery }
503b077aed3SPierre Pronchery 
504e7be843bSPierre 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[],
508e7be843bSPierre 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 
515e7be843bSPierre Pronchery #ifdef FIPS_MODULE
516e7be843bSPierre Pronchery     ctx->verify_message = 1;
517e7be843bSPierre Pronchery #endif
518e7be843bSPierre Pronchery     if (!ecdsa_signverify_init(vctx, ec, ecdsa_set_ctx_params, params,
519e7be843bSPierre Pronchery                                operation, desc))
520e7be843bSPierre Pronchery         return 0;
521e7be843bSPierre Pronchery 
522e7be843bSPierre Pronchery     if (mdname != NULL
523e7be843bSPierre Pronchery         /* was ecdsa_setup_md already called in ecdsa_signverify_init()? */
524e7be843bSPierre Pronchery         && (mdname[0] == '\0' || OPENSSL_strcasecmp(ctx->mdname, mdname) != 0)
525e7be843bSPierre 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,
549e7be843bSPierre Pronchery                                         EVP_PKEY_OP_SIGNMSG,
550e7be843bSPierre Pronchery                                         "ECDSA Digest Sign Init");
551b077aed3SPierre Pronchery }
552b077aed3SPierre Pronchery 
553e7be843bSPierre 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;
560e7be843bSPierre Pronchery     /* Sigalg implementations shouldn't do digest_sign */
561e7be843bSPierre Pronchery     if (ctx->flag_sigalg)
562e7be843bSPierre Pronchery         return 0;
563b077aed3SPierre Pronchery 
564e7be843bSPierre 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;
571e7be843bSPierre Pronchery     int ok = 0;
572b077aed3SPierre Pronchery 
573e7be843bSPierre Pronchery     if (ctx == NULL)
574e7be843bSPierre Pronchery         return 0;
575e7be843bSPierre Pronchery     /* Sigalg implementations shouldn't do digest_sign */
576e7be843bSPierre Pronchery     if (ctx->flag_sigalg)
577b077aed3SPierre Pronchery         return 0;
578b077aed3SPierre Pronchery 
579e7be843bSPierre Pronchery     ok = ecdsa_sign_message_final(ctx, sig, siglen, sigsize);
580e7be843bSPierre Pronchery 
581b077aed3SPierre Pronchery     ctx->flag_allow_md = 1;
582e7be843bSPierre Pronchery 
583e7be843bSPierre Pronchery     return ok;
584e7be843bSPierre Pronchery }
585e7be843bSPierre Pronchery 
586e7be843bSPierre Pronchery static int ecdsa_digest_verify_init(void *vctx, const char *mdname, void *ec,
587e7be843bSPierre Pronchery                                     const OSSL_PARAM params[])
588e7be843bSPierre Pronchery {
589e7be843bSPierre Pronchery     return ecdsa_digest_signverify_init(vctx, mdname, ec, params,
590e7be843bSPierre Pronchery                                         EVP_PKEY_OP_VERIFYMSG,
591e7be843bSPierre 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;
598e7be843bSPierre Pronchery     int ok = 0;
599b077aed3SPierre Pronchery 
600b077aed3SPierre Pronchery     if (!ossl_prov_is_running() || ctx == NULL || ctx->mdctx == NULL)
601b077aed3SPierre Pronchery         return 0;
602b077aed3SPierre Pronchery 
603e7be843bSPierre Pronchery     /* Sigalg implementations shouldn't do digest_verify */
604e7be843bSPierre Pronchery     if (ctx->flag_sigalg)
605b077aed3SPierre Pronchery         return 0;
606e7be843bSPierre Pronchery 
607e7be843bSPierre Pronchery     if (ecdsa_verify_set_sig(ctx, sig, siglen))
608e7be843bSPierre Pronchery         ok = ecdsa_verify_message_final(ctx);
609e7be843bSPierre Pronchery 
610b077aed3SPierre Pronchery     ctx->flag_allow_md = 1;
611e7be843bSPierre Pronchery 
612e7be843bSPierre 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);
621e7be843bSPierre Pronchery     OPENSSL_free(ctx->propq);
622e7be843bSPierre 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);
684e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_octet_string(p,
685e7be843bSPierre Pronchery                                                   ctx->aid_len == 0 ? NULL : ctx->aid_buf,
686e7be843bSPierre 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 
699e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE);
700e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->nonce_type))
701e7be843bSPierre Pronchery         return 0;
702e7be843bSPierre Pronchery 
703e7be843bSPierre Pronchery #ifdef FIPS_MODULE
704e7be843bSPierre Pronchery     p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_FIPS_VERIFY_MESSAGE);
705e7be843bSPierre Pronchery     if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->verify_message))
706e7be843bSPierre Pronchery         return 0;
707e7be843bSPierre Pronchery #endif
708e7be843bSPierre Pronchery 
709e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params))
710e7be843bSPierre 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),
718e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL),
719e7be843bSPierre Pronchery #ifdef FIPS_MODULE
720e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_FIPS_VERIFY_MESSAGE, NULL),
721e7be843bSPierre Pronchery #endif
722e7be843bSPierre 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 
732e7be843bSPierre Pronchery /**
733e7be843bSPierre Pronchery  * @brief Set up common params for ecdsa_set_ctx_params and
734e7be843bSPierre Pronchery  * ecdsa_sigalg_set_ctx_params. The caller is responsible for checking |vctx| is
735e7be843bSPierre Pronchery  * not NULL and |params| is not empty.
736e7be843bSPierre Pronchery  */
737e7be843bSPierre 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 
742e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params,
743e7be843bSPierre Pronchery                                      OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK))
744b077aed3SPierre Pronchery         return 0;
745e7be843bSPierre Pronchery     if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE1, params,
746e7be843bSPierre Pronchery                                      OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK))
747e7be843bSPierre 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 
755e7be843bSPierre Pronchery     p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE);
756e7be843bSPierre Pronchery     if (p != NULL
757e7be843bSPierre Pronchery         && !OSSL_PARAM_get_uint(p, &ctx->nonce_type))
758e7be843bSPierre Pronchery         return 0;
759e7be843bSPierre Pronchery     return 1;
760e7be843bSPierre Pronchery }
761e7be843bSPierre Pronchery 
762e7be843bSPierre Pronchery #define ECDSA_COMMON_SETTABLE_CTX_PARAMS                                      \
763e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL),                          \
764e7be843bSPierre Pronchery     OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL),                   \
765e7be843bSPierre Pronchery     OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)     \
766e7be843bSPierre Pronchery     OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)  \
767e7be843bSPierre Pronchery     OSSL_PARAM_END
768e7be843bSPierre Pronchery 
769e7be843bSPierre Pronchery static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[])
770e7be843bSPierre Pronchery {
771e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
772e7be843bSPierre Pronchery     const OSSL_PARAM *p;
773e7be843bSPierre Pronchery     size_t mdsize = 0;
774e7be843bSPierre Pronchery     int ret;
775e7be843bSPierre Pronchery 
776e7be843bSPierre Pronchery     if (ctx == NULL)
777e7be843bSPierre Pronchery         return 0;
778e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
779e7be843bSPierre Pronchery         return 1;
780e7be843bSPierre Pronchery 
781e7be843bSPierre Pronchery     if ((ret = ecdsa_common_set_ctx_params(ctx, params)) <= 0)
782e7be843bSPierre Pronchery         return ret;
783e7be843bSPierre 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;
797e7be843bSPierre 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),
815e7be843bSPierre 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 },
898e7be843bSPierre Pronchery     OSSL_DISPATCH_END
899b077aed3SPierre Pronchery };
900e7be843bSPierre Pronchery 
901e7be843bSPierre Pronchery /* ------------------------------------------------------------------ */
902e7be843bSPierre Pronchery 
903e7be843bSPierre Pronchery /*
904e7be843bSPierre Pronchery  * So called sigalgs (composite ECDSA+hash) implemented below.  They
905e7be843bSPierre Pronchery  * are pretty much hard coded.
906e7be843bSPierre Pronchery  */
907e7be843bSPierre Pronchery 
908e7be843bSPierre Pronchery static OSSL_FUNC_signature_query_key_types_fn ecdsa_sigalg_query_key_types;
909e7be843bSPierre Pronchery static OSSL_FUNC_signature_settable_ctx_params_fn ecdsa_sigalg_settable_ctx_params;
910e7be843bSPierre Pronchery static OSSL_FUNC_signature_set_ctx_params_fn ecdsa_sigalg_set_ctx_params;
911e7be843bSPierre Pronchery 
912e7be843bSPierre Pronchery /*
913e7be843bSPierre Pronchery  * ecdsa_sigalg_signverify_init() is almost like ecdsa_digest_signverify_init(),
914e7be843bSPierre Pronchery  * just doesn't allow fetching an MD from whatever the user chooses.
915e7be843bSPierre Pronchery  */
916e7be843bSPierre Pronchery static int ecdsa_sigalg_signverify_init(void *vctx, void *vec,
917e7be843bSPierre Pronchery                                       OSSL_FUNC_signature_set_ctx_params_fn *set_ctx_params,
918e7be843bSPierre Pronchery                                       const OSSL_PARAM params[],
919e7be843bSPierre Pronchery                                       const char *mdname,
920e7be843bSPierre Pronchery                                       int operation, const char *desc)
921e7be843bSPierre Pronchery {
922e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
923e7be843bSPierre Pronchery 
924e7be843bSPierre Pronchery     if (!ossl_prov_is_running())
925e7be843bSPierre Pronchery         return 0;
926e7be843bSPierre Pronchery 
927e7be843bSPierre Pronchery     if (!ecdsa_signverify_init(vctx, vec, set_ctx_params, params, operation,
928e7be843bSPierre Pronchery                                desc))
929e7be843bSPierre Pronchery         return 0;
930e7be843bSPierre Pronchery 
931e7be843bSPierre Pronchery     if (!ecdsa_setup_md(ctx, mdname, NULL, desc))
932e7be843bSPierre Pronchery         return 0;
933e7be843bSPierre Pronchery 
934e7be843bSPierre Pronchery     ctx->flag_sigalg = 1;
935e7be843bSPierre Pronchery     ctx->flag_allow_md = 0;
936e7be843bSPierre Pronchery 
937e7be843bSPierre Pronchery     if (ctx->mdctx == NULL) {
938e7be843bSPierre Pronchery         ctx->mdctx = EVP_MD_CTX_new();
939e7be843bSPierre Pronchery         if (ctx->mdctx == NULL)
940e7be843bSPierre Pronchery             goto error;
941e7be843bSPierre Pronchery     }
942e7be843bSPierre Pronchery 
943e7be843bSPierre Pronchery     if (!EVP_DigestInit_ex2(ctx->mdctx, ctx->md, params))
944e7be843bSPierre Pronchery         goto error;
945e7be843bSPierre Pronchery 
946e7be843bSPierre Pronchery     return 1;
947e7be843bSPierre Pronchery 
948e7be843bSPierre Pronchery  error:
949e7be843bSPierre Pronchery     EVP_MD_CTX_free(ctx->mdctx);
950e7be843bSPierre Pronchery     ctx->mdctx = NULL;
951e7be843bSPierre Pronchery     return 0;
952e7be843bSPierre Pronchery }
953e7be843bSPierre Pronchery 
954e7be843bSPierre Pronchery static const char **ecdsa_sigalg_query_key_types(void)
955e7be843bSPierre Pronchery {
956e7be843bSPierre Pronchery     static const char *keytypes[] = { "EC", NULL };
957e7be843bSPierre Pronchery 
958e7be843bSPierre Pronchery     return keytypes;
959e7be843bSPierre Pronchery }
960e7be843bSPierre Pronchery 
961e7be843bSPierre Pronchery static const OSSL_PARAM settable_sigalg_ctx_params[] = {
962e7be843bSPierre Pronchery     OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_SIGNATURE, NULL, 0),
963e7be843bSPierre Pronchery     ECDSA_COMMON_SETTABLE_CTX_PARAMS
964e7be843bSPierre Pronchery };
965e7be843bSPierre Pronchery 
966e7be843bSPierre Pronchery static const OSSL_PARAM *ecdsa_sigalg_settable_ctx_params(void *vctx,
967e7be843bSPierre Pronchery                                                         ossl_unused void *provctx)
968e7be843bSPierre Pronchery {
969e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
970e7be843bSPierre Pronchery 
971e7be843bSPierre Pronchery     if (ctx != NULL && ctx->operation == EVP_PKEY_OP_VERIFYMSG)
972e7be843bSPierre Pronchery         return settable_sigalg_ctx_params;
973e7be843bSPierre Pronchery     return NULL;
974e7be843bSPierre Pronchery }
975e7be843bSPierre Pronchery 
976e7be843bSPierre Pronchery static int ecdsa_sigalg_set_ctx_params(void *vctx, const OSSL_PARAM params[])
977e7be843bSPierre Pronchery {
978e7be843bSPierre Pronchery     PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx;
979e7be843bSPierre Pronchery     const OSSL_PARAM *p;
980e7be843bSPierre Pronchery     int ret;
981e7be843bSPierre Pronchery 
982e7be843bSPierre Pronchery     if (ctx == NULL)
983e7be843bSPierre Pronchery         return 0;
984e7be843bSPierre Pronchery     if (ossl_param_is_empty(params))
985e7be843bSPierre Pronchery         return 1;
986e7be843bSPierre Pronchery 
987e7be843bSPierre Pronchery     if ((ret = ecdsa_common_set_ctx_params(ctx, params)) <= 0)
988e7be843bSPierre Pronchery         return ret;
989e7be843bSPierre Pronchery 
990e7be843bSPierre Pronchery     if (ctx->operation == EVP_PKEY_OP_VERIFYMSG) {
991e7be843bSPierre Pronchery         p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_SIGNATURE);
992e7be843bSPierre Pronchery         if (p != NULL) {
993e7be843bSPierre Pronchery             OPENSSL_free(ctx->sig);
994e7be843bSPierre Pronchery             ctx->sig = NULL;
995e7be843bSPierre Pronchery             ctx->siglen = 0;
996e7be843bSPierre Pronchery             if (!OSSL_PARAM_get_octet_string(p, (void **)&ctx->sig,
997e7be843bSPierre Pronchery                                              0, &ctx->siglen))
998e7be843bSPierre Pronchery                 return 0;
999e7be843bSPierre Pronchery         }
1000e7be843bSPierre Pronchery     }
1001e7be843bSPierre Pronchery     return 1;
1002e7be843bSPierre Pronchery }
1003e7be843bSPierre Pronchery 
1004e7be843bSPierre Pronchery #define IMPL_ECDSA_SIGALG(md, MD)                                       \
1005e7be843bSPierre Pronchery     static OSSL_FUNC_signature_sign_init_fn ecdsa_##md##_sign_init;     \
1006e7be843bSPierre Pronchery     static OSSL_FUNC_signature_sign_message_init_fn                     \
1007e7be843bSPierre Pronchery         ecdsa_##md##_sign_message_init;                                 \
1008e7be843bSPierre Pronchery     static OSSL_FUNC_signature_verify_init_fn ecdsa_##md##_verify_init; \
1009e7be843bSPierre Pronchery     static OSSL_FUNC_signature_verify_message_init_fn                   \
1010e7be843bSPierre Pronchery         ecdsa_##md##_verify_message_init;                               \
1011e7be843bSPierre Pronchery                                                                         \
1012e7be843bSPierre Pronchery     static int                                                          \
1013e7be843bSPierre Pronchery     ecdsa_##md##_sign_init(void *vctx, void *vec,                       \
1014e7be843bSPierre Pronchery                          const OSSL_PARAM params[])                     \
1015e7be843bSPierre Pronchery     {                                                                   \
1016e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Sign Init";           \
1017e7be843bSPierre Pronchery                                                                         \
1018e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1019e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1020e7be843bSPierre Pronchery                                             params, #MD,                \
1021e7be843bSPierre Pronchery                                             EVP_PKEY_OP_SIGN,           \
1022e7be843bSPierre Pronchery                                             desc);                      \
1023e7be843bSPierre Pronchery     }                                                                   \
1024e7be843bSPierre Pronchery                                                                         \
1025e7be843bSPierre Pronchery     static int                                                          \
1026e7be843bSPierre Pronchery     ecdsa_##md##_sign_message_init(void *vctx, void *vec,               \
1027e7be843bSPierre Pronchery                                    const OSSL_PARAM params[])           \
1028e7be843bSPierre Pronchery     {                                                                   \
1029e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Sign Message Init";   \
1030e7be843bSPierre Pronchery                                                                         \
1031e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1032e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1033e7be843bSPierre Pronchery                                             params, #MD,                \
1034e7be843bSPierre Pronchery                                             EVP_PKEY_OP_SIGNMSG,        \
1035e7be843bSPierre Pronchery                                             desc);                      \
1036e7be843bSPierre Pronchery     }                                                                   \
1037e7be843bSPierre Pronchery                                                                         \
1038e7be843bSPierre Pronchery     static int                                                          \
1039e7be843bSPierre Pronchery     ecdsa_##md##_verify_init(void *vctx, void *vec,                     \
1040e7be843bSPierre Pronchery                            const OSSL_PARAM params[])                   \
1041e7be843bSPierre Pronchery     {                                                                   \
1042e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Verify Init";         \
1043e7be843bSPierre Pronchery                                                                         \
1044e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1045e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1046e7be843bSPierre Pronchery                                             params, #MD,                \
1047e7be843bSPierre Pronchery                                             EVP_PKEY_OP_VERIFY,         \
1048e7be843bSPierre Pronchery                                             desc);                      \
1049e7be843bSPierre Pronchery     }                                                                   \
1050e7be843bSPierre Pronchery                                                                         \
1051e7be843bSPierre Pronchery     static int                                                          \
1052e7be843bSPierre Pronchery     ecdsa_##md##_verify_message_init(void *vctx, void *vec,             \
1053e7be843bSPierre Pronchery                                      const OSSL_PARAM params[])         \
1054e7be843bSPierre Pronchery     {                                                                   \
1055e7be843bSPierre Pronchery         static const char desc[] = "ECDSA-" #MD " Verify Message Init"; \
1056e7be843bSPierre Pronchery                                                                         \
1057e7be843bSPierre Pronchery         return ecdsa_sigalg_signverify_init(vctx, vec,                  \
1058e7be843bSPierre Pronchery                                             ecdsa_sigalg_set_ctx_params, \
1059e7be843bSPierre Pronchery                                             params, #MD,                \
1060e7be843bSPierre Pronchery                                             EVP_PKEY_OP_VERIFYMSG,      \
1061e7be843bSPierre Pronchery                                             desc);                      \
1062e7be843bSPierre Pronchery     }                                                                   \
1063e7be843bSPierre Pronchery                                                                         \
1064e7be843bSPierre Pronchery     const OSSL_DISPATCH ossl_ecdsa_##md##_signature_functions[] = {     \
1065e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))ecdsa_newctx },   \
1066e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_INIT,                                \
1067e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_sign_init },                     \
1068e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN, (void (*)(void))ecdsa_sign },       \
1069e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_INIT,                        \
1070e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_sign_message_init },             \
1071e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_UPDATE,                      \
1072e7be843bSPierre Pronchery           (void (*)(void))ecdsa_signverify_message_update },            \
1073e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SIGN_MESSAGE_FINAL,                       \
1074e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sign_message_final },                   \
1075e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_INIT,                              \
1076e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_verify_init },                   \
1077e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY,                                   \
1078e7be843bSPierre Pronchery           (void (*)(void))ecdsa_verify },                               \
1079e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_INIT,                      \
1080e7be843bSPierre Pronchery           (void (*)(void))ecdsa_##md##_verify_message_init },           \
1081e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_UPDATE,                    \
1082e7be843bSPierre Pronchery           (void (*)(void))ecdsa_signverify_message_update },            \
1083e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_VERIFY_MESSAGE_FINAL,                     \
1084e7be843bSPierre Pronchery           (void (*)(void))ecdsa_verify_message_final },                 \
1085e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))ecdsa_freectx }, \
1086e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))ecdsa_dupctx },   \
1087e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_QUERY_KEY_TYPES,                          \
1088e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sigalg_query_key_types },               \
1089e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS,                           \
1090e7be843bSPierre Pronchery           (void (*)(void))ecdsa_get_ctx_params },                       \
1091e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS,                      \
1092e7be843bSPierre Pronchery           (void (*)(void))ecdsa_gettable_ctx_params },                  \
1093e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SET_CTX_PARAMS,                           \
1094e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sigalg_set_ctx_params },                \
1095e7be843bSPierre Pronchery         { OSSL_FUNC_SIGNATURE_SETTABLE_CTX_PARAMS,                      \
1096e7be843bSPierre Pronchery           (void (*)(void))ecdsa_sigalg_settable_ctx_params },           \
1097e7be843bSPierre Pronchery         OSSL_DISPATCH_END                                               \
1098e7be843bSPierre Pronchery     }
1099e7be843bSPierre Pronchery 
1100e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha1, SHA1);
1101e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha224, SHA2-224);
1102e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha256, SHA2-256);
1103e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha384, SHA2-384);
1104e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha512, SHA2-512);
1105e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_224, SHA3-224);
1106e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_256, SHA3-256);
1107e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_384, SHA3-384);
1108e7be843bSPierre Pronchery IMPL_ECDSA_SIGALG(sha3_512, SHA3-512);
1109