blob: 4082611c4a0d55e9ed1aa0d4c348e5d189e3e819 [file] [log] [blame]
Fabio Utzigba829042018-09-18 08:29:34 -03001/*
David Brownaac71112020-02-03 16:13:42 -07002 * SPDX-License-Identifier: Apache-2.0
Fabio Utzigba829042018-09-18 08:29:34 -03003 *
David Brownaac71112020-02-03 16:13:42 -07004 * Copyright (c) 2018-2019 JUUL Labs
Antonio de Angelis02bf0722022-11-22 15:35:43 +00005 * Copyright (c) 2019-2023 Arm Limited
Fabio Utzigba829042018-09-18 08:29:34 -03006 */
7
8#include "mcuboot_config/mcuboot_config.h"
9
10#if defined(MCUBOOT_ENC_IMAGES)
Fabio Utzigba829042018-09-18 08:29:34 -030011#include <stddef.h>
12#include <inttypes.h>
13#include <string.h>
14
Fabio Utzigba829042018-09-18 08:29:34 -030015#if defined(MCUBOOT_ENCRYPT_RSA)
Antonio de Angelis02bf0722022-11-22 15:35:43 +000016#define BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED
17#include "bootutil/crypto/rsa.h"
Fabio Utzigba829042018-09-18 08:29:34 -030018#endif
19
20#if defined(MCUBOOT_ENCRYPT_KW)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090021#include "bootutil/crypto/aes_kw.h"
Fabio Utzigba829042018-09-18 08:29:34 -030022#endif
23
Fabio Utzig5fde8322019-10-23 12:23:08 -030024#if defined(MCUBOOT_ENCRYPT_EC256)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090025#include "bootutil/crypto/ecdh_p256.h"
26#endif
27
28#if defined(MCUBOOT_ENCRYPT_X25519)
29#include "bootutil/crypto/ecdh_x25519.h"
Fabio Utzig6aec6ae2020-04-02 11:06:07 -030030#endif
31
32#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Roland Mikhel03c9ad02023-03-08 15:56:43 +010033#include "bootutil/crypto/sha.h"
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090034#include "bootutil/crypto/hmac_sha256.h"
Fabio Utzig5fde8322019-10-23 12:23:08 -030035#include "mbedtls/oid.h"
36#include "mbedtls/asn1.h"
37#endif
38
Fabio Utzigba829042018-09-18 08:29:34 -030039#include "bootutil/image.h"
40#include "bootutil/enc_key.h"
41#include "bootutil/sign_key.h"
Sherry Zhangb111f982021-07-13 17:11:47 +080042#include "bootutil/crypto/common.h"
Fabio Utzigba829042018-09-18 08:29:34 -030043
44#include "bootutil_priv.h"
45
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090046#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
47#if defined(_compare)
48static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
49{
50 return _compare(a, b, size);
51}
52#else
53static int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
54{
55 const uint8_t *tempa = a;
56 const uint8_t *tempb = b;
57 uint8_t result = 0;
58 unsigned int i;
59
60 for (i = 0; i < size; i++) {
61 result |= tempa[i] ^ tempb[i];
62 }
63 return result;
64}
65#endif
66#endif
67
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020068#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030069static int
Dinesh Kumar K0fa46272023-06-06 16:36:57 +053070key_unwrap(const uint8_t *wrapped, uint8_t *enckey, struct bootutil_key *bootutil_enc_key)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020071{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090072 bootutil_aes_kw_context aes_kw;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020073 int rc;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020074
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090075 bootutil_aes_kw_init(&aes_kw);
Dinesh Kumar K0fa46272023-06-06 16:36:57 +053076 rc = bootutil_aes_kw_set_unwrap_key(&aes_kw, bootutil_enc_key->key, *bootutil_enc_key->len);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090077 if (rc != 0) {
78 goto done;
79 }
80 rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE);
81 if (rc != 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020082 goto done;
83 }
84
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020085done:
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090086 bootutil_aes_kw_drop(&aes_kw);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020087 return rc;
88}
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020089#endif /* MCUBOOT_ENCRYPT_KW */
90
Fabio Utzig5fde8322019-10-23 12:23:08 -030091#if defined(MCUBOOT_ENCRYPT_EC256)
92static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
93static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
94
Fabio Utzig6aec6ae2020-04-02 11:06:07 -030095#define SHARED_KEY_LEN NUM_ECC_BYTES
96#define PRIV_KEY_LEN NUM_ECC_BYTES
97
Fabio Utzig5fde8322019-10-23 12:23:08 -030098/*
99 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
100 * curve keypair. See RFC5208 and RFC5915.
101 */
102static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900103parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300104{
105 int rc;
106 size_t len;
107 int version;
108 mbedtls_asn1_buf alg;
109 mbedtls_asn1_buf param;
110
111 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
112 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
113 return -1;
114 }
115
116 if (*p + len != end) {
117 return -2;
118 }
119
120 version = 0;
121 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
122 return -3;
123 }
124
125 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
126 return -5;
127 }
128
Sherry Zhangb111f982021-07-13 17:11:47 +0800129 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
130 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300131 return -6;
132 }
Sherry Zhangb111f982021-07-13 17:11:47 +0800133 if (param.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
134 memcmp(param.MBEDTLS_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300135 return -7;
136 }
137
138 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
139 return -8;
140 }
141
142 /* RFC5915 - ECPrivateKey */
143
144 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
145 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
146 return -9;
147 }
148
149 version = 0;
150 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
151 return -10;
152 }
153
154 /* privateKey */
155
156 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
157 return -11;
158 }
159
160 if (len != NUM_ECC_BYTES) {
161 return -12;
162 }
163
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900164 memcpy(private_key, *p, len);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300165
166 /* publicKey usually follows but is not parsed here */
167
168 return 0;
169}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300170#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300171
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300172#if defined(MCUBOOT_ENCRYPT_X25519)
173#define X25519_OID "\x6e"
174static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
175 MBEDTLS_OID_ORG_GOV X25519_OID;
176
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300177#define SHARED_KEY_LEN 32
178#define PRIV_KEY_LEN 32
179
180static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900181parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300182{
183 size_t len;
184 int version;
185 mbedtls_asn1_buf alg;
186 mbedtls_asn1_buf param;
187
188 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
189 MBEDTLS_ASN1_SEQUENCE) != 0) {
190 return -1;
191 }
192
193 if (*p + len != end) {
194 return -2;
195 }
196
197 version = 0;
198 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
199 return -3;
200 }
201
202 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
203 return -4;
204 }
205
Sherry Zhangb111f982021-07-13 17:11:47 +0800206 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
207 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300208 return -5;
209 }
210
211 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
212 return -6;
213 }
214
215 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
216 return -7;
217 }
218
219 if (len != PRIV_KEY_LEN) {
220 return -8;
221 }
222
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900223 memcpy(private_key, *p, PRIV_KEY_LEN);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300224 return 0;
225}
226#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
227
228#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300229/*
230 * HKDF as described by RFC5869.
231 *
232 * @param ikm The input data to be derived.
233 * @param ikm_len Length of the input data.
234 * @param info An information tag.
235 * @param info_len Length of the information tag.
236 * @param okm Output of the KDF computation.
237 * @param okm_len On input the requested length; on output the generated length
238 */
239static int
240hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
241 uint8_t *okm, uint16_t *okm_len)
242{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900243 bootutil_hmac_sha256_context hmac;
244 uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
245 uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
246 uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300247 uint16_t off;
248 uint16_t len;
249 uint8_t counter;
250 bool first;
251 int rc;
252
253 /*
254 * Extract
255 */
256
257 if (ikm == NULL || okm == NULL || ikm_len == 0) {
258 return -1;
259 }
260
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900261 bootutil_hmac_sha256_init(&hmac);
262
263 memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
264 rc = bootutil_hmac_sha256_set_key(&hmac, salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
265 if (rc != 0) {
266 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300267 }
268
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900269 rc = bootutil_hmac_sha256_update(&hmac, ikm, ikm_len);
270 if (rc != 0) {
271 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300272 }
273
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900274 rc = bootutil_hmac_sha256_finish(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
275 if (rc != 0) {
276 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300277 }
278
Thomas Altenbach73315f72024-04-04 13:46:38 +0200279 bootutil_hmac_sha256_drop(&hmac);
280
Fabio Utzig5fde8322019-10-23 12:23:08 -0300281 /*
282 * Expand
283 */
284
285 len = *okm_len;
286 counter = 1;
287 first = true;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900288 for (off = 0; len > 0; off += BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, ++counter) {
289 bootutil_hmac_sha256_init(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300290
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900291 rc = bootutil_hmac_sha256_set_key(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
292 if (rc != 0) {
293 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300294 }
295
296 if (first) {
297 first = false;
298 } else {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900299 rc = bootutil_hmac_sha256_update(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
300 if (rc != 0) {
301 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300302 }
303 }
304
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900305 rc = bootutil_hmac_sha256_update(&hmac, info, info_len);
306 if (rc != 0) {
307 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300308 }
309
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900310 rc = bootutil_hmac_sha256_update(&hmac, &counter, 1);
311 if (rc != 0) {
312 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300313 }
314
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900315 rc = bootutil_hmac_sha256_finish(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
316 if (rc != 0) {
317 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300318 }
319
Thomas Altenbach73315f72024-04-04 13:46:38 +0200320 bootutil_hmac_sha256_drop(&hmac);
321
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900322 if (len > BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) {
323 memcpy(&okm[off], T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
324 len -= BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300325 } else {
326 memcpy(&okm[off], T, len);
327 len = 0;
328 }
329 }
330
331 return 0;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900332
333error:
334 bootutil_hmac_sha256_drop(&hmac);
335 return -1;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300336}
337#endif
338
Fabio Utzigba829042018-09-18 08:29:34 -0300339int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900340boot_enc_init(struct enc_key_data *enc_state, uint8_t slot)
341{
342 bootutil_aes_ctr_init(&enc_state[slot].aes_ctr);
343 return 0;
344}
345
346int
347boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot)
348{
349 bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr);
350 return 0;
351}
352
353int
Fabio Utzig4741c452019-12-19 15:32:41 -0300354boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
355 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300356{
357 int rc;
358
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900359 rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]);
360 if (rc != 0) {
361 boot_enc_drop(enc_state, slot);
362 enc_state[slot].valid = 0;
Fabio Utzigba829042018-09-18 08:29:34 -0300363 return -1;
364 }
365
366 enc_state[slot].valid = 1;
367
368 return 0;
369}
370
Fabio Utzig4741c452019-12-19 15:32:41 -0300371#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
372
Fabio Utzigba829042018-09-18 08:29:34 -0300373#if defined(MCUBOOT_ENCRYPT_RSA)
374# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
Fabio Utzigba829042018-09-18 08:29:34 -0300375#elif defined(MCUBOOT_ENCRYPT_KW)
Salome Thirot0f641972021-05-14 11:19:55 +0100376# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW
Fabio Utzig5fde8322019-10-23 12:23:08 -0300377#elif defined(MCUBOOT_ENCRYPT_EC256)
378# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200379# define EC_PUBK_INDEX (0)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300380# define EC_TAG_INDEX (65)
381# define EC_CIPHERKEY_INDEX (65 + 32)
Salome Thirot0f641972021-05-14 11:19:55 +0100382_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig4741c452019-12-19 15:32:41 -0300383 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300384#elif defined(MCUBOOT_ENCRYPT_X25519)
385# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
386# define EC_PUBK_INDEX (0)
387# define EC_TAG_INDEX (32)
388# define EC_CIPHERKEY_INDEX (32 + 32)
Salome Thirot0f641972021-05-14 11:19:55 +0100389_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300390 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300391#endif
392
Antonio de Angelis02bf0722022-11-22 15:35:43 +0000393#if ( (defined(MCUBOOT_ENCRYPT_RSA) && defined(MCUBOOT_USE_MBED_TLS) && !defined(MCUBOOT_USE_PSA_CRYPTO)) || \
394 (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS)) )
Sherry Zhangb111f982021-07-13 17:11:47 +0800395#if MBEDTLS_VERSION_NUMBER >= 0x03000000
396static int fake_rng(void *p_rng, unsigned char *output, size_t len)
397{
398 size_t i;
399
400 (void)p_rng;
401 for (i = 0; i < len; i++) {
402 output[i] = (char)i;
403 }
404
405 return 0;
406}
Antonio de Angelis02bf0722022-11-22 15:35:43 +0000407#endif /* MBEDTLS_VERSION_NUMBER */
408#endif /* (MCUBOOT_ENCRYPT_RSA && MCUBOOT_USE_MBED_TLS && !MCUBOOT_USE_PSA_CRYPTO) ||
409 (MCUBOOT_ENCRYPT_EC256 && MCUBOOT_USE_MBED_TLS) */
Sherry Zhangb111f982021-07-13 17:11:47 +0800410
Fabio Utzigba829042018-09-18 08:29:34 -0300411/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300412 * Decrypt an encryption key TLV.
413 *
414 * @param buf An encryption TLV read from flash (build time fixed length)
Salome Thirot0f641972021-05-14 11:19:55 +0100415 * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300416 */
417int
Fabio Utzig4741c452019-12-19 15:32:41 -0300418boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
Fabio Utzigba829042018-09-18 08:29:34 -0300419{
420#if defined(MCUBOOT_ENCRYPT_RSA)
Antonio de Angelis02bf0722022-11-22 15:35:43 +0000421 bootutil_rsa_context rsa;
Fabio Utzigba829042018-09-18 08:29:34 -0300422 uint8_t *cp;
423 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300424 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200425#endif
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900426#if defined(MCUBOOT_ENCRYPT_EC256)
427 bootutil_ecdh_p256_context ecdh_p256;
428#endif
429#if defined(MCUBOOT_ENCRYPT_X25519)
430 bootutil_ecdh_x25519_context ecdh_x25519;
431#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300432#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900433 bootutil_hmac_sha256_context hmac;
434 bootutil_aes_ctr_context aes_ctr;
435 uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300436 uint8_t shared[SHARED_KEY_LEN];
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900437 uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300438 uint8_t *cp;
439 uint8_t *cpend;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900440 uint8_t private_key[PRIV_KEY_LEN];
441 uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300442 uint16_t len;
Fabio Utzig4741c452019-12-19 15:32:41 -0300443#endif
Dinesh Kumar K0fa46272023-06-06 16:36:57 +0530444 struct bootutil_key *bootutil_enc_key = NULL;
Fabio Utzig4741c452019-12-19 15:32:41 -0300445 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300446
Dinesh Kumar K0fa46272023-06-06 16:36:57 +0530447 rc = boot_enc_retrieve_private_key(&bootutil_enc_key);
448 if (rc) {
449 return rc;
450 }
451
452 if (bootutil_enc_key == NULL) {
453 return rc;
454 }
455
Fabio Utzigba829042018-09-18 08:29:34 -0300456#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300457
Antonio de Angelis02bf0722022-11-22 15:35:43 +0000458 bootutil_rsa_init(&rsa);
Dinesh Kumar K0fa46272023-06-06 16:36:57 +0530459 cp = (uint8_t *)bootutil_enc_key->key;
460 cpend = cp + *bootutil_enc_key->len;
Fabio Utzigba829042018-09-18 08:29:34 -0300461
Antonio de Angelis02bf0722022-11-22 15:35:43 +0000462 /* The enckey is encrypted through RSA so for decryption we need the private key */
463 rc = bootutil_rsa_parse_private_key(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300464 if (rc) {
Antonio de Angelis02bf0722022-11-22 15:35:43 +0000465 bootutil_rsa_drop(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300466 return rc;
467 }
Antonio de Angelis02bf0722022-11-22 15:35:43 +0000468
469 rc = bootutil_rsa_oaep_decrypt(&rsa, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
470 bootutil_rsa_drop(&rsa);
471 if (rc) {
472 return rc;
473 }
Fabio Utzigba829042018-09-18 08:29:34 -0300474
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300475#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
476
477#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300478
Dinesh Kumar K0fa46272023-06-06 16:36:57 +0530479 assert(*bootutil_enc_key->len == BOOT_ENC_KEY_SIZE);
480 rc = key_unwrap(buf, enckey, bootutil_enc_key);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300481
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300482#endif /* defined(MCUBOOT_ENCRYPT_KW) */
483
484#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300485
Dinesh Kumar K0fa46272023-06-06 16:36:57 +0530486 cp = (uint8_t *)bootutil_enc_key->key;
487 cpend = cp + *bootutil_enc_key->len;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300488
489 /*
490 * Load the stored EC256 decryption private key
491 */
492
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900493 rc = parse_ec256_enckey(&cp, cpend, private_key);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300494 if (rc) {
495 return rc;
496 }
497
Fabio Utzig5fde8322019-10-23 12:23:08 -0300498 /*
499 * First "element" in the TLV is the curve point (public key)
500 */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900501 bootutil_ecdh_p256_init(&ecdh_p256);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300502
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900503 rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
504 bootutil_ecdh_p256_drop(&ecdh_p256);
505 if (rc != 0) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300506 return -1;
507 }
508
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300509#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
510
511#if defined(MCUBOOT_ENCRYPT_X25519)
512
Dinesh Kumar K0fa46272023-06-06 16:36:57 +0530513 cp = (uint8_t *)bootutil_enc_key->key;
514 cpend = cp + *bootutil_enc_key->len;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300515
516 /*
517 * Load the stored X25519 decryption private key
518 */
519
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900520 rc = parse_x25519_enckey(&cp, cpend, private_key);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300521 if (rc) {
522 return rc;
523 }
524
525 /*
526 * First "element" in the TLV is the curve point (public key)
527 */
528
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900529 bootutil_ecdh_x25519_init(&ecdh_x25519);
530
531 rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared);
532 bootutil_ecdh_x25519_drop(&ecdh_x25519);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300533 if (!rc) {
534 return -1;
535 }
536
537#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
538
539#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
540
Fabio Utzig5fde8322019-10-23 12:23:08 -0300541 /*
542 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
543 */
544
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900545 len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300546 rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
Fabio Utzig5fde8322019-10-23 12:23:08 -0300547 derived_key, &len);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900548 if (rc != 0 || len != (BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300549 return -1;
550 }
551
552 /*
553 * HMAC the key and check that our received MAC matches the generated tag
554 */
555
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900556 bootutil_hmac_sha256_init(&hmac);
557
Salome Thirot0f641972021-05-14 11:19:55 +0100558 rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOT_ENC_KEY_SIZE], 32);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900559 if (rc != 0) {
560 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300561 return -1;
562 }
563
Salome Thirot0f641972021-05-14 11:19:55 +0100564 rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900565 if (rc != 0) {
566 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300567 return -1;
568 }
569
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200570 /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900571 rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
572 if (rc != 0) {
573 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300574 return -1;
575 }
576
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900577 if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
578 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300579 return -1;
580 }
581
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900582 bootutil_hmac_sha256_drop(&hmac);
583
Fabio Utzig5fde8322019-10-23 12:23:08 -0300584 /*
585 * Finally decrypt the received ciphered key
586 */
587
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900588 bootutil_aes_ctr_init(&aes_ctr);
589 if (rc != 0) {
590 bootutil_aes_ctr_drop(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300591 return -1;
592 }
593
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900594 rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
595 if (rc != 0) {
596 bootutil_aes_ctr_drop(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300597 return -1;
598 }
599
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900600 memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
601 rc = bootutil_aes_ctr_decrypt(&aes_ctr, counter, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, 0, enckey);
602 if (rc != 0) {
603 bootutil_aes_ctr_drop(&aes_ctr);
604 return -1;
605 }
606
607 bootutil_aes_ctr_drop(&aes_ctr);
608
Fabio Utzig5fde8322019-10-23 12:23:08 -0300609 rc = 0;
610
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300611#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300612
Fabio Utzigba829042018-09-18 08:29:34 -0300613 return rc;
614}
615
Fabio Utzig4741c452019-12-19 15:32:41 -0300616/*
617 * Load encryption key.
618 */
619int
620boot_enc_load(struct enc_key_data *enc_state, int image_index,
621 const struct image_header *hdr, const struct flash_area *fap,
622 struct boot_status *bs)
623{
624 uint32_t off;
625 uint16_t len;
626 struct image_tlv_iter it;
627#if MCUBOOT_SWAP_SAVE_ENCTLV
628 uint8_t *buf;
629#else
630 uint8_t buf[EXPECTED_ENC_LEN];
631#endif
632 uint8_t slot;
633 int rc;
634
Dominik Ermel260ae092021-04-23 05:38:45 +0000635 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Fabio Utzig4741c452019-12-19 15:32:41 -0300636 if (rc < 0) {
637 return rc;
638 }
639 slot = rc;
640
641 /* Already loaded... */
642 if (enc_state[slot].valid) {
643 return 1;
644 }
645
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900646 /* Initialize the AES context */
647 boot_enc_init(enc_state, slot);
648
Fabio Utzig4741c452019-12-19 15:32:41 -0300649 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
650 if (rc) {
651 return -1;
652 }
653
654 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
655 if (rc != 0) {
656 return rc;
657 }
658
659 if (len != EXPECTED_ENC_LEN) {
660 return -1;
661 }
662
663#if MCUBOOT_SWAP_SAVE_ENCTLV
664 buf = bs->enctlv[slot];
665 memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
666#endif
667
668 rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
669 if (rc) {
670 return -1;
671 }
672
673 return boot_enc_decrypt(buf, bs->enckey[slot]);
674}
675
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100676bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300677boot_enc_valid(struct enc_key_data *enc_state, int image_index,
678 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300679{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100680 int rc;
681
Dominik Ermel260ae092021-04-23 05:38:45 +0000682 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100683 if (rc < 0) {
684 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300685 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100686 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100687 }
688
689 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300690}
691
692void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300693boot_encrypt(struct enc_key_data *enc_state, int image_index,
694 const struct flash_area *fap, uint32_t off, uint32_t sz,
695 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300696{
697 struct enc_key_data *enc;
Fabio Utzigba829042018-09-18 08:29:34 -0300698 uint8_t nonce[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100699 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300700
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900701 /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
702 the TLVs. */
703 if (sz == 0) {
704 return;
705 }
706
Fabio Utzigba829042018-09-18 08:29:34 -0300707 memset(nonce, 0, 12);
708 off >>= 4;
709 nonce[12] = (uint8_t)(off >> 24);
710 nonce[13] = (uint8_t)(off >> 16);
711 nonce[14] = (uint8_t)(off >> 8);
712 nonce[15] = (uint8_t)off;
713
Dominik Ermel260ae092021-04-23 05:38:45 +0000714 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100715 if (rc < 0) {
716 assert(0);
717 return;
718 }
719
720 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300721 assert(enc->valid == 1);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900722 bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
Fabio Utzigba829042018-09-18 08:29:34 -0300723}
724
Fabio Utzig10ee6482019-08-01 12:04:52 -0300725/**
726 * Clears encrypted state after use.
727 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300728void
729boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300730{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900731 uint8_t slot;
732 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
733 (void)boot_enc_drop(enc_state, slot);
734 }
Fabio Utzig10ee6482019-08-01 12:04:52 -0300735 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300736}
737
738#endif /* MCUBOOT_ENC_IMAGES */