blob: 02f8eef15359d193f6d8e86b325d4d66a3a389df [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
Roman Okhrimenko977b3752022-03-31 14:40:48 +03005 * Copyright (c) 2019-2021 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)
16#include "mbedtls/rsa.h"
Roman Okhrimenko977b3752022-03-31 14:40:48 +030017#if MBEDTLS_VERSION_NUMBER >= 0x03000000
18#include "rsa_alt_helpers.h"
19#else
Fabio Utzig6f4d8f82019-12-12 18:46:06 -030020#include "mbedtls/rsa_internal.h"
Roman Okhrimenko977b3752022-03-31 14:40:48 +030021#endif
Fabio Utzigba829042018-09-18 08:29:34 -030022#include "mbedtls/asn1.h"
23#endif
24
25#if defined(MCUBOOT_ENCRYPT_KW)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090026#include "bootutil/crypto/aes_kw.h"
Fabio Utzigba829042018-09-18 08:29:34 -030027#endif
28
Fabio Utzig5fde8322019-10-23 12:23:08 -030029#if defined(MCUBOOT_ENCRYPT_EC256)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090030#include "bootutil/crypto/ecdh_p256.h"
31#endif
32
33#if defined(MCUBOOT_ENCRYPT_X25519)
34#include "bootutil/crypto/ecdh_x25519.h"
Fabio Utzig6aec6ae2020-04-02 11:06:07 -030035#endif
36
37#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090038#include "bootutil/crypto/sha256.h"
39#include "bootutil/crypto/hmac_sha256.h"
Fabio Utzig5fde8322019-10-23 12:23:08 -030040#include "mbedtls/oid.h"
41#include "mbedtls/asn1.h"
42#endif
43
Fabio Utzigba829042018-09-18 08:29:34 -030044#include "bootutil/image.h"
45#include "bootutil/enc_key.h"
46#include "bootutil/sign_key.h"
Roman Okhrimenko977b3752022-03-31 14:40:48 +030047#include "bootutil/crypto/common.h"
Fabio Utzigba829042018-09-18 08:29:34 -030048
49#include "bootutil_priv.h"
50
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090051#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
52#if defined(_compare)
53static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
54{
55 return _compare(a, b, size);
56}
57#else
58static int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
59{
60 const uint8_t *tempa = a;
61 const uint8_t *tempb = b;
62 uint8_t result = 0;
63 unsigned int i;
64
65 for (i = 0; i < size; i++) {
66 result |= tempa[i] ^ tempb[i];
67 }
68 return result;
69}
70#endif
71#endif
72
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020073#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030074static int
Fabio Utzig4741c452019-12-19 15:32:41 -030075key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020076{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090077 bootutil_aes_kw_context aes_kw;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020078 int rc;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020079
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090080 bootutil_aes_kw_init(&aes_kw);
81 rc = bootutil_aes_kw_set_unwrap_key(&aes_kw, bootutil_enc_key.key, *bootutil_enc_key.len);
Roman Okhrimenko977b3752022-03-31 14:40:48 +030082
83 if (rc == 0) {
84 rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020085 }
86
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090087 bootutil_aes_kw_drop(&aes_kw);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020088 return rc;
89}
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020090#endif /* MCUBOOT_ENCRYPT_KW */
91
Fabio Utzigba829042018-09-18 08:29:34 -030092#if defined(MCUBOOT_ENCRYPT_RSA)
93static int
Fabio Utzig5fde8322019-10-23 12:23:08 -030094parse_rsa_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
Fabio Utzigba829042018-09-18 08:29:34 -030095{
Fabio Utzigba829042018-09-18 08:29:34 -030096 size_t len;
97
Fabio Utzig6f4d8f82019-12-12 18:46:06 -030098 if (mbedtls_asn1_get_tag(p, end, &len,
99 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -0300100 return -1;
101 }
102
103 if (*p + len != end) {
104 return -2;
105 }
106
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300107 /* Non-optional fields. */
Fabio Utzigba829042018-09-18 08:29:34 -0300108 if ( /* version */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300109 mbedtls_asn1_get_int(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(ver)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300110 /* public modulus */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300111 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300112 /* public exponent */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300113 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300114 /* private exponent */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300115 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(D)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300116 /* primes */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300117 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(P)) != 0 ||
118 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(Q)) != 0) {
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300119
Fabio Utzigba829042018-09-18 08:29:34 -0300120 return -3;
121 }
122
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300123#if !defined(MBEDTLS_RSA_NO_CRT)
124 /*
125 * DP/DQ/QP are only used inside mbedTLS if it was built with the
126 * Chinese Remainder Theorem enabled (default). In case it is disabled
127 * we parse, or if not available, we calculate those values.
128 */
129 if (*p < end) {
130 if ( /* d mod (p-1) and d mod (q-1) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300131 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DP)) != 0 ||
132 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DQ)) != 0 ||
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300133 /* q ^ (-1) mod p */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300134 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300135
136 return -4;
137 }
138 } else {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300139 if (mbedtls_rsa_deduce_crt(&ctx->MBEDTLS_CONTEXT_MEMBER(P),
140 &ctx->MBEDTLS_CONTEXT_MEMBER(Q),
141 &ctx->MBEDTLS_CONTEXT_MEMBER(D),
142 &ctx->MBEDTLS_CONTEXT_MEMBER(DP),
143 &ctx->MBEDTLS_CONTEXT_MEMBER(DQ),
144 &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300145 return -5;
146 }
147 }
148#endif
149
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300150 ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
Fabio Utzigba829042018-09-18 08:29:34 -0300151
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300152 if (mbedtls_rsa_check_privkey(ctx) != 0) {
153 return -6;
Fabio Utzigba829042018-09-18 08:29:34 -0300154 }
155
156 return 0;
157}
158#endif
159
Fabio Utzig5fde8322019-10-23 12:23:08 -0300160#if defined(MCUBOOT_ENCRYPT_EC256)
161static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
162static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
163
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300164#define SHARED_KEY_LEN NUM_ECC_BYTES
165#define PRIV_KEY_LEN NUM_ECC_BYTES
166
Fabio Utzig5fde8322019-10-23 12:23:08 -0300167/*
168 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
169 * curve keypair. See RFC5208 and RFC5915.
170 */
171static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900172parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300173{
174 int rc;
175 size_t len;
176 int version;
177 mbedtls_asn1_buf alg;
178 mbedtls_asn1_buf param;
179
180 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
181 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
182 return -1;
183 }
184
185 if (*p + len != end) {
186 return -2;
187 }
188
189 version = 0;
190 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
191 return -3;
192 }
193
194 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
195 return -5;
196 }
197
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300198 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
199 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300200 return -6;
201 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300202 if (param.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
203 memcmp(param.MBEDTLS_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300204 return -7;
205 }
206
207 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
208 return -8;
209 }
210
211 /* RFC5915 - ECPrivateKey */
212
213 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
214 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
215 return -9;
216 }
217
218 version = 0;
219 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
220 return -10;
221 }
222
223 /* privateKey */
224
225 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
226 return -11;
227 }
228
229 if (len != NUM_ECC_BYTES) {
230 return -12;
231 }
232
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300233 (void)memcpy(private_key, *p, len);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300234
235 /* publicKey usually follows but is not parsed here */
236
237 return 0;
238}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300239#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300240
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300241#if defined(MCUBOOT_ENCRYPT_X25519)
242#define X25519_OID "\x6e"
243static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
244 MBEDTLS_OID_ORG_GOV X25519_OID;
245
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300246#define SHARED_KEY_LEN 32
247#define PRIV_KEY_LEN 32
248
249static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900250parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300251{
252 size_t len;
253 int version;
254 mbedtls_asn1_buf alg;
255 mbedtls_asn1_buf param;
256
257 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
258 MBEDTLS_ASN1_SEQUENCE) != 0) {
259 return -1;
260 }
261
262 if (*p + len != end) {
263 return -2;
264 }
265
266 version = 0;
267 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
268 return -3;
269 }
270
271 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
272 return -4;
273 }
274
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300275 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
276 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300277 return -5;
278 }
279
280 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
281 return -6;
282 }
283
284 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
285 return -7;
286 }
287
288 if (len != PRIV_KEY_LEN) {
289 return -8;
290 }
291
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300292 (void)memcpy(private_key, *p, PRIV_KEY_LEN);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300293 return 0;
294}
295#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
296
297#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300298/*
299 * HKDF as described by RFC5869.
300 *
301 * @param ikm The input data to be derived.
302 * @param ikm_len Length of the input data.
303 * @param info An information tag.
304 * @param info_len Length of the information tag.
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200305 * @param salt An salt tag.
306 * @param salt_len Length of the salt tag.
Fabio Utzig5fde8322019-10-23 12:23:08 -0300307 * @param okm Output of the KDF computation.
308 * @param okm_len On input the requested length; on output the generated length
309 */
310static int
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200311hkdf(const uint8_t *ikm, uint16_t ikm_len, const uint8_t *info, uint16_t info_len,
312 const uint8_t *salt, uint16_t salt_len, uint8_t *okm, uint16_t *okm_len)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300313{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900314 bootutil_hmac_sha256_context hmac;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900315 uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
316 uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300317 uint16_t off;
318 uint16_t len;
319 uint8_t counter;
320 bool first;
321 int rc;
322
323 /*
324 * Extract
325 */
326
327 if (ikm == NULL || okm == NULL || ikm_len == 0) {
328 return -1;
329 }
330
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900331 bootutil_hmac_sha256_init(&hmac);
332
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200333 rc = bootutil_hmac_sha256_set_key(&hmac, salt, salt_len);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900334 if (rc != 0) {
335 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300336 }
337
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900338 rc = bootutil_hmac_sha256_update(&hmac, ikm, ikm_len);
339 if (rc != 0) {
340 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300341 }
342
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900343 rc = bootutil_hmac_sha256_finish(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
344 if (rc != 0) {
345 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300346 }
347
348 /*
349 * Expand
350 */
351
352 len = *okm_len;
353 counter = 1;
354 first = true;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900355 for (off = 0; len > 0; off += BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, ++counter) {
356 bootutil_hmac_sha256_init(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300357
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900358 rc = bootutil_hmac_sha256_set_key(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
359 if (rc != 0) {
360 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300361 }
362
363 if (first) {
364 first = false;
365 } else {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900366 rc = bootutil_hmac_sha256_update(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
367 if (rc != 0) {
368 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300369 }
370 }
371
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900372 rc = bootutil_hmac_sha256_update(&hmac, info, info_len);
373 if (rc != 0) {
374 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300375 }
376
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900377 rc = bootutil_hmac_sha256_update(&hmac, &counter, 1);
378 if (rc != 0) {
379 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300380 }
381
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900382 rc = bootutil_hmac_sha256_finish(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
383 if (rc != 0) {
384 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300385 }
386
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900387 if (len > BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300388 (void)memcpy(&okm[off], T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900389 len -= BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300390 } else {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300391 (void)memcpy(&okm[off], T, len);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300392 len = 0;
393 }
394 }
395
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900396 bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300397 return 0;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900398
399error:
400 bootutil_hmac_sha256_drop(&hmac);
401 return -1;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300402}
403#endif
404
Fabio Utzigba829042018-09-18 08:29:34 -0300405int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900406boot_enc_init(struct enc_key_data *enc_state, uint8_t slot)
407{
408 bootutil_aes_ctr_init(&enc_state[slot].aes_ctr);
409 return 0;
410}
411
412int
413boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot)
414{
415 bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr);
416 return 0;
417}
418
419int
Fabio Utzig4741c452019-12-19 15:32:41 -0300420boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
421 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300422{
423 int rc;
424
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900425 rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]);
426 if (rc != 0) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300427 (void)boot_enc_drop(enc_state, slot);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900428 enc_state[slot].valid = 0;
Fabio Utzigba829042018-09-18 08:29:34 -0300429 return -1;
430 }
431
432 enc_state[slot].valid = 1;
433
434 return 0;
435}
436
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200437#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
Fabio Utzig4741c452019-12-19 15:32:41 -0300438
Fabio Utzigba829042018-09-18 08:29:34 -0300439#if defined(MCUBOOT_ENCRYPT_RSA)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200440# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
Fabio Utzigba829042018-09-18 08:29:34 -0300441#elif defined(MCUBOOT_ENCRYPT_KW)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300442# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW
Fabio Utzig5fde8322019-10-23 12:23:08 -0300443#elif defined(MCUBOOT_ENCRYPT_EC256)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200444# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
445# define EXPECTED_ENC_EXT_LEN (EXPECTED_ENC_LEN + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200446# define EC_PUBK_INDEX (0)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300447# define EC_TAG_INDEX (65)
448# define EC_CIPHERKEY_INDEX (65 + 32)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300449_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig4741c452019-12-19 15:32:41 -0300450 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300451#elif defined(MCUBOOT_ENCRYPT_X25519)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200452# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300453# define EC_PUBK_INDEX (0)
454# define EC_TAG_INDEX (32)
455# define EC_CIPHERKEY_INDEX (32 + 32)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300456_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300457 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300458#endif
459
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200460#ifndef EXPECTED_ENC_EXT_LEN
461#define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_LEN
462#endif
463
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300464#if defined(MCUBOOT_ENCRYPT_RSA) || \
465 (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS))
466#if MBEDTLS_VERSION_NUMBER >= 0x03000000
467static int fake_rng(void *p_rng, unsigned char *output, size_t len)
468{
469 size_t i;
470
471 (void)p_rng;
472 for (i = 0; i < len; i++) {
473 output[i] = (char)i;
474 }
475
476 return 0;
477}
478#endif
479#endif /* defined(MCUBOOT_ENCRYPT_RSA) ||
480 defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS) */
481
Fabio Utzigba829042018-09-18 08:29:34 -0300482/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300483 * Decrypt an encryption key TLV.
484 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300485 * @param buf An encryption TLV read from flash (build time fixed length)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200486 * @param sz An encryption TLV buffer data size
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300487 * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300488 */
489int
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200490boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey, uint32_t sz, uint8_t *enciv)
Fabio Utzigba829042018-09-18 08:29:34 -0300491{
492#if defined(MCUBOOT_ENCRYPT_RSA)
493 mbedtls_rsa_context rsa;
494 uint8_t *cp;
495 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300496 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200497#endif
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900498#if defined(MCUBOOT_ENCRYPT_EC256)
499 bootutil_ecdh_p256_context ecdh_p256;
500#endif
501#if defined(MCUBOOT_ENCRYPT_X25519)
502 bootutil_ecdh_x25519_context ecdh_x25519;
503#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300504#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900505 bootutil_hmac_sha256_context hmac;
506 bootutil_aes_ctr_context aes_ctr;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200507 uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900508 uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200509 uint8_t info[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE] = "MCUBoot_ECIES_v1";
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300510 uint8_t shared[SHARED_KEY_LEN];
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200511 uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE + BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE * 2];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300512 uint8_t *cp;
513 uint8_t *cpend;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900514 uint8_t private_key[PRIV_KEY_LEN];
515 uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300516 uint16_t len;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200517 uint16_t out_len;
518 const uint8_t *my_salt = salt;
519 uint8_t *my_key_iv = counter;
520 uint8_t *my_counter = counter;
521#else
522 (void)sz;
523 (void)enciv;
Fabio Utzig4741c452019-12-19 15:32:41 -0300524#endif
525 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300526
Fabio Utzigba829042018-09-18 08:29:34 -0300527#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300528
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300529#if MBEDTLS_VERSION_NUMBER >= 0x03000000
530 mbedtls_rsa_init(&rsa);
531 mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
532#else
Fabio Utzig233af7d2019-08-26 12:06:16 -0300533 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300534#endif
Fabio Utzig233af7d2019-08-26 12:06:16 -0300535 cp = (uint8_t *)bootutil_enc_key.key;
536 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300537
Fabio Utzig5fde8322019-10-23 12:23:08 -0300538 rc = parse_rsa_enckey(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300539 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300540 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300541 return rc;
542 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300543#if MBEDTLS_VERSION_NUMBER >= 0x03000000
544 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, fake_rng, NULL,
545 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
546#else
Fabio Utzig233af7d2019-08-26 12:06:16 -0300547 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
548 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300549#endif
Fabio Utzig233af7d2019-08-26 12:06:16 -0300550 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300551
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300552#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
553
554#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300555
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300556 assert(*bootutil_enc_key.len == BOOT_ENC_KEY_SIZE);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300557 rc = key_unwrap(buf, enckey);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300558
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300559#endif /* defined(MCUBOOT_ENCRYPT_KW) */
560
561#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300562
563 cp = (uint8_t *)bootutil_enc_key.key;
564 cpend = cp + *bootutil_enc_key.len;
565
566 /*
567 * Load the stored EC256 decryption private key
568 */
569
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900570 rc = parse_ec256_enckey(&cp, cpend, private_key);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300571 if (rc) {
572 return rc;
573 }
574
Fabio Utzig5fde8322019-10-23 12:23:08 -0300575 /*
576 * First "element" in the TLV is the curve point (public key)
577 */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900578 bootutil_ecdh_p256_init(&ecdh_p256);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300579
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900580 rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200581
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900582 bootutil_ecdh_p256_drop(&ecdh_p256);
583 if (rc != 0) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300584 return -1;
585 }
586
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300587#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
588
589#if defined(MCUBOOT_ENCRYPT_X25519)
590
591 cp = (uint8_t *)bootutil_enc_key.key;
592 cpend = cp + *bootutil_enc_key.len;
593
594 /*
595 * Load the stored X25519 decryption private key
596 */
597
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900598 rc = parse_x25519_enckey(&cp, cpend, private_key);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300599 if (rc) {
600 return rc;
601 }
602
603 /*
604 * First "element" in the TLV is the curve point (public key)
605 */
606
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900607 bootutil_ecdh_x25519_init(&ecdh_x25519);
608
609 rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared);
610 bootutil_ecdh_x25519_drop(&ecdh_x25519);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300611 if (!rc) {
612 return -1;
613 }
614
615#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
616
617#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
618
Fabio Utzig5fde8322019-10-23 12:23:08 -0300619 /*
620 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
621 */
622
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200623 /* Prepare for default encryption scheme with zero salt and AES IVs */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300624 (void)memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
625 (void)memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200626
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900627 len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200628
629 if (sz > EXPECTED_ENC_LEN) {
630 /* Use new enhanced encryption scheme with randomly generated salt and AES IVs */
631 len += BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE * 2;
632
633 my_salt = &buf[EXPECTED_ENC_LEN];
634
635 my_key_iv = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
636 BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
637
638 my_counter = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
639 BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE +
640 BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
641 }
642
643 out_len = len;
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200644 rc = hkdf(shared, SHARED_KEY_LEN, info, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE,
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200645 my_salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, derived_key, &out_len);
646
647 if (rc != 0 || len != out_len) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300648 return -1;
649 }
650
651 /*
652 * HMAC the key and check that our received MAC matches the generated tag
653 */
654
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900655 bootutil_hmac_sha256_init(&hmac);
656
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300657 rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOT_ENC_KEY_SIZE], BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900658 if (rc != 0) {
659 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300660 return -1;
661 }
662
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300663 rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900664 if (rc != 0) {
665 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300666 return -1;
667 }
668
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200669 /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900670 rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
671 if (rc != 0) {
672 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300673 return -1;
674 }
675
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200676 if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) != 0) {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900677 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300678 return -1;
679 }
680
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900681 bootutil_hmac_sha256_drop(&hmac);
682
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200683 (void)memcpy(enciv, my_counter, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
684
Fabio Utzig5fde8322019-10-23 12:23:08 -0300685 /*
686 * Finally decrypt the received ciphered key
687 */
688
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900689 bootutil_aes_ctr_init(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300690
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900691 rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
692 if (rc != 0) {
693 bootutil_aes_ctr_drop(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300694 return -1;
695 }
696
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200697 rc = bootutil_aes_ctr_decrypt(&aes_ctr, my_key_iv, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, 0, enckey);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900698 if (rc != 0) {
699 bootutil_aes_ctr_drop(&aes_ctr);
700 return -1;
701 }
702
703 bootutil_aes_ctr_drop(&aes_ctr);
704
Fabio Utzig5fde8322019-10-23 12:23:08 -0300705 rc = 0;
706
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300707#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300708
Fabio Utzigba829042018-09-18 08:29:34 -0300709 return rc;
710}
711
Fabio Utzig4741c452019-12-19 15:32:41 -0300712/*
713 * Load encryption key.
714 */
715int
716boot_enc_load(struct enc_key_data *enc_state, int image_index,
717 const struct image_header *hdr, const struct flash_area *fap,
718 struct boot_status *bs)
719{
720 uint32_t off;
721 uint16_t len;
722 struct image_tlv_iter it;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300723#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
Fabio Utzig4741c452019-12-19 15:32:41 -0300724 uint8_t *buf;
725#else
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200726 uint8_t buf[EXPECTED_ENC_EXT_LEN];
Fabio Utzig4741c452019-12-19 15:32:41 -0300727#endif
728 uint8_t slot;
729 int rc;
730
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300731 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Fabio Utzig4741c452019-12-19 15:32:41 -0300732 if (rc < 0) {
733 return rc;
734 }
735 slot = rc;
736
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300737#ifndef MCUBOOT_ENC_IMAGES_XIP
Fabio Utzig4741c452019-12-19 15:32:41 -0300738 /* Already loaded... */
739 if (enc_state[slot].valid) {
740 return 1;
741 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300742#endif
Fabio Utzig4741c452019-12-19 15:32:41 -0300743
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900744 /* Initialize the AES context */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300745 (void)boot_enc_init(enc_state, slot);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900746
Fabio Utzig4741c452019-12-19 15:32:41 -0300747 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
748 if (rc) {
749 return -1;
750 }
751
752 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
753 if (rc != 0) {
754 return rc;
755 }
756
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200757 if ((len < EXPECTED_ENC_LEN) || (len > EXPECTED_ENC_EXT_LEN)) {
Fabio Utzig4741c452019-12-19 15:32:41 -0300758 return -1;
759 }
760
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300761#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
Fabio Utzig4741c452019-12-19 15:32:41 -0300762 buf = bs->enctlv[slot];
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300763 (void)memset(buf, BOOT_UNINITIALIZED_TLV_FILL, BOOT_ENC_TLV_ALIGN_SIZE);
Fabio Utzig4741c452019-12-19 15:32:41 -0300764#endif
765
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200766 rc = flash_area_read(fap, off, buf, len);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300767 if (rc != 0) {
Fabio Utzig4741c452019-12-19 15:32:41 -0300768 return -1;
769 }
770
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200771 return (boot_enc_decrypt(buf, bs->enckey[slot], len, enc_state[slot].aes_iv));
Fabio Utzig4741c452019-12-19 15:32:41 -0300772}
773
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100774bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300775boot_enc_valid(struct enc_key_data *enc_state, int image_index,
776 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300777{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100778 int rc;
779
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300780 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100781 if (rc < 0) {
782 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300783 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100784 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100785 }
786
787 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300788}
789
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300790int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300791boot_encrypt(struct enc_key_data *enc_state, int image_index,
792 const struct flash_area *fap, uint32_t off, uint32_t sz,
793 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300794{
795 struct enc_key_data *enc;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200796 uint8_t *nonce;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100797 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300798
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900799 /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
800 the TLVs. */
801 if (sz == 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300802 return 0;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900803 }
804
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300805#if MCUBOOT_SWAP_USING_SCRATCH
806/* in this case scratch area contains encrypted source block that was copied
807from secondary slot */
808 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
809 rc = 1;
810 }
811 else
812#endif
813 {
814 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
815 if (rc < 0) {
816 assert(0);
817 return rc;
818 }
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100819 }
820
821 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300822 assert(enc->valid == 1);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200823
824 nonce = enc->aes_iv;
825
826 off >>= 4;
827 nonce[12] = (uint8_t)(off >> 24);
828 nonce[13] = (uint8_t)(off >> 16);
829 nonce[14] = (uint8_t)(off >> 8);
830 nonce[15] = (uint8_t)off;
831
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300832 return bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
Fabio Utzigba829042018-09-18 08:29:34 -0300833}
834
Fabio Utzig10ee6482019-08-01 12:04:52 -0300835/**
836 * Clears encrypted state after use.
837 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300838void
839boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300840{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900841 uint8_t slot;
842 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
843 (void)boot_enc_drop(enc_state, slot);
844 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300845 (void)memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300846}
847
848#endif /* MCUBOOT_ENC_IMAGES */