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