Skip to content

Commit 58cc3c4

Browse files
committed
chore(core): use testing tropic attestation key and certificate
1 parent b6713fc commit 58cc3c4

7 files changed

Lines changed: 81 additions & 147 deletions

File tree

core/tools/generate_tropic_model_config.py

Lines changed: 10 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,16 @@
11
#!/usr/bin/env python3
22

3-
import hashlib
43
import os
54
from pathlib import Path
65

76
import click
87
import yaml
9-
from cryptography import x509
10-
from cryptography.hazmat.primitives import serialization
118

129
HERE = Path(__file__).parent
1310
ROOT = HERE.parent.parent.resolve()
1411
CONFIG_DIR = ROOT / "tests" / "tropic_model"
1512
DEST_PATH = CONFIG_DIR / "config.yml"
16-
17-
# private key used by the Tropic model to sign
18-
TROPIC_KEY = CONFIG_DIR / "tropic_key.pem"
19-
20-
# certificate of the Tropic model - signed by the root authority
21-
TROPIC_CERT = CONFIG_DIR / "tropic_cert.pem"
22-
23-
# certificate of the root authority
24-
ROOT_CERT = CONFIG_DIR / "root_cert.pem"
13+
BASE_CONFIG = CONFIG_DIR / "base_config.yml"
2514

