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));
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);
401bool cx_ecschnorr_verify(
const cx_ecfp_public_key_t *pu_key,
410 const uint8_t *r, *s;
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 if (sig_len < 2 * size) {
453 CX_CHECK(cx_bn_alloc_init(&bn_r, size, sig, size));
454 CX_CHECK(cx_bn_alloc_init(&bn_s, size, sig + size, size));
457 CX_CHECK(cx_bn_alloc_init(&bn_r, size, r, r_len));
458 CX_CHECK(cx_bn_alloc_init(&bn_s, size, s, s_len));
461 CX_CHECK(cx_bn_alloc(&bn_d, size));
463 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
467 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
472 CX_CHECK(cx_ecpoint_alloc(&P, pu_key->curve));
473 CX_CHECK(cx_ecpoint_alloc(&Q, pu_key->curve));
474 CX_CHECK(cx_ecpoint_alloc(&R, pu_key->curve));
475 CX_CHECK(cx_ecdomain_generator_bn(pu_key->curve, &P));
476 CX_CHECK(cx_ecpoint_init(&Q, &pu_key->W[1], size, &pu_key->W[1 + size], size));
488 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
492 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
496 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
500 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
507 CX_CHECK(cx_ecpoint_neg(&Q));
508 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
510 cx_sha256_init_no_throw(&H);
511 CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0));
512 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
514 CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size));
515 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
517 CX_CHECK(cx_hash_no_throw(
520 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
521 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
536 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
540 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
544 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
550 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
552 cx_sha256_init_no_throw(&H);
553 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, msg, msg_len, NULL, 0));
554 CX_CHECK(cx_ecpoint_export(&R, x, size, NULL, 0));
558 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
559 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
576 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
580 CX_CHECK(cx_bn_cmp(bn_r, bn_n, &diff));
584 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
588 CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff));
594 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
596 cx_sha256_init_no_throw(&H);
598 CX_CHECK(cx_ecpoint_export(&R, NULL, 0, x, size));
599 odd = x[size - 1] & 1;
600 CX_CHECK(cx_ecpoint_export(&R, x + 1, size, NULL, 0));
601 x[0] = odd ? 0x03 : 0x02;
602 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0));
604 memmove(x + 1, &pu_key->W[1], size);
605 x[0] = (pu_key->W[1 + 2 * size - 1] & 1) ? 0x03 : 0x02;
606 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, 1 + size, NULL, 0));
608 CX_CHECK(cx_hash_no_throw(
611 CX_CHECK(cx_bn_init(bn_d, x, CX_SHA256_SIZE));
612 CX_CHECK(cx_bn_reduce(bn_s, bn_d, bn_n));
613 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
632 CX_CHECK(cx_bn_cmp_u32(bn_r, 0, &diff));
637 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
642 CX_CHECK(cx_bn_cmp(bn_n, bn_s, &diff));
648 cx_sha256_init_no_throw(&H);
649 CX_CHECK(cx_bn_export(bn_r, x, size));
650 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
651 CX_CHECK(cx_hash_no_throw(
653 CX_CHECK(cx_bn_init(bn_s, x, CX_SHA256_SIZE));
654 CX_CHECK(cx_bn_cmp_u32(bn_s, 0, &diff));
658 CX_CHECK(cx_bn_cmp(bn_s, bn_n, &diff));
663 CX_CHECK(cx_bn_init(bn_d, s, s_len));
664 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_d, bn_s));
665 CX_CHECK(cx_ecpoint_export_bn(&R, &bn_s, &bn_d));
666 CX_CHECK(cx_bn_is_odd(bn_d, &odd));
670 CX_CHECK(cx_bn_cmp(bn_r, bn_s, &diff));
681 CX_CHECK(cx_bn_alloc(&bn_x, size));
682 CX_CHECK(cx_bn_alloc(&bn_y, size));
683 CX_CHECK(cx_bn_alloc(&bn_p, size));
684 CX_CHECK(cx_ecdomain_parameter_bn(pu_key->curve, CX_CURVE_PARAM_Field, bn_p));
685 CX_CHECK(cx_ecpoint_export_bn(&Q, &bn_x, &bn_y));
687 CX_CHECK(cx_bn_set_u32(bn_s, 3));
688 CX_CHECK(cx_bn_mod_pow_bn(bn_r, bn_x, bn_s, bn_p));
689 CX_CHECK(cx_bn_set_u32(bn_s, 7));
690 CX_CHECK(cx_bn_mod_add(bn_r, bn_r, bn_s, bn_p));
692 CX_CHECK(cx_bn_copy(bn_s, bn_p));
693 CX_CHECK(cx_bn_set_u32(bn_d, 1));
694 CX_CHECK(cx_bn_add(bn_s, bn_s, bn_d));
695 CX_CHECK(cx_bn_shr(bn_s, 2));
696 CX_CHECK(cx_bn_mod_pow_bn(bn_y, bn_r, bn_s, bn_p));
698 CX_CHECK(cx_bn_is_odd(bn_y, &odd));
701 CX_CHECK(cx_bn_sub(bn_y, bn_p, bn_y));
703 CX_CHECK(cx_ecpoint_init_bn(&Q, bn_x, bn_y));
704 CX_CHECK(cx_ecpoint_is_on_curve(&Q, &is_on_curve));
706 error = CX_EC_INVALID_POINT;
711 cx_sha256_init_no_throw(&H);
712 CX_CHECK(cx_hash_no_throw(
713 (cx_hash_t *) &H,
CX_LAST, BIP0340_challenge,
sizeof(BIP0340_challenge), x, size));
714 cx_sha256_init_no_throw(&H);
715 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
716 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, x, size, NULL, 0));
717 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, sig, size, NULL, 0));
718 CX_CHECK(cx_hash_no_throw((cx_hash_t *) &H, 0, &pu_key->W[1], size, NULL, 0));
723 CX_CHECK(cx_bn_init(bn_x, x, size));
724 CX_CHECK(cx_bn_reduce(bn_r, bn_x, bn_n));
726 CX_CHECK(cx_bn_sub(bn_r, bn_n, bn_r));
728 CX_CHECK(cx_bn_init(bn_s, sig + size, size));
731 CX_CHECK(cx_ecpoint_double_scalarmul_bn(&R, &P, &Q, bn_s, bn_r));
732 CX_CHECK(cx_ecpoint_export_bn(&R, &bn_x, &bn_y));
733 CX_CHECK(cx_bn_is_odd(bn_y, &odd));
735 CX_CHECK(cx_bn_init(bn_r, sig, size));
736 CX_CHECK(cx_bn_cmp(bn_x, bn_r, &diff));
738 if (odd || (diff != 0)) {
739 error = CX_INVALID_PARAMETER;
746 error = CX_INVALID_PARAMETER;
752 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)