David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 1 | # ECDSA signature format |
| 2 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 3 | When the ECDSA SECP256R1 (EC256) signature support was added to MCUboot, a |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 4 | shortcut was taken, and these signatures were padded to make them |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 5 | always a fixed length. Unfortunately, this padding was done in a way |
| 6 | that is not easily reversible. Some crypto libraries (specifically, Mbed |
| 7 | TLS) are fairly strict about the formatting of the ECDSA signature. |
| 8 | This currently means that the ECDSA SECP224R1 (EC) signature |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 9 | checking code will fail to boot about 1 out of every 256 images, |
| 10 | because the signature itself will end in a 0x00 byte, and the code |
| 11 | will remove too much data, invalidating the signature. |
| 12 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 13 | There are two ways to fix this: |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 14 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 15 | - 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 Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 21 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 22 | - 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 Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 27 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 28 | 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 Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 31 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 32 | This document proposes a multi-stage approach to give a transition |
| 33 | period: |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 34 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 35 | 1. Add a `--no-pad-sig` argument to the sign command in |
| 36 | `imgtool.py`. |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 37 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 38 | 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 Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 42 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 43 | 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 Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 47 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 48 | 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 | |
| 53 | After one or more MCUboot release cycles and announcements in the |
David Brown | bf3a3a9 | 2019-12-17 16:08:33 -0700 | [diff] [blame] | 54 | relevant channels, the arguments to `imgtool.py` will change: |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 55 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 56 | - `--no-pad-sig` will still be accepted but will have no effect. |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 57 | |
David Brown | 3639aca | 2019-12-17 16:10:49 -0700 | [diff] [blame] | 58 | - `--pad-sig` will now bring back the old padding behavior. |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 59 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 60 | This will require an update to any scripts that will rely on the default |
| 61 | behavior, but will not specify a specific version of imgtool. |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 62 | |
| 63 | The signature generation in the simulator can be changed at the same |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 64 | time the boot code begins to accept unpadded signatures. The simulator is |
Francesco Servidio | 4ff0c18 | 2021-10-20 15:27:16 +0200 | [diff] [blame] | 65 | always run out of the same tree as the MCUboot code, so there should |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 66 | not be any compatibility issues. |
| 67 | |
| 68 | ## Background |
| 69 | |
| 70 | ECDSA signatures are encoded as ASN.1, notably with the signature |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 71 | itself encoded as follows: |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 72 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 73 | ``` |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 74 | ECDSA-Sig-Value ::= SEQUENCE { |
| 75 | r INTEGER, |
| 76 | s INTEGER |
| 77 | } |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 78 | ``` |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 79 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 80 | Both `r` and `s` are 256-bit numbers. Because these are |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 81 | unsigned numbers that are being encoded in ASN.1 as signed values, if |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 82 | the high bit of the number is set, the DER-encoded representation will |
| 83 | require 33 bytes instead of 32. This means that the length of the |
| 84 | signature will vary by a couple of bytes, depending on whether one or |
| 85 | both of these numbers have the high bit set. |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 86 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 87 | Originally, MCUboot added padding to the entire signature and just |
| 88 | removed any trailing 0 bytes from the data block. This turned out to be fine 255 out of 256 |
| 89 | times, each time the last byte of the signature was non-zero, but if the |
| 90 | signature ended in a zero, MCUboot would remove too many bytes and render the |
| 91 | signature invalid. |
David Brown | 8f057ca | 2019-12-12 16:19:55 -0700 | [diff] [blame] | 92 | |
Francesco Domenico Servidio | 5851150 | 2022-01-11 17:07:13 +0100 | [diff] [blame^] | 93 | The correct approach here is to accept that ECDSA signatures are of |
| 94 | variable length, and to make sure that we can handle them as such. |