2615
VENDOR_CONFIG_DIR = ROOT / "vendor" / "ts-tvl" / "model_configs" / "example_config"
2716
EXTRA_FILES = [
@@ -34,83 +23,22 @@
3423
@click.command()
3524
@click.option("--check", is_flag=True)
3625
def generate_config(check: bool) -> None:
37-
tropic_key = serialization.load_pem_private_key(
38-
TROPIC_KEY.read_bytes(), password=None
39-
)
40-
41-
tropic_a = tropic_key.public_key().public_bytes(
42-
encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw
43-
)
44-
45-
tropic_private_key_bytes = tropic_key.private_bytes(
46-
encoding=serialization.Encoding.Raw,
47-
format=serialization.PrivateFormat.Raw,
48-
encryption_algorithm=serialization.NoEncryption(),
49-
)
50-
51-
# perform clamping
52-
# https://www.jcraige.com/an-explainer-on-ed25519-clamping
53-
h = hashlib.sha512(tropic_private_key_bytes).digest()
54-
tropic_s = bytearray(h[:32])
55-
tropic_s[0] &= 248
56-
tropic_s[31] &= 63
57-
tropic_s[31] |= 64
58-
tropic_s = bytes(tropic_s)
59-
60-
tropic_prefix = hashlib.sha512(tropic_s).digest()[:32]
61-
62-
tropic_cert = x509.load_pem_x509_certificate(TROPIC_CERT.read_bytes())
63-
tropic_cert_der_bytes = tropic_cert.public_bytes(serialization.Encoding.DER)
64-
65-
root_cert = x509.load_pem_x509_certificate(ROOT_CERT.read_bytes())
66-
root_cert_der_bytes = root_cert.public_bytes(serialization.Encoding.DER)
67-
68-
# certificate chain with the length prefix
69-
all_cert_bytes = (
70-
(len(tropic_cert_der_bytes) + len(root_cert_der_bytes)).to_bytes(2, "big")
71-
+ tropic_cert_der_bytes
72-
+ root_cert_der_bytes
73-
)
74-
75-
SLOT_LEN = 444
76-
77-
# make sure they fit in 3 slots, which is what we have available
78-
assert len(all_cert_bytes) < SLOT_LEN * 3
79-
80-
# split the data in 3 slots
81-
slot_1_bytes = all_cert_bytes[:SLOT_LEN]
82-
slot_2_bytes = all_cert_bytes[SLOT_LEN : SLOT_LEN * 2]
83-
slot_3_bytes = all_cert_bytes[SLOT_LEN * 2 : SLOT_LEN * 3]
84-
85-
# save the data starting at slot 3
86-
# see https://github.com/trezor/trezor-firmware/blob/main/core/embed/sec/tropic/inc/sec/tropic.h#L31
87-
TROPIC_DEVICE_CERT_FIRST_SLOT = 3
88-
user_data = {}
89-
for i, data in enumerate([slot_1_bytes, slot_2_bytes, slot_3_bytes]):
90-
if len(data) != 0:
91-
if len(data) < SLOT_LEN: # pad last slot
92-
data += b"\x00" * (SLOT_LEN - len(data))
93-
user_data[TROPIC_DEVICE_CERT_FIRST_SLOT + i] = {"value": data}
94-
9526
config_dict = {
9627
"s_t_priv": "tropic01_ese_private_key_1.pem",
9728
"s_t_pub": "tropic01_ese_public_key_1.pem",
9829
"x509_certificate": "tropic01_ese_certificate_1.pem",
9930
"debug_random_value": b"\x00\xc0\xff\xee",
100-
"r_user_data": user_data, # certificate chain
101-
"r_ecc_keys": { # signing key at index 0
102-
0: {
103-
"a": tropic_a,
104-
"s": tropic_s,
105-
"prefix": tropic_prefix,
106-
"origin": 2, # imported key
107-
}
108-
},
10931
"riscv_fw_version": "1.0.0", # Version of the RISCV Firmware (also know as Application FW) used in TS7 devices
11032
"spect_fw_version": "1.0.0",
11133
}
11234

113-
config = yaml.dump(config_dict)
35+
base_config = yaml.safe_load(BASE_CONFIG.read_text())
36+
overlap = config_dict.keys() & base_config.keys()
37+
if overlap:
38+
raise click.ClickException(
39+
f"Key collision between base_config and generated config: {overlap}"
40+
)
41+
config = yaml.dump({**base_config, **config_dict})
11442

11543
if check:
11644
if not DEST_PATH.exists():
@@ -128,24 +56,11 @@ def generate_config(check: bool) -> None:
12856
print(f"{extra_file_dest} is out of date")
12957
raise click.ClickException("Extra config file is out of date")
13058
else:
131-
tropic_key_stat = TROPIC_KEY.stat()
132-
tropic_cert_stat = TROPIC_CERT.stat()
133-
root_cert_stat = ROOT_CERT.stat()
13459
DEST_PATH.write_text(config)
60+
base_config_stat = BASE_CONFIG.stat()
13561
os.utime(
13662
DEST_PATH,
137-
ns=(
138-
max(
139-
tropic_key_stat.st_atime_ns,
140-
tropic_cert_stat.st_atime_ns,
141-
root_cert_stat.st_atime_ns,
142-
),
143-
max(
144-
tropic_key_stat.st_mtime_ns,
145-
tropic_cert_stat.st_mtime_ns,
146-
root_cert_stat.st_mtime_ns,
147-
),
148-
),
63+
ns=(base_config_stat.st_atime_ns, base_config_stat.st_mtime_ns),
14964
)
15065

15166
for extra_file in EXTRA_FILES:

tests/tropic_model/README.md

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,7 @@ The Tropic model requires:
44
* (I) a keypair and a certificate it will use to communicate to the host (`tropic01_ese_*`) - these are simply copied from [example_config](https://github.com/tropicsquare/ts-tvl/tree/master/model_configs/example_config)
55
* (II) a certificate chain and a keypair that will be used during Trezor's authenticity check
66

7-
The root key, certificate chain and keypair are generated using these commands:
8-
9-
```
10-
# generate root keypair
11-
openssl genpkey -algorithm Ed25519 -out root_key.pem
12-
openssl pkey -in root_key.pem -pubout -out root_pubkey.pem
13-
14-
# see the root pubkey - to be used in test
15-
openssl pkey -in root_pubkey.pem -pubin -outform DER | tail -c 32 | xxd -p -c 256
16-
17-
# generate root certificate (signed by the root key)
18-
openssl req -new -x509 -key root_key.pem -out root_cert.pem -days 36500
19-
20-
# generate device key pair
21-
openssl genpkey -algorithm Ed25519 -out tropic_key.pem
22-
openssl pkey -in tropic_key.pem -pubout -out tropic_pubkey.pem
23-
24-
# generate certificate signing request
25-
openssl req -new -key tropic_key.pem -out tropic.csr -subj "/CN=T3W1"
26-
27-
# use the signing request to generate a device certificate signed by the authority
28-
openssl x509 -req -in tropic.csr -CA root_cert.pem -CAkey root_key.pem -CAcreateserial -out tropic_cert.pem -days 36500
29-
```
7+
The root key, certificate chain, and keypair were generated by provisioning a prodtest emulator using testing keys and copying the Tropic model's saved config.
308

319
`ts-tvl` then uses a YAML config file to load the above keys and certificates.
3210
* (I) go into: `s_t_priv`, `s_t_pub` and `x509_certificate` as required by [`ts-tvl`](https://github.com/tropicsquare/ts-tvl/blob/master/model_configs/example_config/example_config.yml)

tests/tropic_model/base_config.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
r_ecc_keys:
2+
0:
3+
a: !!binary |
4+
9oDGtfPu3mRwCJaejPsZ//YkEh8NfwIrKr7N+WxNoEE=
5+
origin: 1
6+
prefix: !!binary |
7+
CnPByiITyYOnUGxdTN8cqFJPe0GvBmHAKQ3KdYcxeIw=
8+
s: !!binary |
9+
/ax6IByM43A2QFc8ZhtxuCTUKnI4aN92uMu/jyTzdgg=
10+
r_user_data:
11+
3:
12+
free: false
13+
value: !!binary |
14+
A1gwggGPMIIBQaADAgECAghp+14Y3dtpRTAFBgMrZXAwTzELMAkGA1UEBhMCQ1oxHjAcBgNVBAoM
15+
FVRyZXpvciBDb21wYW55IHMuci5vLjEgMB4GA1UEAwwXVHJlem9yIE1hbnVmYWN0dXJpbmcgQ0Ew
16+
IBcNMjYwNTA2MTUyODI1WhgPMjA1NjA1MDYxNTI4MjVaMEcxGzAZBgNVBAMMElQzVzEgVHJlem9y
17+
IFNhZmUgNzEXMBUGA1UEBRMOMTIzNDU2Nzg5MDEyMzQxDzANBgNVBC4TBlRyb3BpYzAqMAUGAytl
18+
cAMhAPaAxrXz7t5kcAiWnoz7Gf/2JBIfDX8CKyq+zflsTaBBo0EwPzAOBgNVHQ8BAf8EBAMCAIAw
19+
DAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBQUqVoIj2To/jFMcZRn6iOSWgNFLzAFBgMrZXADQQBS
20+
7OZFc++tY4vDy3H/9P/P96iu6Nj/Acc73sQn6I8U4QwuWo8BG/CPfOLC9Q0uyft0c/8D6bQZtJEo
21+
pnz74u0PMIIBwTCCAXOgAwIBAgIIafteGJa66SowBQYDK2VwMFQxCzAJBgNV
22+
4:
23+
free: false
24+
value: !!binary |
25+
BAYTAkNaMR4wHAYDVQQKDBVUcmV6b3IgQ29tcGFueSBzLnIuby4xJTAjBgNVBAMMHFRyZXpvciBN
26+
YW51ZmFjdHVyaW5nIFJvb3QgQ0EwIBcNMjYwNTA2MTUyODI1WhgPMjA1NjA1MDYxNTI4MjVaME8x
27+
CzAJBgNVBAYTAkNaMR4wHAYDVQQKDBVUcmV6b3IgQ29tcGFueSBzLnIuby4xIDAeBgNVBAMMF1Ry
28+
ZXpvciBNYW51ZmFjdHVyaW5nIENBMCowBQYDK2VwAyEAWoUPt8reO7zfK2QepOuUtKibeX8UN+bL
29+
tw82YFfo23mjZjBkMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW
30+
BBQUqVoIj2To/jFMcZRn6iOSWgNFLzAfBgNVHSMEGDAWgBRUnfqULSF0erM7XBrqPsO7p7D5IjAF
31+
BgMrZXADQQCAIPusstEozIfzhnlCV/wuwHwJ/4s/Rv/0ElSpa04rvf3XO0DwsD3O2WCjhLdOrcHK
32+
65q6wWdPfDvsoKNcFMsLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
33+
5:
34+
free: false
35+
value: !!binary |
36+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
37+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
38+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
39+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
40+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
41+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
42+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
43+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

tests/tropic_model/config.yml

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,40 @@ debug_random_value: !!binary |
33
r_ecc_keys:
44
0:
55
a: !!binary |
6-
/znnOD2vDW1Znx2ymKbAur+8R+x3vj8uL/e5VUqnH38=
7-
origin: 2
6+
9oDGtfPu3mRwCJaejPsZ//YkEh8NfwIrKr7N+WxNoEE=
7+
origin: 1
88
prefix: !!binary |
9-
a2BLVJLG4DGBZBPl5ipLvlLOj8zovqvCgejgJtWKGw8=
9+
CnPByiITyYOnUGxdTN8cqFJPe0GvBmHAKQ3KdYcxeIw=
1010
s: !!binary |
11-
2JitRIPXXNvDPBcYOyKAWEEGn1k97MfNKx+z4/kNQEk=
11+
/ax6IByM43A2QFc8ZhtxuCTUKnI4aN92uMu/jyTzdgg=
1212
r_user_data:
1313
3:
14+
free: false
1415
value: !!binary |
15-
AhwwgeUwgZgCFAYbogFv5WvsoMxMwanH3uF4NejHMAUGAytlcDANMQswCQYDVQQGEwJDWjAgFw0y
16-
NTEwMDExNTU5MjBaGA8yMTI1MDkwNzE1NTkyMFowHDELMAkGA1UEBhMCQ1oxDTALBgNVBAMMBFQz
17-
VzEwKjAFBgMrZXADIQD/Oec4Pa8NbVmfHbKYpsC6v7xH7He+Py4v97lVSqcffzAFBgMrZXADQQC/
18-
Sg/OI9Oa4IcjAGkqswmsZY782uzrHqqOdb8C9QHMQEJFKggXH39rxtXRU2kmj+ryTkYNA4vUhIKm
19-
+zvKUGkEMIIBMDCB46ADAgECAhRMR5WXXWH8xNquZfZtCCchQO757TAFBgMrZXAwDTELMAkGA1UE
20-
BhMCQ1owIBcNMjUxMDAxMTUzMzA2WhgPMjEyNTA5MDcxNTMzMDZaMA0xCzAJBgNVBAYTAkNaMCow
21-
BQYDK2VwAyEAGrHF8S9FcODeXBao2f7qOB9TyNgT/usOsvt/OT8ra1+jUzBRMB0GA1UdDgQWBBSY
22-
DtrUTbT8JI4eHR/OIHl787VZ1zAfBgNVHSMEGDAWgBSYDtrUTbT8JI4eHR/O
16+
A1gwggGPMIIBQaADAgECAghp+14Y3dtpRTAFBgMrZXAwTzELMAkGA1UEBhMCQ1oxHjAcBgNVBAoM
17+
FVRyZXpvciBDb21wYW55IHMuci5vLjEgMB4GA1UEAwwXVHJlem9yIE1hbnVmYWN0dXJpbmcgQ0Ew
18+
IBcNMjYwNTA2MTUyODI1WhgPMjA1NjA1MDYxNTI4MjVaMEcxGzAZBgNVBAMMElQzVzEgVHJlem9y
19+
IFNhZmUgNzEXMBUGA1UEBRMOMTIzNDU2Nzg5MDEyMzQxDzANBgNVBC4TBlRyb3BpYzAqMAUGAytl
20+
cAMhAPaAxrXz7t5kcAiWnoz7Gf/2JBIfDX8CKyq+zflsTaBBo0EwPzAOBgNVHQ8BAf8EBAMCAIAw
21+
DAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBQUqVoIj2To/jFMcZRn6iOSWgNFLzAFBgMrZXADQQBS
22+
7OZFc++tY4vDy3H/9P/P96iu6Nj/Acc73sQn6I8U4QwuWo8BG/CPfOLC9Q0uyft0c/8D6bQZtJEo
23+
pnz74u0PMIIBwTCCAXOgAwIBAgIIafteGJa66SowBQYDK2VwMFQxCzAJBgNV
2324
4:
25+
free: false
2426
value: !!binary |
25-
IHl787VZ1zAPBgNVHRMBAf8EBTADAQH/MAUGAytlcANBAD2wmHseXqtUk2QJuwRUpdoestUlhKGR
26-
xrD1yhY8fxCvCzU+b4qZffXCyyk4qgDiTgdNHMz04zL6nKcNhT+geAQAAAAAAAAAAAAAAAAAAAAA
27+
BAYTAkNaMR4wHAYDVQQKDBVUcmV6b3IgQ29tcGFueSBzLnIuby4xJTAjBgNVBAMMHFRyZXpvciBN
28+
YW51ZmFjdHVyaW5nIFJvb3QgQ0EwIBcNMjYwNTA2MTUyODI1WhgPMjA1NjA1MDYxNTI4MjVaME8x
29+
CzAJBgNVBAYTAkNaMR4wHAYDVQQKDBVUcmV6b3IgQ29tcGFueSBzLnIuby4xIDAeBgNVBAMMF1Ry
30+
ZXpvciBNYW51ZmFjdHVyaW5nIENBMCowBQYDK2VwAyEAWoUPt8reO7zfK2QepOuUtKibeX8UN+bL
31+
tw82YFfo23mjZjBkMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEAMB0GA1UdDgQW
32+
BBQUqVoIj2To/jFMcZRn6iOSWgNFLzAfBgNVHSMEGDAWgBRUnfqULSF0erM7XBrqPsO7p7D5IjAF
33+
BgMrZXADQQCAIPusstEozIfzhnlCV/wuwHwJ/4s/Rv/0ElSpa04rvf3XO0DwsD3O2WCjhLdOrcHK
34+
65q6wWdPfDvsoKNcFMsLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
35+
5:
36+
free: false
37+
value: !!binary |
38+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
39+
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2740
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2841
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2942
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

tests/tropic_model/root_cert.pem

Lines changed: 0 additions & 9 deletions
This file was deleted.

tests/tropic_model/root_key.pem

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/tropic_model/tropic_key.pem

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)