blob: 838f493b6c57b0971a7a8c2906bae0733f8a60aa [file] [log] [blame] [view]
Fabio Utzigcdfa11a2018-10-01 09:45:54 -03001<!--
David Vincze4e3c47b2020-04-21 17:11:33 +02002 -
3 - Licensed to the Apache Software Foundation (ASF) under one
4 - or more contributor license agreements. See the NOTICE file
5 - distributed with this work for additional information
6 - regarding copyright ownership. The ASF licenses this file
7 - to you under the Apache License, Version 2.0 (the
8 - "License"); you may not use this file except in compliance
9 - with the License. You may obtain a copy of the License at
10 -
11 - http://www.apache.org/licenses/LICENSE-2.0
12 -
13 - Unless required by applicable law or agreed to in writing,
14 - software distributed under the License is distributed on an
15 - "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 - KIND, either express or implied. See the License for the
17 - specific language governing permissions and limitations
18 - under the License.
19 -
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030020-->
21
Ruth Fuchss721cdbc2019-11-01 15:24:39 +010022# Encrypted images
23
Fabio Utzig478ad242019-11-26 08:32:19 -030024## [Rationale](#rationale)
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030025
26To provide confidentiality of image data while in transport to the
27device or while residing on an external flash, `MCUBoot` has support
28for encrypting/decrypting images on-the-fly while upgrading.
29
30The image header needs to flag this image as `ENCRYPTED` (0x04) and
31a TLV with the key must be present in the image. When upgrading the
David Vincze2d736ad2019-02-18 11:50:22 +010032image from the `secondary slot` to the `primary slot` it is automatically
33decrypted (after validation). If swap upgrades are enabled, the image
34located in the `primary slot`, also having the `ENCRYPTED` flag set and the
35TLV present, is re-encrypted while swapping to the `secondary slot`.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030036
Fabio Utzig478ad242019-11-26 08:32:19 -030037## [Threat model](#threat-model)
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030038
39The encrypted image support is supposed to allow for confidentiality
40if the image is not residing on the device or is written to external
David Vincze2d736ad2019-02-18 11:50:22 +010041storage, eg a SPI flash being used for the secondary slot.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030042
43It does not protect against the possibility of attaching a JTAG and
44reading the internal flash memory, or using some attack vector that
45enables dumping the internal flash in any way.
46
Sam Bristowd0ca0ff2019-10-30 20:51:35 +130047Since decrypting requires a private key (or secret if using symmetric
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030048crypto) to reside inside the device, it is the responsibility of the
49device manufacturer to guarantee that this key is already in the device
50and not possible to extract.
51
Fabio Utzig478ad242019-11-26 08:32:19 -030052## [Design](#design)
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030053
54When encrypting an image, only the payload (FW) is encrypted. The header,
55TLVs are still sent as plain data.
56
57Hashing and signing also remain functionally the same way as before,
58applied over the un-encrypted data. Validation on encrypted images, checks
59that the encrypted flag is set and TLV data is OK, then it decrypts each
60image block before sending the data to the hash routines.
61
Roman Okhrimenko977b3752022-03-31 14:40:48 +030062The image is encrypted using AES-CTR-128 or AES-CTR-256, with a counter
63that starts from zero (over the payload blocks) and increments by 1 for each
6416-byte block. AES-CTR was chosen for speed/simplicity and allowing for any
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030065block to be encrypted/decrypted without requiring knowledge of any other
66block (allowing for simple resume operations on swap interruptions).
67
68The key used is a randomized when creating a new image, by `imgtool` or
69`newt`. This key should never be reused and no checks are done for this,
70but randomizing a 16-byte block with a TRNG should make it highly
71improbable that duplicates ever happen.
72
Roman Okhrimenko977b3752022-03-31 14:40:48 +030073To distribute this AES-CTR key, new TLVs were defined. The key can be
74encrypted using either RSA-OAEP, AES-KW (128 or 256 bits depending on the
75AES-CTR key length), ECIES-P256 or ECIES-X25519.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -030076
77For RSA-OAEP a new TLV with value `0x30` is added to the image, for
Roman Okhrimenko977b3752022-03-31 14:40:48 +030078AES-KW a new TLV with value `0x31` is added to the image, for
Fabio Utzig5eaa5762020-04-02 13:30:43 -030079ECIES-P256 a new TLV with value `0x32` is added, and for ECIES-X25519 a
80newt TLV with value `0x33` is added. The contents of those TLVs
Roman Okhrimenko977b3752022-03-31 14:40:48 +030081are the results of applying the given operations over the AES-CTR key.
Fabio Utzigb3f058c2019-10-30 10:51:06 -030082
Fabio Utzig5eaa5762020-04-02 13:30:43 -030083## [ECIES encryption](#ecies-encryption)
Fabio Utzigb3f058c2019-10-30 10:51:06 -030084
85ECIES follows a well defined protocol to generate an encryption key. There are
86multiple standards which differ only on which building blocks are used; for
87MCUBoot we settled on some primitives that are easily found on our crypto
88libraries. The whole key encryption can be summarized as:
89
Fabio Utzig5eaa5762020-04-02 13:30:43 -030090* Generate a new private key and derive the public key; when using ECIES-P256
91 this is a secp256r1 keypair, when using ECIES-X25519 this will be a x25519
92 keypair. Those keys will be our ephemeral keys.
Fabio Utzigb3f058c2019-10-30 10:51:06 -030093* Generate a new secret (DH) using the ephemeral private key and the public key
94 that corresponds to the private key embedded in the HW.
95* Derive the new keys from the secret using HKDF (built on HMAC-SHA256). We
96 are not using a `salt` and using an `info` of `MCUBoot_ECIES_v1`, generating
97 48 bytes of key material.
Roman Okhrimenko977b3752022-03-31 14:40:48 +030098* A new random encryption key is generated (for AES). This is
Fabio Utzigb3f058c2019-10-30 10:51:06 -030099 the AES key used to encrypt the images.
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300100* The key is encrypted with AES-128-CTR or AES-256-CTR and a `nonce` of 0 using
101 the first 16 bytes of key material generated previously by the HKDF.
Fabio Utzigb3f058c2019-10-30 10:51:06 -0300102* The encrypted key now goes through a HMAC-SHA256 using the remaining 32
103 bytes of key material from the HKDF.
104
Fabio Utzig5eaa5762020-04-02 13:30:43 -0300105The final TLV is built from the 65 bytes for ECIES-P256 or 32 bytes for
106ECIES-X25519, which correspond to the ephemeral public key, followed by the
Roman Okhrimenko977b3752022-03-31 14:40:48 +030010732 bytes of MAC tag and the 16 or 32 bytes of the encrypted key, resulting in
108a TLV of 113 or 129 bytes for ECIES-P256 and 80 or 96 bytes for ECIES-X25519.
Fabio Utzigb3f058c2019-10-30 10:51:06 -0300109
Fabio Utzig5eaa5762020-04-02 13:30:43 -0300110The implemenation of ECIES-P256 is named ENC_EC256 in the source code and
111artifacts while ECIES-X25519 is named ENC_X25519.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300112
Fabio Utzig478ad242019-11-26 08:32:19 -0300113## [Upgrade process](#upgrade-process)
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300114
David Vincze2d736ad2019-02-18 11:50:22 +0100115When starting a new upgrade process, `MCUBoot` checks that the image in the
116`secondary slot` has the `ENCRYPTED` flag set and has the required TLV with the
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300117encrypted key. It then uses its internal private/secret key to decrypt
118the TLV containing the key. Given that no errors are found, it will then
119start the validation process, decrypting the blocks before check. A good
120image being determined, the upgrade consists in reading the blocks from
David Vincze2d736ad2019-02-18 11:50:22 +0100121the `secondary slot`, decrypting and writing to the `primary slot`.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300122
123If swap is used for the upgrade process, the encryption happens when
David Vincze2d736ad2019-02-18 11:50:22 +0100124copying the sectors of the `secondary slot` to the scratch area.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300125
126The `scratch` area is not encrypted, so it must reside in the internal
127flash of the MCU to avoid attacks that could interrupt the upgrade and
128dump the data.
129
David Vincze2d736ad2019-02-18 11:50:22 +0100130Also when swap is used, the image in the `primary slot` is checked for
131presence of the `ENCRYPTED` flag and the key TLV. If those are present the
132sectors are re-encrypted when copying from the `primary slot` to
133the `secondary slot`.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300134
135PS: Each encrypted image must have its own key TLV that should be unique
136and used only for this particular image.
137
138Also when swap method is employed, the sizes of both images are saved to
139the status area just before starting the upgrade process, because it
140would be very hard to determine this information when an interruption
141occurs and the information is spread across multiple areas.
142
Fabio Utzig478ad242019-11-26 08:32:19 -0300143## [Creating your keys with imgtool](#creating-your-keys-with-imgtool)
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300144
Harry Jiang68281512020-07-06 16:12:02 +0800145`imgtool` can generate keys by using `imgtool keygen -k <output.pem> -t <type>`,
Fabio Utzigb3f058c2019-10-30 10:51:06 -0300146 where type can be one of `rsa-2048`, `rsa-3072`, `ecdsa-p256`, `ecdsa-p224`
147or `ed25519`. This will generate a keypair or private key.
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300148
Fabio Utzigb3f058c2019-10-30 10:51:06 -0300149To extract the public key in source file form, use
150`imgtool getpub -k <input.pem> -l <lang>`, where lang can be one of `c` or
151`rust` (defaults to `c`).
Fabio Utzigcdfa11a2018-10-01 09:45:54 -0300152
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300153If using AES-KW, follow the steps in the next section to generate the
Fabio Utzigb3f058c2019-10-30 10:51:06 -0300154required keys.
155
Fabio Utzig478ad242019-11-26 08:32:19 -0300156## [Creating your keys with Unix tooling](#creating-your-keys-with-unix-tooling)
Fabio Utzigb3f058c2019-10-30 10:51:06 -0300157
158* If using RSA-OAEP, generate a keypair following steps similar to those
159 described in [signed_images](signed_images.md) to create RSA keys.
160* If using ECIES-P256, generate a keypair following steps similar to those
161 described in [signed_images](signed_images.md) to create ECDSA256 keys.
Fabio Utzig5eaa5762020-04-02 13:30:43 -0300162* If using ECIES-X25519, generate a private key passing the option `-t x25519`
163 to `imgtool keygen` command. To generate public key PEM file the following
164 command can be used: `openssl pkey -in <generated-private-key.pem> -pubout`
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300165* If using AES-KW (`newt` only), the `kek` can be generated with a
166 command like (change count to 32 for a 256 bit key)
167 `dd if=/dev/urandom bs=1 count=16 | base64 > my_kek.b64`