1*62c56f98SSadaf Ebrahimi /*
2*62c56f98SSadaf Ebrahimi * Elliptic curve DSA
3*62c56f98SSadaf Ebrahimi *
4*62c56f98SSadaf Ebrahimi * Copyright The Mbed TLS Contributors
5*62c56f98SSadaf Ebrahimi * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6*62c56f98SSadaf Ebrahimi */
7*62c56f98SSadaf Ebrahimi
8*62c56f98SSadaf Ebrahimi /*
9*62c56f98SSadaf Ebrahimi * References:
10*62c56f98SSadaf Ebrahimi *
11*62c56f98SSadaf Ebrahimi * SEC1 https://www.secg.org/sec1-v2.pdf
12*62c56f98SSadaf Ebrahimi */
13*62c56f98SSadaf Ebrahimi
14*62c56f98SSadaf Ebrahimi #include "common.h"
15*62c56f98SSadaf Ebrahimi
16*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_C)
17*62c56f98SSadaf Ebrahimi
18*62c56f98SSadaf Ebrahimi #include "mbedtls/ecdsa.h"
19*62c56f98SSadaf Ebrahimi #include "mbedtls/asn1write.h"
20*62c56f98SSadaf Ebrahimi
21*62c56f98SSadaf Ebrahimi #include <string.h>
22*62c56f98SSadaf Ebrahimi
23*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
24*62c56f98SSadaf Ebrahimi #include "mbedtls/hmac_drbg.h"
25*62c56f98SSadaf Ebrahimi #endif
26*62c56f98SSadaf Ebrahimi
27*62c56f98SSadaf Ebrahimi #include "mbedtls/platform.h"
28*62c56f98SSadaf Ebrahimi
29*62c56f98SSadaf Ebrahimi #include "mbedtls/platform_util.h"
30*62c56f98SSadaf Ebrahimi #include "mbedtls/error.h"
31*62c56f98SSadaf Ebrahimi
32*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
33*62c56f98SSadaf Ebrahimi
34*62c56f98SSadaf Ebrahimi /*
35*62c56f98SSadaf Ebrahimi * Sub-context for ecdsa_verify()
36*62c56f98SSadaf Ebrahimi */
37*62c56f98SSadaf Ebrahimi struct mbedtls_ecdsa_restart_ver {
38*62c56f98SSadaf Ebrahimi mbedtls_mpi u1, u2; /* intermediate values */
39*62c56f98SSadaf Ebrahimi enum { /* what to do next? */
40*62c56f98SSadaf Ebrahimi ecdsa_ver_init = 0, /* getting started */
41*62c56f98SSadaf Ebrahimi ecdsa_ver_muladd, /* muladd step */
42*62c56f98SSadaf Ebrahimi } state;
43*62c56f98SSadaf Ebrahimi };
44*62c56f98SSadaf Ebrahimi
45*62c56f98SSadaf Ebrahimi /*
46*62c56f98SSadaf Ebrahimi * Init verify restart sub-context
47*62c56f98SSadaf Ebrahimi */
ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx * ctx)48*62c56f98SSadaf Ebrahimi static void ecdsa_restart_ver_init(mbedtls_ecdsa_restart_ver_ctx *ctx)
49*62c56f98SSadaf Ebrahimi {
50*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&ctx->u1);
51*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&ctx->u2);
52*62c56f98SSadaf Ebrahimi ctx->state = ecdsa_ver_init;
53*62c56f98SSadaf Ebrahimi }
54*62c56f98SSadaf Ebrahimi
55*62c56f98SSadaf Ebrahimi /*
56*62c56f98SSadaf Ebrahimi * Free the components of a verify restart sub-context
57*62c56f98SSadaf Ebrahimi */
ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx * ctx)58*62c56f98SSadaf Ebrahimi static void ecdsa_restart_ver_free(mbedtls_ecdsa_restart_ver_ctx *ctx)
59*62c56f98SSadaf Ebrahimi {
60*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
61*62c56f98SSadaf Ebrahimi return;
62*62c56f98SSadaf Ebrahimi }
63*62c56f98SSadaf Ebrahimi
64*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&ctx->u1);
65*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&ctx->u2);
66*62c56f98SSadaf Ebrahimi
67*62c56f98SSadaf Ebrahimi ecdsa_restart_ver_init(ctx);
68*62c56f98SSadaf Ebrahimi }
69*62c56f98SSadaf Ebrahimi
70*62c56f98SSadaf Ebrahimi /*
71*62c56f98SSadaf Ebrahimi * Sub-context for ecdsa_sign()
72*62c56f98SSadaf Ebrahimi */
73*62c56f98SSadaf Ebrahimi struct mbedtls_ecdsa_restart_sig {
74*62c56f98SSadaf Ebrahimi int sign_tries;
75*62c56f98SSadaf Ebrahimi int key_tries;
76*62c56f98SSadaf Ebrahimi mbedtls_mpi k; /* per-signature random */
77*62c56f98SSadaf Ebrahimi mbedtls_mpi r; /* r value */
78*62c56f98SSadaf Ebrahimi enum { /* what to do next? */
79*62c56f98SSadaf Ebrahimi ecdsa_sig_init = 0, /* getting started */
80*62c56f98SSadaf Ebrahimi ecdsa_sig_mul, /* doing ecp_mul() */
81*62c56f98SSadaf Ebrahimi ecdsa_sig_modn, /* mod N computations */
82*62c56f98SSadaf Ebrahimi } state;
83*62c56f98SSadaf Ebrahimi };
84*62c56f98SSadaf Ebrahimi
85*62c56f98SSadaf Ebrahimi /*
86*62c56f98SSadaf Ebrahimi * Init verify sign sub-context
87*62c56f98SSadaf Ebrahimi */
ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx * ctx)88*62c56f98SSadaf Ebrahimi static void ecdsa_restart_sig_init(mbedtls_ecdsa_restart_sig_ctx *ctx)
89*62c56f98SSadaf Ebrahimi {
90*62c56f98SSadaf Ebrahimi ctx->sign_tries = 0;
91*62c56f98SSadaf Ebrahimi ctx->key_tries = 0;
92*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&ctx->k);
93*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&ctx->r);
94*62c56f98SSadaf Ebrahimi ctx->state = ecdsa_sig_init;
95*62c56f98SSadaf Ebrahimi }
96*62c56f98SSadaf Ebrahimi
97*62c56f98SSadaf Ebrahimi /*
98*62c56f98SSadaf Ebrahimi * Free the components of a sign restart sub-context
99*62c56f98SSadaf Ebrahimi */
ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx * ctx)100*62c56f98SSadaf Ebrahimi static void ecdsa_restart_sig_free(mbedtls_ecdsa_restart_sig_ctx *ctx)
101*62c56f98SSadaf Ebrahimi {
102*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
103*62c56f98SSadaf Ebrahimi return;
104*62c56f98SSadaf Ebrahimi }
105*62c56f98SSadaf Ebrahimi
106*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&ctx->k);
107*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&ctx->r);
108*62c56f98SSadaf Ebrahimi }
109*62c56f98SSadaf Ebrahimi
110*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
111*62c56f98SSadaf Ebrahimi /*
112*62c56f98SSadaf Ebrahimi * Sub-context for ecdsa_sign_det()
113*62c56f98SSadaf Ebrahimi */
114*62c56f98SSadaf Ebrahimi struct mbedtls_ecdsa_restart_det {
115*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
116*62c56f98SSadaf Ebrahimi enum { /* what to do next? */
117*62c56f98SSadaf Ebrahimi ecdsa_det_init = 0, /* getting started */
118*62c56f98SSadaf Ebrahimi ecdsa_det_sign, /* make signature */
119*62c56f98SSadaf Ebrahimi } state;
120*62c56f98SSadaf Ebrahimi };
121*62c56f98SSadaf Ebrahimi
122*62c56f98SSadaf Ebrahimi /*
123*62c56f98SSadaf Ebrahimi * Init verify sign_det sub-context
124*62c56f98SSadaf Ebrahimi */
ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx * ctx)125*62c56f98SSadaf Ebrahimi static void ecdsa_restart_det_init(mbedtls_ecdsa_restart_det_ctx *ctx)
126*62c56f98SSadaf Ebrahimi {
127*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_init(&ctx->rng_ctx);
128*62c56f98SSadaf Ebrahimi ctx->state = ecdsa_det_init;
129*62c56f98SSadaf Ebrahimi }
130*62c56f98SSadaf Ebrahimi
131*62c56f98SSadaf Ebrahimi /*
132*62c56f98SSadaf Ebrahimi * Free the components of a sign_det restart sub-context
133*62c56f98SSadaf Ebrahimi */
ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx * ctx)134*62c56f98SSadaf Ebrahimi static void ecdsa_restart_det_free(mbedtls_ecdsa_restart_det_ctx *ctx)
135*62c56f98SSadaf Ebrahimi {
136*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
137*62c56f98SSadaf Ebrahimi return;
138*62c56f98SSadaf Ebrahimi }
139*62c56f98SSadaf Ebrahimi
140*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_free(&ctx->rng_ctx);
141*62c56f98SSadaf Ebrahimi
142*62c56f98SSadaf Ebrahimi ecdsa_restart_det_init(ctx);
143*62c56f98SSadaf Ebrahimi }
144*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
145*62c56f98SSadaf Ebrahimi
146*62c56f98SSadaf Ebrahimi #define ECDSA_RS_ECP (rs_ctx == NULL ? NULL : &rs_ctx->ecp)
147*62c56f98SSadaf Ebrahimi
148*62c56f98SSadaf Ebrahimi /* Utility macro for checking and updating ops budget */
149*62c56f98SSadaf Ebrahimi #define ECDSA_BUDGET(ops) \
150*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecp_check_budget(grp, ECDSA_RS_ECP, ops));
151*62c56f98SSadaf Ebrahimi
152*62c56f98SSadaf Ebrahimi /* Call this when entering a function that needs its own sub-context */
153*62c56f98SSadaf Ebrahimi #define ECDSA_RS_ENTER(SUB) do { \
154*62c56f98SSadaf Ebrahimi /* reset ops count for this call if top-level */ \
155*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->ecp.depth++ == 0) \
156*62c56f98SSadaf Ebrahimi rs_ctx->ecp.ops_done = 0; \
157*62c56f98SSadaf Ebrahimi \
158*62c56f98SSadaf Ebrahimi /* set up our own sub-context if needed */ \
159*62c56f98SSadaf Ebrahimi if (mbedtls_ecp_restart_is_enabled() && \
160*62c56f98SSadaf Ebrahimi rs_ctx != NULL && rs_ctx->SUB == NULL) \
161*62c56f98SSadaf Ebrahimi { \
162*62c56f98SSadaf Ebrahimi rs_ctx->SUB = mbedtls_calloc(1, sizeof(*rs_ctx->SUB)); \
163*62c56f98SSadaf Ebrahimi if (rs_ctx->SUB == NULL) \
164*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ECP_ALLOC_FAILED; \
165*62c56f98SSadaf Ebrahimi \
166*62c56f98SSadaf Ebrahimi ecdsa_restart_## SUB ##_init(rs_ctx->SUB); \
167*62c56f98SSadaf Ebrahimi } \
168*62c56f98SSadaf Ebrahimi } while (0)
169*62c56f98SSadaf Ebrahimi
170*62c56f98SSadaf Ebrahimi /* Call this when leaving a function that needs its own sub-context */
171*62c56f98SSadaf Ebrahimi #define ECDSA_RS_LEAVE(SUB) do { \
172*62c56f98SSadaf Ebrahimi /* clear our sub-context when not in progress (done or error) */ \
173*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->SUB != NULL && \
174*62c56f98SSadaf Ebrahimi ret != MBEDTLS_ERR_ECP_IN_PROGRESS) \
175*62c56f98SSadaf Ebrahimi { \
176*62c56f98SSadaf Ebrahimi ecdsa_restart_## SUB ##_free(rs_ctx->SUB); \
177*62c56f98SSadaf Ebrahimi mbedtls_free(rs_ctx->SUB); \
178*62c56f98SSadaf Ebrahimi rs_ctx->SUB = NULL; \
179*62c56f98SSadaf Ebrahimi } \
180*62c56f98SSadaf Ebrahimi \
181*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL) \
182*62c56f98SSadaf Ebrahimi rs_ctx->ecp.depth--; \
183*62c56f98SSadaf Ebrahimi } while (0)
184*62c56f98SSadaf Ebrahimi
185*62c56f98SSadaf Ebrahimi #else /* MBEDTLS_ECP_RESTARTABLE */
186*62c56f98SSadaf Ebrahimi
187*62c56f98SSadaf Ebrahimi #define ECDSA_RS_ECP NULL
188*62c56f98SSadaf Ebrahimi
189*62c56f98SSadaf Ebrahimi #define ECDSA_BUDGET(ops) /* no-op; for compatibility */
190*62c56f98SSadaf Ebrahimi
191*62c56f98SSadaf Ebrahimi #define ECDSA_RS_ENTER(SUB) (void) rs_ctx
192*62c56f98SSadaf Ebrahimi #define ECDSA_RS_LEAVE(SUB) (void) rs_ctx
193*62c56f98SSadaf Ebrahimi
194*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECP_RESTARTABLE */
195*62c56f98SSadaf Ebrahimi
196*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_DETERMINISTIC) || \
197*62c56f98SSadaf Ebrahimi !defined(MBEDTLS_ECDSA_SIGN_ALT) || \
198*62c56f98SSadaf Ebrahimi !defined(MBEDTLS_ECDSA_VERIFY_ALT)
199*62c56f98SSadaf Ebrahimi /*
200*62c56f98SSadaf Ebrahimi * Derive a suitable integer for group grp from a buffer of length len
201*62c56f98SSadaf Ebrahimi * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
202*62c56f98SSadaf Ebrahimi */
derive_mpi(const mbedtls_ecp_group * grp,mbedtls_mpi * x,const unsigned char * buf,size_t blen)203*62c56f98SSadaf Ebrahimi static int derive_mpi(const mbedtls_ecp_group *grp, mbedtls_mpi *x,
204*62c56f98SSadaf Ebrahimi const unsigned char *buf, size_t blen)
205*62c56f98SSadaf Ebrahimi {
206*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
207*62c56f98SSadaf Ebrahimi size_t n_size = (grp->nbits + 7) / 8;
208*62c56f98SSadaf Ebrahimi size_t use_size = blen > n_size ? n_size : blen;
209*62c56f98SSadaf Ebrahimi
210*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(x, buf, use_size));
211*62c56f98SSadaf Ebrahimi if (use_size * 8 > grp->nbits) {
212*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(x, use_size * 8 - grp->nbits));
213*62c56f98SSadaf Ebrahimi }
214*62c56f98SSadaf Ebrahimi
215*62c56f98SSadaf Ebrahimi /* While at it, reduce modulo N */
216*62c56f98SSadaf Ebrahimi if (mbedtls_mpi_cmp_mpi(x, &grp->N) >= 0) {
217*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_sub_mpi(x, x, &grp->N));
218*62c56f98SSadaf Ebrahimi }
219*62c56f98SSadaf Ebrahimi
220*62c56f98SSadaf Ebrahimi cleanup:
221*62c56f98SSadaf Ebrahimi return ret;
222*62c56f98SSadaf Ebrahimi }
223*62c56f98SSadaf Ebrahimi #endif /* ECDSA_DETERMINISTIC || !ECDSA_SIGN_ALT || !ECDSA_VERIFY_ALT */
224*62c56f98SSadaf Ebrahimi
mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)225*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_can_do(mbedtls_ecp_group_id gid)
226*62c56f98SSadaf Ebrahimi {
227*62c56f98SSadaf Ebrahimi switch (gid) {
228*62c56f98SSadaf Ebrahimi #ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
229*62c56f98SSadaf Ebrahimi case MBEDTLS_ECP_DP_CURVE25519: return 0;
230*62c56f98SSadaf Ebrahimi #endif
231*62c56f98SSadaf Ebrahimi #ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
232*62c56f98SSadaf Ebrahimi case MBEDTLS_ECP_DP_CURVE448: return 0;
233*62c56f98SSadaf Ebrahimi #endif
234*62c56f98SSadaf Ebrahimi default: return 1;
235*62c56f98SSadaf Ebrahimi }
236*62c56f98SSadaf Ebrahimi }
237*62c56f98SSadaf Ebrahimi
238*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
239*62c56f98SSadaf Ebrahimi /*
240*62c56f98SSadaf Ebrahimi * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
241*62c56f98SSadaf Ebrahimi * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
242*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group * grp,mbedtls_mpi * r,mbedtls_mpi * s,const mbedtls_mpi * d,const unsigned char * buf,size_t blen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng,int (* f_rng_blind)(void *,unsigned char *,size_t),void * p_rng_blind,mbedtls_ecdsa_restart_ctx * rs_ctx)243*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_sign_restartable(mbedtls_ecp_group *grp,
244*62c56f98SSadaf Ebrahimi mbedtls_mpi *r, mbedtls_mpi *s,
245*62c56f98SSadaf Ebrahimi const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
246*62c56f98SSadaf Ebrahimi int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
247*62c56f98SSadaf Ebrahimi int (*f_rng_blind)(void *, unsigned char *, size_t),
248*62c56f98SSadaf Ebrahimi void *p_rng_blind,
249*62c56f98SSadaf Ebrahimi mbedtls_ecdsa_restart_ctx *rs_ctx)
250*62c56f98SSadaf Ebrahimi {
251*62c56f98SSadaf Ebrahimi int ret, key_tries, sign_tries;
252*62c56f98SSadaf Ebrahimi int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
253*62c56f98SSadaf Ebrahimi mbedtls_ecp_point R;
254*62c56f98SSadaf Ebrahimi mbedtls_mpi k, e, t;
255*62c56f98SSadaf Ebrahimi mbedtls_mpi *pk = &k, *pr = r;
256*62c56f98SSadaf Ebrahimi
257*62c56f98SSadaf Ebrahimi /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
258*62c56f98SSadaf Ebrahimi if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
259*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
260*62c56f98SSadaf Ebrahimi }
261*62c56f98SSadaf Ebrahimi
262*62c56f98SSadaf Ebrahimi /* Make sure d is in range 1..n-1 */
263*62c56f98SSadaf Ebrahimi if (mbedtls_mpi_cmp_int(d, 1) < 0 || mbedtls_mpi_cmp_mpi(d, &grp->N) >= 0) {
264*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ECP_INVALID_KEY;
265*62c56f98SSadaf Ebrahimi }
266*62c56f98SSadaf Ebrahimi
267*62c56f98SSadaf Ebrahimi mbedtls_ecp_point_init(&R);
268*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&k); mbedtls_mpi_init(&e); mbedtls_mpi_init(&t);
269*62c56f98SSadaf Ebrahimi
270*62c56f98SSadaf Ebrahimi ECDSA_RS_ENTER(sig);
271*62c56f98SSadaf Ebrahimi
272*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
273*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->sig != NULL) {
274*62c56f98SSadaf Ebrahimi /* redirect to our context */
275*62c56f98SSadaf Ebrahimi p_sign_tries = &rs_ctx->sig->sign_tries;
276*62c56f98SSadaf Ebrahimi p_key_tries = &rs_ctx->sig->key_tries;
277*62c56f98SSadaf Ebrahimi pk = &rs_ctx->sig->k;
278*62c56f98SSadaf Ebrahimi pr = &rs_ctx->sig->r;
279*62c56f98SSadaf Ebrahimi
280*62c56f98SSadaf Ebrahimi /* jump to current step */
281*62c56f98SSadaf Ebrahimi if (rs_ctx->sig->state == ecdsa_sig_mul) {
282*62c56f98SSadaf Ebrahimi goto mul;
283*62c56f98SSadaf Ebrahimi }
284*62c56f98SSadaf Ebrahimi if (rs_ctx->sig->state == ecdsa_sig_modn) {
285*62c56f98SSadaf Ebrahimi goto modn;
286*62c56f98SSadaf Ebrahimi }
287*62c56f98SSadaf Ebrahimi }
288*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECP_RESTARTABLE */
289*62c56f98SSadaf Ebrahimi
290*62c56f98SSadaf Ebrahimi *p_sign_tries = 0;
291*62c56f98SSadaf Ebrahimi do {
292*62c56f98SSadaf Ebrahimi if ((*p_sign_tries)++ > 10) {
293*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
294*62c56f98SSadaf Ebrahimi goto cleanup;
295*62c56f98SSadaf Ebrahimi }
296*62c56f98SSadaf Ebrahimi
297*62c56f98SSadaf Ebrahimi /*
298*62c56f98SSadaf Ebrahimi * Steps 1-3: generate a suitable ephemeral keypair
299*62c56f98SSadaf Ebrahimi * and set r = xR mod n
300*62c56f98SSadaf Ebrahimi */
301*62c56f98SSadaf Ebrahimi *p_key_tries = 0;
302*62c56f98SSadaf Ebrahimi do {
303*62c56f98SSadaf Ebrahimi if ((*p_key_tries)++ > 10) {
304*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
305*62c56f98SSadaf Ebrahimi goto cleanup;
306*62c56f98SSadaf Ebrahimi }
307*62c56f98SSadaf Ebrahimi
308*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, pk, f_rng, p_rng));
309*62c56f98SSadaf Ebrahimi
310*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
311*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->sig != NULL) {
312*62c56f98SSadaf Ebrahimi rs_ctx->sig->state = ecdsa_sig_mul;
313*62c56f98SSadaf Ebrahimi }
314*62c56f98SSadaf Ebrahimi
315*62c56f98SSadaf Ebrahimi mul:
316*62c56f98SSadaf Ebrahimi #endif
317*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &R, pk, &grp->G,
318*62c56f98SSadaf Ebrahimi f_rng_blind,
319*62c56f98SSadaf Ebrahimi p_rng_blind,
320*62c56f98SSadaf Ebrahimi ECDSA_RS_ECP));
321*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pr, &R.X, &grp->N));
322*62c56f98SSadaf Ebrahimi } while (mbedtls_mpi_cmp_int(pr, 0) == 0);
323*62c56f98SSadaf Ebrahimi
324*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
325*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->sig != NULL) {
326*62c56f98SSadaf Ebrahimi rs_ctx->sig->state = ecdsa_sig_modn;
327*62c56f98SSadaf Ebrahimi }
328*62c56f98SSadaf Ebrahimi
329*62c56f98SSadaf Ebrahimi modn:
330*62c56f98SSadaf Ebrahimi #endif
331*62c56f98SSadaf Ebrahimi /*
332*62c56f98SSadaf Ebrahimi * Accounting for everything up to the end of the loop
333*62c56f98SSadaf Ebrahimi * (step 6, but checking now avoids saving e and t)
334*62c56f98SSadaf Ebrahimi */
335*62c56f98SSadaf Ebrahimi ECDSA_BUDGET(MBEDTLS_ECP_OPS_INV + 4);
336*62c56f98SSadaf Ebrahimi
337*62c56f98SSadaf Ebrahimi /*
338*62c56f98SSadaf Ebrahimi * Step 5: derive MPI from hashed message
339*62c56f98SSadaf Ebrahimi */
340*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
341*62c56f98SSadaf Ebrahimi
342*62c56f98SSadaf Ebrahimi /*
343*62c56f98SSadaf Ebrahimi * Generate a random value to blind inv_mod in next step,
344*62c56f98SSadaf Ebrahimi * avoiding a potential timing leak.
345*62c56f98SSadaf Ebrahimi */
346*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, &t, f_rng_blind,
347*62c56f98SSadaf Ebrahimi p_rng_blind));
348*62c56f98SSadaf Ebrahimi
349*62c56f98SSadaf Ebrahimi /*
350*62c56f98SSadaf Ebrahimi * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
351*62c56f98SSadaf Ebrahimi */
352*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, pr, d));
353*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(&e, &e, s));
354*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&e, &e, &t));
355*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pk, pk, &t));
356*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pk, pk, &grp->N));
357*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(s, pk, &grp->N));
358*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(s, s, &e));
359*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(s, s, &grp->N));
360*62c56f98SSadaf Ebrahimi } while (mbedtls_mpi_cmp_int(s, 0) == 0);
361*62c56f98SSadaf Ebrahimi
362*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
363*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->sig != NULL) {
364*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_copy(r, pr));
365*62c56f98SSadaf Ebrahimi }
366*62c56f98SSadaf Ebrahimi #endif
367*62c56f98SSadaf Ebrahimi
368*62c56f98SSadaf Ebrahimi cleanup:
369*62c56f98SSadaf Ebrahimi mbedtls_ecp_point_free(&R);
370*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&k); mbedtls_mpi_free(&e); mbedtls_mpi_free(&t);
371*62c56f98SSadaf Ebrahimi
372*62c56f98SSadaf Ebrahimi ECDSA_RS_LEAVE(sig);
373*62c56f98SSadaf Ebrahimi
374*62c56f98SSadaf Ebrahimi return ret;
375*62c56f98SSadaf Ebrahimi }
376*62c56f98SSadaf Ebrahimi
377*62c56f98SSadaf Ebrahimi /*
378*62c56f98SSadaf Ebrahimi * Compute ECDSA signature of a hashed message
379*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_sign(mbedtls_ecp_group * grp,mbedtls_mpi * r,mbedtls_mpi * s,const mbedtls_mpi * d,const unsigned char * buf,size_t blen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)380*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_sign(mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
381*62c56f98SSadaf Ebrahimi const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
382*62c56f98SSadaf Ebrahimi int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
383*62c56f98SSadaf Ebrahimi {
384*62c56f98SSadaf Ebrahimi /* Use the same RNG for both blinding and ephemeral key generation */
385*62c56f98SSadaf Ebrahimi return mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
386*62c56f98SSadaf Ebrahimi f_rng, p_rng, f_rng, p_rng, NULL);
387*62c56f98SSadaf Ebrahimi }
388*62c56f98SSadaf Ebrahimi #endif /* !MBEDTLS_ECDSA_SIGN_ALT */
389*62c56f98SSadaf Ebrahimi
390*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
391*62c56f98SSadaf Ebrahimi /*
392*62c56f98SSadaf Ebrahimi * Deterministic signature wrapper
393*62c56f98SSadaf Ebrahimi *
394*62c56f98SSadaf Ebrahimi * note: The f_rng_blind parameter must not be NULL.
395*62c56f98SSadaf Ebrahimi *
396*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group * grp,mbedtls_mpi * r,mbedtls_mpi * s,const mbedtls_mpi * d,const unsigned char * buf,size_t blen,mbedtls_md_type_t md_alg,int (* f_rng_blind)(void *,unsigned char *,size_t),void * p_rng_blind,mbedtls_ecdsa_restart_ctx * rs_ctx)397*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_sign_det_restartable(mbedtls_ecp_group *grp,
398*62c56f98SSadaf Ebrahimi mbedtls_mpi *r, mbedtls_mpi *s,
399*62c56f98SSadaf Ebrahimi const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
400*62c56f98SSadaf Ebrahimi mbedtls_md_type_t md_alg,
401*62c56f98SSadaf Ebrahimi int (*f_rng_blind)(void *, unsigned char *, size_t),
402*62c56f98SSadaf Ebrahimi void *p_rng_blind,
403*62c56f98SSadaf Ebrahimi mbedtls_ecdsa_restart_ctx *rs_ctx)
404*62c56f98SSadaf Ebrahimi {
405*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
406*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_context rng_ctx;
407*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
408*62c56f98SSadaf Ebrahimi unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
409*62c56f98SSadaf Ebrahimi size_t grp_len = (grp->nbits + 7) / 8;
410*62c56f98SSadaf Ebrahimi const mbedtls_md_info_t *md_info;
411*62c56f98SSadaf Ebrahimi mbedtls_mpi h;
412*62c56f98SSadaf Ebrahimi
413*62c56f98SSadaf Ebrahimi if ((md_info = mbedtls_md_info_from_type(md_alg)) == NULL) {
414*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
415*62c56f98SSadaf Ebrahimi }
416*62c56f98SSadaf Ebrahimi
417*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&h);
418*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_init(&rng_ctx);
419*62c56f98SSadaf Ebrahimi
420*62c56f98SSadaf Ebrahimi ECDSA_RS_ENTER(det);
421*62c56f98SSadaf Ebrahimi
422*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
423*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->det != NULL) {
424*62c56f98SSadaf Ebrahimi /* redirect to our context */
425*62c56f98SSadaf Ebrahimi p_rng = &rs_ctx->det->rng_ctx;
426*62c56f98SSadaf Ebrahimi
427*62c56f98SSadaf Ebrahimi /* jump to current step */
428*62c56f98SSadaf Ebrahimi if (rs_ctx->det->state == ecdsa_det_sign) {
429*62c56f98SSadaf Ebrahimi goto sign;
430*62c56f98SSadaf Ebrahimi }
431*62c56f98SSadaf Ebrahimi }
432*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECP_RESTARTABLE */
433*62c56f98SSadaf Ebrahimi
434*62c56f98SSadaf Ebrahimi /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
435*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(d, data, grp_len));
436*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(derive_mpi(grp, &h, buf, blen));
437*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&h, data + grp_len, grp_len));
438*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_hmac_drbg_seed_buf(p_rng, md_info, data, 2 * grp_len));
439*62c56f98SSadaf Ebrahimi
440*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
441*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->det != NULL) {
442*62c56f98SSadaf Ebrahimi rs_ctx->det->state = ecdsa_det_sign;
443*62c56f98SSadaf Ebrahimi }
444*62c56f98SSadaf Ebrahimi
445*62c56f98SSadaf Ebrahimi sign:
446*62c56f98SSadaf Ebrahimi #endif
447*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_SIGN_ALT)
448*62c56f98SSadaf Ebrahimi (void) f_rng_blind;
449*62c56f98SSadaf Ebrahimi (void) p_rng_blind;
450*62c56f98SSadaf Ebrahimi ret = mbedtls_ecdsa_sign(grp, r, s, d, buf, blen,
451*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_random, p_rng);
452*62c56f98SSadaf Ebrahimi #else
453*62c56f98SSadaf Ebrahimi ret = mbedtls_ecdsa_sign_restartable(grp, r, s, d, buf, blen,
454*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_random, p_rng,
455*62c56f98SSadaf Ebrahimi f_rng_blind, p_rng_blind, rs_ctx);
456*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_SIGN_ALT */
457*62c56f98SSadaf Ebrahimi
458*62c56f98SSadaf Ebrahimi cleanup:
459*62c56f98SSadaf Ebrahimi mbedtls_hmac_drbg_free(&rng_ctx);
460*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&h);
461*62c56f98SSadaf Ebrahimi
462*62c56f98SSadaf Ebrahimi ECDSA_RS_LEAVE(det);
463*62c56f98SSadaf Ebrahimi
464*62c56f98SSadaf Ebrahimi return ret;
465*62c56f98SSadaf Ebrahimi }
466*62c56f98SSadaf Ebrahimi
467*62c56f98SSadaf Ebrahimi /*
468*62c56f98SSadaf Ebrahimi * Deterministic signature wrapper
469*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group * grp,mbedtls_mpi * r,mbedtls_mpi * s,const mbedtls_mpi * d,const unsigned char * buf,size_t blen,mbedtls_md_type_t md_alg,int (* f_rng_blind)(void *,unsigned char *,size_t),void * p_rng_blind)470*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_sign_det_ext(mbedtls_ecp_group *grp, mbedtls_mpi *r,
471*62c56f98SSadaf Ebrahimi mbedtls_mpi *s, const mbedtls_mpi *d,
472*62c56f98SSadaf Ebrahimi const unsigned char *buf, size_t blen,
473*62c56f98SSadaf Ebrahimi mbedtls_md_type_t md_alg,
474*62c56f98SSadaf Ebrahimi int (*f_rng_blind)(void *, unsigned char *,
475*62c56f98SSadaf Ebrahimi size_t),
476*62c56f98SSadaf Ebrahimi void *p_rng_blind)
477*62c56f98SSadaf Ebrahimi {
478*62c56f98SSadaf Ebrahimi return mbedtls_ecdsa_sign_det_restartable(grp, r, s, d, buf, blen, md_alg,
479*62c56f98SSadaf Ebrahimi f_rng_blind, p_rng_blind, NULL);
480*62c56f98SSadaf Ebrahimi }
481*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
482*62c56f98SSadaf Ebrahimi
483*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
484*62c56f98SSadaf Ebrahimi /*
485*62c56f98SSadaf Ebrahimi * Verify ECDSA signature of hashed message (SEC1 4.1.4)
486*62c56f98SSadaf Ebrahimi * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
487*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group * grp,const unsigned char * buf,size_t blen,const mbedtls_ecp_point * Q,const mbedtls_mpi * r,const mbedtls_mpi * s,mbedtls_ecdsa_restart_ctx * rs_ctx)488*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_verify_restartable(mbedtls_ecp_group *grp,
489*62c56f98SSadaf Ebrahimi const unsigned char *buf, size_t blen,
490*62c56f98SSadaf Ebrahimi const mbedtls_ecp_point *Q,
491*62c56f98SSadaf Ebrahimi const mbedtls_mpi *r,
492*62c56f98SSadaf Ebrahimi const mbedtls_mpi *s,
493*62c56f98SSadaf Ebrahimi mbedtls_ecdsa_restart_ctx *rs_ctx)
494*62c56f98SSadaf Ebrahimi {
495*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
496*62c56f98SSadaf Ebrahimi mbedtls_mpi e, s_inv, u1, u2;
497*62c56f98SSadaf Ebrahimi mbedtls_ecp_point R;
498*62c56f98SSadaf Ebrahimi mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
499*62c56f98SSadaf Ebrahimi
500*62c56f98SSadaf Ebrahimi mbedtls_ecp_point_init(&R);
501*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&e); mbedtls_mpi_init(&s_inv);
502*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&u1); mbedtls_mpi_init(&u2);
503*62c56f98SSadaf Ebrahimi
504*62c56f98SSadaf Ebrahimi /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
505*62c56f98SSadaf Ebrahimi if (!mbedtls_ecdsa_can_do(grp->id) || grp->N.p == NULL) {
506*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
507*62c56f98SSadaf Ebrahimi }
508*62c56f98SSadaf Ebrahimi
509*62c56f98SSadaf Ebrahimi ECDSA_RS_ENTER(ver);
510*62c56f98SSadaf Ebrahimi
511*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
512*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->ver != NULL) {
513*62c56f98SSadaf Ebrahimi /* redirect to our context */
514*62c56f98SSadaf Ebrahimi pu1 = &rs_ctx->ver->u1;
515*62c56f98SSadaf Ebrahimi pu2 = &rs_ctx->ver->u2;
516*62c56f98SSadaf Ebrahimi
517*62c56f98SSadaf Ebrahimi /* jump to current step */
518*62c56f98SSadaf Ebrahimi if (rs_ctx->ver->state == ecdsa_ver_muladd) {
519*62c56f98SSadaf Ebrahimi goto muladd;
520*62c56f98SSadaf Ebrahimi }
521*62c56f98SSadaf Ebrahimi }
522*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECP_RESTARTABLE */
523*62c56f98SSadaf Ebrahimi
524*62c56f98SSadaf Ebrahimi /*
525*62c56f98SSadaf Ebrahimi * Step 1: make sure r and s are in range 1..n-1
526*62c56f98SSadaf Ebrahimi */
527*62c56f98SSadaf Ebrahimi if (mbedtls_mpi_cmp_int(r, 1) < 0 || mbedtls_mpi_cmp_mpi(r, &grp->N) >= 0 ||
528*62c56f98SSadaf Ebrahimi mbedtls_mpi_cmp_int(s, 1) < 0 || mbedtls_mpi_cmp_mpi(s, &grp->N) >= 0) {
529*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
530*62c56f98SSadaf Ebrahimi goto cleanup;
531*62c56f98SSadaf Ebrahimi }
532*62c56f98SSadaf Ebrahimi
533*62c56f98SSadaf Ebrahimi /*
534*62c56f98SSadaf Ebrahimi * Step 3: derive MPI from hashed message
535*62c56f98SSadaf Ebrahimi */
536*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(derive_mpi(grp, &e, buf, blen));
537*62c56f98SSadaf Ebrahimi
538*62c56f98SSadaf Ebrahimi /*
539*62c56f98SSadaf Ebrahimi * Step 4: u1 = e / s mod n, u2 = r / s mod n
540*62c56f98SSadaf Ebrahimi */
541*62c56f98SSadaf Ebrahimi ECDSA_BUDGET(MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2);
542*62c56f98SSadaf Ebrahimi
543*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&s_inv, s, &grp->N));
544*62c56f98SSadaf Ebrahimi
545*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu1, &e, &s_inv));
546*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu1, pu1, &grp->N));
547*62c56f98SSadaf Ebrahimi
548*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(pu2, r, &s_inv));
549*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(pu2, pu2, &grp->N));
550*62c56f98SSadaf Ebrahimi
551*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
552*62c56f98SSadaf Ebrahimi if (rs_ctx != NULL && rs_ctx->ver != NULL) {
553*62c56f98SSadaf Ebrahimi rs_ctx->ver->state = ecdsa_ver_muladd;
554*62c56f98SSadaf Ebrahimi }
555*62c56f98SSadaf Ebrahimi
556*62c56f98SSadaf Ebrahimi muladd:
557*62c56f98SSadaf Ebrahimi #endif
558*62c56f98SSadaf Ebrahimi /*
559*62c56f98SSadaf Ebrahimi * Step 5: R = u1 G + u2 Q
560*62c56f98SSadaf Ebrahimi */
561*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecp_muladd_restartable(grp,
562*62c56f98SSadaf Ebrahimi &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP));
563*62c56f98SSadaf Ebrahimi
564*62c56f98SSadaf Ebrahimi if (mbedtls_ecp_is_zero(&R)) {
565*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
566*62c56f98SSadaf Ebrahimi goto cleanup;
567*62c56f98SSadaf Ebrahimi }
568*62c56f98SSadaf Ebrahimi
569*62c56f98SSadaf Ebrahimi /*
570*62c56f98SSadaf Ebrahimi * Step 6: convert xR to an integer (no-op)
571*62c56f98SSadaf Ebrahimi * Step 7: reduce xR mod n (gives v)
572*62c56f98SSadaf Ebrahimi */
573*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&R.X, &R.X, &grp->N));
574*62c56f98SSadaf Ebrahimi
575*62c56f98SSadaf Ebrahimi /*
576*62c56f98SSadaf Ebrahimi * Step 8: check if v (that is, R.X) is equal to r
577*62c56f98SSadaf Ebrahimi */
578*62c56f98SSadaf Ebrahimi if (mbedtls_mpi_cmp_mpi(&R.X, r) != 0) {
579*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
580*62c56f98SSadaf Ebrahimi goto cleanup;
581*62c56f98SSadaf Ebrahimi }
582*62c56f98SSadaf Ebrahimi
583*62c56f98SSadaf Ebrahimi cleanup:
584*62c56f98SSadaf Ebrahimi mbedtls_ecp_point_free(&R);
585*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&e); mbedtls_mpi_free(&s_inv);
586*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&u1); mbedtls_mpi_free(&u2);
587*62c56f98SSadaf Ebrahimi
588*62c56f98SSadaf Ebrahimi ECDSA_RS_LEAVE(ver);
589*62c56f98SSadaf Ebrahimi
590*62c56f98SSadaf Ebrahimi return ret;
591*62c56f98SSadaf Ebrahimi }
592*62c56f98SSadaf Ebrahimi
593*62c56f98SSadaf Ebrahimi /*
594*62c56f98SSadaf Ebrahimi * Verify ECDSA signature of hashed message
595*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_verify(mbedtls_ecp_group * grp,const unsigned char * buf,size_t blen,const mbedtls_ecp_point * Q,const mbedtls_mpi * r,const mbedtls_mpi * s)596*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_verify(mbedtls_ecp_group *grp,
597*62c56f98SSadaf Ebrahimi const unsigned char *buf, size_t blen,
598*62c56f98SSadaf Ebrahimi const mbedtls_ecp_point *Q,
599*62c56f98SSadaf Ebrahimi const mbedtls_mpi *r,
600*62c56f98SSadaf Ebrahimi const mbedtls_mpi *s)
601*62c56f98SSadaf Ebrahimi {
602*62c56f98SSadaf Ebrahimi return mbedtls_ecdsa_verify_restartable(grp, buf, blen, Q, r, s, NULL);
603*62c56f98SSadaf Ebrahimi }
604*62c56f98SSadaf Ebrahimi #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
605*62c56f98SSadaf Ebrahimi
606*62c56f98SSadaf Ebrahimi /*
607*62c56f98SSadaf Ebrahimi * Convert a signature (given by context) to ASN.1
608*62c56f98SSadaf Ebrahimi */
ecdsa_signature_to_asn1(const mbedtls_mpi * r,const mbedtls_mpi * s,unsigned char * sig,size_t sig_size,size_t * slen)609*62c56f98SSadaf Ebrahimi static int ecdsa_signature_to_asn1(const mbedtls_mpi *r, const mbedtls_mpi *s,
610*62c56f98SSadaf Ebrahimi unsigned char *sig, size_t sig_size,
611*62c56f98SSadaf Ebrahimi size_t *slen)
612*62c56f98SSadaf Ebrahimi {
613*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
614*62c56f98SSadaf Ebrahimi unsigned char buf[MBEDTLS_ECDSA_MAX_LEN] = { 0 };
615*62c56f98SSadaf Ebrahimi unsigned char *p = buf + sizeof(buf);
616*62c56f98SSadaf Ebrahimi size_t len = 0;
617*62c56f98SSadaf Ebrahimi
618*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, s));
619*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_mpi(&p, buf, r));
620*62c56f98SSadaf Ebrahimi
621*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_len(&p, buf, len));
622*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CHK_ADD(len, mbedtls_asn1_write_tag(&p, buf,
623*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED |
624*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_SEQUENCE));
625*62c56f98SSadaf Ebrahimi
626*62c56f98SSadaf Ebrahimi if (len > sig_size) {
627*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL;
628*62c56f98SSadaf Ebrahimi }
629*62c56f98SSadaf Ebrahimi
630*62c56f98SSadaf Ebrahimi memcpy(sig, p, len);
631*62c56f98SSadaf Ebrahimi *slen = len;
632*62c56f98SSadaf Ebrahimi
633*62c56f98SSadaf Ebrahimi return 0;
634*62c56f98SSadaf Ebrahimi }
635*62c56f98SSadaf Ebrahimi
636*62c56f98SSadaf Ebrahimi /*
637*62c56f98SSadaf Ebrahimi * Compute and write signature
638*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context * ctx,mbedtls_md_type_t md_alg,const unsigned char * hash,size_t hlen,unsigned char * sig,size_t sig_size,size_t * slen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng,mbedtls_ecdsa_restart_ctx * rs_ctx)639*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_write_signature_restartable(mbedtls_ecdsa_context *ctx,
640*62c56f98SSadaf Ebrahimi mbedtls_md_type_t md_alg,
641*62c56f98SSadaf Ebrahimi const unsigned char *hash, size_t hlen,
642*62c56f98SSadaf Ebrahimi unsigned char *sig, size_t sig_size, size_t *slen,
643*62c56f98SSadaf Ebrahimi int (*f_rng)(void *, unsigned char *, size_t),
644*62c56f98SSadaf Ebrahimi void *p_rng,
645*62c56f98SSadaf Ebrahimi mbedtls_ecdsa_restart_ctx *rs_ctx)
646*62c56f98SSadaf Ebrahimi {
647*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
648*62c56f98SSadaf Ebrahimi mbedtls_mpi r, s;
649*62c56f98SSadaf Ebrahimi if (f_rng == NULL) {
650*62c56f98SSadaf Ebrahimi return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651*62c56f98SSadaf Ebrahimi }
652*62c56f98SSadaf Ebrahimi
653*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&r);
654*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&s);
655*62c56f98SSadaf Ebrahimi
656*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
657*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_det_restartable(&ctx->grp, &r, &s, &ctx->d,
658*62c56f98SSadaf Ebrahimi hash, hlen, md_alg, f_rng,
659*62c56f98SSadaf Ebrahimi p_rng, rs_ctx));
660*62c56f98SSadaf Ebrahimi #else
661*62c56f98SSadaf Ebrahimi (void) md_alg;
662*62c56f98SSadaf Ebrahimi
663*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_SIGN_ALT)
664*62c56f98SSadaf Ebrahimi (void) rs_ctx;
665*62c56f98SSadaf Ebrahimi
666*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign(&ctx->grp, &r, &s, &ctx->d,
667*62c56f98SSadaf Ebrahimi hash, hlen, f_rng, p_rng));
668*62c56f98SSadaf Ebrahimi #else
669*62c56f98SSadaf Ebrahimi /* Use the same RNG for both blinding and ephemeral key generation */
670*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(mbedtls_ecdsa_sign_restartable(&ctx->grp, &r, &s, &ctx->d,
671*62c56f98SSadaf Ebrahimi hash, hlen, f_rng, p_rng, f_rng,
672*62c56f98SSadaf Ebrahimi p_rng, rs_ctx));
673*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_SIGN_ALT */
674*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
675*62c56f98SSadaf Ebrahimi
676*62c56f98SSadaf Ebrahimi MBEDTLS_MPI_CHK(ecdsa_signature_to_asn1(&r, &s, sig, sig_size, slen));
677*62c56f98SSadaf Ebrahimi
678*62c56f98SSadaf Ebrahimi cleanup:
679*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&r);
680*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&s);
681*62c56f98SSadaf Ebrahimi
682*62c56f98SSadaf Ebrahimi return ret;
683*62c56f98SSadaf Ebrahimi }
684*62c56f98SSadaf Ebrahimi
685*62c56f98SSadaf Ebrahimi /*
686*62c56f98SSadaf Ebrahimi * Compute and write signature
687*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context * ctx,mbedtls_md_type_t md_alg,const unsigned char * hash,size_t hlen,unsigned char * sig,size_t sig_size,size_t * slen,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)688*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_write_signature(mbedtls_ecdsa_context *ctx,
689*62c56f98SSadaf Ebrahimi mbedtls_md_type_t md_alg,
690*62c56f98SSadaf Ebrahimi const unsigned char *hash, size_t hlen,
691*62c56f98SSadaf Ebrahimi unsigned char *sig, size_t sig_size, size_t *slen,
692*62c56f98SSadaf Ebrahimi int (*f_rng)(void *, unsigned char *, size_t),
693*62c56f98SSadaf Ebrahimi void *p_rng)
694*62c56f98SSadaf Ebrahimi {
695*62c56f98SSadaf Ebrahimi return mbedtls_ecdsa_write_signature_restartable(
696*62c56f98SSadaf Ebrahimi ctx, md_alg, hash, hlen, sig, sig_size, slen,
697*62c56f98SSadaf Ebrahimi f_rng, p_rng, NULL);
698*62c56f98SSadaf Ebrahimi }
699*62c56f98SSadaf Ebrahimi
700*62c56f98SSadaf Ebrahimi /*
701*62c56f98SSadaf Ebrahimi * Read and check signature
702*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context * ctx,const unsigned char * hash,size_t hlen,const unsigned char * sig,size_t slen)703*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_read_signature(mbedtls_ecdsa_context *ctx,
704*62c56f98SSadaf Ebrahimi const unsigned char *hash, size_t hlen,
705*62c56f98SSadaf Ebrahimi const unsigned char *sig, size_t slen)
706*62c56f98SSadaf Ebrahimi {
707*62c56f98SSadaf Ebrahimi return mbedtls_ecdsa_read_signature_restartable(
708*62c56f98SSadaf Ebrahimi ctx, hash, hlen, sig, slen, NULL);
709*62c56f98SSadaf Ebrahimi }
710*62c56f98SSadaf Ebrahimi
711*62c56f98SSadaf Ebrahimi /*
712*62c56f98SSadaf Ebrahimi * Restartable read and check signature
713*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context * ctx,const unsigned char * hash,size_t hlen,const unsigned char * sig,size_t slen,mbedtls_ecdsa_restart_ctx * rs_ctx)714*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_read_signature_restartable(mbedtls_ecdsa_context *ctx,
715*62c56f98SSadaf Ebrahimi const unsigned char *hash, size_t hlen,
716*62c56f98SSadaf Ebrahimi const unsigned char *sig, size_t slen,
717*62c56f98SSadaf Ebrahimi mbedtls_ecdsa_restart_ctx *rs_ctx)
718*62c56f98SSadaf Ebrahimi {
719*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
720*62c56f98SSadaf Ebrahimi unsigned char *p = (unsigned char *) sig;
721*62c56f98SSadaf Ebrahimi const unsigned char *end = sig + slen;
722*62c56f98SSadaf Ebrahimi size_t len;
723*62c56f98SSadaf Ebrahimi mbedtls_mpi r, s;
724*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&r);
725*62c56f98SSadaf Ebrahimi mbedtls_mpi_init(&s);
726*62c56f98SSadaf Ebrahimi
727*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
728*62c56f98SSadaf Ebrahimi MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
729*62c56f98SSadaf Ebrahimi ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
730*62c56f98SSadaf Ebrahimi goto cleanup;
731*62c56f98SSadaf Ebrahimi }
732*62c56f98SSadaf Ebrahimi
733*62c56f98SSadaf Ebrahimi if (p + len != end) {
734*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_ECP_BAD_INPUT_DATA,
735*62c56f98SSadaf Ebrahimi MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
736*62c56f98SSadaf Ebrahimi goto cleanup;
737*62c56f98SSadaf Ebrahimi }
738*62c56f98SSadaf Ebrahimi
739*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_asn1_get_mpi(&p, end, &r)) != 0 ||
740*62c56f98SSadaf Ebrahimi (ret = mbedtls_asn1_get_mpi(&p, end, &s)) != 0) {
741*62c56f98SSadaf Ebrahimi ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
742*62c56f98SSadaf Ebrahimi goto cleanup;
743*62c56f98SSadaf Ebrahimi }
744*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
745*62c56f98SSadaf Ebrahimi (void) rs_ctx;
746*62c56f98SSadaf Ebrahimi
747*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ecdsa_verify(&ctx->grp, hash, hlen,
748*62c56f98SSadaf Ebrahimi &ctx->Q, &r, &s)) != 0) {
749*62c56f98SSadaf Ebrahimi goto cleanup;
750*62c56f98SSadaf Ebrahimi }
751*62c56f98SSadaf Ebrahimi #else
752*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ecdsa_verify_restartable(&ctx->grp, hash, hlen,
753*62c56f98SSadaf Ebrahimi &ctx->Q, &r, &s, rs_ctx)) != 0) {
754*62c56f98SSadaf Ebrahimi goto cleanup;
755*62c56f98SSadaf Ebrahimi }
756*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
757*62c56f98SSadaf Ebrahimi
758*62c56f98SSadaf Ebrahimi /* At this point we know that the buffer starts with a valid signature.
759*62c56f98SSadaf Ebrahimi * Return 0 if the buffer just contains the signature, and a specific
760*62c56f98SSadaf Ebrahimi * error code if the valid signature is followed by more data. */
761*62c56f98SSadaf Ebrahimi if (p != end) {
762*62c56f98SSadaf Ebrahimi ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
763*62c56f98SSadaf Ebrahimi }
764*62c56f98SSadaf Ebrahimi
765*62c56f98SSadaf Ebrahimi cleanup:
766*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&r);
767*62c56f98SSadaf Ebrahimi mbedtls_mpi_free(&s);
768*62c56f98SSadaf Ebrahimi
769*62c56f98SSadaf Ebrahimi return ret;
770*62c56f98SSadaf Ebrahimi }
771*62c56f98SSadaf Ebrahimi
772*62c56f98SSadaf Ebrahimi #if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
773*62c56f98SSadaf Ebrahimi /*
774*62c56f98SSadaf Ebrahimi * Generate key pair
775*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_genkey(mbedtls_ecdsa_context * ctx,mbedtls_ecp_group_id gid,int (* f_rng)(void *,unsigned char *,size_t),void * p_rng)776*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_genkey(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
777*62c56f98SSadaf Ebrahimi int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
778*62c56f98SSadaf Ebrahimi {
779*62c56f98SSadaf Ebrahimi int ret = 0;
780*62c56f98SSadaf Ebrahimi ret = mbedtls_ecp_group_load(&ctx->grp, gid);
781*62c56f98SSadaf Ebrahimi if (ret != 0) {
782*62c56f98SSadaf Ebrahimi return ret;
783*62c56f98SSadaf Ebrahimi }
784*62c56f98SSadaf Ebrahimi
785*62c56f98SSadaf Ebrahimi return mbedtls_ecp_gen_keypair(&ctx->grp, &ctx->d,
786*62c56f98SSadaf Ebrahimi &ctx->Q, f_rng, p_rng);
787*62c56f98SSadaf Ebrahimi }
788*62c56f98SSadaf Ebrahimi #endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
789*62c56f98SSadaf Ebrahimi
790*62c56f98SSadaf Ebrahimi /*
791*62c56f98SSadaf Ebrahimi * Set context from an mbedtls_ecp_keypair
792*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context * ctx,const mbedtls_ecp_keypair * key)793*62c56f98SSadaf Ebrahimi int mbedtls_ecdsa_from_keypair(mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key)
794*62c56f98SSadaf Ebrahimi {
795*62c56f98SSadaf Ebrahimi int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
796*62c56f98SSadaf Ebrahimi if ((ret = mbedtls_ecp_group_copy(&ctx->grp, &key->grp)) != 0 ||
797*62c56f98SSadaf Ebrahimi (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0 ||
798*62c56f98SSadaf Ebrahimi (ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0) {
799*62c56f98SSadaf Ebrahimi mbedtls_ecdsa_free(ctx);
800*62c56f98SSadaf Ebrahimi }
801*62c56f98SSadaf Ebrahimi
802*62c56f98SSadaf Ebrahimi return ret;
803*62c56f98SSadaf Ebrahimi }
804*62c56f98SSadaf Ebrahimi
805*62c56f98SSadaf Ebrahimi /*
806*62c56f98SSadaf Ebrahimi * Initialize context
807*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_init(mbedtls_ecdsa_context * ctx)808*62c56f98SSadaf Ebrahimi void mbedtls_ecdsa_init(mbedtls_ecdsa_context *ctx)
809*62c56f98SSadaf Ebrahimi {
810*62c56f98SSadaf Ebrahimi mbedtls_ecp_keypair_init(ctx);
811*62c56f98SSadaf Ebrahimi }
812*62c56f98SSadaf Ebrahimi
813*62c56f98SSadaf Ebrahimi /*
814*62c56f98SSadaf Ebrahimi * Free context
815*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_free(mbedtls_ecdsa_context * ctx)816*62c56f98SSadaf Ebrahimi void mbedtls_ecdsa_free(mbedtls_ecdsa_context *ctx)
817*62c56f98SSadaf Ebrahimi {
818*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
819*62c56f98SSadaf Ebrahimi return;
820*62c56f98SSadaf Ebrahimi }
821*62c56f98SSadaf Ebrahimi
822*62c56f98SSadaf Ebrahimi mbedtls_ecp_keypair_free(ctx);
823*62c56f98SSadaf Ebrahimi }
824*62c56f98SSadaf Ebrahimi
825*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECP_RESTARTABLE)
826*62c56f98SSadaf Ebrahimi /*
827*62c56f98SSadaf Ebrahimi * Initialize a restart context
828*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx * ctx)829*62c56f98SSadaf Ebrahimi void mbedtls_ecdsa_restart_init(mbedtls_ecdsa_restart_ctx *ctx)
830*62c56f98SSadaf Ebrahimi {
831*62c56f98SSadaf Ebrahimi mbedtls_ecp_restart_init(&ctx->ecp);
832*62c56f98SSadaf Ebrahimi
833*62c56f98SSadaf Ebrahimi ctx->ver = NULL;
834*62c56f98SSadaf Ebrahimi ctx->sig = NULL;
835*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
836*62c56f98SSadaf Ebrahimi ctx->det = NULL;
837*62c56f98SSadaf Ebrahimi #endif
838*62c56f98SSadaf Ebrahimi }
839*62c56f98SSadaf Ebrahimi
840*62c56f98SSadaf Ebrahimi /*
841*62c56f98SSadaf Ebrahimi * Free the components of a restart context
842*62c56f98SSadaf Ebrahimi */
mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx * ctx)843*62c56f98SSadaf Ebrahimi void mbedtls_ecdsa_restart_free(mbedtls_ecdsa_restart_ctx *ctx)
844*62c56f98SSadaf Ebrahimi {
845*62c56f98SSadaf Ebrahimi if (ctx == NULL) {
846*62c56f98SSadaf Ebrahimi return;
847*62c56f98SSadaf Ebrahimi }
848*62c56f98SSadaf Ebrahimi
849*62c56f98SSadaf Ebrahimi mbedtls_ecp_restart_free(&ctx->ecp);
850*62c56f98SSadaf Ebrahimi
851*62c56f98SSadaf Ebrahimi ecdsa_restart_ver_free(ctx->ver);
852*62c56f98SSadaf Ebrahimi mbedtls_free(ctx->ver);
853*62c56f98SSadaf Ebrahimi ctx->ver = NULL;
854*62c56f98SSadaf Ebrahimi
855*62c56f98SSadaf Ebrahimi ecdsa_restart_sig_free(ctx->sig);
856*62c56f98SSadaf Ebrahimi mbedtls_free(ctx->sig);
857*62c56f98SSadaf Ebrahimi ctx->sig = NULL;
858*62c56f98SSadaf Ebrahimi
859*62c56f98SSadaf Ebrahimi #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
860*62c56f98SSadaf Ebrahimi ecdsa_restart_det_free(ctx->det);
861*62c56f98SSadaf Ebrahimi mbedtls_free(ctx->det);
862*62c56f98SSadaf Ebrahimi ctx->det = NULL;
863*62c56f98SSadaf Ebrahimi #endif
864*62c56f98SSadaf Ebrahimi }
865*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECP_RESTARTABLE */
866*62c56f98SSadaf Ebrahimi
867*62c56f98SSadaf Ebrahimi #endif /* MBEDTLS_ECDSA_C */
868