diff --git a/Makefile b/Makefile index 27db3664..f6b156e5 100644 --- a/Makefile +++ b/Makefile @@ -149,8 +149,8 @@ gdb_firmware: $(FIRMWARE_BUILD_DIR)/firmware.elf ## start remote gdb session to ## misc commands: vendorheader: ## construct default vendor header - ./tools/build_vendorheader 'e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351:d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869:772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef' 1 0.0 SatoshiLabs assets/satoshilabs_120.toif embed/firmware/vendorheader.bin - ./tools/binctl embed/firmware/vendorheader.bin -s 1 4444444444444444444444444444444444444444444444444444444444444444 + ./tools/build_vendorheader 'e28a8970753332bd72fef413e6b0b2ef1b4aadda7aa2c141f233712a6876b351:d4eec1869fb1b8a4e817516ad5a931557cb56805c3eb16e8f3a803d647df7869:772c8a442b7db06e166cfbc1ccbcbcde6f3eba76a4e98ef3ffc519502237d6ef' 2 0.0 DEVEL assets/vendor_devel.toif embed/firmware/vendorheader.bin + ./tools/binctl embed/firmware/vendorheader.bin -s 1:2 4444444444444444444444444444444444444444444444444444444444444444:4545454545454545454545454545454545454545454545454545454545454545 binctl: ## print info about binary files ./tools/binctl $(BOOTLOADER_BUILD_DIR)/bootloader.bin diff --git a/SConscript.bootloader b/SConscript.bootloader index 42e2137f..5674a2a4 100644 --- a/SConscript.bootloader +++ b/SConscript.bootloader @@ -169,5 +169,5 @@ program_bin = env.Command( source=program_elf, action=[ '$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET', - '$BINCTL $TARGET -s 1 4141414141414141414141414141414141414141414141414141414141414141', + '$BINCTL $TARGET -s 1:2 4141414141414141414141414141414141414141414141414141414141414141:4242424242424242424242424242424242424242424242424242424242424242', ], ) diff --git a/SConscript.firmware b/SConscript.firmware index 944fdb9d..3b0eed04 100644 --- a/SConscript.firmware +++ b/SConscript.firmware @@ -434,7 +434,7 @@ program_bin = env.Command( source=program_elf, action=[ '$OBJCOPY -O binary -j .header -j .flash -j .data $SOURCE $TARGET', - '$BINCTL $TARGET -s 1 4747474747474747474747474747474747474747474747474747474747474747', + '$BINCTL $TARGET -s 1:2 4747474747474747474747474747474747474747474747474747474747474747:4848484848484848484848484848484848484848484848484848484848484848', ], ) program0_bin = env.Command( diff --git a/assets/satoshilabs_120.toif b/assets/satoshilabs_120.toif deleted file mode 100644 index e7711ba0..00000000 Binary files a/assets/satoshilabs_120.toif and /dev/null differ diff --git a/assets/vendor_devel.png b/assets/vendor_devel.png new file mode 100644 index 00000000..9014bddd Binary files /dev/null and b/assets/vendor_devel.png differ diff --git a/assets/vendor_devel.toif b/assets/vendor_devel.toif new file mode 100644 index 00000000..e4867104 Binary files /dev/null and b/assets/vendor_devel.toif differ diff --git a/embed/boardloader/main.c b/embed/boardloader/main.c index 64746133..a0bc8626 100644 --- a/embed/boardloader/main.c +++ b/embed/boardloader/main.c @@ -104,7 +104,7 @@ bool copy_sdcard(void) return true; } -const uint8_t BOARDLOADER_KEY_M = 1; +const uint8_t BOARDLOADER_KEY_M = 2; const uint8_t BOARDLOADER_KEY_N = 3; static const uint8_t * const BOARDLOADER_KEYS[] = { (const uint8_t *)"\xdb\x99\x5f\xe2\x51\x69\xd1\x41\xca\xb9\xbb\xba\x92\xba\xa0\x1f\x9f\x2e\x1e\xce\x7d\xf4\xcb\x2a\xc0\x51\x90\xf3\x7f\xcc\x1f\x9d", diff --git a/embed/bootloader/main.c b/embed/bootloader/main.c index 451c7770..05f90ab5 100644 --- a/embed/bootloader/main.c +++ b/embed/bootloader/main.c @@ -47,7 +47,7 @@ void display_vendor(const uint8_t *vimg, const char *vstr, uint32_t vstr_len, ui display_refresh(); } -const uint8_t BOOTLOADER_KEY_M = 1; +const uint8_t BOOTLOADER_KEY_M = 2; const uint8_t BOOTLOADER_KEY_N = 3; static const uint8_t * const BOOTLOADER_KEYS[] = { (const uint8_t *)"\xd7\x59\x79\x3b\xbc\x13\xa2\x81\x9a\x82\x7c\x76\xad\xb6\xfb\xa8\xa4\x9a\xee\x00\x7f\x49\xf2\xd0\x99\x2d\x99\xb8\x25\xad\x2c\x48", diff --git a/tools/binctl b/tools/binctl index bb3b8fb9..e6571d9c 100755 --- a/tools/binctl +++ b/tools/binctl @@ -8,16 +8,36 @@ import binascii import pyblake2 import ed25519raw +import ed25519cosi def sign_data(seckeys, data): + digest = pyblake2.blake2s(data).digest() if len(seckeys) == 1: sk = seckeys[0] pk = ed25519raw.publickey(sk) - digest = pyblake2.blake2s(data).digest() return ed25519raw.signature(digest, sk, pk) else: - raise NotImplementedError + pubkeys = [ed25519raw.publickey(sk) for sk in seckeys] + ctr = 0 + nonces = [] + commits = [] + for sk in seckeys: + r, R = ed25519cosi.get_nonce(sk, digest, ctr) + nonces.append(r) + commits.append(R) + global_pk = ed25519cosi.combine_keys(pubkeys) + global_R = ed25519cosi.combine_keys(commits) + sigs = [] + for sk, r, R in zip(seckeys, nonces, commits): + h = ed25519raw.H(sk) + b = ed25519raw.b + a = 2**(b - 2) + sum(2**i * ed25519raw.bit(h, i) for i in range(3, b - 2)) + S = (r + ed25519raw.Hint(global_R + global_pk + digest) * a) % ed25519raw.l + sigs.append(ed25519raw.encodeint(S)) + sig = ed25519cosi.combine_sig(global_R, sigs) + ed25519raw.checkvalid(sig, digest, global_pk) + return sig def format_sigmask(sigmask): @@ -186,6 +206,14 @@ class VendorHeader(object): return header def sign(self, sigmask, seckeys): + # check whether provided arguments match vsig_m/vsig_n + if len(seckeys) != self.vsig_m: + raise Exception('invalid number of signatures (vsig_m expected %d, got %d)' % (self.vsig_m, len(seckeys))) + if sigmask >= (1 << self.vsig_n): + raise Exception('signature index is higher than vsig_n (%d)' % self.vsig_n) + if bin(sigmask).count('1') != self.vsig_m: + raise Exception('invalid number of indexes (vsig_m expected %d, got %d)' % (self.vsig_m, bin(sigmask).count('1'))) + # sign header = self.serialize_header(sig=False) self.sigmask = sigmask self.sig = sign_data(seckeys, header) @@ -224,7 +252,7 @@ def main(): sigmask = 0 if ':' in sys.argv[3]: for idx in sys.argv[3].split(':'): - sigmask = 1 << (int(idx) - 1) + sigmask |= 1 << (int(idx) - 1) else: sigmask = 1 << (int(sys.argv[3]) - 1) if ':' in sys.argv[4]: diff --git a/tools/ed25519cosi.py b/tools/ed25519cosi.py index a056c483..9b4317b2 100644 --- a/tools/ed25519cosi.py +++ b/tools/ed25519cosi.py @@ -220,17 +220,17 @@ def test(data): sks.append(seckey) pks.append(pubkey) ctr = 0 - (r, R) = get_nonce(seckey, digest, ctr) + r, R = get_nonce(seckey, digest, ctr) print('Local nonce: %s' % hex(ed25519raw.encodeint(r))) print('Local commit: %s' % hex(R)) nonces.append(r) commits.append(R) - globalPk = combine_keys([pks[i] for i in keyset]) - globalR = combine_keys([commits[i] for i in keyset]) + global_pk = combine_keys([pks[i] for i in keyset]) + global_R = combine_keys([commits[i] for i in keyset]) print('-----------------') - print('Global pubkey: %s' % hex(globalPk)) - print('Global commit: %s' % hex(globalR)) + print('Global pubkey: %s' % hex(global_pk)) + print('Global commit: %s' % hex(global_R)) print('-----------------') for i in range(0, N): @@ -240,17 +240,15 @@ def test(data): R = commits[i] h = ed25519raw.H(seckey) b = ed25519raw.b - a = 2**(b - 2) + sum(2**i * ed25519raw.bit(h, i) - for i in range(3, b - 2)) - S = (r + ed25519raw.Hint(globalR + globalPk + digest) * a) % ed25519raw.l + a = 2**(b - 2) + sum(2**i * ed25519raw.bit(h, i) for i in range(3, b - 2)) + S = (r + ed25519raw.Hint(global_R + global_pk + digest) * a) % ed25519raw.l print('Local sig %d: %s' % (i + 1, hex(ed25519raw.encodeint(S)))) - commits.append(R) sigs.append(ed25519raw.encodeint(S)) print('-----------------') - sig = combine_sig(globalR, [sigs[i] for i in keyset]) + sig = combine_sig(global_R, [sigs[i] for i in keyset]) print('Global sig: %s' % hex(sig)) - ed25519raw.checkvalid(sig, digest, globalPk) + ed25519raw.checkvalid(sig, digest, global_pk) print('Valid Signature!') diff --git a/tools/ed25519raw.py b/tools/ed25519raw.py index 2fd060a9..24c7d687 100644 --- a/tools/ed25519raw.py +++ b/tools/ed25519raw.py @@ -14,7 +14,7 @@ def H(m): def expmod(b, e, m): if e < 0: - raise Exception("negative exponent") + raise Exception('negative exponent') if e == 0: return 1 t = expmod(b, e >> 1, m)**2 % m @@ -120,18 +120,18 @@ def decodepoint(s): x = q - x P = [x, y] if not isoncurve(P): - raise Exception("decoding point that is not on curve") + raise Exception('decoding point that is not on curve') return P def checkvalid(s, m, pk): if len(s) != b >> 2: - raise Exception("signature length is wrong") + raise Exception('signature length is wrong') if len(pk) != b >> 3: - raise Exception("public-key length is wrong") + raise Exception('public-key length is wrong') R = decodepoint(s[0:b >> 3]) A = decodepoint(pk) S = decodeint(s[b >> 3:b >> 2]) h = Hint(encodepoint(R) + pk + m) if scalarmult(B, S) != edwards(R, scalarmult(A, h)): - raise Exception("signature does not pass verification") + raise Exception('signature does not pass verification')