1# ECDSA signature format
2
3When the ECDSA SECP256R1 (EC256) signature support was added to MCUboot, a
4shortcut was taken, and these signatures were padded to make them
5always 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.
8
9There are two ways to fix this:
10
11  - Use a reversible padding scheme. This solution requires
12    at least one pad byte to always be added (to set the length). This
13    padding would be somewhat incompatible across versions (older
14    EC256 would work, while newer MCUboot code would reject old
15    signatures. The EC code would work reliably only in the new
16    combination).
17
18  - Remove the padding entirely. Depending on the tool used, this solution
19    requires some rethinking of how TLV generation is implemented so
20    that the length does not need to be known until the signature is
21    generated. These tools are usually written in higher-level
22    languages, so this change should not be difficult.
23
24    However, this will also break compatibility with older versions,
25    because images generated with newer tools will not
26    work with older versions of MCUboot.
27
28This document proposes a multi-stage approach to give a transition
29period:
30
31  1. Add a `--no-pad-sig` argument to the sign command in
32     `imgtool.py`.
33
34     Without this argument, the images are padded with the
35     existing scheme. With this argument, the ECDSA is encoded
36     without any padding. The `--pad-sig` argument is also
37     accepted, but it is already the default.
38
39  2. MCUboot will be modified to allow unpadded signatures right away.
40     The existing EC256 implementations will still work (with or
41     without padding), and the existing EC implementation will be able
42     to accept padded and unpadded signatures.
43
44  3. An Mbed TLS implementation of EC256 can be added, but it will require
45     the `--no-pad-sig` signature to be able to boot all generated
46     images. Without the argument, 3 out of 4 images generated will have
47     padding and will be considered invalid.
48
49After one or more MCUboot release cycles and announcements in the
50relevant channels, the arguments to `imgtool.py` will change:
51
52  - `--no-pad-sig` will still be accepted but will have no effect.
53
54  - `--pad-sig` will now bring back the old padding behavior.
55
56This will require an update to any scripts that will rely on the default
57behavior, but will not specify a specific version of imgtool.
58
59The signature generation in the simulator can be changed at the same
60time the boot code begins to accept unpadded signatures. The simulator is
61always run out of the same tree as the MCUboot code, so there should
62not be any compatibility issues.
63
64## Background
65
66ECDSA signatures are encoded as ASN.1, notably with the signature
67itself encoded as follows:
68
69```
70    ECDSA-Sig-Value ::= SEQUENCE {
71      r  INTEGER,
72      s  INTEGER
73    }
74```
75
76Both `r` and `s` are 256-bit numbers. Because these are
77unsigned numbers that are being encoded in ASN.1 as signed values, if
78the high bit of the number is set, the DER-encoded representation will
79require 33 bytes instead of 32. This means that the length of the
80signature will vary by a couple of bytes, depending on whether one or
81both of these numbers have the high bit set.
82
83Originally, MCUboot added padding to the entire signature and just
84removed any trailing 0 bytes from the data block. This turned out to be fine 255 out of 256
85times, each time the last byte of the signature was non-zero, but if the
86signature ended in a zero, MCUboot would remove too many bytes and render the
87signature invalid.
88
89The correct approach here is to accept that ECDSA signatures are of
90variable length, and to make sure that we can handle them as such.
91