1 /*
2 * SPDX-License-Identifier: Apache-2.0
3 *
4 * Copyright (c) 2018-2019 JUUL Labs
5 * Copyright (c) 2019-2023 Arm Limited
6 */
7
8 #include "mcuboot_config/mcuboot_config.h"
9
10 #if defined(MCUBOOT_ENC_IMAGES)
11 #include <stddef.h>
12 #include <inttypes.h>
13 #include <string.h>
14
15 #if defined(MCUBOOT_ENCRYPT_RSA)
16 #define BOOTUTIL_CRYPTO_RSA_CRYPT_ENABLED
17 #include "bootutil/crypto/rsa.h"
18 #endif
19
20 #if defined(MCUBOOT_ENCRYPT_KW)
21 #include "bootutil/crypto/aes_kw.h"
22 #endif
23
24 #if defined(MCUBOOT_ENCRYPT_EC256)
25 #include "bootutil/crypto/ecdh_p256.h"
26 #endif
27
28 #if defined(MCUBOOT_ENCRYPT_X25519)
29 #include "bootutil/crypto/ecdh_x25519.h"
30 #endif
31
32 #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
33 #include "bootutil/crypto/sha.h"
34 #include "bootutil/crypto/hmac_sha256.h"
35 #include "mbedtls/oid.h"
36 #include "mbedtls/asn1.h"
37 #endif
38
39 #include "bootutil/image.h"
40 #include "bootutil/enc_key.h"
41 #include "bootutil/sign_key.h"
42 #include "bootutil/crypto/common.h"
43
44 #include "bootutil_priv.h"
45
46 #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
47 #if defined(_compare)
bootutil_constant_time_compare(const uint8_t * a,const uint8_t * b,size_t size)48 static 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
bootutil_constant_time_compare(const uint8_t * a,const uint8_t * b,size_t size)53 static 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
68 #if defined(MCUBOOT_ENCRYPT_KW)
69 static int
key_unwrap(const uint8_t * wrapped,uint8_t * enckey)70 key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
71 {
72 bootutil_aes_kw_context aes_kw;
73 int rc;
74
75 bootutil_aes_kw_init(&aes_kw);
76 rc = bootutil_aes_kw_set_unwrap_key(&aes_kw, bootutil_enc_key.key, *bootutil_enc_key.len);
77 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) {
82 goto done;
83 }
84
85 done:
86 bootutil_aes_kw_drop(&aes_kw);
87 return rc;
88 }
89 #endif /* MCUBOOT_ENCRYPT_KW */
90
91 #if defined(MCUBOOT_ENCRYPT_EC256)
92 static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
93 static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
94
95 #define SHARED_KEY_LEN NUM_ECC_BYTES
96 #define PRIV_KEY_LEN NUM_ECC_BYTES
97
98 /*
99 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
100 * curve keypair. See RFC5208 and RFC5915.
101 */
102 static int
parse_ec256_enckey(uint8_t ** p,uint8_t * end,uint8_t * private_key)103 parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
104 {
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, ¶m)) != 0) {
126 return -5;
127 }
128
129 if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
130 memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
131 return -6;
132 }
133 if (param.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
134 memcmp(param.ASN1_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
135 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
164 memcpy(private_key, *p, len);
165
166 /* publicKey usually follows but is not parsed here */
167
168 return 0;
169 }
170 #endif /* defined(MCUBOOT_ENCRYPT_EC256) */
171
172 #if defined(MCUBOOT_ENCRYPT_X25519)
173 #define X25519_OID "\x6e"
174 static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
175 MBEDTLS_OID_ORG_GOV X25519_OID;
176
177 #define SHARED_KEY_LEN 32
178 #define PRIV_KEY_LEN 32
179
180 static int
parse_x25519_enckey(uint8_t ** p,uint8_t * end,uint8_t * private_key)181 parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
182 {
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, ¶m) != 0) {
203 return -4;
204 }
205
206 if (alg.ASN1_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
207 memcmp(alg.ASN1_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
208 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
223 memcpy(private_key, *p, PRIV_KEY_LEN);
224 return 0;
225 }
226 #endif /* defined(MCUBOOT_ENCRYPT_X25519) */
227
228 #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
229 /*
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 */
239 static int
hkdf(uint8_t * ikm,uint16_t ikm_len,uint8_t * info,uint16_t info_len,uint8_t * okm,uint16_t * okm_len)240 hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
241 uint8_t *okm, uint16_t *okm_len)
242 {
243 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];
247 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
261 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;
267 }
268
269 rc = bootutil_hmac_sha256_update(&hmac, ikm, ikm_len);
270 if (rc != 0) {
271 goto error;
272 }
273
274 rc = bootutil_hmac_sha256_finish(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
275 if (rc != 0) {
276 goto error;
277 }
278
279 bootutil_hmac_sha256_drop(&hmac);
280
281 /*
282 * Expand
283 */
284
285 len = *okm_len;
286 counter = 1;
287 first = true;
288 for (off = 0; len > 0; off += BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, ++counter) {
289 bootutil_hmac_sha256_init(&hmac);
290
291 rc = bootutil_hmac_sha256_set_key(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
292 if (rc != 0) {
293 goto error;
294 }
295
296 if (first) {
297 first = false;
298 } else {
299 rc = bootutil_hmac_sha256_update(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
300 if (rc != 0) {
301 goto error;
302 }
303 }
304
305 rc = bootutil_hmac_sha256_update(&hmac, info, info_len);
306 if (rc != 0) {
307 goto error;
308 }
309
310 rc = bootutil_hmac_sha256_update(&hmac, &counter, 1);
311 if (rc != 0) {
312 goto error;
313 }
314
315 rc = bootutil_hmac_sha256_finish(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
316 if (rc != 0) {
317 goto error;
318 }
319
320 bootutil_hmac_sha256_drop(&hmac);
321
322 if (len > BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) {
323 memcpy(&okm[off], T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
324 len -= BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
325 } else {
326 memcpy(&okm[off], T, len);
327 len = 0;
328 }
329 }
330
331 return 0;
332
333 error:
334 bootutil_hmac_sha256_drop(&hmac);
335 return -1;
336 }
337 #endif
338
339 int
boot_enc_init(struct enc_key_data * enc_state,uint8_t slot)340 boot_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
346 int
boot_enc_drop(struct enc_key_data * enc_state,uint8_t slot)347 boot_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
353 int
boot_enc_set_key(struct enc_key_data * enc_state,uint8_t slot,const struct boot_status * bs)354 boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
355 const struct boot_status *bs)
356 {
357 int rc;
358
359 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;
363 return -1;
364 }
365
366 enc_state[slot].valid = 1;
367
368 return 0;
369 }
370
371 #define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
372
373 #if defined(MCUBOOT_ENCRYPT_RSA)
374 # define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
375 #elif defined(MCUBOOT_ENCRYPT_KW)
376 # define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW
377 #elif defined(MCUBOOT_ENCRYPT_EC256)
378 # define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
379 # define EC_PUBK_INDEX (0)
380 # define EC_TAG_INDEX (65)
381 # define EC_CIPHERKEY_INDEX (65 + 32)
382 _Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
383 "Please fix ECIES-P256 component indexes");
384 #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)
389 _Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
390 "Please fix ECIES-X25519 component indexes");
391 #endif
392
393 #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)) )
395 #if MBEDTLS_VERSION_NUMBER >= 0x03000000
fake_rng(void * p_rng,unsigned char * output,size_t len)396 static 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 }
407 #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) */
410
411 /*
412 * Decrypt an encryption key TLV.
413 *
414 * @param buf An encryption TLV read from flash (build time fixed length)
415 * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key.
416 */
417 int
boot_enc_decrypt(const uint8_t * buf,uint8_t * enckey)418 boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
419 {
420 #if defined(MCUBOOT_ENCRYPT_RSA)
421 bootutil_rsa_context rsa;
422 uint8_t *cp;
423 uint8_t *cpend;
424 size_t olen;
425 #endif
426 #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
432 #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
433 bootutil_hmac_sha256_context hmac;
434 bootutil_aes_ctr_context aes_ctr;
435 uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
436 uint8_t shared[SHARED_KEY_LEN];
437 uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
438 uint8_t *cp;
439 uint8_t *cpend;
440 uint8_t private_key[PRIV_KEY_LEN];
441 uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
442 uint16_t len;
443 #endif
444 int rc = -1;
445
446 #if defined(MCUBOOT_ENCRYPT_RSA)
447
448 bootutil_rsa_init(&rsa);
449 cp = (uint8_t *)bootutil_enc_key.key;
450 cpend = cp + *bootutil_enc_key.len;
451
452 /* The enckey is encrypted through RSA so for decryption we need the private key */
453 rc = bootutil_rsa_parse_private_key(&rsa, &cp, cpend);
454 if (rc) {
455 bootutil_rsa_drop(&rsa);
456 return rc;
457 }
458
459 rc = bootutil_rsa_oaep_decrypt(&rsa, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
460 bootutil_rsa_drop(&rsa);
461 if (rc) {
462 return rc;
463 }
464
465 #endif /* defined(MCUBOOT_ENCRYPT_RSA) */
466
467 #if defined(MCUBOOT_ENCRYPT_KW)
468
469 assert(*bootutil_enc_key.len == BOOT_ENC_KEY_SIZE);
470 rc = key_unwrap(buf, enckey);
471
472 #endif /* defined(MCUBOOT_ENCRYPT_KW) */
473
474 #if defined(MCUBOOT_ENCRYPT_EC256)
475
476 cp = (uint8_t *)bootutil_enc_key.key;
477 cpend = cp + *bootutil_enc_key.len;
478
479 /*
480 * Load the stored EC256 decryption private key
481 */
482
483 rc = parse_ec256_enckey(&cp, cpend, private_key);
484 if (rc) {
485 return rc;
486 }
487
488 /*
489 * First "element" in the TLV is the curve point (public key)
490 */
491 bootutil_ecdh_p256_init(&ecdh_p256);
492
493 rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
494 bootutil_ecdh_p256_drop(&ecdh_p256);
495 if (rc != 0) {
496 return -1;
497 }
498
499 #endif /* defined(MCUBOOT_ENCRYPT_EC256) */
500
501 #if defined(MCUBOOT_ENCRYPT_X25519)
502
503 cp = (uint8_t *)bootutil_enc_key.key;
504 cpend = cp + *bootutil_enc_key.len;
505
506 /*
507 * Load the stored X25519 decryption private key
508 */
509
510 rc = parse_x25519_enckey(&cp, cpend, private_key);
511 if (rc) {
512 return rc;
513 }
514
515 /*
516 * First "element" in the TLV is the curve point (public key)
517 */
518
519 bootutil_ecdh_x25519_init(&ecdh_x25519);
520
521 rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared);
522 bootutil_ecdh_x25519_drop(&ecdh_x25519);
523 if (!rc) {
524 return -1;
525 }
526
527 #endif /* defined(MCUBOOT_ENCRYPT_X25519) */
528
529 #if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
530
531 /*
532 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
533 */
534
535 len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
536 rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
537 derived_key, &len);
538 if (rc != 0 || len != (BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) {
539 return -1;
540 }
541
542 /*
543 * HMAC the key and check that our received MAC matches the generated tag
544 */
545
546 bootutil_hmac_sha256_init(&hmac);
547
548 rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOT_ENC_KEY_SIZE], 32);
549 if (rc != 0) {
550 (void)bootutil_hmac_sha256_drop(&hmac);
551 return -1;
552 }
553
554 rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE);
555 if (rc != 0) {
556 (void)bootutil_hmac_sha256_drop(&hmac);
557 return -1;
558 }
559
560 /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */
561 rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
562 if (rc != 0) {
563 (void)bootutil_hmac_sha256_drop(&hmac);
564 return -1;
565 }
566
567 if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
568 (void)bootutil_hmac_sha256_drop(&hmac);
569 return -1;
570 }
571
572 bootutil_hmac_sha256_drop(&hmac);
573
574 /*
575 * Finally decrypt the received ciphered key
576 */
577
578 bootutil_aes_ctr_init(&aes_ctr);
579 if (rc != 0) {
580 bootutil_aes_ctr_drop(&aes_ctr);
581 return -1;
582 }
583
584 rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
585 if (rc != 0) {
586 bootutil_aes_ctr_drop(&aes_ctr);
587 return -1;
588 }
589
590 memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
591 rc = bootutil_aes_ctr_decrypt(&aes_ctr, counter, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, 0, enckey);
592 if (rc != 0) {
593 bootutil_aes_ctr_drop(&aes_ctr);
594 return -1;
595 }
596
597 bootutil_aes_ctr_drop(&aes_ctr);
598
599 rc = 0;
600
601 #endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
602
603 return rc;
604 }
605
606 /*
607 * Load encryption key.
608 */
609 int
boot_enc_load(struct enc_key_data * enc_state,int image_index,const struct image_header * hdr,const struct flash_area * fap,struct boot_status * bs)610 boot_enc_load(struct enc_key_data *enc_state, int image_index,
611 const struct image_header *hdr, const struct flash_area *fap,
612 struct boot_status *bs)
613 {
614 uint32_t off;
615 uint16_t len;
616 struct image_tlv_iter it;
617 #if MCUBOOT_SWAP_SAVE_ENCTLV
618 uint8_t *buf;
619 #else
620 uint8_t buf[EXPECTED_ENC_LEN];
621 #endif
622 uint8_t slot;
623 int rc;
624
625 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
626 if (rc < 0) {
627 return rc;
628 }
629 slot = rc;
630
631 /* Already loaded... */
632 if (enc_state[slot].valid) {
633 return 1;
634 }
635
636 /* Initialize the AES context */
637 boot_enc_init(enc_state, slot);
638
639 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
640 if (rc) {
641 return -1;
642 }
643
644 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
645 if (rc != 0) {
646 return rc;
647 }
648
649 if (len != EXPECTED_ENC_LEN) {
650 return -1;
651 }
652
653 #if MCUBOOT_SWAP_SAVE_ENCTLV
654 buf = bs->enctlv[slot];
655 memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
656 #endif
657
658 rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
659 if (rc) {
660 return -1;
661 }
662
663 return boot_enc_decrypt(buf, bs->enckey[slot]);
664 }
665
666 bool
boot_enc_valid(struct enc_key_data * enc_state,int image_index,const struct flash_area * fap)667 boot_enc_valid(struct enc_key_data *enc_state, int image_index,
668 const struct flash_area *fap)
669 {
670 int rc;
671
672 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
673 if (rc < 0) {
674 /* can't get proper slot number - skip encryption, */
675 /* postpone the error for a upper layer */
676 return false;
677 }
678
679 return enc_state[rc].valid;
680 }
681
682 void
boot_encrypt(struct enc_key_data * enc_state,int image_index,const struct flash_area * fap,uint32_t off,uint32_t sz,uint32_t blk_off,uint8_t * buf)683 boot_encrypt(struct enc_key_data *enc_state, int image_index,
684 const struct flash_area *fap, uint32_t off, uint32_t sz,
685 uint32_t blk_off, uint8_t *buf)
686 {
687 struct enc_key_data *enc;
688 uint8_t nonce[16];
689 int rc;
690
691 /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
692 the TLVs. */
693 if (sz == 0) {
694 return;
695 }
696
697 memset(nonce, 0, 12);
698 off >>= 4;
699 nonce[12] = (uint8_t)(off >> 24);
700 nonce[13] = (uint8_t)(off >> 16);
701 nonce[14] = (uint8_t)(off >> 8);
702 nonce[15] = (uint8_t)off;
703
704 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
705 if (rc < 0) {
706 assert(0);
707 return;
708 }
709
710 enc = &enc_state[rc];
711 assert(enc->valid == 1);
712 bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
713 }
714
715 /**
716 * Clears encrypted state after use.
717 */
718 void
boot_enc_zeroize(struct enc_key_data * enc_state)719 boot_enc_zeroize(struct enc_key_data *enc_state)
720 {
721 uint8_t slot;
722 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
723 (void)boot_enc_drop(enc_state, slot);
724 }
725 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
726 }
727
728 #endif /* MCUBOOT_ENC_IMAGES */
729