blob: 50ca96167e58a55bedc9661fc50517adc5362b05 [file] [log] [blame] [view]
David Brown8f057ca2019-12-12 16:19:55 -07001# ECDSA signature format
2
Francesco Domenico Servidio58511502022-01-11 17:07:13 +01003When the ECDSA SECP256R1 (EC256) signature support was added to MCUboot, a
David Brown8f057ca2019-12-12 16:19:55 -07004shortcut was taken, and these signatures were padded to make them
Francesco Domenico Servidio58511502022-01-11 17:07:13 +01005always a fixed length. Unfortunately, this padding was done in a way
6that is not easily reversible. Some crypto libraries (specifically, Mbed
7TLS) are fairly strict about the formatting of the ECDSA signature.
8This currently means that the ECDSA SECP224R1 (EC) signature
David Brown8f057ca2019-12-12 16:19:55 -07009checking code will fail to boot about 1 out of every 256 images,
10because the signature itself will end in a 0x00 byte, and the code
11will remove too much data, invalidating the signature.
12
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010013There are two ways to fix this:
David Brown8f057ca2019-12-12 16:19:55 -070014
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010015 - Use a reversible padding scheme. This solution requires
16 at least one pad byte to always be added (to set the length). This
17 padding would be somewhat incompatible across versions (older
18 EC256 would work, while newer MCUboot code would reject old
19 signatures. The EC code would work reliably only in the new
20 combination).
David Brown8f057ca2019-12-12 16:19:55 -070021
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010022 - Remove the padding entirely. Depending on the tool used, this solution
23 requires some rethinking of how TLV generation is implemented so
24 that the length does not need to be known until the signature is
25 generated. These tools are usually written in higher-level
26 languages, so this change should not be difficult.
David Brown8f057ca2019-12-12 16:19:55 -070027
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010028 However, this will also break compatibility with older versions,
29 because images generated with newer tools will not
30 work with older versions of MCUboot.
David Brown8f057ca2019-12-12 16:19:55 -070031
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010032This document proposes a multi-stage approach to give a transition
33period:
David Brown8f057ca2019-12-12 16:19:55 -070034
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010035 1. Add a `--no-pad-sig` argument to the sign command in
36 `imgtool.py`.
David Brown8f057ca2019-12-12 16:19:55 -070037
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010038 Without this argument, the images are padded with the
39 existing scheme. With this argument, the ECDSA is encoded
40 without any padding. The `--pad-sig` argument is also
41 accepted, but it is already the default.
David Brown8f057ca2019-12-12 16:19:55 -070042
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010043 2. MCUboot will be modified to allow unpadded signatures right away.
44 The existing EC256 implementations will still work (with or
45 without padding), and the existing EC implementation will be able
46 to accept padded and unpadded signatures.
David Brown8f057ca2019-12-12 16:19:55 -070047
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010048 3. An Mbed TLS implementation of EC256 can be added, but it will require
49 the `--no-pad-sig` signature to be able to boot all generated
50 images. Without the argument, 3 out of 4 images generated will have
51 padding and will be considered invalid.
52
53After one or more MCUboot release cycles and announcements in the
David Brownbf3a3a92019-12-17 16:08:33 -070054relevant channels, the arguments to `imgtool.py` will change:
David Brown8f057ca2019-12-12 16:19:55 -070055
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010056 - `--no-pad-sig` will still be accepted but will have no effect.
David Brown8f057ca2019-12-12 16:19:55 -070057
David Brown3639aca2019-12-17 16:10:49 -070058 - `--pad-sig` will now bring back the old padding behavior.
David Brown8f057ca2019-12-12 16:19:55 -070059
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010060This will require an update to any scripts that will rely on the default
61behavior, but will not specify a specific version of imgtool.
David Brown8f057ca2019-12-12 16:19:55 -070062
63The signature generation in the simulator can be changed at the same
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010064time the boot code begins to accept unpadded signatures. The simulator is
Francesco Servidio4ff0c182021-10-20 15:27:16 +020065always run out of the same tree as the MCUboot code, so there should
David Brown8f057ca2019-12-12 16:19:55 -070066not be any compatibility issues.
67
68## Background
69
70ECDSA signatures are encoded as ASN.1, notably with the signature
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010071itself encoded as follows:
David Brown8f057ca2019-12-12 16:19:55 -070072
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010073```
David Brown8f057ca2019-12-12 16:19:55 -070074 ECDSA-Sig-Value ::= SEQUENCE {
75 r INTEGER,
76 s INTEGER
77 }
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010078```
David Brown8f057ca2019-12-12 16:19:55 -070079
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010080Both `r` and `s` are 256-bit numbers. Because these are
David Brown8f057ca2019-12-12 16:19:55 -070081unsigned numbers that are being encoded in ASN.1 as signed values, if
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010082the high bit of the number is set, the DER-encoded representation will
83require 33 bytes instead of 32. This means that the length of the
84signature will vary by a couple of bytes, depending on whether one or
85both of these numbers have the high bit set.
David Brown8f057ca2019-12-12 16:19:55 -070086
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010087Originally, MCUboot added padding to the entire signature and just
88removed any trailing 0 bytes from the data block. This turned out to be fine 255 out of 256
89times, each time the last byte of the signature was non-zero, but if the
90signature ended in a zero, MCUboot would remove too many bytes and render the
91signature invalid.
David Brown8f057ca2019-12-12 16:19:55 -070092
Francesco Domenico Servidio58511502022-01-11 17:07:13 +010093The correct approach here is to accept that ECDSA signatures are of
94variable length, and to make sure that we can handle them as such.