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