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