xref: /optee_os/lib/libmbedtls/mbedtls/library/ecdsa.c (revision 3d3b05918ec9052ba13de82fbcaba204766eb636)
1c6672fdcSEdison Ai // SPDX-License-Identifier: Apache-2.0
2817466cbSJens Wiklander /*
3817466cbSJens Wiklander  *  Elliptic curve DSA
4817466cbSJens Wiklander  *
5817466cbSJens Wiklander  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
6817466cbSJens Wiklander  *
7817466cbSJens Wiklander  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8817466cbSJens Wiklander  *  not use this file except in compliance with the License.
9817466cbSJens Wiklander  *  You may obtain a copy of the License at
10817466cbSJens Wiklander  *
11817466cbSJens Wiklander  *  http://www.apache.org/licenses/LICENSE-2.0
12817466cbSJens Wiklander  *
13817466cbSJens Wiklander  *  Unless required by applicable law or agreed to in writing, software
14817466cbSJens Wiklander  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15817466cbSJens Wiklander  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16817466cbSJens Wiklander  *  See the License for the specific language governing permissions and
17817466cbSJens Wiklander  *  limitations under the License.
18817466cbSJens Wiklander  *
19817466cbSJens Wiklander  *  This file is part of mbed TLS (https://tls.mbed.org)
20817466cbSJens Wiklander  */
21817466cbSJens Wiklander 
22817466cbSJens Wiklander /*
23817466cbSJens Wiklander  * References:
24817466cbSJens Wiklander  *
25817466cbSJens Wiklander  * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
26817466cbSJens Wiklander  */
27817466cbSJens Wiklander 
28817466cbSJens Wiklander #if !defined(MBEDTLS_CONFIG_FILE)
29817466cbSJens Wiklander #include "mbedtls/config.h"
30817466cbSJens Wiklander #else
31817466cbSJens Wiklander #include MBEDTLS_CONFIG_FILE
32817466cbSJens Wiklander #endif
33817466cbSJens Wiklander 
34817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_C)
35817466cbSJens Wiklander 
36817466cbSJens Wiklander #include "mbedtls/ecdsa.h"
37817466cbSJens Wiklander #include "mbedtls/asn1write.h"
38817466cbSJens Wiklander 
39817466cbSJens Wiklander #include <string.h>
40817466cbSJens Wiklander 
41817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
42817466cbSJens Wiklander #include "mbedtls/hmac_drbg.h"
43817466cbSJens Wiklander #endif
44817466cbSJens Wiklander 
45*3d3b0591SJens Wiklander #if defined(MBEDTLS_PLATFORM_C)
46*3d3b0591SJens Wiklander #include "mbedtls/platform.h"
47*3d3b0591SJens Wiklander #else
48*3d3b0591SJens Wiklander #include <stdlib.h>
49*3d3b0591SJens Wiklander #define mbedtls_calloc    calloc
50*3d3b0591SJens Wiklander #define mbedtls_free       free
51*3d3b0591SJens Wiklander #endif
52*3d3b0591SJens Wiklander 
53*3d3b0591SJens Wiklander #include "mbedtls/platform_util.h"
54*3d3b0591SJens Wiklander 
55*3d3b0591SJens Wiklander /* Parameter validation macros based on platform_util.h */
56*3d3b0591SJens Wiklander #define ECDSA_VALIDATE_RET( cond )    \
57*3d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
58*3d3b0591SJens Wiklander #define ECDSA_VALIDATE( cond )        \
59*3d3b0591SJens Wiklander     MBEDTLS_INTERNAL_VALIDATE( cond )
60*3d3b0591SJens Wiklander 
61*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
62*3d3b0591SJens Wiklander 
63*3d3b0591SJens Wiklander /*
64*3d3b0591SJens Wiklander  * Sub-context for ecdsa_verify()
65*3d3b0591SJens Wiklander  */
66*3d3b0591SJens Wiklander struct mbedtls_ecdsa_restart_ver
67*3d3b0591SJens Wiklander {
68*3d3b0591SJens Wiklander     mbedtls_mpi u1, u2;     /* intermediate values  */
69*3d3b0591SJens Wiklander     enum {                  /* what to do next?     */
70*3d3b0591SJens Wiklander         ecdsa_ver_init = 0, /* getting started      */
71*3d3b0591SJens Wiklander         ecdsa_ver_muladd,   /* muladd step          */
72*3d3b0591SJens Wiklander     } state;
73*3d3b0591SJens Wiklander };
74*3d3b0591SJens Wiklander 
75*3d3b0591SJens Wiklander /*
76*3d3b0591SJens Wiklander  * Init verify restart sub-context
77*3d3b0591SJens Wiklander  */
78*3d3b0591SJens Wiklander static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
79*3d3b0591SJens Wiklander {
80*3d3b0591SJens Wiklander     mbedtls_mpi_init( &ctx->u1 );
81*3d3b0591SJens Wiklander     mbedtls_mpi_init( &ctx->u2 );
82*3d3b0591SJens Wiklander     ctx->state = ecdsa_ver_init;
83*3d3b0591SJens Wiklander }
84*3d3b0591SJens Wiklander 
85*3d3b0591SJens Wiklander /*
86*3d3b0591SJens Wiklander  * Free the components of a verify restart sub-context
87*3d3b0591SJens Wiklander  */
88*3d3b0591SJens Wiklander static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
89*3d3b0591SJens Wiklander {
90*3d3b0591SJens Wiklander     if( ctx == NULL )
91*3d3b0591SJens Wiklander         return;
92*3d3b0591SJens Wiklander 
93*3d3b0591SJens Wiklander     mbedtls_mpi_free( &ctx->u1 );
94*3d3b0591SJens Wiklander     mbedtls_mpi_free( &ctx->u2 );
95*3d3b0591SJens Wiklander 
96*3d3b0591SJens Wiklander     ecdsa_restart_ver_init( ctx );
97*3d3b0591SJens Wiklander }
98*3d3b0591SJens Wiklander 
99*3d3b0591SJens Wiklander /*
100*3d3b0591SJens Wiklander  * Sub-context for ecdsa_sign()
101*3d3b0591SJens Wiklander  */
102*3d3b0591SJens Wiklander struct mbedtls_ecdsa_restart_sig
103*3d3b0591SJens Wiklander {
104*3d3b0591SJens Wiklander     int sign_tries;
105*3d3b0591SJens Wiklander     int key_tries;
106*3d3b0591SJens Wiklander     mbedtls_mpi k;          /* per-signature random */
107*3d3b0591SJens Wiklander     mbedtls_mpi r;          /* r value              */
108*3d3b0591SJens Wiklander     enum {                  /* what to do next?     */
109*3d3b0591SJens Wiklander         ecdsa_sig_init = 0, /* getting started      */
110*3d3b0591SJens Wiklander         ecdsa_sig_mul,      /* doing ecp_mul()      */
111*3d3b0591SJens Wiklander         ecdsa_sig_modn,     /* mod N computations   */
112*3d3b0591SJens Wiklander     } state;
113*3d3b0591SJens Wiklander };
114*3d3b0591SJens Wiklander 
115*3d3b0591SJens Wiklander /*
116*3d3b0591SJens Wiklander  * Init verify sign sub-context
117*3d3b0591SJens Wiklander  */
118*3d3b0591SJens Wiklander static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
119*3d3b0591SJens Wiklander {
120*3d3b0591SJens Wiklander     ctx->sign_tries = 0;
121*3d3b0591SJens Wiklander     ctx->key_tries = 0;
122*3d3b0591SJens Wiklander     mbedtls_mpi_init( &ctx->k );
123*3d3b0591SJens Wiklander     mbedtls_mpi_init( &ctx->r );
124*3d3b0591SJens Wiklander     ctx->state = ecdsa_sig_init;
125*3d3b0591SJens Wiklander }
126*3d3b0591SJens Wiklander 
127*3d3b0591SJens Wiklander /*
128*3d3b0591SJens Wiklander  * Free the components of a sign restart sub-context
129*3d3b0591SJens Wiklander  */
130*3d3b0591SJens Wiklander static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
131*3d3b0591SJens Wiklander {
132*3d3b0591SJens Wiklander     if( ctx == NULL )
133*3d3b0591SJens Wiklander         return;
134*3d3b0591SJens Wiklander 
135*3d3b0591SJens Wiklander     mbedtls_mpi_free( &ctx->k );
136*3d3b0591SJens Wiklander     mbedtls_mpi_free( &ctx->r );
137*3d3b0591SJens Wiklander }
138*3d3b0591SJens Wiklander 
139*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
140*3d3b0591SJens Wiklander /*
141*3d3b0591SJens Wiklander  * Sub-context for ecdsa_sign_det()
142*3d3b0591SJens Wiklander  */
143*3d3b0591SJens Wiklander struct mbedtls_ecdsa_restart_det
144*3d3b0591SJens Wiklander {
145*3d3b0591SJens Wiklander     mbedtls_hmac_drbg_context rng_ctx;  /* DRBG state   */
146*3d3b0591SJens Wiklander     enum {                      /* what to do next?     */
147*3d3b0591SJens Wiklander         ecdsa_det_init = 0,     /* getting started      */
148*3d3b0591SJens Wiklander         ecdsa_det_sign,         /* make signature       */
149*3d3b0591SJens Wiklander     } state;
150*3d3b0591SJens Wiklander };
151*3d3b0591SJens Wiklander 
152*3d3b0591SJens Wiklander /*
153*3d3b0591SJens Wiklander  * Init verify sign_det sub-context
154*3d3b0591SJens Wiklander  */
155*3d3b0591SJens Wiklander static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
156*3d3b0591SJens Wiklander {
157*3d3b0591SJens Wiklander     mbedtls_hmac_drbg_init( &ctx->rng_ctx );
158*3d3b0591SJens Wiklander     ctx->state = ecdsa_det_init;
159*3d3b0591SJens Wiklander }
160*3d3b0591SJens Wiklander 
161*3d3b0591SJens Wiklander /*
162*3d3b0591SJens Wiklander  * Free the components of a sign_det restart sub-context
163*3d3b0591SJens Wiklander  */
164*3d3b0591SJens Wiklander static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
165*3d3b0591SJens Wiklander {
166*3d3b0591SJens Wiklander     if( ctx == NULL )
167*3d3b0591SJens Wiklander         return;
168*3d3b0591SJens Wiklander 
169*3d3b0591SJens Wiklander     mbedtls_hmac_drbg_free( &ctx->rng_ctx );
170*3d3b0591SJens Wiklander 
171*3d3b0591SJens Wiklander     ecdsa_restart_det_init( ctx );
172*3d3b0591SJens Wiklander }
173*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
174*3d3b0591SJens Wiklander 
175*3d3b0591SJens Wiklander #define ECDSA_RS_ECP    &rs_ctx->ecp
176*3d3b0591SJens Wiklander 
177*3d3b0591SJens Wiklander /* Utility macro for checking and updating ops budget */
178*3d3b0591SJens Wiklander #define ECDSA_BUDGET( ops )   \
179*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, &rs_ctx->ecp, ops ) );
180*3d3b0591SJens Wiklander 
181*3d3b0591SJens Wiklander /* Call this when entering a function that needs its own sub-context */
182*3d3b0591SJens Wiklander #define ECDSA_RS_ENTER( SUB )   do {                                 \
183*3d3b0591SJens Wiklander     /* reset ops count for this call if top-level */                 \
184*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 )                 \
185*3d3b0591SJens Wiklander         rs_ctx->ecp.ops_done = 0;                                    \
186*3d3b0591SJens Wiklander                                                                      \
187*3d3b0591SJens Wiklander     /* set up our own sub-context if needed */                       \
188*3d3b0591SJens Wiklander     if( mbedtls_ecp_restart_is_enabled() &&                          \
189*3d3b0591SJens Wiklander         rs_ctx != NULL && rs_ctx->SUB == NULL )                      \
190*3d3b0591SJens Wiklander     {                                                                \
191*3d3b0591SJens Wiklander         rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) );   \
192*3d3b0591SJens Wiklander         if( rs_ctx->SUB == NULL )                                    \
193*3d3b0591SJens Wiklander             return( MBEDTLS_ERR_ECP_ALLOC_FAILED );                  \
194*3d3b0591SJens Wiklander                                                                      \
195*3d3b0591SJens Wiklander         ecdsa_restart_## SUB ##_init( rs_ctx->SUB );                 \
196*3d3b0591SJens Wiklander     }                                                                \
197*3d3b0591SJens Wiklander } while( 0 )
198*3d3b0591SJens Wiklander 
199*3d3b0591SJens Wiklander /* Call this when leaving a function that needs its own sub-context */
200*3d3b0591SJens Wiklander #define ECDSA_RS_LEAVE( SUB )   do {                                 \
201*3d3b0591SJens Wiklander     /* clear our sub-context when not in progress (done or error) */ \
202*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->SUB != NULL &&                     \
203*3d3b0591SJens Wiklander         ret != MBEDTLS_ERR_ECP_IN_PROGRESS )                         \
204*3d3b0591SJens Wiklander     {                                                                \
205*3d3b0591SJens Wiklander         ecdsa_restart_## SUB ##_free( rs_ctx->SUB );                 \
206*3d3b0591SJens Wiklander         mbedtls_free( rs_ctx->SUB );                                 \
207*3d3b0591SJens Wiklander         rs_ctx->SUB = NULL;                                          \
208*3d3b0591SJens Wiklander     }                                                                \
209*3d3b0591SJens Wiklander                                                                      \
210*3d3b0591SJens Wiklander     if( rs_ctx != NULL )                                             \
211*3d3b0591SJens Wiklander         rs_ctx->ecp.depth--;                                         \
212*3d3b0591SJens Wiklander } while( 0 )
213*3d3b0591SJens Wiklander 
214*3d3b0591SJens Wiklander #else /* MBEDTLS_ECP_RESTARTABLE */
215*3d3b0591SJens Wiklander 
216*3d3b0591SJens Wiklander #define ECDSA_RS_ECP    NULL
217*3d3b0591SJens Wiklander 
218*3d3b0591SJens Wiklander #define ECDSA_BUDGET( ops )   /* no-op; for compatibility */
219*3d3b0591SJens Wiklander 
220*3d3b0591SJens Wiklander #define ECDSA_RS_ENTER( SUB )   (void) rs_ctx
221*3d3b0591SJens Wiklander #define ECDSA_RS_LEAVE( SUB )   (void) rs_ctx
222*3d3b0591SJens Wiklander 
223*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
224*3d3b0591SJens Wiklander 
225817466cbSJens Wiklander /*
226817466cbSJens Wiklander  * Derive a suitable integer for group grp from a buffer of length len
227817466cbSJens Wiklander  * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
228817466cbSJens Wiklander  */
229817466cbSJens Wiklander static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
230817466cbSJens Wiklander                        const unsigned char *buf, size_t blen )
231817466cbSJens Wiklander {
232817466cbSJens Wiklander     int ret;
233817466cbSJens Wiklander     size_t n_size = ( grp->nbits + 7 ) / 8;
234817466cbSJens Wiklander     size_t use_size = blen > n_size ? n_size : blen;
235817466cbSJens Wiklander 
236817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) );
237817466cbSJens Wiklander     if( use_size * 8 > grp->nbits )
238817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) );
239817466cbSJens Wiklander 
240817466cbSJens Wiklander     /* While at it, reduce modulo N */
241817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 )
242817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) );
243817466cbSJens Wiklander 
244817466cbSJens Wiklander cleanup:
245817466cbSJens Wiklander     return( ret );
246817466cbSJens Wiklander }
247817466cbSJens Wiklander 
248*3d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDSA_SIGN_ALT)
249817466cbSJens Wiklander /*
250817466cbSJens Wiklander  * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
251817466cbSJens Wiklander  * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
252817466cbSJens Wiklander  */
253*3d3b0591SJens Wiklander static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
254*3d3b0591SJens Wiklander                 mbedtls_mpi *r, mbedtls_mpi *s,
255817466cbSJens Wiklander                 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
256*3d3b0591SJens Wiklander                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
257*3d3b0591SJens Wiklander                 mbedtls_ecdsa_restart_ctx *rs_ctx )
258817466cbSJens Wiklander {
259*3d3b0591SJens Wiklander     int ret, key_tries, sign_tries;
260*3d3b0591SJens Wiklander     int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
261817466cbSJens Wiklander     mbedtls_ecp_point R;
262817466cbSJens Wiklander     mbedtls_mpi k, e, t;
263*3d3b0591SJens Wiklander     mbedtls_mpi *pk = &k, *pr = r;
264817466cbSJens Wiklander 
265817466cbSJens Wiklander     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
266817466cbSJens Wiklander     if( grp->N.p == NULL )
267817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
268817466cbSJens Wiklander 
269*3d3b0591SJens Wiklander     /* Make sure d is in range 1..n-1 */
270*3d3b0591SJens Wiklander     if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
271*3d3b0591SJens Wiklander         return( MBEDTLS_ERR_ECP_INVALID_KEY );
272*3d3b0591SJens Wiklander 
273817466cbSJens Wiklander     mbedtls_ecp_point_init( &R );
274817466cbSJens Wiklander     mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
275817466cbSJens Wiklander 
276*3d3b0591SJens Wiklander     ECDSA_RS_ENTER( sig );
277817466cbSJens Wiklander 
278*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
279*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->sig != NULL )
280*3d3b0591SJens Wiklander     {
281*3d3b0591SJens Wiklander         /* redirect to our context */
282*3d3b0591SJens Wiklander         p_sign_tries = &rs_ctx->sig->sign_tries;
283*3d3b0591SJens Wiklander         p_key_tries = &rs_ctx->sig->key_tries;
284*3d3b0591SJens Wiklander         pk = &rs_ctx->sig->k;
285*3d3b0591SJens Wiklander         pr = &rs_ctx->sig->r;
286*3d3b0591SJens Wiklander 
287*3d3b0591SJens Wiklander         /* jump to current step */
288*3d3b0591SJens Wiklander         if( rs_ctx->sig->state == ecdsa_sig_mul )
289*3d3b0591SJens Wiklander             goto mul;
290*3d3b0591SJens Wiklander         if( rs_ctx->sig->state == ecdsa_sig_modn )
291*3d3b0591SJens Wiklander             goto modn;
292*3d3b0591SJens Wiklander     }
293*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
294*3d3b0591SJens Wiklander 
295*3d3b0591SJens Wiklander     *p_sign_tries = 0;
296*3d3b0591SJens Wiklander     do
297*3d3b0591SJens Wiklander     {
298*3d3b0591SJens Wiklander         if( *p_sign_tries++ > 10 )
299817466cbSJens Wiklander         {
300817466cbSJens Wiklander             ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
301817466cbSJens Wiklander             goto cleanup;
302817466cbSJens Wiklander         }
303*3d3b0591SJens Wiklander 
304*3d3b0591SJens Wiklander         /*
305*3d3b0591SJens Wiklander          * Steps 1-3: generate a suitable ephemeral keypair
306*3d3b0591SJens Wiklander          * and set r = xR mod n
307*3d3b0591SJens Wiklander          */
308*3d3b0591SJens Wiklander         *p_key_tries = 0;
309*3d3b0591SJens Wiklander         do
310*3d3b0591SJens Wiklander         {
311*3d3b0591SJens Wiklander             if( *p_key_tries++ > 10 )
312*3d3b0591SJens Wiklander             {
313*3d3b0591SJens Wiklander                 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
314*3d3b0591SJens Wiklander                 goto cleanup;
315817466cbSJens Wiklander             }
316*3d3b0591SJens Wiklander 
317*3d3b0591SJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
318*3d3b0591SJens Wiklander 
319*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
320*3d3b0591SJens Wiklander             if( rs_ctx != NULL && rs_ctx->sig != NULL )
321*3d3b0591SJens Wiklander                 rs_ctx->sig->state = ecdsa_sig_mul;
322*3d3b0591SJens Wiklander 
323*3d3b0591SJens Wiklander mul:
324*3d3b0591SJens Wiklander #endif
325*3d3b0591SJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
326*3d3b0591SJens Wiklander                                                   f_rng, p_rng, ECDSA_RS_ECP ) );
327*3d3b0591SJens Wiklander             MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
328*3d3b0591SJens Wiklander         }
329*3d3b0591SJens Wiklander         while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
330*3d3b0591SJens Wiklander 
331*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
332*3d3b0591SJens Wiklander         if( rs_ctx != NULL && rs_ctx->sig != NULL )
333*3d3b0591SJens Wiklander             rs_ctx->sig->state = ecdsa_sig_modn;
334*3d3b0591SJens Wiklander 
335*3d3b0591SJens Wiklander modn:
336*3d3b0591SJens Wiklander #endif
337*3d3b0591SJens Wiklander         /*
338*3d3b0591SJens Wiklander          * Accounting for everything up to the end of the loop
339*3d3b0591SJens Wiklander          * (step 6, but checking now avoids saving e and t)
340*3d3b0591SJens Wiklander          */
341*3d3b0591SJens Wiklander         ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
342817466cbSJens Wiklander 
343817466cbSJens Wiklander         /*
344817466cbSJens Wiklander          * Step 5: derive MPI from hashed message
345817466cbSJens Wiklander          */
346817466cbSJens Wiklander         MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
347817466cbSJens Wiklander 
348817466cbSJens Wiklander         /*
349817466cbSJens Wiklander          * Generate a random value to blind inv_mod in next step,
350817466cbSJens Wiklander          * avoiding a potential timing leak.
351817466cbSJens Wiklander          */
352*3d3b0591SJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng, p_rng ) );
353817466cbSJens Wiklander 
354817466cbSJens Wiklander         /*
355817466cbSJens Wiklander          * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
356817466cbSJens Wiklander          */
357*3d3b0591SJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
358817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
359817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
360*3d3b0591SJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
361*3d3b0591SJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
362817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
363817466cbSJens Wiklander         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
364817466cbSJens Wiklander     }
365817466cbSJens Wiklander     while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
366817466cbSJens Wiklander 
367*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
368*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->sig != NULL )
369*3d3b0591SJens Wiklander         mbedtls_mpi_copy( r, pr );
370*3d3b0591SJens Wiklander #endif
371*3d3b0591SJens Wiklander 
372817466cbSJens Wiklander cleanup:
373817466cbSJens Wiklander     mbedtls_ecp_point_free( &R );
374817466cbSJens Wiklander     mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
375817466cbSJens Wiklander 
376*3d3b0591SJens Wiklander     ECDSA_RS_LEAVE( sig );
377*3d3b0591SJens Wiklander 
378817466cbSJens Wiklander     return( ret );
379817466cbSJens Wiklander }
380817466cbSJens Wiklander 
381*3d3b0591SJens Wiklander /*
382*3d3b0591SJens Wiklander  * Compute ECDSA signature of a hashed message
383*3d3b0591SJens Wiklander  */
384*3d3b0591SJens Wiklander int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
385*3d3b0591SJens Wiklander                 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
386*3d3b0591SJens Wiklander                 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
387*3d3b0591SJens Wiklander {
388*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( grp   != NULL );
389*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( r     != NULL );
390*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( s     != NULL );
391*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( d     != NULL );
392*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( f_rng != NULL );
393*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
394*3d3b0591SJens Wiklander 
395*3d3b0591SJens Wiklander     return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
396*3d3b0591SJens Wiklander                                     f_rng, p_rng, NULL ) );
397*3d3b0591SJens Wiklander }
398*3d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDSA_SIGN_ALT */
399*3d3b0591SJens Wiklander 
400817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
401817466cbSJens Wiklander /*
402817466cbSJens Wiklander  * Deterministic signature wrapper
403817466cbSJens Wiklander  */
404*3d3b0591SJens Wiklander static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
405*3d3b0591SJens Wiklander                     mbedtls_mpi *r, mbedtls_mpi *s,
406817466cbSJens Wiklander                     const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
407*3d3b0591SJens Wiklander                     mbedtls_md_type_t md_alg,
408*3d3b0591SJens Wiklander                     mbedtls_ecdsa_restart_ctx *rs_ctx )
409817466cbSJens Wiklander {
410817466cbSJens Wiklander     int ret;
411817466cbSJens Wiklander     mbedtls_hmac_drbg_context rng_ctx;
412*3d3b0591SJens Wiklander     mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
413817466cbSJens Wiklander     unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
414817466cbSJens Wiklander     size_t grp_len = ( grp->nbits + 7 ) / 8;
415817466cbSJens Wiklander     const mbedtls_md_info_t *md_info;
416817466cbSJens Wiklander     mbedtls_mpi h;
417817466cbSJens Wiklander 
418817466cbSJens Wiklander     if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
419817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
420817466cbSJens Wiklander 
421817466cbSJens Wiklander     mbedtls_mpi_init( &h );
422817466cbSJens Wiklander     mbedtls_hmac_drbg_init( &rng_ctx );
423817466cbSJens Wiklander 
424*3d3b0591SJens Wiklander     ECDSA_RS_ENTER( det );
425*3d3b0591SJens Wiklander 
426*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
427*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->det != NULL )
428*3d3b0591SJens Wiklander     {
429*3d3b0591SJens Wiklander         /* redirect to our context */
430*3d3b0591SJens Wiklander         p_rng = &rs_ctx->det->rng_ctx;
431*3d3b0591SJens Wiklander 
432*3d3b0591SJens Wiklander         /* jump to current step */
433*3d3b0591SJens Wiklander         if( rs_ctx->det->state == ecdsa_det_sign )
434*3d3b0591SJens Wiklander             goto sign;
435*3d3b0591SJens Wiklander     }
436*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
437*3d3b0591SJens Wiklander 
438817466cbSJens Wiklander     /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
439817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
440817466cbSJens Wiklander     MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
441817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
442*3d3b0591SJens Wiklander     mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
443817466cbSJens Wiklander 
444*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
445*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->det != NULL )
446*3d3b0591SJens Wiklander         rs_ctx->det->state = ecdsa_det_sign;
447*3d3b0591SJens Wiklander 
448*3d3b0591SJens Wiklander sign:
449*3d3b0591SJens Wiklander #endif
450*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_SIGN_ALT)
451817466cbSJens Wiklander     ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
452*3d3b0591SJens Wiklander                               mbedtls_hmac_drbg_random, p_rng );
453*3d3b0591SJens Wiklander #else
454*3d3b0591SJens Wiklander     ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
455*3d3b0591SJens Wiklander                       mbedtls_hmac_drbg_random, p_rng, rs_ctx );
456*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_SIGN_ALT */
457817466cbSJens Wiklander 
458817466cbSJens Wiklander cleanup:
459817466cbSJens Wiklander     mbedtls_hmac_drbg_free( &rng_ctx );
460817466cbSJens Wiklander     mbedtls_mpi_free( &h );
461817466cbSJens Wiklander 
462*3d3b0591SJens Wiklander     ECDSA_RS_LEAVE( det );
463*3d3b0591SJens Wiklander 
464817466cbSJens Wiklander     return( ret );
465817466cbSJens Wiklander }
466*3d3b0591SJens Wiklander 
467*3d3b0591SJens Wiklander /*
468*3d3b0591SJens Wiklander  * Deterministic signature wrapper
469*3d3b0591SJens Wiklander  */
470*3d3b0591SJens Wiklander int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
471*3d3b0591SJens Wiklander                     const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
472*3d3b0591SJens Wiklander                     mbedtls_md_type_t md_alg )
473*3d3b0591SJens Wiklander {
474*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( grp   != NULL );
475*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( r     != NULL );
476*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( s     != NULL );
477*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( d     != NULL );
478*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( buf   != NULL || blen == 0 );
479*3d3b0591SJens Wiklander 
480*3d3b0591SJens Wiklander     return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg, NULL ) );
481*3d3b0591SJens Wiklander }
482817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
483817466cbSJens Wiklander 
484*3d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
485817466cbSJens Wiklander /*
486817466cbSJens Wiklander  * Verify ECDSA signature of hashed message (SEC1 4.1.4)
487817466cbSJens Wiklander  * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
488817466cbSJens Wiklander  */
489*3d3b0591SJens Wiklander static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
490817466cbSJens Wiklander                                      const unsigned char *buf, size_t blen,
491*3d3b0591SJens Wiklander                                      const mbedtls_ecp_point *Q,
492*3d3b0591SJens Wiklander                                      const mbedtls_mpi *r, const mbedtls_mpi *s,
493*3d3b0591SJens Wiklander                                      mbedtls_ecdsa_restart_ctx *rs_ctx )
494817466cbSJens Wiklander {
495817466cbSJens Wiklander     int ret;
496817466cbSJens Wiklander     mbedtls_mpi e, s_inv, u1, u2;
497817466cbSJens Wiklander     mbedtls_ecp_point R;
498*3d3b0591SJens Wiklander     mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
499817466cbSJens Wiklander 
500817466cbSJens Wiklander     mbedtls_ecp_point_init( &R );
501*3d3b0591SJens Wiklander     mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
502*3d3b0591SJens Wiklander     mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
503817466cbSJens Wiklander 
504817466cbSJens Wiklander     /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
505817466cbSJens Wiklander     if( grp->N.p == NULL )
506817466cbSJens Wiklander         return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
507817466cbSJens Wiklander 
508*3d3b0591SJens Wiklander     ECDSA_RS_ENTER( ver );
509*3d3b0591SJens Wiklander 
510*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
511*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->ver != NULL )
512*3d3b0591SJens Wiklander     {
513*3d3b0591SJens Wiklander         /* redirect to our context */
514*3d3b0591SJens Wiklander         pu1 = &rs_ctx->ver->u1;
515*3d3b0591SJens Wiklander         pu2 = &rs_ctx->ver->u2;
516*3d3b0591SJens Wiklander 
517*3d3b0591SJens Wiklander         /* jump to current step */
518*3d3b0591SJens Wiklander         if( rs_ctx->ver->state == ecdsa_ver_muladd )
519*3d3b0591SJens Wiklander             goto muladd;
520*3d3b0591SJens Wiklander     }
521*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
522*3d3b0591SJens Wiklander 
523817466cbSJens Wiklander     /*
524817466cbSJens Wiklander      * Step 1: make sure r and s are in range 1..n-1
525817466cbSJens Wiklander      */
526817466cbSJens Wiklander     if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
527817466cbSJens Wiklander         mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 )
528817466cbSJens Wiklander     {
529817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
530817466cbSJens Wiklander         goto cleanup;
531817466cbSJens Wiklander     }
532817466cbSJens Wiklander 
533817466cbSJens Wiklander     /*
534817466cbSJens Wiklander      * Step 3: derive MPI from hashed message
535817466cbSJens Wiklander      */
536817466cbSJens Wiklander     MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
537817466cbSJens Wiklander 
538817466cbSJens Wiklander     /*
539817466cbSJens Wiklander      * Step 4: u1 = e / s mod n, u2 = r / s mod n
540817466cbSJens Wiklander      */
541*3d3b0591SJens Wiklander     ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
542*3d3b0591SJens Wiklander 
543817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
544817466cbSJens Wiklander 
545*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
546*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
547817466cbSJens Wiklander 
548*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
549*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
550817466cbSJens Wiklander 
551*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
552*3d3b0591SJens Wiklander     if( rs_ctx != NULL && rs_ctx->ver != NULL )
553*3d3b0591SJens Wiklander         rs_ctx->ver->state = ecdsa_ver_muladd;
554*3d3b0591SJens Wiklander 
555*3d3b0591SJens Wiklander muladd:
556*3d3b0591SJens Wiklander #endif
557817466cbSJens Wiklander     /*
558817466cbSJens Wiklander      * Step 5: R = u1 G + u2 Q
559817466cbSJens Wiklander      */
560*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
561*3d3b0591SJens Wiklander                      &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
562817466cbSJens Wiklander 
563817466cbSJens Wiklander     if( mbedtls_ecp_is_zero( &R ) )
564817466cbSJens Wiklander     {
565817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
566817466cbSJens Wiklander         goto cleanup;
567817466cbSJens Wiklander     }
568817466cbSJens Wiklander 
569817466cbSJens Wiklander     /*
570817466cbSJens Wiklander      * Step 6: convert xR to an integer (no-op)
571817466cbSJens Wiklander      * Step 7: reduce xR mod n (gives v)
572817466cbSJens Wiklander      */
573817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
574817466cbSJens Wiklander 
575817466cbSJens Wiklander     /*
576817466cbSJens Wiklander      * Step 8: check if v (that is, R.X) is equal to r
577817466cbSJens Wiklander      */
578817466cbSJens Wiklander     if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 )
579817466cbSJens Wiklander     {
580817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
581817466cbSJens Wiklander         goto cleanup;
582817466cbSJens Wiklander     }
583817466cbSJens Wiklander 
584817466cbSJens Wiklander cleanup:
585817466cbSJens Wiklander     mbedtls_ecp_point_free( &R );
586*3d3b0591SJens Wiklander     mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
587*3d3b0591SJens Wiklander     mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
588*3d3b0591SJens Wiklander 
589*3d3b0591SJens Wiklander     ECDSA_RS_LEAVE( ver );
590817466cbSJens Wiklander 
591817466cbSJens Wiklander     return( ret );
592817466cbSJens Wiklander }
593817466cbSJens Wiklander 
594817466cbSJens Wiklander /*
595*3d3b0591SJens Wiklander  * Verify ECDSA signature of hashed message
596*3d3b0591SJens Wiklander  */
597*3d3b0591SJens Wiklander int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
598*3d3b0591SJens Wiklander                           const unsigned char *buf, size_t blen,
599*3d3b0591SJens Wiklander                           const mbedtls_ecp_point *Q,
600*3d3b0591SJens Wiklander                           const mbedtls_mpi *r,
601*3d3b0591SJens Wiklander                           const mbedtls_mpi *s)
602*3d3b0591SJens Wiklander {
603*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( grp != NULL );
604*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( Q   != NULL );
605*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( r   != NULL );
606*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( s   != NULL );
607*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
608*3d3b0591SJens Wiklander 
609*3d3b0591SJens Wiklander     return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
610*3d3b0591SJens Wiklander }
611*3d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
612*3d3b0591SJens Wiklander 
613*3d3b0591SJens Wiklander /*
614817466cbSJens Wiklander  * Convert a signature (given by context) to ASN.1
615817466cbSJens Wiklander  */
616817466cbSJens Wiklander static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
617817466cbSJens Wiklander                                     unsigned char *sig, size_t *slen )
618817466cbSJens Wiklander {
619817466cbSJens Wiklander     int ret;
620817466cbSJens Wiklander     unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
621817466cbSJens Wiklander     unsigned char *p = buf + sizeof( buf );
622817466cbSJens Wiklander     size_t len = 0;
623817466cbSJens Wiklander 
624817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) );
625817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) );
626817466cbSJens Wiklander 
627817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) );
628817466cbSJens Wiklander     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
629817466cbSJens Wiklander                                        MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
630817466cbSJens Wiklander 
631817466cbSJens Wiklander     memcpy( sig, p, len );
632817466cbSJens Wiklander     *slen = len;
633817466cbSJens Wiklander 
634817466cbSJens Wiklander     return( 0 );
635817466cbSJens Wiklander }
636817466cbSJens Wiklander 
637817466cbSJens Wiklander /*
638817466cbSJens Wiklander  * Compute and write signature
639817466cbSJens Wiklander  */
640*3d3b0591SJens Wiklander int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
641*3d3b0591SJens Wiklander                            mbedtls_md_type_t md_alg,
642817466cbSJens Wiklander                            const unsigned char *hash, size_t hlen,
643817466cbSJens Wiklander                            unsigned char *sig, size_t *slen,
644817466cbSJens Wiklander                            int (*f_rng)(void *, unsigned char *, size_t),
645*3d3b0591SJens Wiklander                            void *p_rng,
646*3d3b0591SJens Wiklander                            mbedtls_ecdsa_restart_ctx *rs_ctx )
647817466cbSJens Wiklander {
648817466cbSJens Wiklander     int ret;
649817466cbSJens Wiklander     mbedtls_mpi r, s;
650*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( ctx  != NULL );
651*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( hash != NULL );
652*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( sig  != NULL );
653*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( slen != NULL );
654817466cbSJens Wiklander 
655817466cbSJens Wiklander     mbedtls_mpi_init( &r );
656817466cbSJens Wiklander     mbedtls_mpi_init( &s );
657817466cbSJens Wiklander 
658817466cbSJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
659817466cbSJens Wiklander     (void) f_rng;
660817466cbSJens Wiklander     (void) p_rng;
661817466cbSJens Wiklander 
662*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
663*3d3b0591SJens Wiklander                              hash, hlen, md_alg, rs_ctx ) );
664817466cbSJens Wiklander #else
665817466cbSJens Wiklander     (void) md_alg;
666817466cbSJens Wiklander 
667*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_SIGN_ALT)
668817466cbSJens Wiklander     MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
669817466cbSJens Wiklander                          hash, hlen, f_rng, p_rng ) );
670*3d3b0591SJens Wiklander #else
671*3d3b0591SJens Wiklander     MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
672*3d3b0591SJens Wiklander                          hash, hlen, f_rng, p_rng, rs_ctx ) );
673*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_SIGN_ALT */
674*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_DETERMINISTIC */
675817466cbSJens Wiklander 
676817466cbSJens Wiklander     MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
677817466cbSJens Wiklander 
678817466cbSJens Wiklander cleanup:
679817466cbSJens Wiklander     mbedtls_mpi_free( &r );
680817466cbSJens Wiklander     mbedtls_mpi_free( &s );
681817466cbSJens Wiklander 
682817466cbSJens Wiklander     return( ret );
683817466cbSJens Wiklander }
684817466cbSJens Wiklander 
685*3d3b0591SJens Wiklander /*
686*3d3b0591SJens Wiklander  * Compute and write signature
687*3d3b0591SJens Wiklander  */
688*3d3b0591SJens Wiklander int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx,
689*3d3b0591SJens Wiklander                                  mbedtls_md_type_t md_alg,
690*3d3b0591SJens Wiklander                                  const unsigned char *hash, size_t hlen,
691*3d3b0591SJens Wiklander                                  unsigned char *sig, size_t *slen,
692*3d3b0591SJens Wiklander                                  int (*f_rng)(void *, unsigned char *, size_t),
693*3d3b0591SJens Wiklander                                  void *p_rng )
694*3d3b0591SJens Wiklander {
695*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( ctx  != NULL );
696*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( hash != NULL );
697*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( sig  != NULL );
698*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( slen != NULL );
699*3d3b0591SJens Wiklander     return( mbedtls_ecdsa_write_signature_restartable(
700*3d3b0591SJens Wiklander                 ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
701*3d3b0591SJens Wiklander }
702*3d3b0591SJens Wiklander 
703817466cbSJens Wiklander #if !defined(MBEDTLS_DEPRECATED_REMOVED) && \
704817466cbSJens Wiklander     defined(MBEDTLS_ECDSA_DETERMINISTIC)
705817466cbSJens Wiklander int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
706817466cbSJens Wiklander                                const unsigned char *hash, size_t hlen,
707817466cbSJens Wiklander                                unsigned char *sig, size_t *slen,
708817466cbSJens Wiklander                                mbedtls_md_type_t md_alg )
709817466cbSJens Wiklander {
710*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( ctx  != NULL );
711*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( hash != NULL );
712*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( sig  != NULL );
713*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( slen != NULL );
714817466cbSJens Wiklander     return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
715817466cbSJens Wiklander                                    NULL, NULL ) );
716817466cbSJens Wiklander }
717817466cbSJens Wiklander #endif
718817466cbSJens Wiklander 
719817466cbSJens Wiklander /*
720817466cbSJens Wiklander  * Read and check signature
721817466cbSJens Wiklander  */
722817466cbSJens Wiklander int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
723817466cbSJens Wiklander                           const unsigned char *hash, size_t hlen,
724817466cbSJens Wiklander                           const unsigned char *sig, size_t slen )
725817466cbSJens Wiklander {
726*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( ctx  != NULL );
727*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( hash != NULL );
728*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( sig  != NULL );
729*3d3b0591SJens Wiklander     return( mbedtls_ecdsa_read_signature_restartable(
730*3d3b0591SJens Wiklander                 ctx, hash, hlen, sig, slen, NULL ) );
731*3d3b0591SJens Wiklander }
732*3d3b0591SJens Wiklander 
733*3d3b0591SJens Wiklander /*
734*3d3b0591SJens Wiklander  * Restartable read and check signature
735*3d3b0591SJens Wiklander  */
736*3d3b0591SJens Wiklander int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
737*3d3b0591SJens Wiklander                           const unsigned char *hash, size_t hlen,
738*3d3b0591SJens Wiklander                           const unsigned char *sig, size_t slen,
739*3d3b0591SJens Wiklander                           mbedtls_ecdsa_restart_ctx *rs_ctx )
740*3d3b0591SJens Wiklander {
741817466cbSJens Wiklander     int ret;
742817466cbSJens Wiklander     unsigned char *p = (unsigned char *) sig;
743817466cbSJens Wiklander     const unsigned char *end = sig + slen;
744817466cbSJens Wiklander     size_t len;
745817466cbSJens Wiklander     mbedtls_mpi r, s;
746*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( ctx  != NULL );
747*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( hash != NULL );
748*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( sig  != NULL );
749817466cbSJens Wiklander 
750817466cbSJens Wiklander     mbedtls_mpi_init( &r );
751817466cbSJens Wiklander     mbedtls_mpi_init( &s );
752817466cbSJens Wiklander 
753817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
754817466cbSJens Wiklander                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
755817466cbSJens Wiklander     {
756817466cbSJens Wiklander         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
757817466cbSJens Wiklander         goto cleanup;
758817466cbSJens Wiklander     }
759817466cbSJens Wiklander 
760817466cbSJens Wiklander     if( p + len != end )
761817466cbSJens Wiklander     {
762817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA +
763817466cbSJens Wiklander               MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
764817466cbSJens Wiklander         goto cleanup;
765817466cbSJens Wiklander     }
766817466cbSJens Wiklander 
767817466cbSJens Wiklander     if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 ||
768817466cbSJens Wiklander         ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 )
769817466cbSJens Wiklander     {
770817466cbSJens Wiklander         ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
771817466cbSJens Wiklander         goto cleanup;
772817466cbSJens Wiklander     }
773*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_VERIFY_ALT)
774817466cbSJens Wiklander     if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
775817466cbSJens Wiklander                                       &ctx->Q, &r, &s ) ) != 0 )
776817466cbSJens Wiklander         goto cleanup;
777*3d3b0591SJens Wiklander #else
778*3d3b0591SJens Wiklander     if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
779*3d3b0591SJens Wiklander                               &ctx->Q, &r, &s, rs_ctx ) ) != 0 )
780*3d3b0591SJens Wiklander         goto cleanup;
781*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECDSA_VERIFY_ALT */
782817466cbSJens Wiklander 
783*3d3b0591SJens Wiklander     /* At this point we know that the buffer starts with a valid signature.
784*3d3b0591SJens Wiklander      * Return 0 if the buffer just contains the signature, and a specific
785*3d3b0591SJens Wiklander      * error code if the valid signature is followed by more data. */
786817466cbSJens Wiklander     if( p != end )
787817466cbSJens Wiklander         ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
788817466cbSJens Wiklander 
789817466cbSJens Wiklander cleanup:
790817466cbSJens Wiklander     mbedtls_mpi_free( &r );
791817466cbSJens Wiklander     mbedtls_mpi_free( &s );
792817466cbSJens Wiklander 
793817466cbSJens Wiklander     return( ret );
794817466cbSJens Wiklander }
795817466cbSJens Wiklander 
796*3d3b0591SJens Wiklander #if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
797817466cbSJens Wiklander /*
798817466cbSJens Wiklander  * Generate key pair
799817466cbSJens Wiklander  */
800817466cbSJens Wiklander int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
801817466cbSJens Wiklander                   int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
802817466cbSJens Wiklander {
803*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( ctx   != NULL );
804*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( f_rng != NULL );
805*3d3b0591SJens Wiklander 
806817466cbSJens Wiklander     return( mbedtls_ecp_group_load( &ctx->grp, gid ) ||
807817466cbSJens Wiklander             mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) );
808817466cbSJens Wiklander }
809*3d3b0591SJens Wiklander #endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
810817466cbSJens Wiklander 
811817466cbSJens Wiklander /*
812817466cbSJens Wiklander  * Set context from an mbedtls_ecp_keypair
813817466cbSJens Wiklander  */
814817466cbSJens Wiklander int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
815817466cbSJens Wiklander {
816817466cbSJens Wiklander     int ret;
817*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( ctx != NULL );
818*3d3b0591SJens Wiklander     ECDSA_VALIDATE_RET( key != NULL );
819817466cbSJens Wiklander 
820817466cbSJens Wiklander     if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
821817466cbSJens Wiklander         ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
822817466cbSJens Wiklander         ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
823817466cbSJens Wiklander     {
824817466cbSJens Wiklander         mbedtls_ecdsa_free( ctx );
825817466cbSJens Wiklander     }
826817466cbSJens Wiklander 
827817466cbSJens Wiklander     return( ret );
828817466cbSJens Wiklander }
829817466cbSJens Wiklander 
830817466cbSJens Wiklander /*
831817466cbSJens Wiklander  * Initialize context
832817466cbSJens Wiklander  */
833817466cbSJens Wiklander void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
834817466cbSJens Wiklander {
835*3d3b0591SJens Wiklander     ECDSA_VALIDATE( ctx != NULL );
836*3d3b0591SJens Wiklander 
837817466cbSJens Wiklander     mbedtls_ecp_keypair_init( ctx );
838817466cbSJens Wiklander }
839817466cbSJens Wiklander 
840817466cbSJens Wiklander /*
841817466cbSJens Wiklander  * Free context
842817466cbSJens Wiklander  */
843817466cbSJens Wiklander void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
844817466cbSJens Wiklander {
845*3d3b0591SJens Wiklander     if( ctx == NULL )
846*3d3b0591SJens Wiklander         return;
847*3d3b0591SJens Wiklander 
848817466cbSJens Wiklander     mbedtls_ecp_keypair_free( ctx );
849817466cbSJens Wiklander }
850817466cbSJens Wiklander 
851*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECP_RESTARTABLE)
852*3d3b0591SJens Wiklander /*
853*3d3b0591SJens Wiklander  * Initialize a restart context
854*3d3b0591SJens Wiklander  */
855*3d3b0591SJens Wiklander void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
856*3d3b0591SJens Wiklander {
857*3d3b0591SJens Wiklander     ECDSA_VALIDATE( ctx != NULL );
858*3d3b0591SJens Wiklander 
859*3d3b0591SJens Wiklander     mbedtls_ecp_restart_init( &ctx->ecp );
860*3d3b0591SJens Wiklander 
861*3d3b0591SJens Wiklander     ctx->ver = NULL;
862*3d3b0591SJens Wiklander     ctx->sig = NULL;
863*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
864*3d3b0591SJens Wiklander     ctx->det = NULL;
865*3d3b0591SJens Wiklander #endif
866*3d3b0591SJens Wiklander }
867*3d3b0591SJens Wiklander 
868*3d3b0591SJens Wiklander /*
869*3d3b0591SJens Wiklander  * Free the components of a restart context
870*3d3b0591SJens Wiklander  */
871*3d3b0591SJens Wiklander void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
872*3d3b0591SJens Wiklander {
873*3d3b0591SJens Wiklander     if( ctx == NULL )
874*3d3b0591SJens Wiklander         return;
875*3d3b0591SJens Wiklander 
876*3d3b0591SJens Wiklander     mbedtls_ecp_restart_free( &ctx->ecp );
877*3d3b0591SJens Wiklander 
878*3d3b0591SJens Wiklander     ecdsa_restart_ver_free( ctx->ver );
879*3d3b0591SJens Wiklander     mbedtls_free( ctx->ver );
880*3d3b0591SJens Wiklander     ctx->ver = NULL;
881*3d3b0591SJens Wiklander 
882*3d3b0591SJens Wiklander     ecdsa_restart_sig_free( ctx->sig );
883*3d3b0591SJens Wiklander     mbedtls_free( ctx->sig );
884*3d3b0591SJens Wiklander     ctx->sig = NULL;
885*3d3b0591SJens Wiklander 
886*3d3b0591SJens Wiklander #if defined(MBEDTLS_ECDSA_DETERMINISTIC)
887*3d3b0591SJens Wiklander     ecdsa_restart_det_free( ctx->det );
888*3d3b0591SJens Wiklander     mbedtls_free( ctx->det );
889*3d3b0591SJens Wiklander     ctx->det = NULL;
890*3d3b0591SJens Wiklander #endif
891*3d3b0591SJens Wiklander }
892*3d3b0591SJens Wiklander #endif /* MBEDTLS_ECP_RESTARTABLE */
893*3d3b0591SJens Wiklander 
894817466cbSJens Wiklander #endif /* MBEDTLS_ECDSA_C */
895