blob: bf99573bfe13619163a4bf6a5ed61b8d11f15b0c [file] [log] [blame]
Edison Aic6672fd2018-02-28 15:01:47 +08001// SPDX-License-Identifier: Apache-2.0
Jens Wiklander817466c2018-05-22 13:49:31 +02002/*
3 * Elliptic curve DSA
4 *
5 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
Jens Wiklander817466c2018-05-22 13:49:31 +02006 *
7 * Licensed under the Apache License, Version 2.0 (the "License"); you may
8 * not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22/*
23 * References:
24 *
25 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg
26 */
27
28#if !defined(MBEDTLS_CONFIG_FILE)
29#include "mbedtls/config.h"
30#else
31#include MBEDTLS_CONFIG_FILE
32#endif
33
34#if defined(MBEDTLS_ECDSA_C)
35
36#include "mbedtls/ecdsa.h"
37#include "mbedtls/asn1write.h"
38
39#include <string.h>
40
41#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
42#include "mbedtls/hmac_drbg.h"
43#endif
44
Jens Wiklander3d3b0592019-03-20 15:30:29 +010045#if defined(MBEDTLS_PLATFORM_C)
46#include "mbedtls/platform.h"
47#else
48#include <stdlib.h>
49#define mbedtls_calloc calloc
50#define mbedtls_free free
51#endif
52
53#include "mbedtls/platform_util.h"
Jerome Forissier11fa71b2020-04-20 17:17:56 +020054#include "mbedtls/error.h"
Jens Wiklander3d3b0592019-03-20 15:30:29 +010055
56/* Parameter validation macros based on platform_util.h */
57#define ECDSA_VALIDATE_RET( cond ) \
58 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA )
59#define ECDSA_VALIDATE( cond ) \
60 MBEDTLS_INTERNAL_VALIDATE( cond )
61
62#if defined(MBEDTLS_ECP_RESTARTABLE)
63
64/*
65 * Sub-context for ecdsa_verify()
66 */
67struct mbedtls_ecdsa_restart_ver
68{
69 mbedtls_mpi u1, u2; /* intermediate values */
70 enum { /* what to do next? */
71 ecdsa_ver_init = 0, /* getting started */
72 ecdsa_ver_muladd, /* muladd step */
73 } state;
74};
75
76/*
77 * Init verify restart sub-context
78 */
79static void ecdsa_restart_ver_init( mbedtls_ecdsa_restart_ver_ctx *ctx )
80{
81 mbedtls_mpi_init( &ctx->u1 );
82 mbedtls_mpi_init( &ctx->u2 );
83 ctx->state = ecdsa_ver_init;
84}
85
86/*
87 * Free the components of a verify restart sub-context
88 */
89static void ecdsa_restart_ver_free( mbedtls_ecdsa_restart_ver_ctx *ctx )
90{
91 if( ctx == NULL )
92 return;
93
94 mbedtls_mpi_free( &ctx->u1 );
95 mbedtls_mpi_free( &ctx->u2 );
96
97 ecdsa_restart_ver_init( ctx );
98}
99
100/*
101 * Sub-context for ecdsa_sign()
102 */
103struct mbedtls_ecdsa_restart_sig
104{
105 int sign_tries;
106 int key_tries;
107 mbedtls_mpi k; /* per-signature random */
108 mbedtls_mpi r; /* r value */
109 enum { /* what to do next? */
110 ecdsa_sig_init = 0, /* getting started */
111 ecdsa_sig_mul, /* doing ecp_mul() */
112 ecdsa_sig_modn, /* mod N computations */
113 } state;
114};
115
116/*
117 * Init verify sign sub-context
118 */
119static void ecdsa_restart_sig_init( mbedtls_ecdsa_restart_sig_ctx *ctx )
120{
121 ctx->sign_tries = 0;
122 ctx->key_tries = 0;
123 mbedtls_mpi_init( &ctx->k );
124 mbedtls_mpi_init( &ctx->r );
125 ctx->state = ecdsa_sig_init;
126}
127
128/*
129 * Free the components of a sign restart sub-context
130 */
131static void ecdsa_restart_sig_free( mbedtls_ecdsa_restart_sig_ctx *ctx )
132{
133 if( ctx == NULL )
134 return;
135
136 mbedtls_mpi_free( &ctx->k );
137 mbedtls_mpi_free( &ctx->r );
138}
139
140#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
141/*
142 * Sub-context for ecdsa_sign_det()
143 */
144struct mbedtls_ecdsa_restart_det
145{
146 mbedtls_hmac_drbg_context rng_ctx; /* DRBG state */
147 enum { /* what to do next? */
148 ecdsa_det_init = 0, /* getting started */
149 ecdsa_det_sign, /* make signature */
150 } state;
151};
152
153/*
154 * Init verify sign_det sub-context
155 */
156static void ecdsa_restart_det_init( mbedtls_ecdsa_restart_det_ctx *ctx )
157{
158 mbedtls_hmac_drbg_init( &ctx->rng_ctx );
159 ctx->state = ecdsa_det_init;
160}
161
162/*
163 * Free the components of a sign_det restart sub-context
164 */
165static void ecdsa_restart_det_free( mbedtls_ecdsa_restart_det_ctx *ctx )
166{
167 if( ctx == NULL )
168 return;
169
170 mbedtls_hmac_drbg_free( &ctx->rng_ctx );
171
172 ecdsa_restart_det_init( ctx );
173}
174#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
175
Jerome Forissier5b25c762020-04-07 11:18:49 +0200176#define ECDSA_RS_ECP ( rs_ctx == NULL ? NULL : &rs_ctx->ecp )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100177
178/* Utility macro for checking and updating ops budget */
179#define ECDSA_BUDGET( ops ) \
Jerome Forissier5b25c762020-04-07 11:18:49 +0200180 MBEDTLS_MPI_CHK( mbedtls_ecp_check_budget( grp, ECDSA_RS_ECP, ops ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100181
182/* Call this when entering a function that needs its own sub-context */
183#define ECDSA_RS_ENTER( SUB ) do { \
184 /* reset ops count for this call if top-level */ \
185 if( rs_ctx != NULL && rs_ctx->ecp.depth++ == 0 ) \
186 rs_ctx->ecp.ops_done = 0; \
187 \
188 /* set up our own sub-context if needed */ \
189 if( mbedtls_ecp_restart_is_enabled() && \
190 rs_ctx != NULL && rs_ctx->SUB == NULL ) \
191 { \
192 rs_ctx->SUB = mbedtls_calloc( 1, sizeof( *rs_ctx->SUB ) ); \
193 if( rs_ctx->SUB == NULL ) \
194 return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); \
195 \
196 ecdsa_restart_## SUB ##_init( rs_ctx->SUB ); \
197 } \
198} while( 0 )
199
200/* Call this when leaving a function that needs its own sub-context */
201#define ECDSA_RS_LEAVE( SUB ) do { \
202 /* clear our sub-context when not in progress (done or error) */ \
203 if( rs_ctx != NULL && rs_ctx->SUB != NULL && \
204 ret != MBEDTLS_ERR_ECP_IN_PROGRESS ) \
205 { \
206 ecdsa_restart_## SUB ##_free( rs_ctx->SUB ); \
207 mbedtls_free( rs_ctx->SUB ); \
208 rs_ctx->SUB = NULL; \
209 } \
210 \
211 if( rs_ctx != NULL ) \
212 rs_ctx->ecp.depth--; \
213} while( 0 )
214
215#else /* MBEDTLS_ECP_RESTARTABLE */
216
217#define ECDSA_RS_ECP NULL
218
219#define ECDSA_BUDGET( ops ) /* no-op; for compatibility */
220
221#define ECDSA_RS_ENTER( SUB ) (void) rs_ctx
222#define ECDSA_RS_LEAVE( SUB ) (void) rs_ctx
223
224#endif /* MBEDTLS_ECP_RESTARTABLE */
225
Jens Wiklander817466c2018-05-22 13:49:31 +0200226/*
227 * Derive a suitable integer for group grp from a buffer of length len
228 * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3
229 */
230static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x,
231 const unsigned char *buf, size_t blen )
232{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200233 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200234 size_t n_size = ( grp->nbits + 7 ) / 8;
235 size_t use_size = blen > n_size ? n_size : blen;
236
237 MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) );
238 if( use_size * 8 > grp->nbits )
239 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) );
240
241 /* While at it, reduce modulo N */
242 if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 )
243 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) );
244
245cleanup:
246 return( ret );
247}
248
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100249#if !defined(MBEDTLS_ECDSA_SIGN_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200250/*
251 * Compute ECDSA signature of a hashed message (SEC1 4.1.3)
252 * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message)
253 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100254static int ecdsa_sign_restartable( mbedtls_ecp_group *grp,
255 mbedtls_mpi *r, mbedtls_mpi *s,
Jens Wiklander817466c2018-05-22 13:49:31 +0200256 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100257 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200258 int (*f_rng_blind)(void *, unsigned char *, size_t),
259 void *p_rng_blind,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100260 mbedtls_ecdsa_restart_ctx *rs_ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +0200261{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100262 int ret, key_tries, sign_tries;
263 int *p_sign_tries = &sign_tries, *p_key_tries = &key_tries;
Jens Wiklander817466c2018-05-22 13:49:31 +0200264 mbedtls_ecp_point R;
265 mbedtls_mpi k, e, t;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100266 mbedtls_mpi *pk = &k, *pr = r;
Jens Wiklander817466c2018-05-22 13:49:31 +0200267
268 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200269 if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200270 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
271
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100272 /* Make sure d is in range 1..n-1 */
273 if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 )
274 return( MBEDTLS_ERR_ECP_INVALID_KEY );
275
Jens Wiklander817466c2018-05-22 13:49:31 +0200276 mbedtls_ecp_point_init( &R );
277 mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t );
278
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100279 ECDSA_RS_ENTER( sig );
280
281#if defined(MBEDTLS_ECP_RESTARTABLE)
282 if( rs_ctx != NULL && rs_ctx->sig != NULL )
283 {
284 /* redirect to our context */
285 p_sign_tries = &rs_ctx->sig->sign_tries;
286 p_key_tries = &rs_ctx->sig->key_tries;
287 pk = &rs_ctx->sig->k;
288 pr = &rs_ctx->sig->r;
289
290 /* jump to current step */
291 if( rs_ctx->sig->state == ecdsa_sig_mul )
292 goto mul;
293 if( rs_ctx->sig->state == ecdsa_sig_modn )
294 goto modn;
295 }
296#endif /* MBEDTLS_ECP_RESTARTABLE */
297
298 *p_sign_tries = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200299 do
300 {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200301 if( (*p_sign_tries)++ > 10 )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100302 {
303 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
304 goto cleanup;
305 }
306
Jens Wiklander817466c2018-05-22 13:49:31 +0200307 /*
308 * Steps 1-3: generate a suitable ephemeral keypair
309 * and set r = xR mod n
310 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100311 *p_key_tries = 0;
Jens Wiklander817466c2018-05-22 13:49:31 +0200312 do
313 {
Jerome Forissier5b25c762020-04-07 11:18:49 +0200314 if( (*p_key_tries)++ > 10 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200315 {
316 ret = MBEDTLS_ERR_ECP_RANDOM_FAILED;
317 goto cleanup;
318 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100319
320 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, pk, f_rng, p_rng ) );
321
322#if defined(MBEDTLS_ECP_RESTARTABLE)
323 if( rs_ctx != NULL && rs_ctx->sig != NULL )
324 rs_ctx->sig->state = ecdsa_sig_mul;
325
326mul:
327#endif
328 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &R, pk, &grp->G,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200329 f_rng_blind,
330 p_rng_blind,
331 ECDSA_RS_ECP ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100332 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pr, &R.X, &grp->N ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200333 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100334 while( mbedtls_mpi_cmp_int( pr, 0 ) == 0 );
335
336#if defined(MBEDTLS_ECP_RESTARTABLE)
337 if( rs_ctx != NULL && rs_ctx->sig != NULL )
338 rs_ctx->sig->state = ecdsa_sig_modn;
339
340modn:
341#endif
342 /*
343 * Accounting for everything up to the end of the loop
344 * (step 6, but checking now avoids saving e and t)
345 */
346 ECDSA_BUDGET( MBEDTLS_ECP_OPS_INV + 4 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200347
348 /*
349 * Step 5: derive MPI from hashed message
350 */
351 MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
352
353 /*
354 * Generate a random value to blind inv_mod in next step,
355 * avoiding a potential timing leak.
356 */
Jerome Forissier5b25c762020-04-07 11:18:49 +0200357 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, &t, f_rng_blind,
358 p_rng_blind ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200359
360 /*
361 * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n
362 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100363 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, pr, d ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200364 MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) );
365 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100366 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pk, pk, &t ) );
Jerome Forissier5b25c762020-04-07 11:18:49 +0200367 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pk, pk, &grp->N ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100368 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, pk, &grp->N ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200369 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) );
370 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200371 }
372 while( mbedtls_mpi_cmp_int( s, 0 ) == 0 );
373
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100374#if defined(MBEDTLS_ECP_RESTARTABLE)
375 if( rs_ctx != NULL && rs_ctx->sig != NULL )
376 mbedtls_mpi_copy( r, pr );
377#endif
378
Jens Wiklander817466c2018-05-22 13:49:31 +0200379cleanup:
380 mbedtls_ecp_point_free( &R );
381 mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t );
382
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100383 ECDSA_RS_LEAVE( sig );
384
Jens Wiklander817466c2018-05-22 13:49:31 +0200385 return( ret );
386}
387
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200388int mbedtls_ecdsa_can_do( mbedtls_ecp_group_id gid )
389{
390 switch( gid )
391 {
392#ifdef MBEDTLS_ECP_DP_CURVE25519_ENABLED
393 case MBEDTLS_ECP_DP_CURVE25519: return 0;
394#endif
395#ifdef MBEDTLS_ECP_DP_CURVE448_ENABLED
396 case MBEDTLS_ECP_DP_CURVE448: return 0;
397#endif
398 default: return 1;
399 }
400}
401
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100402/*
403 * Compute ECDSA signature of a hashed message
404 */
405int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s,
406 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
407 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
408{
409 ECDSA_VALIDATE_RET( grp != NULL );
410 ECDSA_VALIDATE_RET( r != NULL );
411 ECDSA_VALIDATE_RET( s != NULL );
412 ECDSA_VALIDATE_RET( d != NULL );
413 ECDSA_VALIDATE_RET( f_rng != NULL );
414 ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
415
Jerome Forissier5b25c762020-04-07 11:18:49 +0200416 /* Use the same RNG for both blinding and ephemeral key generation */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100417 return( ecdsa_sign_restartable( grp, r, s, d, buf, blen,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200418 f_rng, p_rng, f_rng, p_rng, NULL ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100419}
420#endif /* !MBEDTLS_ECDSA_SIGN_ALT */
421
Jens Wiklander817466c2018-05-22 13:49:31 +0200422#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
423/*
424 * Deterministic signature wrapper
425 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100426static int ecdsa_sign_det_restartable( mbedtls_ecp_group *grp,
427 mbedtls_mpi *r, mbedtls_mpi *s,
Jens Wiklander817466c2018-05-22 13:49:31 +0200428 const mbedtls_mpi *d, const unsigned char *buf, size_t blen,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100429 mbedtls_md_type_t md_alg,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200430 int (*f_rng_blind)(void *, unsigned char *, size_t),
431 void *p_rng_blind,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100432 mbedtls_ecdsa_restart_ctx *rs_ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +0200433{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200434 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200435 mbedtls_hmac_drbg_context rng_ctx;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100436 mbedtls_hmac_drbg_context *p_rng = &rng_ctx;
Jens Wiklander817466c2018-05-22 13:49:31 +0200437 unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES];
438 size_t grp_len = ( grp->nbits + 7 ) / 8;
439 const mbedtls_md_info_t *md_info;
440 mbedtls_mpi h;
441
442 if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL )
443 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
444
445 mbedtls_mpi_init( &h );
446 mbedtls_hmac_drbg_init( &rng_ctx );
447
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100448 ECDSA_RS_ENTER( det );
449
450#if defined(MBEDTLS_ECP_RESTARTABLE)
451 if( rs_ctx != NULL && rs_ctx->det != NULL )
452 {
453 /* redirect to our context */
454 p_rng = &rs_ctx->det->rng_ctx;
455
456 /* jump to current step */
457 if( rs_ctx->det->state == ecdsa_det_sign )
458 goto sign;
459 }
460#endif /* MBEDTLS_ECP_RESTARTABLE */
461
Jens Wiklander817466c2018-05-22 13:49:31 +0200462 /* Use private key and message hash (reduced) to initialize HMAC_DRBG */
463 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) );
464 MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) );
465 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100466 mbedtls_hmac_drbg_seed_buf( p_rng, md_info, data, 2 * grp_len );
Jens Wiklander817466c2018-05-22 13:49:31 +0200467
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100468#if defined(MBEDTLS_ECP_RESTARTABLE)
469 if( rs_ctx != NULL && rs_ctx->det != NULL )
470 rs_ctx->det->state = ecdsa_det_sign;
471
472sign:
473#endif
474#if defined(MBEDTLS_ECDSA_SIGN_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200475 ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100476 mbedtls_hmac_drbg_random, p_rng );
477#else
Jerome Forissier5b25c762020-04-07 11:18:49 +0200478 if( f_rng_blind != NULL )
479 ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
480 mbedtls_hmac_drbg_random, p_rng,
481 f_rng_blind, p_rng_blind, rs_ctx );
482 else
483 {
484 mbedtls_hmac_drbg_context *p_rng_blind_det;
485
486#if !defined(MBEDTLS_ECP_RESTARTABLE)
487 /*
488 * To avoid reusing rng_ctx and risking incorrect behavior we seed a
489 * second HMAC-DRBG with the same seed. We also apply a label to avoid
490 * reusing the bits of the ephemeral key for blinding and eliminate the
491 * risk that they leak this way.
492 */
493 const char* blind_label = "BLINDING CONTEXT";
494 mbedtls_hmac_drbg_context rng_ctx_blind;
495
496 mbedtls_hmac_drbg_init( &rng_ctx_blind );
497 p_rng_blind_det = &rng_ctx_blind;
Jerome Forissier5b25c762020-04-07 11:18:49 +0200498 mbedtls_hmac_drbg_seed_buf( p_rng_blind_det, md_info,
499 data, 2 * grp_len );
500 ret = mbedtls_hmac_drbg_update_ret( p_rng_blind_det,
501 (const unsigned char*) blind_label,
502 strlen( blind_label ) );
503 if( ret != 0 )
504 {
505 mbedtls_hmac_drbg_free( &rng_ctx_blind );
506 goto cleanup;
507 }
508#else
509 /*
510 * In the case of restartable computations we would either need to store
511 * the second RNG in the restart context too or set it up at every
512 * restart. The first option would penalize the correct application of
513 * the function and the second would defeat the purpose of the
514 * restartable feature.
515 *
516 * Therefore in this case we reuse the original RNG. This comes with the
517 * price that the resulting signature might not be a valid deterministic
518 * ECDSA signature with a very low probability (same magnitude as
519 * successfully guessing the private key). However even then it is still
520 * a valid ECDSA signature.
521 */
522 p_rng_blind_det = p_rng;
523#endif /* MBEDTLS_ECP_RESTARTABLE */
524
525 /*
526 * Since the output of the RNGs is always the same for the same key and
527 * message, this limits the efficiency of blinding and leaks information
528 * through side channels. After mbedtls_ecdsa_sign_det() is removed NULL
529 * won't be a valid value for f_rng_blind anymore. Therefore it should
530 * be checked by the caller and this branch and check can be removed.
531 */
532 ret = ecdsa_sign_restartable( grp, r, s, d, buf, blen,
533 mbedtls_hmac_drbg_random, p_rng,
534 mbedtls_hmac_drbg_random, p_rng_blind_det,
535 rs_ctx );
536
537#if !defined(MBEDTLS_ECP_RESTARTABLE)
538 mbedtls_hmac_drbg_free( &rng_ctx_blind );
539#endif
540 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100541#endif /* MBEDTLS_ECDSA_SIGN_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200542
543cleanup:
544 mbedtls_hmac_drbg_free( &rng_ctx );
545 mbedtls_mpi_free( &h );
546
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100547 ECDSA_RS_LEAVE( det );
548
Jens Wiklander817466c2018-05-22 13:49:31 +0200549 return( ret );
550}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100551
552/*
Jerome Forissier5b25c762020-04-07 11:18:49 +0200553 * Deterministic signature wrappers
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100554 */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200555
556#if !defined(MBEDTLS_DEPRECATED_REMOVED)
Jerome Forissier5b25c762020-04-07 11:18:49 +0200557int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r,
558 mbedtls_mpi *s, const mbedtls_mpi *d,
559 const unsigned char *buf, size_t blen,
560 mbedtls_md_type_t md_alg )
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100561{
562 ECDSA_VALIDATE_RET( grp != NULL );
563 ECDSA_VALIDATE_RET( r != NULL );
564 ECDSA_VALIDATE_RET( s != NULL );
565 ECDSA_VALIDATE_RET( d != NULL );
566 ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
567
Jerome Forissier5b25c762020-04-07 11:18:49 +0200568 return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
569 NULL, NULL, NULL ) );
570}
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200571#endif /* MBEDTLS_DEPRECATED_REMOVED */
Jerome Forissier5b25c762020-04-07 11:18:49 +0200572
573int mbedtls_ecdsa_sign_det_ext( mbedtls_ecp_group *grp, mbedtls_mpi *r,
574 mbedtls_mpi *s, const mbedtls_mpi *d,
575 const unsigned char *buf, size_t blen,
576 mbedtls_md_type_t md_alg,
577 int (*f_rng_blind)(void *, unsigned char *,
578 size_t),
579 void *p_rng_blind )
580{
581 ECDSA_VALIDATE_RET( grp != NULL );
582 ECDSA_VALIDATE_RET( r != NULL );
583 ECDSA_VALIDATE_RET( s != NULL );
584 ECDSA_VALIDATE_RET( d != NULL );
585 ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
586 ECDSA_VALIDATE_RET( f_rng_blind != NULL );
587
588 return( ecdsa_sign_det_restartable( grp, r, s, d, buf, blen, md_alg,
589 f_rng_blind, p_rng_blind, NULL ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100590}
Jens Wiklander817466c2018-05-22 13:49:31 +0200591#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
592
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100593#if !defined(MBEDTLS_ECDSA_VERIFY_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200594/*
595 * Verify ECDSA signature of hashed message (SEC1 4.1.4)
596 * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message)
597 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100598static int ecdsa_verify_restartable( mbedtls_ecp_group *grp,
599 const unsigned char *buf, size_t blen,
600 const mbedtls_ecp_point *Q,
601 const mbedtls_mpi *r, const mbedtls_mpi *s,
602 mbedtls_ecdsa_restart_ctx *rs_ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +0200603{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200604 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200605 mbedtls_mpi e, s_inv, u1, u2;
606 mbedtls_ecp_point R;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100607 mbedtls_mpi *pu1 = &u1, *pu2 = &u2;
Jens Wiklander817466c2018-05-22 13:49:31 +0200608
609 mbedtls_ecp_point_init( &R );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100610 mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv );
611 mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 );
Jens Wiklander817466c2018-05-22 13:49:31 +0200612
613 /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200614 if( ! mbedtls_ecdsa_can_do( grp->id ) || grp->N.p == NULL )
Jens Wiklander817466c2018-05-22 13:49:31 +0200615 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
616
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100617 ECDSA_RS_ENTER( ver );
618
619#if defined(MBEDTLS_ECP_RESTARTABLE)
620 if( rs_ctx != NULL && rs_ctx->ver != NULL )
621 {
622 /* redirect to our context */
623 pu1 = &rs_ctx->ver->u1;
624 pu2 = &rs_ctx->ver->u2;
625
626 /* jump to current step */
627 if( rs_ctx->ver->state == ecdsa_ver_muladd )
628 goto muladd;
629 }
630#endif /* MBEDTLS_ECP_RESTARTABLE */
631
Jens Wiklander817466c2018-05-22 13:49:31 +0200632 /*
633 * Step 1: make sure r and s are in range 1..n-1
634 */
635 if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 ||
636 mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 )
637 {
638 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
639 goto cleanup;
640 }
641
642 /*
Jens Wiklander817466c2018-05-22 13:49:31 +0200643 * Step 3: derive MPI from hashed message
644 */
645 MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) );
646
647 /*
648 * Step 4: u1 = e / s mod n, u2 = r / s mod n
649 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100650 ECDSA_BUDGET( MBEDTLS_ECP_OPS_CHK + MBEDTLS_ECP_OPS_INV + 2 );
651
Jens Wiklander817466c2018-05-22 13:49:31 +0200652 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) );
653
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100654 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu1, &e, &s_inv ) );
655 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu1, pu1, &grp->N ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200656
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100657 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( pu2, r, &s_inv ) );
658 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( pu2, pu2, &grp->N ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200659
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100660#if defined(MBEDTLS_ECP_RESTARTABLE)
661 if( rs_ctx != NULL && rs_ctx->ver != NULL )
662 rs_ctx->ver->state = ecdsa_ver_muladd;
663
664muladd:
665#endif
Jens Wiklander817466c2018-05-22 13:49:31 +0200666 /*
667 * Step 5: R = u1 G + u2 Q
Jens Wiklander817466c2018-05-22 13:49:31 +0200668 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100669 MBEDTLS_MPI_CHK( mbedtls_ecp_muladd_restartable( grp,
670 &R, pu1, &grp->G, pu2, Q, ECDSA_RS_ECP ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200671
672 if( mbedtls_ecp_is_zero( &R ) )
673 {
674 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
675 goto cleanup;
676 }
677
678 /*
679 * Step 6: convert xR to an integer (no-op)
680 * Step 7: reduce xR mod n (gives v)
681 */
682 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) );
683
684 /*
685 * Step 8: check if v (that is, R.X) is equal to r
686 */
687 if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 )
688 {
689 ret = MBEDTLS_ERR_ECP_VERIFY_FAILED;
690 goto cleanup;
691 }
692
693cleanup:
694 mbedtls_ecp_point_free( &R );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100695 mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv );
696 mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 );
697
698 ECDSA_RS_LEAVE( ver );
Jens Wiklander817466c2018-05-22 13:49:31 +0200699
700 return( ret );
701}
702
703/*
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100704 * Verify ECDSA signature of hashed message
705 */
706int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp,
707 const unsigned char *buf, size_t blen,
708 const mbedtls_ecp_point *Q,
709 const mbedtls_mpi *r,
710 const mbedtls_mpi *s)
711{
712 ECDSA_VALIDATE_RET( grp != NULL );
713 ECDSA_VALIDATE_RET( Q != NULL );
714 ECDSA_VALIDATE_RET( r != NULL );
715 ECDSA_VALIDATE_RET( s != NULL );
716 ECDSA_VALIDATE_RET( buf != NULL || blen == 0 );
717
718 return( ecdsa_verify_restartable( grp, buf, blen, Q, r, s, NULL ) );
719}
720#endif /* !MBEDTLS_ECDSA_VERIFY_ALT */
721
722/*
Jens Wiklander817466c2018-05-22 13:49:31 +0200723 * Convert a signature (given by context) to ASN.1
724 */
725static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s,
726 unsigned char *sig, size_t *slen )
727{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200728 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200729 unsigned char buf[MBEDTLS_ECDSA_MAX_LEN];
730 unsigned char *p = buf + sizeof( buf );
731 size_t len = 0;
732
733 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) );
734 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) );
735
736 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) );
737 MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf,
738 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) );
739
740 memcpy( sig, p, len );
741 *slen = len;
742
743 return( 0 );
744}
745
746/*
747 * Compute and write signature
748 */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100749int mbedtls_ecdsa_write_signature_restartable( mbedtls_ecdsa_context *ctx,
750 mbedtls_md_type_t md_alg,
Jens Wiklander817466c2018-05-22 13:49:31 +0200751 const unsigned char *hash, size_t hlen,
752 unsigned char *sig, size_t *slen,
753 int (*f_rng)(void *, unsigned char *, size_t),
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100754 void *p_rng,
755 mbedtls_ecdsa_restart_ctx *rs_ctx )
Jens Wiklander817466c2018-05-22 13:49:31 +0200756{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200757 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200758 mbedtls_mpi r, s;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100759 ECDSA_VALIDATE_RET( ctx != NULL );
760 ECDSA_VALIDATE_RET( hash != NULL );
761 ECDSA_VALIDATE_RET( sig != NULL );
762 ECDSA_VALIDATE_RET( slen != NULL );
Jens Wiklander817466c2018-05-22 13:49:31 +0200763
764 mbedtls_mpi_init( &r );
765 mbedtls_mpi_init( &s );
766
767#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100768 MBEDTLS_MPI_CHK( ecdsa_sign_det_restartable( &ctx->grp, &r, &s, &ctx->d,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200769 hash, hlen, md_alg, f_rng,
770 p_rng, rs_ctx ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200771#else
772 (void) md_alg;
773
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100774#if defined(MBEDTLS_ECDSA_SIGN_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200775 MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d,
776 hash, hlen, f_rng, p_rng ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100777#else
Jerome Forissier5b25c762020-04-07 11:18:49 +0200778 /* Use the same RNG for both blinding and ephemeral key generation */
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100779 MBEDTLS_MPI_CHK( ecdsa_sign_restartable( &ctx->grp, &r, &s, &ctx->d,
Jerome Forissier5b25c762020-04-07 11:18:49 +0200780 hash, hlen, f_rng, p_rng, f_rng,
781 p_rng, rs_ctx ) );
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100782#endif /* MBEDTLS_ECDSA_SIGN_ALT */
783#endif /* MBEDTLS_ECDSA_DETERMINISTIC */
Jens Wiklander817466c2018-05-22 13:49:31 +0200784
785 MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) );
786
787cleanup:
788 mbedtls_mpi_free( &r );
789 mbedtls_mpi_free( &s );
790
791 return( ret );
792}
793
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100794/*
795 * Compute and write signature
796 */
797int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx,
798 mbedtls_md_type_t md_alg,
799 const unsigned char *hash, size_t hlen,
800 unsigned char *sig, size_t *slen,
801 int (*f_rng)(void *, unsigned char *, size_t),
802 void *p_rng )
803{
804 ECDSA_VALIDATE_RET( ctx != NULL );
805 ECDSA_VALIDATE_RET( hash != NULL );
806 ECDSA_VALIDATE_RET( sig != NULL );
807 ECDSA_VALIDATE_RET( slen != NULL );
808 return( mbedtls_ecdsa_write_signature_restartable(
809 ctx, md_alg, hash, hlen, sig, slen, f_rng, p_rng, NULL ) );
810}
811
812#if !defined(MBEDTLS_DEPRECATED_REMOVED) && \
Jens Wiklander817466c2018-05-22 13:49:31 +0200813 defined(MBEDTLS_ECDSA_DETERMINISTIC)
814int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx,
815 const unsigned char *hash, size_t hlen,
816 unsigned char *sig, size_t *slen,
817 mbedtls_md_type_t md_alg )
818{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100819 ECDSA_VALIDATE_RET( ctx != NULL );
820 ECDSA_VALIDATE_RET( hash != NULL );
821 ECDSA_VALIDATE_RET( sig != NULL );
822 ECDSA_VALIDATE_RET( slen != NULL );
Jens Wiklander817466c2018-05-22 13:49:31 +0200823 return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen,
824 NULL, NULL ) );
825}
826#endif
827
828/*
829 * Read and check signature
830 */
831int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx,
832 const unsigned char *hash, size_t hlen,
833 const unsigned char *sig, size_t slen )
834{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100835 ECDSA_VALIDATE_RET( ctx != NULL );
836 ECDSA_VALIDATE_RET( hash != NULL );
837 ECDSA_VALIDATE_RET( sig != NULL );
838 return( mbedtls_ecdsa_read_signature_restartable(
839 ctx, hash, hlen, sig, slen, NULL ) );
840}
841
842/*
843 * Restartable read and check signature
844 */
845int mbedtls_ecdsa_read_signature_restartable( mbedtls_ecdsa_context *ctx,
846 const unsigned char *hash, size_t hlen,
847 const unsigned char *sig, size_t slen,
848 mbedtls_ecdsa_restart_ctx *rs_ctx )
849{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200850 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander817466c2018-05-22 13:49:31 +0200851 unsigned char *p = (unsigned char *) sig;
852 const unsigned char *end = sig + slen;
853 size_t len;
854 mbedtls_mpi r, s;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100855 ECDSA_VALIDATE_RET( ctx != NULL );
856 ECDSA_VALIDATE_RET( hash != NULL );
857 ECDSA_VALIDATE_RET( sig != NULL );
Jens Wiklander817466c2018-05-22 13:49:31 +0200858
859 mbedtls_mpi_init( &r );
860 mbedtls_mpi_init( &s );
861
862 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
863 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
864 {
865 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
866 goto cleanup;
867 }
868
869 if( p + len != end )
870 {
871 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA +
872 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
873 goto cleanup;
874 }
875
876 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 ||
877 ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 )
878 {
879 ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
880 goto cleanup;
881 }
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100882#if defined(MBEDTLS_ECDSA_VERIFY_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200883 if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen,
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100884 &ctx->Q, &r, &s ) ) != 0 )
Jens Wiklander817466c2018-05-22 13:49:31 +0200885 goto cleanup;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100886#else
887 if( ( ret = ecdsa_verify_restartable( &ctx->grp, hash, hlen,
888 &ctx->Q, &r, &s, rs_ctx ) ) != 0 )
889 goto cleanup;
890#endif /* MBEDTLS_ECDSA_VERIFY_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200891
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100892 /* At this point we know that the buffer starts with a valid signature.
893 * Return 0 if the buffer just contains the signature, and a specific
894 * error code if the valid signature is followed by more data. */
Jens Wiklander817466c2018-05-22 13:49:31 +0200895 if( p != end )
896 ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH;
897
898cleanup:
899 mbedtls_mpi_free( &r );
900 mbedtls_mpi_free( &s );
901
902 return( ret );
903}
904
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100905#if !defined(MBEDTLS_ECDSA_GENKEY_ALT)
Jens Wiklander817466c2018-05-22 13:49:31 +0200906/*
907 * Generate key pair
908 */
909int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid,
910 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
911{
Jerome Forissier5b25c762020-04-07 11:18:49 +0200912 int ret = 0;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100913 ECDSA_VALIDATE_RET( ctx != NULL );
914 ECDSA_VALIDATE_RET( f_rng != NULL );
915
Jerome Forissier5b25c762020-04-07 11:18:49 +0200916 ret = mbedtls_ecp_group_load( &ctx->grp, gid );
917 if( ret != 0 )
918 return( ret );
919
920 return( mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d,
921 &ctx->Q, f_rng, p_rng ) );
Jens Wiklander817466c2018-05-22 13:49:31 +0200922}
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100923#endif /* !MBEDTLS_ECDSA_GENKEY_ALT */
Jens Wiklander817466c2018-05-22 13:49:31 +0200924
925/*
926 * Set context from an mbedtls_ecp_keypair
927 */
928int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key )
929{
Jerome Forissier11fa71b2020-04-20 17:17:56 +0200930 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100931 ECDSA_VALIDATE_RET( ctx != NULL );
932 ECDSA_VALIDATE_RET( key != NULL );
Jens Wiklander817466c2018-05-22 13:49:31 +0200933
934 if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 ||
935 ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ||
936 ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 )
937 {
938 mbedtls_ecdsa_free( ctx );
939 }
940
941 return( ret );
942}
943
944/*
945 * Initialize context
946 */
947void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx )
948{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100949 ECDSA_VALIDATE( ctx != NULL );
950
Jens Wiklander817466c2018-05-22 13:49:31 +0200951 mbedtls_ecp_keypair_init( ctx );
952}
953
954/*
955 * Free context
956 */
957void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx )
958{
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100959 if( ctx == NULL )
960 return;
961
Jens Wiklander817466c2018-05-22 13:49:31 +0200962 mbedtls_ecp_keypair_free( ctx );
963}
964
Jens Wiklander3d3b0592019-03-20 15:30:29 +0100965#if defined(MBEDTLS_ECP_RESTARTABLE)
966/*
967 * Initialize a restart context
968 */
969void mbedtls_ecdsa_restart_init( mbedtls_ecdsa_restart_ctx *ctx )
970{
971 ECDSA_VALIDATE( ctx != NULL );
972
973 mbedtls_ecp_restart_init( &ctx->ecp );
974
975 ctx->ver = NULL;
976 ctx->sig = NULL;
977#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
978 ctx->det = NULL;
979#endif
980}
981
982/*
983 * Free the components of a restart context
984 */
985void mbedtls_ecdsa_restart_free( mbedtls_ecdsa_restart_ctx *ctx )
986{
987 if( ctx == NULL )
988 return;
989
990 mbedtls_ecp_restart_free( &ctx->ecp );
991
992 ecdsa_restart_ver_free( ctx->ver );
993 mbedtls_free( ctx->ver );
994 ctx->ver = NULL;
995
996 ecdsa_restart_sig_free( ctx->sig );
997 mbedtls_free( ctx->sig );
998 ctx->sig = NULL;
999
1000#if defined(MBEDTLS_ECDSA_DETERMINISTIC)
1001 ecdsa_restart_det_free( ctx->det );
1002 mbedtls_free( ctx->det );
1003 ctx->det = NULL;
1004#endif
1005}
1006#endif /* MBEDTLS_ECP_RESTARTABLE */
1007
Jens Wiklander817466c2018-05-22 13:49:31 +02001008#endif /* MBEDTLS_ECDSA_C */