diff --git a/common/protob/messages-crypto.proto b/common/protob/messages-crypto.proto
index 38429790d..4953e6159 100644
--- a/common/protob/messages-crypto.proto
+++ b/common/protob/messages-crypto.proto
@@ -97,8 +97,8 @@ message ECDHSessionKey {
* @next Failure
*/
message CosiCommit {
- repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
- optional bytes data = 2; // Data to be signed
+ repeated uint32 address_n = 1; // BIP-32 path to derive the key from master node
+ optional bytes data = 2 [deprecated=true]; // Data to be signed. Deprecated in 1.10.2, the field is not needed, since CoSi commitments are no longer deterministic.
}
/**
diff --git a/core/.changelog.d/2130.changed b/core/.changelog.d/2130.changed
deleted file mode 100644
index 16dd999c3..000000000
--- a/core/.changelog.d/2130.changed
+++ /dev/null
@@ -1 +0,0 @@
-Remove power-down power-up cycle from touch controller initialization in firmware
diff --git a/core/.changelog.d/2230.added b/core/.changelog.d/2230.added
deleted file mode 100644
index 7e9b19fa8..000000000
--- a/core/.changelog.d/2230.added
+++ /dev/null
@@ -1 +0,0 @@
-Add model R emulator
diff --git a/core/.changelog.d/2232.added b/core/.changelog.d/2232.added
deleted file mode 100644
index 4fb98c8fd..000000000
--- a/core/.changelog.d/2232.added
+++ /dev/null
@@ -1 +0,0 @@
-Add support for Monero HF15 features.
diff --git a/core/.changelog.d/2243.added b/core/.changelog.d/2243.added
deleted file mode 100644
index c595a95a2..000000000
--- a/core/.changelog.d/2243.added
+++ /dev/null
@@ -1 +0,0 @@
-Add basic Trezor Model R hardware support
diff --git a/core/.changelog.d/2249.added b/core/.changelog.d/2249.added
deleted file mode 100644
index a93105eb3..000000000
--- a/core/.changelog.d/2249.added
+++ /dev/null
@@ -1 +0,0 @@
-Show the fee rate on the singing confirmation screen.
diff --git a/core/.changelog.d/2261.changed b/core/.changelog.d/2261.changed
deleted file mode 100644
index 48b6f4ae2..000000000
--- a/core/.changelog.d/2261.changed
+++ /dev/null
@@ -1 +0,0 @@
-Updated secp256k1-zkp.
diff --git a/core/.changelog.d/2284.added b/core/.changelog.d/2284.added
deleted file mode 100644
index d6fbe284e..000000000
--- a/core/.changelog.d/2284.added
+++ /dev/null
@@ -1 +0,0 @@
-Jump and stay in bootloader from firmware through SVC call reverse trampoline.
diff --git a/core/.changelog.d/2297.added b/core/.changelog.d/2297.added
deleted file mode 100644
index 1ca22a4af..000000000
--- a/core/.changelog.d/2297.added
+++ /dev/null
@@ -1 +0,0 @@
-Expose raw pixel access to Rust
diff --git a/core/.changelog.d/2300.added b/core/.changelog.d/2300.added
deleted file mode 100644
index 63c33ae2b..000000000
--- a/core/.changelog.d/2300.added
+++ /dev/null
@@ -1 +0,0 @@
-Add RGB LED for Model R
diff --git a/core/.changelog.d/2313.changed b/core/.changelog.d/2313.changed
deleted file mode 100644
index bc3d8084f..000000000
--- a/core/.changelog.d/2313.changed
+++ /dev/null
@@ -1 +0,0 @@
-Cardano internal refactors
diff --git a/core/.changelog.d/2324.added b/core/.changelog.d/2324.added
deleted file mode 100644
index c4a38a07c..000000000
--- a/core/.changelog.d/2324.added
+++ /dev/null
@@ -1 +0,0 @@
-Boardloader capabilities structure
diff --git a/core/.changelog.d/2354.added b/core/.changelog.d/2354.added
deleted file mode 100644
index b05831806..000000000
--- a/core/.changelog.d/2354.added
+++ /dev/null
@@ -1 +0,0 @@
-Support for Cardano Babbage era transaction items
diff --git a/core/.changelog.d/2354.changed b/core/.changelog.d/2354.changed
deleted file mode 100644
index af7c964c8..000000000
--- a/core/.changelog.d/2354.changed
+++ /dev/null
@@ -1,2 +0,0 @@
-Allow Cardano's `required_signers` in ordinary and multisig transactions
-Allow Cardano's `datum_hash` in non-script outputs
diff --git a/core/.changelog.d/2355.added b/core/.changelog.d/2355.added
deleted file mode 100644
index cb6264b39..000000000
--- a/core/.changelog.d/2355.added
+++ /dev/null
@@ -1 +0,0 @@
-Add "Show All"/"Show Simple" choice to Cardano transaction signing
diff --git a/core/.changelog.d/2380.added b/core/.changelog.d/2380.added
deleted file mode 100644
index e646a026f..000000000
--- a/core/.changelog.d/2380.added
+++ /dev/null
@@ -1 +0,0 @@
-Documentation for embedded C+Rust debugging
diff --git a/core/.changelog.d/2394.added b/core/.changelog.d/2394.added
deleted file mode 100644
index 49b957304..000000000
--- a/core/.changelog.d/2394.added
+++ /dev/null
@@ -1 +0,0 @@
-Show thousands separator when displaying large amounts.
diff --git a/core/.changelog.d/2415.fixed b/core/.changelog.d/2415.fixed
deleted file mode 100644
index a724ef5c1..000000000
--- a/core/.changelog.d/2415.fixed
+++ /dev/null
@@ -1 +0,0 @@
-Ensure correct order when verifying external inputs in Bitcoin signing.
diff --git a/core/.changelog.d/2422.fixed b/core/.changelog.d/2422.fixed
deleted file mode 100644
index 1fc900a63..000000000
--- a/core/.changelog.d/2422.fixed
+++ /dev/null
@@ -1 +0,0 @@
-Fix Decred transaction weight calculation.
diff --git a/core/.changelog.d/2433.removed b/core/.changelog.d/2433.removed
deleted file mode 100644
index 6daff5d0a..000000000
--- a/core/.changelog.d/2433.removed
+++ /dev/null
@@ -1 +0,0 @@
-Remove firmware dumping capability.
diff --git a/core/.changelog.d/642.changed b/core/.changelog.d/642.changed
deleted file mode 100644
index c19556c29..000000000
--- a/core/.changelog.d/642.changed
+++ /dev/null
@@ -1 +0,0 @@
-Refactor and cleanup of Monero code.
diff --git a/core/.changelog.d/642.removed b/core/.changelog.d/642.removed
deleted file mode 100644
index 66b75e098..000000000
--- a/core/.changelog.d/642.removed
+++ /dev/null
@@ -1 +0,0 @@
-Removed support for obsolete Monero hardfork 12 and below
diff --git a/core/.changelog.d/973.fixed b/core/.changelog.d/973.fixed
deleted file mode 100644
index c03f3f63f..000000000
--- a/core/.changelog.d/973.fixed
+++ /dev/null
@@ -1 +0,0 @@
-_(Emulator)_ Emulator window will always react to shutdown events, even while waiting for USB packets.
diff --git a/core/CHANGELOG.md b/core/CHANGELOG.md
index a35333d42..8c725e75a 100644
--- a/core/CHANGELOG.md
+++ b/core/CHANGELOG.md
@@ -4,6 +4,39 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [2.5.2] (17th August 2022)
+
+### Added
+- Add model R emulator [#2230]
+- Add support for Monero HF15 features. [#2232]
+- Add basic Trezor Model R hardware support [#2243]
+- Show the fee rate on the signing confirmation screen. [#2249]
+- Jump and stay in bootloader from firmware through SVC call reverse trampoline. [#2284]
+- Expose raw pixel access to Rust [#2297]
+- Add RGB LED for Model R [#2300]
+- Boardloader capabilities structure [#2324]
+- Support for Cardano Babbage era transaction items [#2354]
+- Add "Show All"/"Show Simple" choice to Cardano transaction signing [#2355]
+- Documentation for embedded C+Rust debugging [#2380]
+- Show thousands separator when displaying large amounts. [#2394]
+
+### Changed
+- Refactor and cleanup of Monero code. [#642]
+- Remove power-down power-up cycle from touch controller initialization in firmware [#2130]
+- Updated secp256k1-zkp. [#2261]
+- Cardano internal refactors [#2313]
+- Allow Cardano's `required_signers` in ordinary and multisig transactions
+ Allow Cardano's `datum_hash` in non-script outputs [#2354]
+
+### Removed
+- Removed support for obsolete Monero hardfork 12 and below [#642]
+- Remove firmware dumping capability. [#2433]
+
+### Fixed
+- _(Emulator)_ Emulator window will always react to shutdown events, even while waiting for USB packets. [#973]
+- Ensure correct order when verifying external inputs in Bitcoin signing. [#2415]
+- Fix Decred transaction weight calculation. [#2422]
+
## 2.5.1 [18th May 2022]
@@ -483,10 +516,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#24]: https://github.com/trezor/trezor-firmware/pull/24
[#379]: https://github.com/trezor/trezor-firmware/pull/379
+[#642]: https://github.com/trezor/trezor-firmware/pull/642
[#741]: https://github.com/trezor/trezor-firmware/pull/741
[#800]: https://github.com/trezor/trezor-firmware/pull/800
[#948]: https://github.com/trezor/trezor-firmware/pull/948
[#958]: https://github.com/trezor/trezor-firmware/pull/958
+[#973]: https://github.com/trezor/trezor-firmware/pull/973
[#982]: https://github.com/trezor/trezor-firmware/pull/982
[#1018]: https://github.com/trezor/trezor-firmware/pull/1018
[#1027]: https://github.com/trezor/trezor-firmware/pull/1027
@@ -594,9 +629,27 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#2077]: https://github.com/trezor/trezor-firmware/pull/2077
[#2100]: https://github.com/trezor/trezor-firmware/pull/2100
[#2114]: https://github.com/trezor/trezor-firmware/pull/2114
+[#2130]: https://github.com/trezor/trezor-firmware/pull/2130
[#2135]: https://github.com/trezor/trezor-firmware/pull/2135
[#2144]: https://github.com/trezor/trezor-firmware/pull/2144
[#2166]: https://github.com/trezor/trezor-firmware/pull/2166
[#2167]: https://github.com/trezor/trezor-firmware/pull/2167
[#2181]: https://github.com/trezor/trezor-firmware/pull/2181
+[#2230]: https://github.com/trezor/trezor-firmware/pull/2230
+[#2232]: https://github.com/trezor/trezor-firmware/pull/2232
[#2239]: https://github.com/trezor/trezor-firmware/pull/2239
+[#2243]: https://github.com/trezor/trezor-firmware/pull/2243
+[#2249]: https://github.com/trezor/trezor-firmware/pull/2249
+[#2261]: https://github.com/trezor/trezor-firmware/pull/2261
+[#2284]: https://github.com/trezor/trezor-firmware/pull/2284
+[#2297]: https://github.com/trezor/trezor-firmware/pull/2297
+[#2300]: https://github.com/trezor/trezor-firmware/pull/2300
+[#2313]: https://github.com/trezor/trezor-firmware/pull/2313
+[#2324]: https://github.com/trezor/trezor-firmware/pull/2324
+[#2354]: https://github.com/trezor/trezor-firmware/pull/2354
+[#2355]: https://github.com/trezor/trezor-firmware/pull/2355
+[#2380]: https://github.com/trezor/trezor-firmware/pull/2380
+[#2394]: https://github.com/trezor/trezor-firmware/pull/2394
+[#2415]: https://github.com/trezor/trezor-firmware/pull/2415
+[#2422]: https://github.com/trezor/trezor-firmware/pull/2422
+[#2433]: https://github.com/trezor/trezor-firmware/pull/2433
diff --git a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
index 3aac1d9b3..17fea3cbc 100644
--- a/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
+++ b/core/embed/extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
@@ -240,6 +240,25 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(
mod_trezorcrypto_ed25519_cosi_combine_signatures_obj,
mod_trezorcrypto_ed25519_cosi_combine_signatures);
+/// def cosi_commit() -> tuple[bytes, bytes]:
+/// """
+/// Generate a nonce and commitment for the CoSi cosigning scheme.
+/// """
+STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_commit() {
+ vstr_t nonce = {0};
+ vstr_t commitment = {0};
+ vstr_init_len(&nonce, 32);
+ vstr_init_len(&commitment, 32);
+ ed25519_cosi_commit(*(ed25519_secret_key *)nonce.buf,
+ *(ed25519_public_key *)commitment.buf);
+ mp_obj_tuple_t *tuple = MP_OBJ_TO_PTR(mp_obj_new_tuple(2, NULL));
+ tuple->items[0] = mp_obj_new_str_from_vstr(&mp_type_bytes, &nonce);
+ tuple->items[1] = mp_obj_new_str_from_vstr(&mp_type_bytes, &commitment);
+ return MP_OBJ_FROM_PTR(tuple);
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_0(mod_trezorcrypto_ed25519_cosi_commit_obj,
+ mod_trezorcrypto_ed25519_cosi_commit);
+
/// def cosi_sign(
/// secret_key: bytes,
/// message: bytes,
@@ -272,12 +291,15 @@ STATIC mp_obj_t mod_trezorcrypto_ed25519_cosi_sign(size_t n_args,
}
vstr_t sig = {0};
vstr_init_len(&sig, sizeof(ed25519_cosi_signature));
- ;
- ed25519_cosi_sign(msg.buf, msg.len, *(const ed25519_secret_key *)sk.buf,
- *(const ed25519_secret_key *)nonce.buf,
- *(const ed25519_public_key *)sigR.buf,
- *(const ed25519_secret_key *)pk.buf,
- *(ed25519_cosi_signature *)sig.buf);
+ if (0 != ed25519_cosi_sign(msg.buf, msg.len,
+ *(const ed25519_secret_key *)sk.buf,
+ *(const ed25519_secret_key *)nonce.buf,
+ *(const ed25519_public_key *)sigR.buf,
+ *(const ed25519_secret_key *)pk.buf,
+ *(ed25519_cosi_signature *)sig.buf)) {
+ vstr_clear(&sig);
+ mp_raise_ValueError("Signing failed");
+ }
return mp_obj_new_str_from_vstr(&mp_type_bytes, &sig);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(
@@ -301,6 +323,8 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_ed25519_globals_table[] = {
MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_publickeys_obj)},
{MP_ROM_QSTR(MP_QSTR_cosi_combine_signatures),
MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_combine_signatures_obj)},
+ {MP_ROM_QSTR(MP_QSTR_cosi_commit),
+ MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_commit_obj)},
{MP_ROM_QSTR(MP_QSTR_cosi_sign),
MP_ROM_PTR(&mod_trezorcrypto_ed25519_cosi_sign_obj)},
};
diff --git a/core/mocks/generated/trezorcrypto/ed25519.pyi b/core/mocks/generated/trezorcrypto/ed25519.pyi
index 54d527a1e..451b34682 100644
--- a/core/mocks/generated/trezorcrypto/ed25519.pyi
+++ b/core/mocks/generated/trezorcrypto/ed25519.pyi
@@ -53,6 +53,13 @@ def cosi_combine_signatures(R: bytes, signatures: list[bytes]) -> bytes:
"""
+# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
+def cosi_commit() -> tuple[bytes, bytes]:
+ """
+ Generate a nonce and commitment for the CoSi cosigning scheme.
+ """
+
+
# extmod/modtrezorcrypto/modtrezorcrypto-ed25519.h
def cosi_sign(
secret_key: bytes,
diff --git a/core/src/trezor/messages.py b/core/src/trezor/messages.py
index 17b6e8f04..b8d6b9aed 100644
--- a/core/src/trezor/messages.py
+++ b/core/src/trezor/messages.py
@@ -1928,13 +1928,11 @@ if TYPE_CHECKING:
class CosiCommit(protobuf.MessageType):
address_n: "list[int]"
- data: "bytes | None"
def __init__(
self,
*,
address_n: "list[int] | None" = None,
- data: "bytes | None" = None,
) -> None:
pass
diff --git a/core/tests/test_trezor.crypto.curve.ed25519_cosi.py b/core/tests/test_trezor.crypto.curve.ed25519_cosi.py
index 7a398241e..92d65869b 100644
--- a/core/tests/test_trezor.crypto.curve.ed25519_cosi.py
+++ b/core/tests/test_trezor.crypto.curve.ed25519_cosi.py
@@ -26,8 +26,7 @@ class TestCryptoEd25519Cosi(unittest.TestCase):
nonces = [None] * N
Rs = [None] * N
for j in range(N):
- nonces[j] = ed25519.generate_secret()
- Rs[j] = ed25519.publickey(nonces[j])
+ nonces[j], Rs[j] = ed25519.cosi_commit()
R = ed25519.cosi_combine_publickeys(Rs)
diff --git a/crypto/ed25519-donna/ed25519.c b/crypto/ed25519-donna/ed25519.c
index e25407a2a..6b7413421 100644
--- a/crypto/ed25519-donna/ed25519.c
+++ b/crypto/ed25519-donna/ed25519.c
@@ -18,6 +18,7 @@
#include "ed25519.h"
#include "ed25519-hash-custom.h"
+#include "rand.h"
#include "memzero.h"
/*
@@ -50,16 +51,34 @@ ED25519_FN(ed25519_publickey) (const ed25519_secret_key sk, ed25519_public_key p
}
void
+ED25519_FN(ed25519_cosi_commit) (ed25519_secret_key nonce, ed25519_public_key commitment) {
+ bignum256modm r = {0};
+ ge25519 ALIGN(16) R;
+ unsigned char extnonce[64] = {0};
+
+ /* r = random512 mod L */
+ random_buffer(extnonce, sizeof(extnonce));
+ expand256_modm(r, extnonce, sizeof(extnonce));
+ memzero(&extnonce, sizeof(extnonce));
+ contract256_modm(nonce, r);
+
+ /* R = rB */
+ ge25519_scalarmult_base_niels(&R, ge25519_niels_base_multiples, r);
+ memzero(&r, sizeof(r));
+ ge25519_pack(commitment, &R);
+}
+
+int
ED25519_FN(ed25519_cosi_sign) (const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_secret_key nonce, const ed25519_public_key R, const ed25519_public_key pk, ed25519_cosi_signature sig) {
bignum256modm r = {0}, S = {0}, a = {0};
- hash_512bits extsk = {0}, extnonce = {0}, hram = {0};
+ hash_512bits extsk = {0}, hram = {0};
ed25519_extsk(extsk, sk);
- ed25519_extsk(extnonce, nonce);
- /* r = nonce */
- expand256_modm(r, extnonce, 32);
- memzero(&extnonce, sizeof(extnonce));
+ /* r */
+ expand_raw256_modm(r, nonce);
+ if (!is_reduced256_modm(r))
+ return -1;
/* S = H(R,A,m).. */
ed25519_hram(hram, R, pk, m, mlen);
@@ -77,6 +96,8 @@ ED25519_FN(ed25519_cosi_sign) (const unsigned char *m, size_t mlen, const ed2551
/* S = (r + H(R,A,m)a) mod L */
contract256_modm(sig, S);
+
+ return 0;
}
void
@@ -155,7 +176,7 @@ ED25519_FN(ed25519_sign_open) (const unsigned char *m, size_t mlen, const ed2551
/* S */
expand_raw256_modm(S, RS + 32);
if (!is_reduced256_modm(S))
- return -1;
+ return -1;
/* SB - H(R,A,m)A */
ge25519_double_scalarmult_vartime(&R, &A, hram, S);
diff --git a/crypto/ed25519-donna/ed25519.h b/crypto/ed25519-donna/ed25519.h
index f01957561..b5fe78950 100644
--- a/crypto/ed25519-donna/ed25519.h
+++ b/crypto/ed25519-donna/ed25519.h
@@ -35,7 +35,8 @@ void curve25519_scalarmult_basepoint(curve25519_key mypublic, const curve25519_k
int ed25519_cosi_combine_publickeys(ed25519_public_key res, CONST ed25519_public_key *pks, size_t n);
void ed25519_cosi_combine_signatures(ed25519_signature res, const ed25519_public_key R, CONST ed25519_cosi_signature *sigs, size_t n);
-void ed25519_cosi_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key key, const ed25519_secret_key nonce, const ed25519_public_key R, const ed25519_public_key pk, ed25519_cosi_signature sig);
+void ed25519_cosi_commit(ed25519_secret_key nonce, ed25519_public_key commitment);
+int ed25519_cosi_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key key, const ed25519_secret_key nonce, const ed25519_public_key R, const ed25519_public_key pk, ed25519_cosi_signature sig);
#if defined(__cplusplus)
}
diff --git a/crypto/tests/test_check.c b/crypto/tests/test_check.c
index 9a417f493..437e1e75e 100644
--- a/crypto/tests/test_check.c
+++ b/crypto/tests/test_check.c
@@ -6885,8 +6885,7 @@ START_TEST(test_ed25519_cosi) {
/* phase 1: create nonces, commitments (R values) and combine commitments */
for (int j = 0; j < N; j++) {
- generate_rfc6979(nonces[j], &rng);
- ed25519_publickey(nonces[j], Rs[j]);
+ ed25519_cosi_commit(nonces[j], Rs[j]);
}
res = ed25519_cosi_combine_publickeys(R, Rs, N);
ck_assert_int_eq(res, 0);
@@ -6894,7 +6893,9 @@ START_TEST(test_ed25519_cosi) {
MARK_SECRET_DATA(keys, sizeof(keys));
/* phase 2: sign and combine signatures */
for (int j = 0; j < N; j++) {
- ed25519_cosi_sign(msg, sizeof(msg), keys[j], nonces[j], R, pk, sigs[j]);
+ res = ed25519_cosi_sign(msg, sizeof(msg), keys[j], nonces[j], R, pk,
+ sigs[j]);
+ ck_assert_int_eq(res, 0);
}
UNMARK_SECRET_DATA(sigs, sizeof(sigs));
diff --git a/legacy/firmware/.changelog.d/2249.added b/legacy/firmware/.changelog.d/2249.added
deleted file mode 100644
index a93105eb3..000000000
--- a/legacy/firmware/.changelog.d/2249.added
+++ /dev/null
@@ -1 +0,0 @@
-Show the fee rate on the singing confirmation screen.
diff --git a/legacy/firmware/.changelog.d/2261.changed b/legacy/firmware/.changelog.d/2261.changed
deleted file mode 100644
index 48b6f4ae2..000000000
--- a/legacy/firmware/.changelog.d/2261.changed
+++ /dev/null
@@ -1 +0,0 @@
-Updated secp256k1-zkp.
diff --git a/legacy/firmware/.changelog.d/2394.added b/legacy/firmware/.changelog.d/2394.added
deleted file mode 100644
index 49b957304..000000000
--- a/legacy/firmware/.changelog.d/2394.added
+++ /dev/null
@@ -1 +0,0 @@
-Show thousands separator when displaying large amounts.
diff --git a/legacy/firmware/.changelog.d/2422.fixed b/legacy/firmware/.changelog.d/2422.fixed
deleted file mode 100644
index da81d2d1d..000000000
--- a/legacy/firmware/.changelog.d/2422.fixed
+++ /dev/null
@@ -1 +0,0 @@
-Fix rounding in fee rate computation.
diff --git a/legacy/firmware/.changelog.d/2433.removed b/legacy/firmware/.changelog.d/2433.removed
deleted file mode 100644
index 6daff5d0a..000000000
--- a/legacy/firmware/.changelog.d/2433.removed
+++ /dev/null
@@ -1 +0,0 @@
-Remove firmware dumping capability.
diff --git a/legacy/firmware/CHANGELOG.md b/legacy/firmware/CHANGELOG.md
index b7b99f84c..97247e77a 100644
--- a/legacy/firmware/CHANGELOG.md
+++ b/legacy/firmware/CHANGELOG.md
@@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
+## [1.11.2] (17th August 2022)
+
+### Added
+- Show the fee rate on the signing confirmation screen. [#2249]
+- Show thousands separator when displaying large amounts. [#2394]
+
+### Changed
+- Updated secp256k1-zkp. [#2261]
+
+### Removed
+- Remove firmware dumping capability. [#2433]
+
+### Security
+- Fix potential security issues in recovery workflow.
+- Fix key extraction vulnerability in Cothority Collective Signing (CoSi).
+- Fix nonce bias in CoSi signing.
+
## 1.11.1 [18th May 2022]
@@ -543,3 +560,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
[#2144]: https://github.com/trezor/trezor-firmware/pull/2144
[#2181]: https://github.com/trezor/trezor-firmware/pull/2181
[#2239]: https://github.com/trezor/trezor-firmware/pull/2239
+[#2249]: https://github.com/trezor/trezor-firmware/pull/2249
+[#2261]: https://github.com/trezor/trezor-firmware/pull/2261
+[#2394]: https://github.com/trezor/trezor-firmware/pull/2394
+[#2422]: https://github.com/trezor/trezor-firmware/pull/2422
+[#2433]: https://github.com/trezor/trezor-firmware/pull/2433
diff --git a/legacy/firmware/fsm.c b/legacy/firmware/fsm.c
index b7a5e723d..756a6a740 100644
--- a/legacy/firmware/fsm.c
+++ b/legacy/firmware/fsm.c
@@ -44,7 +44,6 @@
#include "protect.h"
#include "recovery.h"
#include "reset.h"
-#include "rfc6979.h"
#include "rng.h"
#include "secp256k1.h"
#include "signing.h"
diff --git a/legacy/firmware/fsm_msg_crypto.h b/legacy/firmware/fsm_msg_crypto.h
index 595f47dfe..1cdd6d541 100644
--- a/legacy/firmware/fsm_msg_crypto.h
+++ b/legacy/firmware/fsm_msg_crypto.h
@@ -17,6 +17,10 @@
* along with this library. If not, see .
*/
+static uint8_t cosi_nonce[32] = {0};
+static uint8_t cosi_commitment[32] = {0};
+static bool cosi_nonce_is_set = false;
+
void fsm_msgCipherKeyValue(const CipherKeyValue *msg) {
CHECK_INITIALIZED
@@ -256,8 +260,6 @@ void fsm_msgCosiCommit(const CosiCommit *msg) {
CHECK_INITIALIZED
- CHECK_PARAM(msg->has_data, _("No data provided"));
-
CHECK_PIN
if (!fsm_checkCosiPath(msg->address_n_count, msg->address_n)) {
@@ -265,30 +267,21 @@ void fsm_msgCosiCommit(const CosiCommit *msg) {
return;
}
- layoutCosiCommitSign(msg->address_n, msg->address_n_count, msg->data.bytes,
- msg->data.size, false);
- if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
- fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
- layoutHome();
- return;
- }
-
const HDNode *node = fsm_getDerivedNode(ED25519_NAME, msg->address_n,
msg->address_n_count, NULL);
if (!node) return;
- uint8_t nonce[32];
- sha256_Raw(msg->data.bytes, msg->data.size, nonce);
- rfc6979_state rng;
- init_rfc6979(node->private_key, nonce, NULL, &rng);
- generate_rfc6979(nonce, &rng);
+ if (!cosi_nonce_is_set) {
+ ed25519_cosi_commit(cosi_nonce, cosi_commitment);
+ cosi_nonce_is_set = true;
+ }
resp->has_commitment = true;
resp->has_pubkey = true;
resp->commitment.size = 32;
resp->pubkey.size = 32;
- ed25519_publickey(nonce, resp->commitment.bytes);
+ memcpy(resp->commitment.bytes, cosi_commitment, sizeof(cosi_commitment));
ed25519_publickey(node->private_key, resp->pubkey.bytes);
msg_write(MessageType_MessageType_CosiCommitment, resp);
@@ -306,6 +299,12 @@ void fsm_msgCosiSign(const CosiSign *msg) {
CHECK_PARAM(msg->has_global_pubkey && msg->global_pubkey.size == 32,
_("Invalid global pubkey"));
+ if (!cosi_nonce_is_set) {
+ fsm_sendFailure(FailureType_Failure_ProcessError, _("CoSi nonce not set"));
+ layoutHome();
+ return;
+ }
+
if (!fsm_checkCosiPath(msg->address_n_count, msg->address_n)) {
layoutHome();
return;
@@ -313,8 +312,8 @@ void fsm_msgCosiSign(const CosiSign *msg) {
CHECK_PIN
- layoutCosiCommitSign(msg->address_n, msg->address_n_count, msg->data.bytes,
- msg->data.size, true);
+ layoutCosiSign(msg->address_n, msg->address_n_count, msg->data.bytes,
+ msg->data.size);
if (!protectButton(ButtonRequestType_ButtonRequest_ProtectCall, false)) {
fsm_sendFailure(FailureType_Failure_ActionCancelled, NULL);
layoutHome();
@@ -325,18 +324,16 @@ void fsm_msgCosiSign(const CosiSign *msg) {
msg->address_n_count, NULL);
if (!node) return;
- uint8_t nonce[32];
- sha256_Raw(msg->data.bytes, msg->data.size, nonce);
- rfc6979_state rng;
- init_rfc6979(node->private_key, nonce, NULL, &rng);
- generate_rfc6979(nonce, &rng);
-
resp->signature.size = 32;
+ cosi_nonce_is_set = false;
- ed25519_cosi_sign(msg->data.bytes, msg->data.size, node->private_key, nonce,
- msg->global_commitment.bytes, msg->global_pubkey.bytes,
- resp->signature.bytes);
-
- msg_write(MessageType_MessageType_CosiSignature, resp);
+ if (ed25519_cosi_sign(msg->data.bytes, msg->data.size, node->private_key,
+ cosi_nonce, msg->global_commitment.bytes,
+ msg->global_pubkey.bytes, resp->signature.bytes) == 0) {
+ msg_write(MessageType_MessageType_CosiSignature, resp);
+ } else {
+ fsm_sendFailure(FailureType_Failure_FirmwareError, NULL);
+ }
+ memzero(cosi_nonce, sizeof(cosi_nonce));
layoutHome();
}
diff --git a/legacy/firmware/layout2.c b/legacy/firmware/layout2.c
index 48452c056..1334b7e34 100644
--- a/legacy/firmware/layout2.c
+++ b/legacy/firmware/layout2.c
@@ -1220,18 +1220,13 @@ static inline bool is_slip18(const uint32_t *address_n,
(address_n[1] & PATH_UNHARDEN_MASK) <= 9;
}
-void layoutCosiCommitSign(const uint32_t *address_n, size_t address_n_count,
- const uint8_t *data, uint32_t len, bool final_sign) {
- char *desc = final_sign ? _("CoSi sign message?") : _("CoSi commit message?");
+void layoutCosiSign(const uint32_t *address_n, size_t address_n_count,
+ const uint8_t *data, uint32_t len) {
+ char *desc = _("CoSi sign message?");
char desc_buf[32] = {0};
if (is_slip18(address_n, address_n_count)) {
- if (final_sign) {
- strlcpy(desc_buf, _("CoSi sign index #?"), sizeof(desc_buf));
- desc_buf[16] = '0' + (address_n[1] & PATH_UNHARDEN_MASK);
- } else {
- strlcpy(desc_buf, _("CoSi commit index #?"), sizeof(desc_buf));
- desc_buf[18] = '0' + (address_n[1] & PATH_UNHARDEN_MASK);
- }
+ strlcpy(desc_buf, _("CoSi sign index #?"), sizeof(desc_buf));
+ desc_buf[16] = '0' + (address_n[1] & PATH_UNHARDEN_MASK);
desc = desc_buf;
}
char str[4][17] = {0};
diff --git a/legacy/firmware/layout2.h b/legacy/firmware/layout2.h
index 77966d720..7f88da70f 100644
--- a/legacy/firmware/layout2.h
+++ b/legacy/firmware/layout2.h
@@ -105,8 +105,8 @@ void layoutNEMTransferPayload(const uint8_t *payload, size_t length,
void layoutNEMMosaicDescription(const char *description);
void layoutNEMLevy(const NEMMosaicDefinition *definition, uint8_t network);
-void layoutCosiCommitSign(const uint32_t *address_n, size_t address_n_count,
- const uint8_t *data, uint32_t len, bool final_sign);
+void layoutCosiSign(const uint32_t *address_n, size_t address_n_count,
+ const uint8_t *data, uint32_t len);
void layoutConfirmAutoLockDelay(uint32_t delay_ms);
void layoutConfirmSafetyChecks(SafetyCheckLevel safety_checks_level);
diff --git a/legacy/firmware/protob/messages-crypto.options b/legacy/firmware/protob/messages-crypto.options
index 36a80ff1c..c4774819c 100644
--- a/legacy/firmware/protob/messages-crypto.options
+++ b/legacy/firmware/protob/messages-crypto.options
@@ -6,7 +6,7 @@ CipherKeyValue.iv max_size:16
CipheredKeyValue.value max_size:1024
CosiCommit.address_n max_count:8
-CosiCommit.data max_size:32
+CosiCommit.data type:FT_IGNORE
CosiCommitment.commitment max_size:32
CosiCommitment.pubkey max_size:32
diff --git a/legacy/firmware/recovery.c b/legacy/firmware/recovery.c
index 317fb2e20..6aae892ef 100644
--- a/legacy/firmware/recovery.c
+++ b/legacy/firmware/recovery.c
@@ -37,12 +37,12 @@
/* number of words expected in the new seed */
static uint32_t word_count;
-/* recovery mode:
- * 0: not recovering
- * 1: recover by scrambled plain text words
- * 2: recover by matrix entry
- */
-static int awaiting_word = 0;
+/* recovery mode */
+static enum {
+ RECOVERY_NONE = 0, // recovery not in progress
+ RECOVERY_SCRAMBLED = 1, // standard recovery by scrambled plain text words
+ RECOVERY_MATRIX = 2, // advanced recovery by matrix entry
+} recovery_mode = RECOVERY_NONE;
/* True if we should not write anything back to config
* (can be used for testing seed for correctness).
@@ -145,7 +145,7 @@ static void format_number(char *dest, int number) {
static void recovery_request(void) {
WordRequest resp = {0};
memzero(&resp, sizeof(WordRequest));
- if (awaiting_word == 1) {
+ if (recovery_mode == RECOVERY_SCRAMBLED) {
resp.type = WordRequestType_WordRequestType_Plain;
} else if (word_index % 4 == 3) {
resp.type = WordRequestType_WordRequestType_Matrix6;
@@ -217,7 +217,9 @@ static void recovery_done(void) {
fsm_sendFailure(FailureType_Failure_DataError,
_("Invalid seed, are words in correct order?"));
}
- awaiting_word = 0;
+ memzero(words, sizeof(words));
+ word_pincode = 0;
+ recovery_mode = RECOVERY_NONE;
layoutHome();
}
@@ -476,6 +478,9 @@ void recovery_init(uint32_t _word_count, bool passphrase_protection,
bool _dry_run) {
if (_word_count != 12 && _word_count != 18 && _word_count != 24) return;
+ recovery_mode = RECOVERY_NONE;
+ word_pincode = 0;
+ word_index = 0;
word_count = _word_count;
enforce_wordlist = _enforce_wordlist;
dry_run = _dry_run;
@@ -504,10 +509,9 @@ void recovery_init(uint32_t _word_count, bool passphrase_protection,
config_setU2FCounter(u2f_counter);
}
+ // Prefer matrix recovery if the host supports it.
if ((type & RecoveryDeviceType_RecoveryDeviceType_Matrix) != 0) {
- awaiting_word = 2;
- word_index = 0;
- word_pincode = 0;
+ recovery_mode = RECOVERY_MATRIX;
next_matrix();
} else {
for (uint32_t i = 0; i < word_count; i++) {
@@ -517,8 +521,7 @@ void recovery_init(uint32_t _word_count, bool passphrase_protection,
word_order[i] = 0;
}
random_permute(word_order, 24);
- awaiting_word = 1;
- word_index = 0;
+ recovery_mode = RECOVERY_SCRAMBLED;
next_word();
}
}
@@ -527,29 +530,18 @@ static void recovery_scrambledword(const char *word) {
int index = -1;
if (enforce_wordlist) { // check if word is valid
index = mnemonic_find_word(word);
- }
- if (word_pos == 0) { // fake word
- if (strcmp(word, fake_word) != 0) {
+ if (index < 0) { // not found
if (!dry_run) {
session_clear(true);
}
- fsm_sendFailure(FailureType_Failure_ProcessError,
- _("Wrong word retyped"));
- layoutHome();
+ fsm_sendFailure(FailureType_Failure_DataError,
+ _("Word not found in a wordlist"));
+ recovery_abort();
return;
}
- } else { // real word
- if (enforce_wordlist) {
- if (index < 0) { // not found
- if (!dry_run) {
- session_clear(true);
- }
- fsm_sendFailure(FailureType_Failure_DataError,
- _("Word not found in a wordlist"));
- layoutHome();
- return;
- }
- }
+ }
+
+ if (word_pos != 0) { // ignore fake words
strlcpy(words[word_pos - 1], word, sizeof(words[word_pos - 1]));
}
@@ -565,11 +557,11 @@ static void recovery_scrambledword(const char *word) {
* for scrambled recovery.
*/
void recovery_word(const char *word) {
- switch (awaiting_word) {
- case 2:
+ switch (recovery_mode) {
+ case RECOVERY_MATRIX:
recovery_digit(word[0]);
break;
- case 1:
+ case RECOVERY_SCRAMBLED:
recovery_scrambledword(word);
break;
default:
@@ -582,9 +574,11 @@ void recovery_word(const char *word) {
/* Abort recovery.
*/
void recovery_abort(void) {
- if (awaiting_word) {
+ memzero(words, sizeof(words));
+ word_pincode = 0;
+ if (recovery_mode != RECOVERY_NONE) {
layoutHome();
- awaiting_word = 0;
+ recovery_mode = RECOVERY_NONE;
}
}
diff --git a/python/.changelog.d/noissue.removed b/python/.changelog.d/noissue.removed
new file mode 100644
index 000000000..5acaf6aa7
--- /dev/null
+++ b/python/.changelog.d/noissue.removed
@@ -0,0 +1 @@
+Remove DATA parameter from trezorctl cosi commit.
diff --git a/python/src/trezorlib/cli/cosi.py b/python/src/trezorlib/cli/cosi.py
index 4607e7982..d84189f99 100644
--- a/python/src/trezorlib/cli/cosi.py
+++ b/python/src/trezorlib/cli/cosi.py
@@ -14,7 +14,8 @@
# You should have received a copy of the License along with this library.
# If not, see .
-from typing import TYPE_CHECKING
+import warnings
+from typing import TYPE_CHECKING, Optional
import click
@@ -35,14 +36,17 @@ def cli() -> None:
@cli.command()
@click.option("-n", "--address", required=True, help=PATH_HELP)
-@click.argument("data")
+@click.argument("data_deprecated", required=False)
@with_client
def commit(
- client: "TrezorClient", address: str, data: str
+ client: "TrezorClient", address: str, data_deprecated: Optional[str]
) -> "messages.CosiCommitment":
"""Ask device to commit to CoSi signing."""
+ if data_deprecated is not None:
+ warnings.warn("'data' argument is deprecated")
+
address_n = tools.parse_path(address)
- return cosi.commit(client, address_n, bytes.fromhex(data))
+ return cosi.commit(client, address_n)
@cli.command()
diff --git a/python/src/trezorlib/cosi.py b/python/src/trezorlib/cosi.py
index fbcf603eb..77786a90f 100644
--- a/python/src/trezorlib/cosi.py
+++ b/python/src/trezorlib/cosi.py
@@ -14,8 +14,9 @@
# You should have received a copy of the License along with this library.
# If not, see .
+import warnings
from functools import reduce
-from typing import TYPE_CHECKING, Iterable, List, Tuple
+from typing import TYPE_CHECKING, Iterable, List, Optional, Tuple
from . import _ed25519, messages
from .tools import expect
@@ -141,8 +142,17 @@ def sign_with_privkey(
@expect(messages.CosiCommitment)
-def commit(client: "TrezorClient", n: "Address", data: bytes) -> "MessageType":
- return client.call(messages.CosiCommit(address_n=n, data=data))
+def commit(
+ client: "TrezorClient", n: "Address", data: Optional[bytes] = None
+) -> "MessageType":
+ if data is not None:
+ warnings.warn(
+ "'data' argument is deprecated",
+ DeprecationWarning,
+ stacklevel=2,
+ )
+
+ return client.call(messages.CosiCommit(address_n=n))
@expect(messages.CosiSignature)
diff --git a/tests/device_tests/misc/test_cosi.py b/tests/device_tests/misc/test_cosi.py
index 048552e2b..0f7a0cce9 100644
--- a/tests/device_tests/misc/test_cosi.py
+++ b/tests/device_tests/misc/test_cosi.py
@@ -24,75 +24,87 @@ from trezorlib.tools import parse_path
pytestmark = pytest.mark.skip_t2
+DIGEST = sha256(b"this is not a pipe").digest()
-def test_cosi_commit(client: Client):
- digest = sha256(b"this is a message").digest()
- c0 = cosi.commit(client, parse_path("m/10018h/0h"), digest)
- c1 = cosi.commit(client, parse_path("m/10018h/1h"), digest)
- c2 = cosi.commit(client, parse_path("m/10018h/2h"), digest)
+def test_cosi_pubkey(client: Client):
+ c0 = cosi.commit(client, parse_path("m/10018h/0h"))
+ c1 = cosi.commit(client, parse_path("m/10018h/1h"))
+ c2 = cosi.commit(client, parse_path("m/10018h/2h"))
assert c0.pubkey != c1.pubkey
assert c0.pubkey != c2.pubkey
assert c1.pubkey != c2.pubkey
- assert c0.commitment != c1.commitment
- assert c0.commitment != c2.commitment
- assert c1.commitment != c2.commitment
-
- digestb = sha256(b"this is a different message").digest()
- c0b = cosi.commit(client, parse_path("m/10018h/0h"), digestb)
- c1b = cosi.commit(client, parse_path("m/10018h/1h"), digestb)
- c2b = cosi.commit(client, parse_path("m/10018h/2h"), digestb)
+def test_cosi_nonce(client: Client):
+ # The nonce/commitment must change after each signing.
+ c0 = cosi.commit(client, parse_path("m/10018h/0h"))
+ cosi.sign(client, parse_path("m/10018h/0h"), DIGEST, c0.commitment, c0.pubkey)
+ c1 = cosi.commit(client, parse_path("m/10018h/0h"))
+ assert c0.commitment != c1.commitment
- assert c0.pubkey == c0b.pubkey
- assert c1.pubkey == c1b.pubkey
- assert c2.pubkey == c2b.pubkey
- assert c0.commitment != c0b.commitment
- assert c1.commitment != c1b.commitment
- assert c2.commitment != c2b.commitment
+def test_cosi_sign1(client: Client):
+ # Single party signature.
+ commit = cosi.commit(client, parse_path("m/10018h/0h"))
+ sig = cosi.sign(
+ client, parse_path("m/10018h/0h"), DIGEST, commit.commitment, commit.pubkey
+ )
+ signature = cosi.combine_sig(commit.commitment, [sig.signature])
+ cosi.verify_combined(signature, DIGEST, commit.pubkey)
-def test_cosi_sign(client: Client):
- digest = sha256(b"this is a message").digest()
+def test_cosi_sign2(client: Client):
+ # Two party signature.
+ remote_commit = cosi.commit(client, parse_path("m/10018h/1h"))
- c0 = cosi.commit(client, parse_path("m/10018h/0h"), digest)
- c1 = cosi.commit(client, parse_path("m/10018h/1h"), digest)
- c2 = cosi.commit(client, parse_path("m/10018h/2h"), digest)
+ local_privkey = sha256(b"private key").digest()[:32]
+ local_pubkey = cosi.pubkey_from_privkey(local_privkey)
+ local_nonce, local_commitment = cosi.get_nonce(local_privkey, DIGEST, 42)
- global_pk = cosi.combine_keys([c0.pubkey, c1.pubkey, c2.pubkey])
- global_R = cosi.combine_keys([c0.commitment, c1.commitment, c2.commitment])
+ global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey])
+ global_R = cosi.combine_keys([remote_commit.commitment, local_commitment])
- # fmt: off
- sig0 = cosi.sign(client, parse_path("m/10018h/0h"), digest, global_R, global_pk)
- sig1 = cosi.sign(client, parse_path("m/10018h/1h"), digest, global_R, global_pk)
- sig2 = cosi.sign(client, parse_path("m/10018h/2h"), digest, global_R, global_pk)
- # fmt: on
+ remote_sig = cosi.sign(
+ client, parse_path("m/10018h/1h"), DIGEST, global_R, global_pk
+ )
+ local_sig = cosi.sign_with_privkey(
+ DIGEST, local_privkey, global_pk, local_nonce, global_R
+ )
+ signature = cosi.combine_sig(global_R, [remote_sig.signature, local_sig])
- sig = cosi.combine_sig(global_R, [sig0.signature, sig1.signature, sig2.signature])
+ cosi.verify_combined(signature, DIGEST, global_pk)
- cosi.verify_combined(sig, digest, global_pk)
+def test_cosi_sign3(client: Client):
+ # Three party signature.
+ remote_commit = cosi.commit(client, parse_path("m/10018h/2h"))
-def test_cosi_compat(client: Client):
- digest = sha256(b"this is not a pipe").digest()
- remote_commit = cosi.commit(client, parse_path("m/10018h/0h"), digest)
+ local_privkey1 = sha256(b"private key").digest()[:32]
+ local_pubkey1 = cosi.pubkey_from_privkey(local_privkey1)
+ local_nonce1, local_commitment1 = cosi.get_nonce(local_privkey1, DIGEST, 42)
- local_privkey = sha256(b"private key").digest()[:32]
- local_pubkey = cosi.pubkey_from_privkey(local_privkey)
- local_nonce, local_commitment = cosi.get_nonce(local_privkey, digest, 42)
+ local_privkey2 = sha256(b"private key").digest()[:32]
+ local_pubkey2 = cosi.pubkey_from_privkey(local_privkey2)
+ local_nonce2, local_commitment2 = cosi.get_nonce(local_privkey2, DIGEST, 42)
- global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey])
- global_R = cosi.combine_keys([remote_commit.commitment, local_commitment])
+ global_pk = cosi.combine_keys([remote_commit.pubkey, local_pubkey1, local_pubkey2])
+ global_R = cosi.combine_keys(
+ [remote_commit.commitment, local_commitment1, local_commitment2]
+ )
remote_sig = cosi.sign(
- client, parse_path("m/10018h/0h"), digest, global_R, global_pk
+ client, parse_path("m/10018h/2h"), DIGEST, global_R, global_pk
)
- local_sig = cosi.sign_with_privkey(
- digest, local_privkey, global_pk, local_nonce, global_R
+ local_sig1 = cosi.sign_with_privkey(
+ DIGEST, local_privkey1, global_pk, local_nonce1, global_R
+ )
+ local_sig2 = cosi.sign_with_privkey(
+ DIGEST, local_privkey2, global_pk, local_nonce2, global_R
+ )
+ signature = cosi.combine_sig(
+ global_R, [remote_sig.signature, local_sig1, local_sig2]
)
- sig = cosi.combine_sig(global_R, [remote_sig.signature, local_sig])
- cosi.verify_combined(sig, digest, global_pk)
+ cosi.verify_combined(signature, DIGEST, global_pk)
diff --git a/tests/ui_tests/fixtures.json b/tests/ui_tests/fixtures.json
index cd7016936..986b666f7 100644
--- a/tests/ui_tests/fixtures.json
+++ b/tests/ui_tests/fixtures.json
@@ -393,9 +393,11 @@
"T1_ethereum-test_signtx.py::test_signtx_eip1559[unknown_erc20]": "548c1f22918351e9cbcc1e16d8ba67bc2e7460b9a92cfc6c8bfa0a2b063e68da",
"T1_ethereum-test_signtx.py::test_signtx_eip1559_access_list": "f6c5f398d4e80fc8f93cf70e9b10de24b9a968db04dc6ea21b28d1a273f04ca1",
"T1_ethereum-test_signtx.py::test_signtx_eip1559_access_list_larger": "f6c5f398d4e80fc8f93cf70e9b10de24b9a968db04dc6ea21b28d1a273f04ca1",
-"T1_misc-test_cosi.py::test_cosi_commit": "c943c92750d6072a3b272c1a9dca815ee7504293e4c1d85a76d5af9c2e415297",
-"T1_misc-test_cosi.py::test_cosi_compat": "dfdc383ac1dd9f1bb63b52c8623d3788491e7a954f6f0374fe0963e823a5e0c5",
-"T1_misc-test_cosi.py::test_cosi_sign": "54f589eaca23d0e1a055280920b9a40c7ba7a5b34779270090a8361113af4574",
+"T1_misc-test_cosi.py::test_cosi_nonce": "6990c238036b79368fea1dc1e3e8871d7788322bbee7425d14c53623bc8182e8",
+"T1_misc-test_cosi.py::test_cosi_pubkey": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+"T1_misc-test_cosi.py::test_cosi_sign1": "6990c238036b79368fea1dc1e3e8871d7788322bbee7425d14c53623bc8182e8",
+"T1_misc-test_cosi.py::test_cosi_sign2": "0852e7433ec54a0ace301b683417107a9805095acd954010b665266503a79f36",
+"T1_misc-test_cosi.py::test_cosi_sign3": "d04fca2d97f7117ffc79ae52d192086aba2f9c64e89db27e20a930e9048f1d81",
"T1_misc-test_msg_cipherkeyvalue.py::test_decrypt": "a849d9e11e222d1348ce3135680a2a61ed265692adeba4bd48af2fdc65207e61",
"T1_misc-test_msg_cipherkeyvalue.py::test_decrypt_badlen": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"T1_misc-test_msg_cipherkeyvalue.py::test_encrypt": "e36d5b5db4b3733c9f484b149c0f966b3dd66e8b54e1b5bccf9da5cca7abed91",