blob: 2f7a996a7e73383167737cd671fe4677f029326c [file] [log] [blame]
Jens Wiklander817466c2018-05-22 13:49:31 +02001/*
2 * Elliptic curve DSA
3 *
Jerome Forissier79013242021-07-28 10:24:04 +02004 * Copyright The Mbed TLS Contributors
Tom Van Eyckc1633172024-04-09 18:44:13 +02005 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Jens Wiklander817466c2018-05-22 13:49:31 +02006 */
7
8/*
9 * References:
10 *
Tom Van Eyckc1633172024-04-09 18:44:13 +020011 * SEC1 https://www.secg.org/sec1-v2.pdf
Jens Wiklander817466c2018-05-22 13:49:31 +020012 */
13
Jerome Forissier79013242021-07-28 10:24:04 +020014#include "common.h"
Jens Wiklander817466c2018-05-22 13:49:31 +020015
16#if defined(MBEDTLS_ECDSA_C)
17
18#include "mbedtls/ecdsa.h"
19#include "mbedtls/asn1write.h"
20
21#include <string.h>
22
23#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
24#include "mbedtls/hmac_drbg.h"
25#endif
26
Jens Wiklander3d3b0592019-03-20 15:30:29 +010027#include "mbedtls/platform.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010028
29#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020030#include "mbedtls/error.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010031
Jens Wiklander3d3b0592019-03-20 15:30:29 +010032#if defined(MBEDTLS_ECP_RESTARTABLE)
33
34/*
35 * Sub-context for ecdsa_verify()
36 */
Jens Wiklander32b31802023-10-06 16:59:46 +020037struct mbedtls_ecdsa_restart_ver {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010038 mbedtls_mpi u1, u2; /* intermediate values */
39 enum { /* what to do next? */
40 ecdsa_ver_init = 0, /* getting started */
41 ecdsa_ver_muladd, /* muladd step */
42 } state;
43};
44
45/*
46 * Init verify restart sub-context
47 */
Jens Wiklander32b31802023-10-06 16:59:46 +020048static void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010049{
Jens Wiklander32b31802023-10-06 16:59:46 +020050 mbedtls_mpi_init(&ctx->u1);
51 mbedtls_mpi_init(&ctx->u2);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010052 ctx->state = ecdsa_ver_init;
53}
54
55/*
56 * Free the components of a verify restart sub-context
57 */
Jens Wiklander32b31802023-10-06 16:59:46 +020058static void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010059{
Jens Wiklander32b31802023-10-06 16:59:46 +020060 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010061 return;
Jens Wiklander32b31802023-10-06 16:59:46 +020062 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +010063
Jens Wiklander32b31802023-10-06 16:59:46 +020064 mbedtls_mpi_free(&ctx->u1);
65 mbedtls_mpi_free(&ctx->u2);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010066
Jens Wiklander32b31802023-10-06 16:59:46 +020067 ecdsa_restart_ver_init(ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010068}
69
70/*
71 * Sub-context for ecdsa_sign()
72 */
Jens Wiklander32b31802023-10-06 16:59:46 +020073struct mbedtls_ecdsa_restart_sig {
Jens Wiklander3d3b0592019-03-20 15:30:29 +010074 int sign_tries;
75 int key_tries;
76 mbedtls_mpi k; /* per-signature random */
77 mbedtls_mpi r; /* r value */
78 enum { /* what to do next? */
79 ecdsa_sig_init = 0, /* getting started */
80 ecdsa_sig_mul, /* doing ecp_mul() */
81 ecdsa_sig_modn, /* mod N computations */
82 } state;
83};
84
85/*
86 * Init verify sign sub-context
87 */
Jens Wiklander32b31802023-10-06 16:59:46 +020088static void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +010089{
90 ctx->sign_tries = 0;
91 ctx->key_tries = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +020092 mbedtls_mpi_init(&ctx->k);
93 mbedtls_mpi_init(&ctx->r);
Jens Wiklander3d3b0592019-03-20 15:30:29 +010094 ctx->state = ecdsa_sig_init;
95}
96
97/*
98 * Free the components of a sign restart sub-context
99 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200100static void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100101{
Jens Wiklander32b31802023-10-06 16:59:46 +0200102 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100103 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200104 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100105
Jens Wiklander32b31802023-10-06 16:59:46 +0200106 mbedtls_mpi_free(&ctx->k);
107 mbedtls_mpi_free(&ctx->r);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100108}
109
110#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
111/*
112 * Sub-context for ecdsa_sign_det()
113 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200114struct mbedtls_ecdsa_restart_det {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100115 mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
116 enum { /* what to do next? */
117 ecdsa_det_init = 0, /* getting started */
118 ecdsa_det_sign, /* make signature */
119 } state;
120};
121
122/*
123 * Init verify sign_det sub-context
124 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200125static void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100126{
Jens Wiklander32b31802023-10-06 16:59:46 +0200127 mbedtls_hmac_drbg_init(&ctx->rng_ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100128 ctx->state = ecdsa_det_init;
129}
130
131/*
132 * Free the components of a sign_det restart sub-context
133 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200134static void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100135{
Jens Wiklander32b31802023-10-06 16:59:46 +0200136 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100137 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200138 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100139
Jens Wiklander32b31802023-10-06 16:59:46 +0200140 mbedtls_hmac_drbg_free(&ctx->rng_ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100141
Jens Wiklander32b31802023-10-06 16:59:46 +0200142 ecdsa_restart_det_init(ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100143}
144#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
145
Jens Wiklander32b31802023-10-06 16:59:46 +0200146#define ECDSA_RS_ECP (rs_ctx == NULL ? NULL : &rs_ctx->ecp)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100147
148/* Utility macro for checking and updating ops budget */
Jens Wiklander32b31802023-10-06 16:59:46 +0200149#define ECDSA_BUDGET(ops) \
150 MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100151
152/* Call this when entering a function that needs its own sub-context */
Jens Wiklander32b31802023-10-06 16:59:46 +0200153#define ECDSA_RS_ENTER(SUB) do { \
154 /* reset ops count for this call if top-level */ \
155 if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100156 rs_ctx->ecp.ops_done = 0; \
157 \
Jens Wiklander32b31802023-10-06 16:59:46 +0200158 /* set up our own sub-context if needed */ \
159 if (mbedtls_ecp_restart_is_enabled() && \
160 rs_ctx != NULL && rs_ctx->SUB == NULL) \
161 { \
162 rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \
163 if (rs_ctx->SUB == NULL) \
164 return MBEDTLS_ERR_ECP_ALLOC_FAILED; \
165 \
166 ecdsa_restart_## SUB ##_init(rs_ctx->SUB); \
167 } \
168} while (0)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100169
170/* Call this when leaving a function that needs its own sub-context */
Jens Wiklander32b31802023-10-06 16:59:46 +0200171#define ECDSA_RS_LEAVE(SUB) do { \
172 /* clear our sub-context when not in progress (done or error) */ \
173 if (rs_ctx != NULL && rs_ctx->SUB != NULL && \
174 ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \
175 { \
176 ecdsa_restart_## SUB ##_free(rs_ctx->SUB); \
177 mbedtls_free(rs_ctx->SUB); \
178 rs_ctx->SUB = NULL; \
179 } \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100180 \
Jens Wiklander32b31802023-10-06 16:59:46 +0200181 if (rs_ctx != NULL) \
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100182 rs_ctx->ecp.depth--; \
Jens Wiklander32b31802023-10-06 16:59:46 +0200183} while (0)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100184
185#else /* MBEDTLS_ECP_RESTARTABLE */
186
187#define ECDSA_RS_ECP NULL
188
Jens Wiklander32b31802023-10-06 16:59:46 +0200189#define ECDSA_BUDGET(ops) /* no-op; for compatibility */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100190
Jens Wiklander32b31802023-10-06 16:59:46 +0200191#define ECDSA_RS_ENTER(SUB) (void) rs_ctx
192#define ECDSA_RS_LEAVE(SUB) (void) rs_ctx
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100193
194#endif /* MBEDTLS_ECP_RESTARTABLE */
195
Jerome Forissier79013242021-07-28 10:24:04 +0200196#if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \
197 !defined(MBEDTLS_ECDSA_SIGN_ALT) || \
198 !defined(MBEDTLS_ECDSA_VERIFY_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200199/*
200 * Derive a suitable integer for group grp from a buffer of length len
201 * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
202 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200203static int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x,
204 const unsigned char *buf, size_t blen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200205{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200206 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200207 size_t n_size = (grp->nbits + 7) / 8;
Jens Wiklander817466c2018-05-22 13:49:31 +0200208 size_t use_size = blen > n_size ? n_size : blen;
209
Jens Wiklander32b31802023-10-06 16:59:46 +0200210 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size));
211 if (use_size * 8 > grp->nbits) {
212 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits));
213 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200214
215 /* While at it, reduce modulo N */
Jens Wiklander32b31802023-10-06 16:59:46 +0200216 if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) {
217 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N));
218 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200219
220cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200221 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200222}
Jerome Forissier79013242021-07-28 10:24:04 +0200223#endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200224
Tom Van Eyckc1633172024-04-09 18:44:13 +0200225int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)
226{
227 switch (gid) {
228#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
229 case MBEDTLS_ECP_DP_CURVE25519: return 0;
230#endif
231#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
232 case MBEDTLS_ECP_DP_CURVE448: return 0;
233#endif
234 default: return 1;
235 }
236}
237
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100238#if !defined(MBEDTLS_ECDSA_SIGN_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200239/*
240 * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
241 * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
242 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200243int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp,
244 mbedtls_mpi *r, mbedtls_mpi *s,
245 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
246 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
247 int (*f_rng_blind)(void *, unsigned char *, size_t),
248 void *p_rng_blind,
249 mbedtls_ecdsa_restart_ctx *rs_ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200250{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100251 int ret, key_tries, sign_tries;
252 int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
Jens Wiklander817466c2018-05-22 13:49:31 +0200253 mbedtls_ecp_point R;
254 mbedtls_mpi k, e, t;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100255 mbedtls_mpi *pk = &k, *pr = r;
Jens Wiklander817466c2018-05-22 13:49:31 +0200256
257 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
Jens Wiklander32b31802023-10-06 16:59:46 +0200258 if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
259 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
260 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200261
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100262 /* Make sure d is in range 1..n-1 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200263 if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {
264 return MBEDTLS_ERR_ECP_INVALID_KEY;
265 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100266
Jens Wiklander32b31802023-10-06 16:59:46 +0200267 mbedtls_ecp_point_init(&R);
268 mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&t);
Jens Wiklander817466c2018-05-22 13:49:31 +0200269
Jens Wiklander32b31802023-10-06 16:59:46 +0200270 ECDSA_RS_ENTER(sig);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100271
272#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200273 if (rs_ctx != NULL && rs_ctx->sig != NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100274 /* redirect to our context */
275 p_sign_tries = &rs_ctx->sig->sign_tries;
276 p_key_tries = &rs_ctx->sig->key_tries;
277 pk = &rs_ctx->sig->k;
278 pr = &rs_ctx->sig->r;
279
280 /* jump to current step */
Jens Wiklander32b31802023-10-06 16:59:46 +0200281 if (rs_ctx->sig->state == ecdsa_sig_mul) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100282 goto mul;
Jens Wiklander32b31802023-10-06 16:59:46 +0200283 }
284 if (rs_ctx->sig->state == ecdsa_sig_modn) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100285 goto modn;
Jens Wiklander32b31802023-10-06 16:59:46 +0200286 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100287 }
288#endif /* MBEDTLS_ECP_RESTARTABLE */
289
290 *p_sign_tries = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200291 do {
292 if ((*p_sign_tries)++ > 10) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100293 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
294 goto cleanup;
295 }
296
Jens Wiklander817466c2018-05-22 13:49:31 +0200297 /*
298 * Steps 1-3: generate a suitable ephemeral keypair
299 * and set r = xR mod n
300 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100301 *p_key_tries = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200302 do {
303 if ((*p_key_tries)++ > 10) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200304 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
305 goto cleanup;
306 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100307
Jens Wiklander32b31802023-10-06 16:59:46 +0200308 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100309
310#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200311 if (rs_ctx != NULL && rs_ctx->sig != NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100312 rs_ctx->sig->state = ecdsa_sig_mul;
Jens Wiklander32b31802023-10-06 16:59:46 +0200313 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100314
315mul:
316#endif
Jens Wiklander32b31802023-10-06 16:59:46 +0200317 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G,
318 f_rng_blind,
319 p_rng_blind,
320 ECDSA_RS_ECP));
321 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N));
322 } while (mbedtls_mpi_cmp_int(pr, 0) == 0);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100323
324#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200325 if (rs_ctx != NULL && rs_ctx->sig != NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100326 rs_ctx->sig->state = ecdsa_sig_modn;
Jens Wiklander32b31802023-10-06 16:59:46 +0200327 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100328
329modn:
330#endif
331 /*
332 * Accounting for everything up to the end of the loop
333 * (step 6, but checking now avoids saving e and t)
334 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200335 ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4);
Jens Wiklander817466c2018-05-22 13:49:31 +0200336
337 /*
338 * Step 5: derive MPI from hashed message
339 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200340 MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200341
342 /*
343 * Generate a random value to blind inv_mod in next step,
344 * avoiding a potential timing leak.
345 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200346 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, &t, f_rng_blind,
347 p_rng_blind));
Jens Wiklander817466c2018-05-22 13:49:31 +0200348
349 /*
350 * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
351 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200352 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d));
353 MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s));
354 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&e, &e, &t));
355 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pk, pk, &t));
356 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pk, pk, &grp->N));
357 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(s, pk, &grp->N));
358 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e));
359 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N));
360 } while (mbedtls_mpi_cmp_int(s, 0) == 0);
Jens Wiklander817466c2018-05-22 13:49:31 +0200361
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100362#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200363 if (rs_ctx != NULL && rs_ctx->sig != NULL) {
Tom Van Eyckc1633172024-04-09 18:44:13 +0200364 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr));
Jens Wiklander32b31802023-10-06 16:59:46 +0200365 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100366#endif
367
Jens Wiklander817466c2018-05-22 13:49:31 +0200368cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200369 mbedtls_ecp_point_free(&R);
370 mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&t);
Jens Wiklander817466c2018-05-22 13:49:31 +0200371
Jens Wiklander32b31802023-10-06 16:59:46 +0200372 ECDSA_RS_LEAVE(sig);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100373
Jens Wiklander32b31802023-10-06 16:59:46 +0200374 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200375}
376
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100377/*
378 * Compute ECDSA signature of a hashed message
379 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200380int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
381 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
382 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100383{
Jerome Forissier5b25c762020-04-07 11:18:49 +0200384 /* Use the same RNG for both blinding and ephemeral key generation */
Jens Wiklander32b31802023-10-06 16:59:46 +0200385 return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
386 f_rng, p_rng, f_rng, p_rng, NULL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100387}
388#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
389
Jens Wiklander817466c2018-05-22 13:49:31 +0200390#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
391/*
392 * Deterministic signature wrapper
Jens Wiklander32b31802023-10-06 16:59:46 +0200393 *
394 * note: The f_rng_blind parameter must not be NULL.
395 *
Jens Wiklander817466c2018-05-22 13:49:31 +0200396 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200397int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,
398 mbedtls_mpi *r, mbedtls_mpi *s,
399 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
400 mbedtls_md_type_t md_alg,
401 int (*f_rng_blind)(void *, unsigned char *, size_t),
402 void *p_rng_blind,
403 mbedtls_ecdsa_restart_ctx *rs_ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200404{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200405 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200406 mbedtls_hmac_drbg_context rng_ctx;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100407 mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200408 unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
Jens Wiklander32b31802023-10-06 16:59:46 +0200409 size_t grp_len = (grp->nbits + 7) / 8;
Jens Wiklander817466c2018-05-22 13:49:31 +0200410 const mbedtls_md_info_t *md_info;
411 mbedtls_mpi h;
412
Jens Wiklander32b31802023-10-06 16:59:46 +0200413 if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) {
414 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
415 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200416
Jens Wiklander32b31802023-10-06 16:59:46 +0200417 mbedtls_mpi_init(&h);
418 mbedtls_hmac_drbg_init(&rng_ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200419
Jens Wiklander32b31802023-10-06 16:59:46 +0200420 ECDSA_RS_ENTER(det);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100421
422#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200423 if (rs_ctx != NULL && rs_ctx->det != NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100424 /* redirect to our context */
425 p_rng = &rs_ctx->det->rng_ctx;
426
427 /* jump to current step */
Jens Wiklander32b31802023-10-06 16:59:46 +0200428 if (rs_ctx->det->state == ecdsa_det_sign) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100429 goto sign;
Jens Wiklander32b31802023-10-06 16:59:46 +0200430 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100431 }
432#endif /* MBEDTLS_ECP_RESTARTABLE */
433
Jens Wiklander817466c2018-05-22 13:49:31 +0200434 /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
Jens Wiklander32b31802023-10-06 16:59:46 +0200435 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));
436 MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));
437 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));
Tom Van Eyckc1633172024-04-09 18:44:13 +0200438 MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len));
Jens Wiklander817466c2018-05-22 13:49:31 +0200439
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100440#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200441 if (rs_ctx != NULL && rs_ctx->det != NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100442 rs_ctx->det->state = ecdsa_det_sign;
Jens Wiklander32b31802023-10-06 16:59:46 +0200443 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100444
445sign:
446#endif
447#if defined(MBEDTLS_ECDSA_SIGN_ALT)
Jerome Forissier79013242021-07-28 10:24:04 +0200448 (void) f_rng_blind;
449 (void) p_rng_blind;
Jens Wiklander32b31802023-10-06 16:59:46 +0200450 ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen,
451 mbedtls_hmac_drbg_random, p_rng);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100452#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200453 ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
454 mbedtls_hmac_drbg_random, p_rng,
455 f_rng_blind, p_rng_blind, rs_ctx);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100456#endif /* MBEDTLS_ECDSA_SIGN_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200457
458cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200459 mbedtls_hmac_drbg_free(&rng_ctx);
460 mbedtls_mpi_free(&h);
Jens Wiklander817466c2018-05-22 13:49:31 +0200461
Jens Wiklander32b31802023-10-06 16:59:46 +0200462 ECDSA_RS_LEAVE(det);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100463
Jens Wiklander32b31802023-10-06 16:59:46 +0200464 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200465}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100466
467/*
Jens Wiklander32b31802023-10-06 16:59:46 +0200468 * Deterministic signature wrapper
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100469 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200470int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,
471 mbedtls_mpi *s, const mbedtls_mpi *d,
472 const unsigned char *buf, size_t blen,
473 mbedtls_md_type_t md_alg,
474 int (*f_rng_blind)(void *, unsigned char *,
475 size_t),
476 void *p_rng_blind)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100477{
Jens Wiklander32b31802023-10-06 16:59:46 +0200478 return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,
479 f_rng_blind, p_rng_blind, NULL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100480}
Jens Wiklander817466c2018-05-22 13:49:31 +0200481#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
482
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100483#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200484/*
485 * Verify ECDSA signature of hashed message (SEC1 4.1.4)
486 * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
487 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200488int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100489 const unsigned char *buf, size_t blen,
490 const mbedtls_ecp_point *Q,
Jens Wiklander32b31802023-10-06 16:59:46 +0200491 const mbedtls_mpi *r,
492 const mbedtls_mpi *s,
493 mbedtls_ecdsa_restart_ctx *rs_ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200494{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200495 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200496 mbedtls_mpi e, s_inv, u1, u2;
497 mbedtls_ecp_point R;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100498 mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
Jens Wiklander817466c2018-05-22 13:49:31 +0200499
Jens Wiklander32b31802023-10-06 16:59:46 +0200500 mbedtls_ecp_point_init(&R);
501 mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv);
502 mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2);
Jens Wiklander817466c2018-05-22 13:49:31 +0200503
504 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
Jens Wiklander32b31802023-10-06 16:59:46 +0200505 if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
506 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
507 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200508
Jens Wiklander32b31802023-10-06 16:59:46 +0200509 ECDSA_RS_ENTER(ver);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100510
511#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200512 if (rs_ctx != NULL && rs_ctx->ver != NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100513 /* redirect to our context */
514 pu1 = &rs_ctx->ver->u1;
515 pu2 = &rs_ctx->ver->u2;
516
517 /* jump to current step */
Jens Wiklander32b31802023-10-06 16:59:46 +0200518 if (rs_ctx->ver->state == ecdsa_ver_muladd) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100519 goto muladd;
Jens Wiklander32b31802023-10-06 16:59:46 +0200520 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100521 }
522#endif /* MBEDTLS_ECP_RESTARTABLE */
523
Jens Wiklander817466c2018-05-22 13:49:31 +0200524 /*
525 * Step 1: make sure r and s are in range 1..n-1
526 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200527 if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 ||
528 mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200529 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
530 goto cleanup;
531 }
532
533 /*
Jens Wiklander817466c2018-05-22 13:49:31 +0200534 * Step 3: derive MPI from hashed message
535 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200536 MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200537
538 /*
539 * Step 4: u1 = e / s mod n, u2 = r / s mod n
540 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200541 ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100542
Jens Wiklander32b31802023-10-06 16:59:46 +0200543 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&s_inv, s, &grp->N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200544
Jens Wiklander32b31802023-10-06 16:59:46 +0200545 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv));
546 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200547
Jens Wiklander32b31802023-10-06 16:59:46 +0200548 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv));
549 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200550
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100551#if defined(MBEDTLS_ECP_RESTARTABLE)
Jens Wiklander32b31802023-10-06 16:59:46 +0200552 if (rs_ctx != NULL && rs_ctx->ver != NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100553 rs_ctx->ver->state = ecdsa_ver_muladd;
Jens Wiklander32b31802023-10-06 16:59:46 +0200554 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100555
556muladd:
557#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200558 /*
559 * Step 5: R = u1 G + u2 Q
Jens Wiklander817466c2018-05-22 13:49:31 +0200560 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200561 MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp,
562 &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP));
Jens Wiklander817466c2018-05-22 13:49:31 +0200563
Jens Wiklander32b31802023-10-06 16:59:46 +0200564 if (mbedtls_ecp_is_zero(&R)) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200565 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
566 goto cleanup;
567 }
568
569 /*
570 * Step 6: convert xR to an integer (no-op)
571 * Step 7: reduce xR mod n (gives v)
572 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200573 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N));
Jens Wiklander817466c2018-05-22 13:49:31 +0200574
575 /*
576 * Step 8: check if v (that is, R.X) is equal to r
577 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200578 if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200579 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
580 goto cleanup;
581 }
582
583cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200584 mbedtls_ecp_point_free(&R);
585 mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv);
586 mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100587
Jens Wiklander32b31802023-10-06 16:59:46 +0200588 ECDSA_RS_LEAVE(ver);
Jens Wiklander817466c2018-05-22 13:49:31 +0200589
Jens Wiklander32b31802023-10-06 16:59:46 +0200590 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200591}
592
593/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100594 * Verify ECDSA signature of hashed message
595 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200596int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,
597 const unsigned char *buf, size_t blen,
598 const mbedtls_ecp_point *Q,
599 const mbedtls_mpi *r,
600 const mbedtls_mpi *s)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100601{
Jens Wiklander32b31802023-10-06 16:59:46 +0200602 return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100603}
604#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
605
606/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200607 * Convert a signature (given by context) to ASN.1
608 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200609static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,
610 unsigned char *sig, size_t sig_size,
611 size_t *slen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200612{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200613 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200614 unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
615 unsigned char *p = buf + sizeof(buf);
Jens Wiklander817466c2018-05-22 13:49:31 +0200616 size_t len = 0;
617
Jens Wiklander32b31802023-10-06 16:59:46 +0200618 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));
619 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));
Jens Wiklander817466c2018-05-22 13:49:31 +0200620
Jens Wiklander32b31802023-10-06 16:59:46 +0200621 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
622 MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,
623 MBEDTLS_ASN1_CONSTRUCTED |
624 MBEDTLS_ASN1_SEQUENCE));
Jens Wiklander817466c2018-05-22 13:49:31 +0200625
Jens Wiklander32b31802023-10-06 16:59:46 +0200626 if (len > sig_size) {
627 return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
628 }
629
630 memcpy(sig, p, len);
Jens Wiklander817466c2018-05-22 13:49:31 +0200631 *slen = len;
632
Jens Wiklander32b31802023-10-06 16:59:46 +0200633 return 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200634}
635
636/*
637 * Compute and write signature
638 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200639int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
640 mbedtls_md_type_t md_alg,
641 const unsigned char *hash, size_t hlen,
642 unsigned char *sig, size_t sig_size, size_t *slen,
643 int (*f_rng)(void *, unsigned char *, size_t),
644 void *p_rng,
645 mbedtls_ecdsa_restart_ctx *rs_ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200646{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200647 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200648 mbedtls_mpi r, s;
Jens Wiklander32b31802023-10-06 16:59:46 +0200649 if (f_rng == NULL) {
650 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200652
Jens Wiklander32b31802023-10-06 16:59:46 +0200653 mbedtls_mpi_init(&r);
654 mbedtls_mpi_init(&s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200655
656#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
Jens Wiklander32b31802023-10-06 16:59:46 +0200657 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,
658 hash, hlen, md_alg, f_rng,
659 p_rng, rs_ctx));
Jens Wiklander817466c2018-05-22 13:49:31 +0200660#else
661 (void) md_alg;
662
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100663#if defined(MBEDTLS_ECDSA_SIGN_ALT)
Jerome Forissier79013242021-07-28 10:24:04 +0200664 (void) rs_ctx;
665
Jens Wiklander32b31802023-10-06 16:59:46 +0200666 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d,
667 hash, hlen, f_rng, p_rng));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100668#else
Jerome Forissier5b25c762020-04-07 11:18:49 +0200669 /* Use the same RNG for both blinding and ephemeral key generation */
Jens Wiklander32b31802023-10-06 16:59:46 +0200670 MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,
671 hash, hlen, f_rng, p_rng, f_rng,
672 p_rng, rs_ctx));
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100673#endif /* MBEDTLS_ECDSA_SIGN_ALT */
674#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
Jens Wiklander817466c2018-05-22 13:49:31 +0200675
Jens Wiklander32b31802023-10-06 16:59:46 +0200676 MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen));
Jens Wiklander817466c2018-05-22 13:49:31 +0200677
678cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200679 mbedtls_mpi_free(&r);
680 mbedtls_mpi_free(&s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200681
Jens Wiklander32b31802023-10-06 16:59:46 +0200682 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200683}
684
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100685/*
686 * Compute and write signature
687 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200688int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
689 mbedtls_md_type_t md_alg,
690 const unsigned char *hash, size_t hlen,
691 unsigned char *sig, size_t sig_size, size_t *slen,
692 int (*f_rng)(void *, unsigned char *, size_t),
693 void *p_rng)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100694{
Jens Wiklander32b31802023-10-06 16:59:46 +0200695 return mbedtls_ecdsa_write_signature_restartable(
696 ctx, md_alg, hash, hlen, sig, sig_size, slen,
697 f_rng, p_rng, NULL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100698}
699
Jens Wiklander817466c2018-05-22 13:49:31 +0200700/*
701 * Read and check signature
702 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200703int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
704 const unsigned char *hash, size_t hlen,
705 const unsigned char *sig, size_t slen)
Jens Wiklander817466c2018-05-22 13:49:31 +0200706{
Jens Wiklander32b31802023-10-06 16:59:46 +0200707 return mbedtls_ecdsa_read_signature_restartable(
708 ctx, hash, hlen, sig, slen, NULL);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100709}
710
711/*
712 * Restartable read and check signature
713 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200714int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,
715 const unsigned char *hash, size_t hlen,
716 const unsigned char *sig, size_t slen,
717 mbedtls_ecdsa_restart_ctx *rs_ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100718{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200719 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200720 unsigned char *p = (unsigned char *) sig;
721 const unsigned char *end = sig + slen;
722 size_t len;
723 mbedtls_mpi r, s;
Jens Wiklander32b31802023-10-06 16:59:46 +0200724 mbedtls_mpi_init(&r);
725 mbedtls_mpi_init(&s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200726
Jens Wiklander32b31802023-10-06 16:59:46 +0200727 if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
728 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200729 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
730 goto cleanup;
731 }
732
Jens Wiklander32b31802023-10-06 16:59:46 +0200733 if (p + len != end) {
734 ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
735 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
Jens Wiklander817466c2018-05-22 13:49:31 +0200736 goto cleanup;
737 }
738
Jens Wiklander32b31802023-10-06 16:59:46 +0200739 if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 ||
740 (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200741 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
742 goto cleanup;
743 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100744#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
Jerome Forissier79013242021-07-28 10:24:04 +0200745 (void) rs_ctx;
746
Jens Wiklander32b31802023-10-06 16:59:46 +0200747 if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen,
748 &ctx->Q, &r, &s)) != 0) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200749 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200750 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100751#else
Jens Wiklander32b31802023-10-06 16:59:46 +0200752 if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen,
753 &ctx->Q, &r, &s, rs_ctx)) != 0) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100754 goto cleanup;
Jens Wiklander32b31802023-10-06 16:59:46 +0200755 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100756#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200757
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100758 /* At this point we know that the buffer starts with a valid signature.
759 * Return 0 if the buffer just contains the signature, and a specific
760 * error code if the valid signature is followed by more data. */
Jens Wiklander32b31802023-10-06 16:59:46 +0200761 if (p != end) {
Jens Wiklander817466c2018-05-22 13:49:31 +0200762 ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
Jens Wiklander32b31802023-10-06 16:59:46 +0200763 }
Jens Wiklander817466c2018-05-22 13:49:31 +0200764
765cleanup:
Jens Wiklander32b31802023-10-06 16:59:46 +0200766 mbedtls_mpi_free(&r);
767 mbedtls_mpi_free(&s);
Jens Wiklander817466c2018-05-22 13:49:31 +0200768
Jens Wiklander32b31802023-10-06 16:59:46 +0200769 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200770}
771
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100772#if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200773/*
774 * Generate key pair
775 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200776int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
777 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
Jens Wiklander817466c2018-05-22 13:49:31 +0200778{
Jerome Forissier5b25c762020-04-07 11:18:49 +0200779 int ret = 0;
Jens Wiklander32b31802023-10-06 16:59:46 +0200780 ret = mbedtls_ecp_group_load(&ctx->grp, gid);
781 if (ret != 0) {
782 return ret;
783 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100784
Jens Wiklander32b31802023-10-06 16:59:46 +0200785 return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d,
786 &ctx->Q, f_rng, p_rng);
Jens Wiklander817466c2018-05-22 13:49:31 +0200787}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100788#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200789
790/*
791 * Set context from an mbedtls_ecp_keypair
792 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200793int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key)
Jens Wiklander817466c2018-05-22 13:49:31 +0200794{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200795 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander32b31802023-10-06 16:59:46 +0200796 if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 ||
797 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 ||
798 (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) {
799 mbedtls_ecdsa_free(ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200800 }
801
Jens Wiklander32b31802023-10-06 16:59:46 +0200802 return ret;
Jens Wiklander817466c2018-05-22 13:49:31 +0200803}
804
805/*
806 * Initialize context
807 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200808void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200809{
Jens Wiklander32b31802023-10-06 16:59:46 +0200810 mbedtls_ecp_keypair_init(ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200811}
812
813/*
814 * Free context
815 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200816void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx)
Jens Wiklander817466c2018-05-22 13:49:31 +0200817{
Jens Wiklander32b31802023-10-06 16:59:46 +0200818 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100819 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200820 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100821
Jens Wiklander32b31802023-10-06 16:59:46 +0200822 mbedtls_ecp_keypair_free(ctx);
Jens Wiklander817466c2018-05-22 13:49:31 +0200823}
824
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100825#if defined(MBEDTLS_ECP_RESTARTABLE)
826/*
827 * Initialize a restart context
828 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200829void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100830{
Jens Wiklander32b31802023-10-06 16:59:46 +0200831 mbedtls_ecp_restart_init(&ctx->ecp);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100832
833 ctx->ver = NULL;
834 ctx->sig = NULL;
835#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
836 ctx->det = NULL;
837#endif
838}
839
840/*
841 * Free the components of a restart context
842 */
Jens Wiklander32b31802023-10-06 16:59:46 +0200843void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100844{
Jens Wiklander32b31802023-10-06 16:59:46 +0200845 if (ctx == NULL) {
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100846 return;
Jens Wiklander32b31802023-10-06 16:59:46 +0200847 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100848
Jens Wiklander32b31802023-10-06 16:59:46 +0200849 mbedtls_ecp_restart_free(&ctx->ecp);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100850
Jens Wiklander32b31802023-10-06 16:59:46 +0200851 ecdsa_restart_ver_free(ctx->ver);
852 mbedtls_free(ctx->ver);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100853 ctx->ver = NULL;
854
Jens Wiklander32b31802023-10-06 16:59:46 +0200855 ecdsa_restart_sig_free(ctx->sig);
856 mbedtls_free(ctx->sig);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100857 ctx->sig = NULL;
858
859#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
Jens Wiklander32b31802023-10-06 16:59:46 +0200860 ecdsa_restart_det_free(ctx->det);
861 mbedtls_free(ctx->det);
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100862 ctx->det = NULL;
863#endif
864}
865#endif /* MBEDTLS_ECP_RESTARTABLE */
866
Jens Wiklander817466c2018-05-22 13:49:31 +0200867#endif /* MBEDTLS_ECDSA_C */