34const uint8_t BIP0340_challenge[]
35 = {
'B',
'I',
'P',
'0',
'3',
'4',
'0',
'/',
'c',
'h',
'a',
'l',
'l',
'e',
'n',
'g',
'e'};
36const uint8_t BIP0340_aux[] = {
'B',
'I',
'P',
'0',
'3',
'4',
'0',
'/',
'a',
'u',
'x'};
37const uint8_t BIP0340_nonce[] = {
'B',
'I',
'P',
'0',
'3',
'4',
'0',
'/',
'n',
'o',
'n',
'c',
'e'};
39cx_err_t cx_ecschnorr_sign_no_throw(
const cx_ecfp_private_key_t *pv_key,
47#define CX_MAX_TRIES 100
52 cx_bn_t bn_k, bn_d, bn_r, bn_s, bn_n;
61 CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size));
65 return CX_EC_INVALID_CURVE;
69 if (hashID != CX_SHA256 || size != 32 || !CX_CURVE_RANGE(pv_key->curve, WEIERSTRASS)
70 || pv_key->d_len != size) {
71 return CX_INVALID_PARAMETER;
76 return CX_INVALID_PARAMETER;
79 CX_CHECK(cx_bn_lock(size, 0));
80 CX_CHECK(cx_bn_alloc(&bn_n, size));
81 CX_CHECK(cx_ecdomain_parameter_bn(pv_key->curve, CX_CURVE_PARAM_Order, bn_n));
82 CX_CHECK(cx_bn_alloc(&bn_k, size));
83 CX_CHECK(cx_bn_alloc(&bn_d, size));
84 CX_CHECK(cx_bn_alloc(&bn_r, size));
85 CX_CHECK(cx_bn_alloc(&bn_s, size));
86 CX_CHECK(cx_ecpoint_alloc(&Q, pv_key->curve));
90 CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q));
91 CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, size));
93 CX_CHECK(cx_bn_init(bn_d, pv_key->d, size));
94 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, P, size));
95 odd = P[size - 1] & 1;
97 CX_CHECK(cx_bn_sub(bn_d, bn_n, bn_d));
101 cx_sha256_init_no_throw(&H);
103 cx_hash_no_throw((cx_hash_t *) &H,
CX_LAST, BIP0340_aux,
sizeof(BIP0340_aux), R, size));
104 cx_sha256_init_no_throw(&H);
105 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
106 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
109 CX_CHECK(cx_bn_init(bn_k, R, size));
110 CX_CHECK(cx_bn_xor(bn_r, bn_d, bn_k));
111 CX_CHECK(cx_bn_export(bn_r, sig, size));
114 cx_sha256_init_no_throw(&H);
115 CX_CHECK(cx_hash_no_throw(
116 (cx_hash_t *) &H,
CX_LAST, BIP0340_nonce,
sizeof(BIP0340_nonce), R, size));
117 cx_sha256_init_no_throw(&H);
118 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
119 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
120 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
121 CX_CHECK(cx_ecpoint_export(&Q, P, size, NULL, 0));
122 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, P, size, NULL, 0));
123 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H,
CX_LAST |
CX_NO_REINIT, msg, size, sig, size));
129 if (tries == CX_MAX_TRIES) {
138 CX_CHECK(cx_bn_init(bn_r, sig, size));
139 CX_CHECK(cx_bn_reduce(bn_k, bn_r, bn_n));
143 CX_CHECK(cx_bn_rng(bn_k, bn_n));
147 error = CX_INVALID_PARAMETER;
151 CX_CHECK(cx_bn_cmp_u32(bn_k, 0, &diff));
153 error = CX_INVALID_PARAMETER;
157 CX_CHECK(cx_bn_export(bn_k, sig, size));
162 CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q));
163 CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, sig, size));
172 cx_sha256_init_no_throw(&H);
173 CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0));
174 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
176 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
177 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
179 CX_CHECK(cx_hash_no_throw(
182 CX_CHECK(cx_bn_init(bn_d, R, 32));
183 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
184 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
190 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
191 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
192 CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n));
193 CX_CHECK(cx_bn_set_u32(bn_k, 0));
194 CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n));
196 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
200 CX_CHECK(cx_bn_export(bn_s, S, 32));
208 cx_sha256_init_no_throw(&H);
209 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, msg, msg_len, NULL, 0));
210 CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0));
211 CX_CHECK(cx_hash_no_throw(
214 CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE));
215 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
216 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
222 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
223 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
224 CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n));
226 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
230 CX_CHECK(cx_bn_export(bn_s, S, 32));
246 cx_sha256_init_no_throw(&H);
247 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
248 odd = sig[size - 1] & 1;
249 CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0));
250 sig[0] = odd ? 0x03 : 0x02;
251 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, 1 + size, NULL, 0));
253 CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q));
254 CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, pv_key->d_len));
255 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
256 odd = sig[size - 1] & 1;
257 CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0));
258 sig[0] = odd ? 0x03 : 0x02;
259 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, 1 + size, NULL, 0));
261 CX_CHECK(cx_hash_no_throw(
266 CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE));
267 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
268 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
272 CX_CHECK(cx_bn_export(bn_r, R, 32));
274 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
275 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
276 CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n));
277 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
281 CX_CHECK(cx_bn_export(bn_s, S, 32));
293 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
294 odd = sig[size - 1] & 1;
297 CX_CHECK(cx_bn_mod_sub(bn_k, bn_n, bn_k, bn_n));
298 CX_CHECK(cx_bn_export(bn_k, sig, size));
302 CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0));
303 CX_CHECK(cx_bn_init(bn_d, R, size));
304 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
305 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
310 cx_sha256_init_no_throw(&H);
311 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
312 CX_CHECK(cx_hash_no_throw(
315 CX_CHECK(cx_bn_init(bn_r, sig, 32));
316 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
320 CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff));
325 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
326 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
327 CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n));
328 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
332 CX_CHECK(cx_bn_export(bn_s, S, 32));
339 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
340 odd = sig[size - 1] & 1;
342 CX_CHECK(cx_bn_sub(bn_k, bn_n, bn_k));
343 CX_CHECK(cx_bn_export(bn_k, sig, size));
346 CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0));
350 cx_sha256_init_no_throw(&H);
351 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H,
354 sizeof(BIP0340_challenge),
357 cx_sha256_init_no_throw(&H);
358 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
359 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
360 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
361 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, P, size, NULL, 0));
362 CX_CHECK(cx_hash_no_throw(
366 CX_CHECK(cx_bn_init(bn_s, sig, size));
367 CX_CHECK(cx_bn_reduce(bn_r, bn_s, bn_n));
370 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
371 CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n));
372 CX_CHECK(cx_bn_set_u32(bn_k, 0));
373 CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n));
375 CX_CHECK(cx_bn_export(bn_s, S, size));
379 error = CX_INVALID_PARAMETER;
384 cx_hash_destroy((cx_hash_t *) &H);
386 if (error == CX_OK) {
390 memcpy(sig + 32, S, 32);
394 *sig_len = cx_ecfp_encode_sig_der(sig, *sig_len, R, size, S, size);
400bool cx_ecschnorr_verify(
const cx_ecfp_public_key_t *pu_key,
409 const uint8_t *r, *s;
411 cx_ecpoint_t R, P, Q;
414 volatile int verified;
417 bool is_on_curve =
false;
419 cx_bn_t bn_d, bn_r, bn_s, bn_n;
420 cx_bn_t bn_x, bn_y, bn_p;
422 CX_CHECK(cx_ecdomain_parameters_length(pu_key->curve, &size));
426 error = CX_EC_INVALID_CURVE;
431 if (!CX_CURVE_RANGE(pu_key->curve, WEIERSTRASS) || hashID != CX_SHA256 || size != 32
432 || pu_key->W_len != 1 + 2 * size) {
437 if (!cx_ecfp_decode_sig_der(sig, sig_len, size, &r, &r_len, &s, &s_len)) {
442 CX_CHECK(cx_bn_lock(size, 0));
445 CX_CHECK(cx_bn_alloc(&bn_n, size));
446 CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Order, bn_n));
448 CX_CHECK(cx_bn_alloc_init(&bn_r, size, sig, size));
449 CX_CHECK(cx_bn_alloc_init(&bn_s, size, sig + size, size));
452 CX_CHECK(cx_bn_alloc_init(&bn_r, size, r, r_len));
453 CX_CHECK(cx_bn_alloc_init(&bn_s, size, s, s_len));
456 CX_CHECK(cx_bn_alloc(&bn_d, size));
458 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
462 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
467 CX_CHECK(cx_ecpoint_alloc(&P, pu_key->curve));
468 CX_CHECK(cx_ecpoint_alloc(&Q, pu_key->curve));
469 CX_CHECK(cx_ecpoint_alloc(&R, pu_key->curve));
470 CX_CHECK(cx_ecdomain_generator_bn(pu_key->curve, &P));
471 CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size));
483 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
487 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
491 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
495 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
502 CX_CHECK(cx_ecpoint_neg(&Q));
503 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
505 cx_sha256_init_no_throw(&H);
506 CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0));
507 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
509 CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size));
510 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
512 CX_CHECK(cx_hash_no_throw(
515 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
516 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
531 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
535 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
539 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
545 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
547 cx_sha256_init_no_throw(&H);
548 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, msg, msg_len, NULL, 0));
549 CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0));
553 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
554 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
571 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
575 CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff));
579 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
583 CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff));
589 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
591 cx_sha256_init_no_throw(&H);
593 CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size));
594 odd = x[size - 1] & 1;
595 CX_CHECK(cx_ecpoint_export(&R, x + 1, size, NULL, 0));
596 x[0] = odd ? 0x03 : 0x02;
597 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0));
599 memmove(x + 1, &pu_key->W[1], size);
600 x[0] = (pu_key->W[1 + 2 * size - 1] & 1) ? 0x03 : 0x02;
601 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0));
603 CX_CHECK(cx_hash_no_throw(
606 CX_CHECK(cx_bn_init(bn_d, x, CX_SHA256_SIZE));
607 CX_CHECK(cx_bn_reduce(bn_s, bn_d, bn_n));
608 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
627 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
632 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
637 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
643 cx_sha256_init_no_throw(&H);
644 CX_CHECK(cx_bn_export(bn_r, x, size));
645 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
646 CX_CHECK(cx_hash_no_throw(
648 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
649 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
653 CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff));
658 CX_CHECK(cx_bn_init(bn_d, s, s_len));
659 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_d, bn_s));
660 CX_CHECK(cx_ecpoint_export_bn(&R, &bn_s, &bn_d));
661 CX_CHECK(cx_bn_is_odd(bn_d, &odd));
665 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
676 CX_CHECK(cx_bn_alloc(&bn_x, size));
677 CX_CHECK(cx_bn_alloc(&bn_y, size));
678 CX_CHECK(cx_bn_alloc(&bn_p, size));
679 CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Field, bn_p));
680 CX_CHECK(cx_ecpoint_export_bn(&Q, &bn_x, &bn_y));
682 CX_CHECK(cx_bn_set_u32(bn_s, 3));
683 CX_CHECK(cx_bn_mod_pow_bn(bn_r, bn_x, bn_s, bn_p));
684 CX_CHECK(cx_bn_set_u32(bn_s, 7));
685 CX_CHECK(cx_bn_mod_add(bn_r, bn_r, bn_s, bn_p));
687 CX_CHECK(cx_bn_copy(bn_s, bn_p));
688 CX_CHECK(cx_bn_set_u32(bn_d, 1));
689 CX_CHECK(cx_bn_add(bn_s, bn_s, bn_d));
690 CX_CHECK(cx_bn_shr(bn_s, 2));
691 CX_CHECK(cx_bn_mod_pow_bn(bn_y, bn_r, bn_s, bn_p));
693 CX_CHECK(cx_bn_is_odd(bn_y, &odd));
696 CX_CHECK(cx_bn_sub(bn_y, bn_p, bn_y));
698 CX_CHECK(cx_ecpoint_init_bn(&Q, bn_x, bn_y));
699 CX_CHECK(cx_ecpoint_is_on_curve(&Q, &is_on_curve));
701 error = CX_EC_INVALID_POINT;
706 cx_sha256_init_no_throw(&H);
707 CX_CHECK(cx_hash_no_throw(
708 (cx_hash_t *) &H,
CX_LAST, BIP0340_challenge,
sizeof(BIP0340_challenge), x, size));
709 cx_sha256_init_no_throw(&H);
710 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
711 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
712 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
713 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, &pu_key->W[1], size, NULL, 0));
718 CX_CHECK(cx_bn_init(bn_x, x, size));
719 CX_CHECK(cx_bn_reduce(bn_r, bn_x, bn_n));
721 CX_CHECK(cx_bn_sub(bn_r, bn_n, bn_r));
723 CX_CHECK(cx_bn_init(bn_s, sig + size, size));
726 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
727 CX_CHECK(cx_ecpoint_export_bn(&R, &bn_x, &bn_y));
728 CX_CHECK(cx_bn_is_odd(bn_y, &odd));
730 CX_CHECK(cx_bn_init(bn_r, sig, size));
731 CX_CHECK(cx_bn_cmp(bn_x, bn_r, &diff));
733 if (odd || (diff != 0)) {
734 error = CX_INVALID_PARAMETER;
741 error = CX_INVALID_PARAMETER;
747 return error == CX_OK && verified;
#define CX_ECSCHNORR_ISO14888_X
#define CX_ECSCHNORR_BSI03111
#define CX_ECSCHNORR_BIP0340
#define CX_ECSCHNORR_LIBSECP
#define CX_ECSCHNORR_ISO14888_XY
Key pair generation based on elliptic curves.
EDDSA (Edwards Curve Digital Signature Algorithm)