docs: Write up some docs about ecdsa padding
Start with some documentation on ECDSA signatures, and the problems with
the current padding approach. Present a plan to support correctly
formatted ECDSA signatures, and how to handle the transition both in the
C code, as well as the tooling that signs images.
Signed-off-by: David Brown <david.brown@linaro.org>
diff --git a/docs/ecdsa.md b/docs/ecdsa.md
new file mode 100644
index 0000000..410d519
--- /dev/null
+++ b/docs/ecdsa.md
@@ -0,0 +1,89 @@
+# ECDSA signature format
+
+When ECDSA SECP256R1 (EC256) signature support was added to MCUboot, a
+shortcut was taken, and these signatures were padded to make them
+always a fixed length. Unfortunately, this padding was done in a way
+that is not easily reversible. Some crypto libraries are fairly
+strict about the formatting of the ECDSA signature (specifically, mbed
+TLS). This currently means that the ECDSA SECP224R1 (EC) signature
+checking code will fail to boot about 1 out of every 256 images,
+because the signature itself will end in a 0x00 byte, and the code
+will remove too much data, invalidating the signature.
+
+There are a couple of ways to fix this:
+
+ 1. Use a reversible padding scheme. This will work, but requires
+ at least one pad byte always be added (to set the length). This
+ padding would be somewhat incompatible across versions (older
+ EC256 would work, newer mcuboot code would reject old
+ signatures. EC code would only reliably work in the new
+ combination).
+
+ 2. Remove the padding entirely. Depending on which tool, this will
+ require some rethinking of how TLV generation is implemented so
+ that the length does not need to be known until the signature is
+ generated. These tools are all written in higher-level
+ languages and this change should not be difficult.
+
+ However, this will also break compatibility with older version,
+ significantly in that images generated with newer tools will not
+ work with older versions of MCUboot.
+
+This document proposes a multi-stage approach, to give a transition
+period.
+
+ - First, add a `--valid-ecdsa` argument to the sign command in
+ `imgtool.py`. Without this, the images will be padded with the
+ existing scheme, and with the argument, the ecdsa will be encoded
+ without any padding.
+
+ - MCUboot will be modified to allow unpadded signatures right away.
+ The existing EC256 implementations will still work (with or
+ without padding), and the existing EC implementation will begin
+ accepting all signatures.
+
+ - An mbed TLS implementation of EC256 can be added, but will require
+ the `--valid-ecdsa` signature to be able to boot all generated
+ images (without the argument 3 of out 4 images generated will have
+ padding, and be considered invalid).
+
+After one or more MCUboot release cycles, and announcements over
+relevant channels, the arguments to mcuboot will change:
+
+ - `--valid-ecdsa` will still be accepted, but have no effect.
+
+ - `--invalid-ecdsa` will now bring back the old padding behavior.
+
+This will require a change to any scripts that are relying on this
+behavior, but not specifying a specific version of imgtool.
+
+The signature generation in the simulator can be changed at the same
+time the boot code begins to accept unpadded signatures. The sim is
+always run out of the same tree as the mcuboot code, so there should
+not be any compatibility issues.
+
+## Background
+
+ECDSA signatures are encoded as ASN.1, notably with the signature
+itself being encoded as:
+
+ ECDSA-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+ }
+
+where both `r` and `s` are 256-bit numbers. Because these are
+unsigned numbers that are being encoded in ASN.1 as signed values, if
+the high bit of the number is set, the DER encoded representation will
+require 33 bytes instead of 32. This means that the length of the
+signature will vary by a couple of bytes, depending on whether on of
+both of these numbers has the high bit set.
+
+Originally, MCUboot added padding to the entire signature, and just
+removed 0 bytes from the data block. This would be fine 255/256
+times, when the last byte of the signature was non-zero, but if the
+signature ended in a zero, it would remove too many bytes, and the
+signature would be considered invalid.
+
+The correct approach here is to accept that ECDSA signatures are
+variable length, and make sure that we can handle them as such.
diff --git a/docs/index.md b/docs/index.md
index d9c70cb..3c4d1a3 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -20,6 +20,7 @@
- [Bootloader design](design.md)
- [Encrypted images](encrypted_images.md)
- [imgtool](imgtool.md) - image signing and key management
+- [ecdsa](ecdsa.md) - Information about ECDSA signature formats
- Usage instructions:
- [Zephyr](readme-zephyr.md)
- [Mynewt](readme-mynewt.md)