35 const uint8_t BIP0340_challenge[]
36 = {
'B',
'I',
'P',
'0',
'3',
'4',
'0',
'/',
'c',
'h',
'a',
'l',
'l',
'e',
'n',
'g',
'e'};
37 const uint8_t BIP0340_aux[] = {
'B',
'I',
'P',
'0',
'3',
'4',
'0',
'/',
'a',
'u',
'x'};
38 const uint8_t BIP0340_nonce[] = {
'B',
'I',
'P',
'0',
'3',
'4',
'0',
'/',
'n',
'o',
'n',
'c',
'e'};
40 cx_err_t cx_ecschnorr_sign_no_throw(
const cx_ecfp_private_key_t *pv_key,
48 #define CX_MAX_TRIES 100
53 cx_bn_t bn_k, bn_d, bn_r, bn_s, bn_n;
62 CX_CHECK(cx_ecdomain_parameters_length(pv_key->curve, &size));
66 return CX_EC_INVALID_CURVE;
70 if (hashID != CX_SHA256 || size != 32 || !CX_CURVE_RANGE(pv_key->curve, WEIERSTRASS)
71 || pv_key->d_len != size) {
72 return CX_INVALID_PARAMETER;
77 return CX_INVALID_PARAMETER;
80 CX_CHECK(cx_bn_lock(size, 0));
81 CX_CHECK(cx_bn_alloc(&bn_n, size));
82 CX_CHECK(cx_ecdomain_parameter_bn(pv_key->curve, CX_CURVE_PARAM_Order, bn_n));
83 CX_CHECK(cx_bn_alloc(&bn_k, size));
84 CX_CHECK(cx_bn_alloc(&bn_d, size));
85 CX_CHECK(cx_bn_alloc(&bn_r, size));
86 CX_CHECK(cx_bn_alloc(&bn_s, size));
87 CX_CHECK(cx_ecpoint_alloc(&Q, pv_key->curve));
91 CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q));
92 CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, size));
94 CX_CHECK(cx_bn_init(bn_d, pv_key->d, size));
95 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, P, size));
96 odd = P[size - 1] & 1;
98 CX_CHECK(cx_bn_sub(bn_d, bn_n, bn_d));
102 cx_sha256_init_no_throw(&H);
104 cx_hash_no_throw((cx_hash_t *) &H,
CX_LAST, BIP0340_aux,
sizeof(BIP0340_aux), R, size));
105 cx_sha256_init_no_throw(&H);
106 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
107 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
110 CX_CHECK(cx_bn_init(bn_k, R, size));
111 CX_CHECK(cx_bn_xor(bn_r, bn_d, bn_k));
112 CX_CHECK(cx_bn_export(bn_r, sig, size));
115 cx_sha256_init_no_throw(&H);
116 CX_CHECK(cx_hash_no_throw(
117 (cx_hash_t *) &H,
CX_LAST, BIP0340_nonce,
sizeof(BIP0340_nonce), R, size));
118 cx_sha256_init_no_throw(&H);
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, R, size, NULL, 0));
121 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
122 CX_CHECK(cx_ecpoint_export(&Q, P, size, NULL, 0));
123 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, P, size, NULL, 0));
124 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H,
CX_LAST |
CX_NO_REINIT, msg, size, sig, size));
130 if (tries == CX_MAX_TRIES) {
139 CX_CHECK(cx_bn_init(bn_r, sig, size));
140 CX_CHECK(cx_bn_reduce(bn_k, bn_r, bn_n));
144 CX_CHECK(cx_bn_rng(bn_k, bn_n));
148 error = CX_INVALID_PARAMETER;
152 CX_CHECK(cx_bn_cmp_u32(bn_k, 0, &diff));
154 error = CX_INVALID_PARAMETER;
158 CX_CHECK(cx_bn_export(bn_k, sig, size));
163 CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q));
164 CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, sig, size));
173 cx_sha256_init_no_throw(&H);
174 CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0));
175 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
177 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
178 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
180 CX_CHECK(cx_hash_no_throw(
183 CX_CHECK(cx_bn_init(bn_d, R, 32));
184 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
185 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
191 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
192 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
193 CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n));
194 CX_CHECK(cx_bn_set_u32(bn_k, 0));
195 CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n));
197 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
201 CX_CHECK(cx_bn_export(bn_s, S, 32));
209 cx_sha256_init_no_throw(&H);
210 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, msg, msg_len, NULL, 0));
211 CX_CHECK(cx_ecpoint_export(&Q, sig, size, NULL, 0));
212 CX_CHECK(cx_hash_no_throw(
215 CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE));
216 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
217 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
223 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
224 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
225 CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n));
227 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
231 CX_CHECK(cx_bn_export(bn_s, S, 32));
247 cx_sha256_init_no_throw(&H);
248 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
249 odd = sig[size - 1] & 1;
250 CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0));
251 sig[0] = odd ? 0x03 : 0x02;
252 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, 1 + size, NULL, 0));
254 CX_CHECK(cx_ecdomain_generator_bn(pv_key->curve, &Q));
255 CX_CHECK(cx_ecpoint_rnd_fixed_scalarmul(&Q, pv_key->d, pv_key->d_len));
256 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
257 odd = sig[size - 1] & 1;
258 CX_CHECK(cx_ecpoint_export(&Q, sig + 1, size, NULL, 0));
259 sig[0] = odd ? 0x03 : 0x02;
260 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, 1 + size, NULL, 0));
262 CX_CHECK(cx_hash_no_throw(
267 CX_CHECK(cx_bn_init(bn_d, R, CX_SHA256_SIZE));
268 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
269 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
273 CX_CHECK(cx_bn_export(bn_r, R, 32));
275 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
276 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
277 CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n));
278 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
282 CX_CHECK(cx_bn_export(bn_s, S, 32));
294 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
295 odd = sig[size - 1] & 1;
298 CX_CHECK(cx_bn_mod_sub(bn_k, bn_n, bn_k, bn_n));
299 CX_CHECK(cx_bn_export(bn_k, sig, size));
303 CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0));
304 CX_CHECK(cx_bn_init(bn_d, R, size));
305 CX_CHECK(cx_bn_reduce(bn_r, bn_d, bn_n));
306 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
311 cx_sha256_init_no_throw(&H);
312 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
313 CX_CHECK(cx_hash_no_throw(
316 CX_CHECK(cx_bn_init(bn_r, sig, 32));
317 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
321 CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff));
326 CX_CHECK(cx_bn_init(bn_d, pv_key->d, pv_key->d_len));
327 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
328 CX_CHECK(cx_bn_mod_sub(bn_s, bn_k, bn_s, bn_n));
329 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
333 CX_CHECK(cx_bn_export(bn_s, S, 32));
340 CX_CHECK(cx_ecpoint_export(&Q, NULL, 0, sig, size));
341 odd = sig[size - 1] & 1;
343 CX_CHECK(cx_bn_sub(bn_k, bn_n, bn_k));
344 CX_CHECK(cx_bn_export(bn_k, sig, size));
347 CX_CHECK(cx_ecpoint_export(&Q, R, size, NULL, 0));
351 cx_sha256_init_no_throw(&H);
352 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H,
355 sizeof(BIP0340_challenge),
358 cx_sha256_init_no_throw(&H);
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, sig, size, NULL, 0));
361 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, R, size, NULL, 0));
362 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, P, size, NULL, 0));
363 CX_CHECK(cx_hash_no_throw(
367 CX_CHECK(cx_bn_init(bn_s, sig, size));
368 CX_CHECK(cx_bn_reduce(bn_r, bn_s, bn_n));
371 CX_CHECK(cx_bn_mod_mul(bn_s, bn_d, bn_r, bn_n));
372 CX_CHECK(cx_bn_mod_add(bn_s, bn_k, bn_s, bn_n));
373 CX_CHECK(cx_bn_set_u32(bn_k, 0));
374 CX_CHECK(cx_bn_mod_sub(bn_s, bn_s, bn_k, bn_n));
376 CX_CHECK(cx_bn_export(bn_s, S, size));
380 error = CX_INVALID_PARAMETER;
385 cx_hash_destroy((cx_hash_t *) &H);
387 if (error == CX_OK) {
391 memcpy(sig + 32, S, 32);
395 *sig_len = cx_ecfp_encode_sig_der(sig, *sig_len, R, size, S, size);
401 bool cx_ecschnorr_verify(
const cx_ecfp_public_key_t *pu_key,
412 cx_ecpoint_t R, P, Q;
415 volatile int verified;
418 bool is_on_curve =
false;
420 cx_bn_t bn_d, bn_r, bn_s, bn_n;
421 cx_bn_t bn_x, bn_y, bn_p;
423 CX_CHECK(cx_ecdomain_parameters_length(pu_key->curve, &size));
427 error = CX_EC_INVALID_CURVE;
432 if (!CX_CURVE_RANGE(pu_key->curve, WEIERSTRASS) || hashID != CX_SHA256 || size != 32
433 || pu_key->W_len != 1 + 2 * size) {
438 if (!cx_ecfp_decode_sig_der(sig, sig_len, size, &r, &r_len, &s, &s_len)) {
443 CX_CHECK(cx_bn_lock(size, 0));
446 CX_CHECK(cx_bn_alloc(&bn_n, size));
447 CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Order, bn_n));
449 CX_CHECK(cx_bn_alloc_init(&bn_r, size, sig, size));
450 CX_CHECK(cx_bn_alloc_init(&bn_s, size, sig + size, size));
453 CX_CHECK(cx_bn_alloc_init(&bn_r, size, r, r_len));
454 CX_CHECK(cx_bn_alloc_init(&bn_s, size, s, s_len));
457 CX_CHECK(cx_bn_alloc(&bn_d, size));
459 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
463 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
468 CX_CHECK(cx_ecpoint_alloc(&P, pu_key->curve));
469 CX_CHECK(cx_ecpoint_alloc(&Q, pu_key->curve));
470 CX_CHECK(cx_ecpoint_alloc(&R, pu_key->curve));
471 CX_CHECK(cx_ecdomain_generator_bn(pu_key->curve, &P));
472 CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size));
484 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
488 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
492 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
496 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
503 CX_CHECK(cx_ecpoint_neg(&Q));
504 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
506 cx_sha256_init_no_throw(&H);
507 CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0));
508 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
510 CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size));
511 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
513 CX_CHECK(cx_hash_no_throw(
516 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
517 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
532 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
536 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
540 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
546 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
548 cx_sha256_init_no_throw(&H);
549 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, msg, msg_len, NULL, 0));
550 CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0));
554 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
555 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
572 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
576 CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff));
580 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
584 CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff));
590 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
592 cx_sha256_init_no_throw(&H);
594 CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size));
595 odd = x[size - 1] & 1;
596 CX_CHECK(cx_ecpoint_export(&R, x + 1, size, NULL, 0));
597 x[0] = odd ? 0x03 : 0x02;
598 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0));
600 memmove(x + 1, &pu_key->W[1], size);
601 x[0] = (pu_key->W[1 + 2 * size - 1] & 1) ? 0x03 : 0x02;
602 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0));
604 CX_CHECK(cx_hash_no_throw(
607 CX_CHECK(cx_bn_init(bn_d, x, CX_SHA256_SIZE));
608 CX_CHECK(cx_bn_reduce(bn_s, bn_d, bn_n));
609 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
628 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
633 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
638 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
644 cx_sha256_init_no_throw(&H);
645 CX_CHECK(cx_bn_export(bn_r, x, size));
646 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
647 CX_CHECK(cx_hash_no_throw(
649 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
650 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
654 CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff));
659 CX_CHECK(cx_bn_init(bn_d, s, s_len));
660 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_d, bn_s));
661 CX_CHECK(cx_ecpoint_export_bn(&R, &bn_s, &bn_d));
662 CX_CHECK(cx_bn_is_odd(bn_d, &odd));
666 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
677 CX_CHECK(cx_bn_alloc(&bn_x, size));
678 CX_CHECK(cx_bn_alloc(&bn_y, size));
679 CX_CHECK(cx_bn_alloc(&bn_p, size));
680 CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Field, bn_p));
681 CX_CHECK(cx_ecpoint_export_bn(&Q, &bn_x, &bn_y));
683 CX_CHECK(cx_bn_set_u32(bn_s, 3));
684 CX_CHECK(cx_bn_mod_pow_bn(bn_r, bn_x, bn_s, bn_p));
685 CX_CHECK(cx_bn_set_u32(bn_s, 7));
686 CX_CHECK(cx_bn_mod_add(bn_r, bn_r, bn_s, bn_p));
688 CX_CHECK(cx_bn_copy(bn_s, bn_p));
689 CX_CHECK(cx_bn_set_u32(bn_d, 1));
690 CX_CHECK(cx_bn_add(bn_s, bn_s, bn_d));
691 CX_CHECK(cx_bn_shr(bn_s, 2));
692 CX_CHECK(cx_bn_mod_pow_bn(bn_y, bn_r, bn_s, bn_p));
694 CX_CHECK(cx_bn_is_odd(bn_y, &odd));
697 CX_CHECK(cx_bn_sub(bn_y, bn_p, bn_y));
699 CX_CHECK(cx_ecpoint_init_bn(&Q, bn_x, bn_y));
700 CX_CHECK(cx_ecpoint_is_on_curve(&Q, &is_on_curve));
702 error = CX_EC_INVALID_POINT;
707 cx_sha256_init_no_throw(&H);
708 CX_CHECK(cx_hash_no_throw(
709 (cx_hash_t *) &H,
CX_LAST, BIP0340_challenge,
sizeof(BIP0340_challenge), x, size));
710 cx_sha256_init_no_throw(&H);
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, x, size, NULL, 0));
713 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
714 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, &pu_key->W[1], size, NULL, 0));
719 CX_CHECK(cx_bn_init(bn_x, x, size));
720 CX_CHECK(cx_bn_reduce(bn_r, bn_x, bn_n));
722 CX_CHECK(cx_bn_sub(bn_r, bn_n, bn_r));
724 CX_CHECK(cx_bn_init(bn_s, sig + size, size));
727 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
728 CX_CHECK(cx_ecpoint_export_bn(&R, &bn_x, &bn_y));
729 CX_CHECK(cx_bn_is_odd(bn_y, &odd));
731 CX_CHECK(cx_bn_init(bn_r, sig, size));
732 CX_CHECK(cx_bn_cmp(bn_x, bn_r, &diff));
734 if (odd || (diff != 0)) {
735 error = CX_INVALID_PARAMETER;
742 error = CX_INVALID_PARAMETER;
748 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