Skip to content

Commit d71b79a

Browse files
committed
Add implementation notes
1 parent f26292c commit d71b79a

File tree

2 files changed

+162
-0
lines changed

2 files changed

+162
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ yourself.
114114

115115
## Maintainance
116116

117+
See [Implementation notes](doc/implementation-notes.md) for more
118+
in-depth notes on the program.
119+
117120
- `tkey-verification` contains an in-code database mapping known
118121
hardware revisions (first half of the Unique Device Identifier) to
119122
their expected firmware size and hash. This needs to be maintained

doc/implementation-notes.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Implementation notes
2+
3+
## Assets
4+
5+
There are some compiled-in assets:
6+
7+
- application binaries: The device apps used for both vendor signing
8+
and device signatures.
9+
- vendor public keys: The public key extracted from a vendor TKey
10+
during vendor signing and used for verification. Might be several,
11+
including historical keys no longer being used for vendor signing.
12+
- known firmwares: Expected firmwares for all provisioned TKeys.
13+
14+
Commands are responsible for initializing their own assets. For
15+
instance, `verify` needs all three, but `remote-sign` and
16+
`serve-signer` need only two, and `show-pubkey` needs none.
17+
18+
### Application binaries
19+
20+
Initialized by calling `appbins.go:NewAppBins()`.
21+
22+
Actual binaries are located in the `bins` directory stored like this:
23+
24+
- `name-tag`, like `signer-v1.0.1.bin`: the actual device app binary.
25+
- `name-tag.sha512`, like `signer-v1.0.1.bin.sha512`: the SHA-512
26+
digest of the above file to help ensure we don't make mistakes.
27+
28+
### Vendor public keys
29+
30+
Initialized by calling `vendorpubkeys.go:NewVendorKeys()`. Needs to
31+
know the appbins (see above) and the current hash digest of the app to
32+
run as the device app to perform signing.
33+
34+
The actual vendor keys are defined in the text file
35+
`vendor-signing-pubkeys.txt`, which is embedded in the binary at build
36+
time and parsed at start. It contains:
37+
38+
- the public key
39+
- the name and tag of the device app to use for vendor signing.
40+
- the hash digest of that device app.
41+
42+
Example content:
43+
44+
```
45+
50d9a125f51d85ffa1fb12011bdae05d39e03cda2a35d0daf3077072daabbb10 verisigner-v0.0.3 f8ecdcda53a296636a0297c250b27fb649860645626cc8ad935eabb4c43ea3e1841c40300544fade4189aa4143c1ca8fe82361e3d874b42b0e2404793a170142
46+
```
47+
48+
In use, it's initialized like this:
49+
50+
```go
51+
appBins, err := NewAppBins(latestAppHash)
52+
vendorKeys, err := NewVendorKeys(appBins, currentVendorHash)
53+
```
54+
55+
The current public key can be accessed with:
56+
57+
```go
58+
vendorKeys.Current()
59+
``
60+
61+
### Known firmwares
62+
63+
Initialized by calling `firmwares.go:NewFirmwares()`.
64+
65+
It's used by probing a TKey for UDI, then looking up a firmware for a
66+
specific UDI with `GetFirmware(udi)`. Now you know the size and the
67+
SHA-512 digest of the expected firmware and call the device app to ask
68+
it for a digest.
69+
70+
## `serve-signer` command
71+
72+
Defined in `servesigner.go`.
73+
74+
- Initialises its assets using `NewAppBins()` and `NewVendorKeys()`.
75+
76+
- Connects to a vendor TKey, loads the current vendor signing device
77+
app.
78+
79+
- Sets up a HTTPS server exposing a simple API through "net/rpc". The
80+
RPC commands are in `api.go`.
81+
82+
- Waits for commands.
83+
84+
- When a `Sign` command appears it requests the device app to sign the
85+
message and returns an OK or error. It writes the signature over the
86+
message and some metadata under the signatures directory. Note that
87+
it doesn't store the message itself. A verifier needs to recreate
88+
the message themselves from their TKey.
89+
90+
- Goes back to wait for more commands.
91+
92+
## `remote-sign` command
93+
94+
Defined in `remotesign.go`.
95+
96+
- Sets up its assets using `NewAppBins()` and `NewFirmwares()`.
97+
98+
- Connects to a TKey during provisioning and loads the current device
99+
app for use during provisioning.
100+
101+
- Extracts the public key.
102+
103+
- Verifies that firmware digest is as expected.
104+
105+
- Verifies that the TKey can sign a random challenge, proving that it
106+
has the corresponding private key.
107+
108+
- Builds a message to be signed.
109+
110+
- Asks the server (same program but started with `serve-signer`) to
111+
sign the message.
112+
113+
## `verify` command
114+
115+
Defined in `verify.go`.
116+
117+
- Initialises its assets by using `NewAppBins()`, `NewVendorKeys()`,
118+
and `NewFirmwares()`.
119+
120+
- Connects to a TKey, request UDI.
121+
122+
- If this is `verify --show-url` we just construct the URL from the
123+
UDI, outputs that and exits.
124+
125+
- Otherwise, we fetch the verification data from something like
126+
`https://tkey.tillitis.se/verify/0133708100000002`.
127+
128+
- Look up the necessary device app to load from our embedded assets
129+
and load it.
130+
131+
- Extract the public key.
132+
133+
- Look up the expected firmware hash digest from the UDI.
134+
135+
- Compare the firmware digest of the TKey compared to the expected.
136+
137+
- Recreate the message seen during provisioning.
138+
139+
- Verify vendor's signature over the message against any of the
140+
vendor's known public keys.
141+
142+
- Sign and verify a random challenge, proving that the TKey knows the
143+
corresponding private key.
144+
145+
## `show-pubkey` command
146+
147+
Defined in `showpubkey.go`.
148+
149+
- Connects to a TKey.
150+
151+
- Reads the device app file, on the path passed to it in `--app`.
152+
153+
- Computes the SHA-512 digest of the file.
154+
155+
- Loads the app device.
156+
157+
- Extracts the public key.
158+
159+
- Prints the public key, the name-tag, and the app digest.

0 commit comments

Comments
 (0)