blob: 6d37ecb5733387cee9d932cc56aa3417a5609d0a [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
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +020051#ifdef MCUBOOT_ENC_IMAGES_XIP_MULTI
52#include "xip_encryption.h"
53#endif /* MCUBOOT_ENC_IMAGES_XIP_MULTI */
54
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090055#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
56#if defined(_compare)
57static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
58{
59 return _compare(a, b, size);
60}
61#else
62static int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
63{
64 const uint8_t *tempa = a;
65 const uint8_t *tempb = b;
66 uint8_t result = 0;
67 unsigned int i;
68
69 for (i = 0; i < size; i++) {
70 result |= tempa[i] ^ tempb[i];
71 }
72 return result;
73}
74#endif
75#endif
76
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020077#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030078static int
Fabio Utzig4741c452019-12-19 15:32:41 -030079key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020080{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090081 bootutil_aes_kw_context aes_kw;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020082 int rc;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020083
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090084 bootutil_aes_kw_init(&aes_kw);
85 rc = bootutil_aes_kw_set_unwrap_key(&aes_kw, bootutil_enc_key.key, *bootutil_enc_key.len);
Roman Okhrimenko977b3752022-03-31 14:40:48 +030086
87 if (rc == 0) {
88 rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020089 }
90
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090091 bootutil_aes_kw_drop(&aes_kw);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020092 return rc;
93}
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020094#endif /* MCUBOOT_ENCRYPT_KW */
95
Fabio Utzigba829042018-09-18 08:29:34 -030096#if defined(MCUBOOT_ENCRYPT_RSA)
97static int
Fabio Utzig5fde8322019-10-23 12:23:08 -030098parse_rsa_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
Fabio Utzigba829042018-09-18 08:29:34 -030099{
Fabio Utzigba829042018-09-18 08:29:34 -0300100 size_t len;
101
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300102 if (mbedtls_asn1_get_tag(p, end, &len,
103 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -0300104 return -1;
105 }
106
107 if (*p + len != end) {
108 return -2;
109 }
110
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300111 /* Non-optional fields. */
Fabio Utzigba829042018-09-18 08:29:34 -0300112 if ( /* version */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300113 mbedtls_asn1_get_int(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(ver)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300114 /* public modulus */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300115 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300116 /* public exponent */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300117 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300118 /* private exponent */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300119 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(D)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300120 /* primes */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300121 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(P)) != 0 ||
122 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(Q)) != 0) {
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300123
Fabio Utzigba829042018-09-18 08:29:34 -0300124 return -3;
125 }
126
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300127#if !defined(MBEDTLS_RSA_NO_CRT)
128 /*
129 * DP/DQ/QP are only used inside mbedTLS if it was built with the
130 * Chinese Remainder Theorem enabled (default). In case it is disabled
131 * we parse, or if not available, we calculate those values.
132 */
133 if (*p < end) {
134 if ( /* d mod (p-1) and d mod (q-1) */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300135 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DP)) != 0 ||
136 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(DQ)) != 0 ||
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300137 /* q ^ (-1) mod p */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300138 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300139
140 return -4;
141 }
142 } else {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300143 if (mbedtls_rsa_deduce_crt(&ctx->MBEDTLS_CONTEXT_MEMBER(P),
144 &ctx->MBEDTLS_CONTEXT_MEMBER(Q),
145 &ctx->MBEDTLS_CONTEXT_MEMBER(D),
146 &ctx->MBEDTLS_CONTEXT_MEMBER(DP),
147 &ctx->MBEDTLS_CONTEXT_MEMBER(DQ),
148 &ctx->MBEDTLS_CONTEXT_MEMBER(QP)) != 0) {
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300149 return -5;
150 }
151 }
152#endif
153
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300154 ctx->MBEDTLS_CONTEXT_MEMBER(len) = mbedtls_mpi_size(&ctx->MBEDTLS_CONTEXT_MEMBER(N));
Fabio Utzigba829042018-09-18 08:29:34 -0300155
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300156 if (mbedtls_rsa_check_privkey(ctx) != 0) {
157 return -6;
Fabio Utzigba829042018-09-18 08:29:34 -0300158 }
159
160 return 0;
161}
162#endif
163
Fabio Utzig5fde8322019-10-23 12:23:08 -0300164#if defined(MCUBOOT_ENCRYPT_EC256)
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200165#if !defined(MCUBOOT_USE_PSA_CRYPTO)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300166static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
167static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200168#endif
Fabio Utzig5fde8322019-10-23 12:23:08 -0300169
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300170#define SHARED_KEY_LEN NUM_ECC_BYTES
171#define PRIV_KEY_LEN NUM_ECC_BYTES
172
Fabio Utzig5fde8322019-10-23 12:23:08 -0300173/*
174 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
175 * curve keypair. See RFC5208 and RFC5915.
176 */
177static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900178parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300179{
180 int rc;
181 size_t len;
182 int version;
183 mbedtls_asn1_buf alg;
184 mbedtls_asn1_buf param;
185
186 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
187 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
188 return -1;
189 }
190
191 if (*p + len != end) {
192 return -2;
193 }
194
195 version = 0;
196 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
197 return -3;
198 }
199
200 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
201 return -5;
202 }
203
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200204#if !defined(MCUBOOT_USE_PSA_CRYPTO)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300205 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
206 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300207 return -6;
208 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300209 if (param.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
210 memcmp(param.MBEDTLS_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300211 return -7;
212 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200213#endif
Fabio Utzig5fde8322019-10-23 12:23:08 -0300214
215 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
216 return -8;
217 }
218
219 /* RFC5915 - ECPrivateKey */
220
221 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
222 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
223 return -9;
224 }
225
226 version = 0;
227 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
228 return -10;
229 }
230
231 /* privateKey */
232
233 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
234 return -11;
235 }
236
237 if (len != NUM_ECC_BYTES) {
238 return -12;
239 }
240
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300241 (void)memcpy(private_key, *p, len);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300242
243 /* publicKey usually follows but is not parsed here */
244
245 return 0;
246}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300247#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300248
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300249#if defined(MCUBOOT_ENCRYPT_X25519)
250#define X25519_OID "\x6e"
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200251#if !defined(MCUBOOT_USE_PSA_CRYPTO)
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300252static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
253 MBEDTLS_OID_ORG_GOV X25519_OID;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200254#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300255
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300256#define SHARED_KEY_LEN 32
257#define PRIV_KEY_LEN 32
258
259static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900260parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300261{
262 size_t len;
263 int version;
264 mbedtls_asn1_buf alg;
265 mbedtls_asn1_buf param;
266
267 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
268 MBEDTLS_ASN1_SEQUENCE) != 0) {
269 return -1;
270 }
271
272 if (*p + len != end) {
273 return -2;
274 }
275
276 version = 0;
277 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
278 return -3;
279 }
280
281 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
282 return -4;
283 }
284
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200285#if !defined(MCUBOOT_USE_PSA_CRYPTO)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300286 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
287 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300288 return -5;
289 }
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200290#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300291
292 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
293 return -6;
294 }
295
296 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
297 return -7;
298 }
299
300 if (len != PRIV_KEY_LEN) {
301 return -8;
302 }
303
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300304 (void)memcpy(private_key, *p, PRIV_KEY_LEN);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300305 return 0;
306}
307#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
308
309#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300310/*
311 * HKDF as described by RFC5869.
312 *
313 * @param ikm The input data to be derived.
314 * @param ikm_len Length of the input data.
315 * @param info An information tag.
316 * @param info_len Length of the information tag.
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200317 * @param salt An salt tag.
318 * @param salt_len Length of the salt tag.
Fabio Utzig5fde8322019-10-23 12:23:08 -0300319 * @param okm Output of the KDF computation.
320 * @param okm_len On input the requested length; on output the generated length
321 */
322static int
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200323hkdf(const uint8_t *ikm, uint16_t ikm_len, const uint8_t *info, uint16_t info_len,
324 const uint8_t *salt, uint16_t salt_len, uint8_t *okm, uint16_t *okm_len)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300325{
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200326#if !defined(MCUBOOT_USE_PSA_CRYPTO)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900327 bootutil_hmac_sha256_context hmac;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900328 uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
329 uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300330 uint16_t off;
331 uint16_t len;
332 uint8_t counter;
333 bool first;
334 int rc;
335
336 /*
337 * Extract
338 */
339
340 if (ikm == NULL || okm == NULL || ikm_len == 0) {
341 return -1;
342 }
343
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900344 bootutil_hmac_sha256_init(&hmac);
345
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200346 rc = bootutil_hmac_sha256_set_key(&hmac, salt, salt_len);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900347 if (rc != 0) {
348 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300349 }
350
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900351 rc = bootutil_hmac_sha256_update(&hmac, ikm, ikm_len);
352 if (rc != 0) {
353 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300354 }
355
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900356 rc = bootutil_hmac_sha256_finish(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
357 if (rc != 0) {
358 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300359 }
360
361 /*
362 * Expand
363 */
364
365 len = *okm_len;
366 counter = 1;
367 first = true;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900368 for (off = 0; len > 0; off += BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, ++counter) {
369 bootutil_hmac_sha256_init(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300370
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900371 rc = bootutil_hmac_sha256_set_key(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
372 if (rc != 0) {
373 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300374 }
375
376 if (first) {
377 first = false;
378 } else {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900379 rc = bootutil_hmac_sha256_update(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
380 if (rc != 0) {
381 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300382 }
383 }
384
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900385 rc = bootutil_hmac_sha256_update(&hmac, info, info_len);
386 if (rc != 0) {
387 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300388 }
389
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900390 rc = bootutil_hmac_sha256_update(&hmac, &counter, 1);
391 if (rc != 0) {
392 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300393 }
394
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900395 rc = bootutil_hmac_sha256_finish(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
396 if (rc != 0) {
397 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300398 }
399
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900400 if (len > BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300401 (void)memcpy(&okm[off], T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900402 len -= BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300403 } else {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300404 (void)memcpy(&okm[off], T, len);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300405 len = 0;
406 }
407 }
408
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900409 bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300410 return 0;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900411
412error:
413 bootutil_hmac_sha256_drop(&hmac);
414 return -1;
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200415#else
416 psa_status_t status;
417 psa_key_handle_t key_handle;
418 psa_key_derivation_operation_t operation = psa_key_derivation_operation_init();
419
420 {
421 psa_key_attributes_t key_attributes = psa_key_attributes_init();
422 psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
423 psa_set_key_algorithm(&key_attributes, PSA_ALG_HKDF(PSA_ALG_SHA_256));
424 psa_set_key_type(&key_attributes, PSA_KEY_TYPE_DERIVE);
425 psa_set_key_bits(&key_attributes, 256u);
426
427 status = psa_import_key(&key_attributes, ikm, ikm_len, &key_handle);
428 }
429
430 if (status == PSA_SUCCESS)
431 {
432 status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF(PSA_ALG_SHA_256));
433 }
434
435 if (status == PSA_SUCCESS)
436 {
437 status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, salt, salt_len);
438 }
439
440 if (status == PSA_SUCCESS)
441 {
442 status = psa_key_derivation_input_key(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, key_handle);
443 }
444
445 if (status == PSA_SUCCESS)
446 {
447 status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO, info, info_len);
448 }
449
450 if (status == PSA_SUCCESS)
451 {
452 status = psa_key_derivation_output_bytes(&operation, okm, *okm_len);
453 }
454
455 psa_key_derivation_abort(&operation);
456 psa_destroy_key(key_handle);
457
458 if (status != PSA_SUCCESS)
459 {
460 return -1;
461 }
462
463 return 0;
464#endif
Fabio Utzig5fde8322019-10-23 12:23:08 -0300465}
466#endif
467
Fabio Utzigba829042018-09-18 08:29:34 -0300468int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900469boot_enc_init(struct enc_key_data *enc_state, uint8_t slot)
470{
471 bootutil_aes_ctr_init(&enc_state[slot].aes_ctr);
472 return 0;
473}
474
475int
476boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot)
477{
478 bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr);
479 return 0;
480}
481
482int
Fabio Utzig4741c452019-12-19 15:32:41 -0300483boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
484 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300485{
486 int rc;
487
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900488 rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]);
489 if (rc != 0) {
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300490 (void)boot_enc_drop(enc_state, slot);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900491 enc_state[slot].valid = 0;
Fabio Utzigba829042018-09-18 08:29:34 -0300492 return -1;
493 }
494
495 enc_state[slot].valid = 1;
496
497 return 0;
498}
499
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200500#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
Fabio Utzig4741c452019-12-19 15:32:41 -0300501
Fabio Utzigba829042018-09-18 08:29:34 -0300502#if defined(MCUBOOT_ENCRYPT_RSA)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200503# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
Fabio Utzigba829042018-09-18 08:29:34 -0300504#elif defined(MCUBOOT_ENCRYPT_KW)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300505# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW
Fabio Utzig5fde8322019-10-23 12:23:08 -0300506#elif defined(MCUBOOT_ENCRYPT_EC256)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200507# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
508# define EXPECTED_ENC_EXT_LEN (EXPECTED_ENC_LEN + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200509# define EC_PUBK_INDEX (0)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300510# define EC_TAG_INDEX (65)
511# define EC_CIPHERKEY_INDEX (65 + 32)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300512_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig4741c452019-12-19 15:32:41 -0300513 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300514#elif defined(MCUBOOT_ENCRYPT_X25519)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200515# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300516# define EC_PUBK_INDEX (0)
517# define EC_TAG_INDEX (32)
518# define EC_CIPHERKEY_INDEX (32 + 32)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300519_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300520 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300521#endif
522
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200523#ifndef EXPECTED_ENC_EXT_LEN
524#define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_LEN
525#endif
526
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300527#if defined(MCUBOOT_ENCRYPT_RSA) || \
528 (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS))
529#if MBEDTLS_VERSION_NUMBER >= 0x03000000
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200530#if !defined(MCUBOOT_USE_PSA_CRYPTO)
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300531static int fake_rng(void *p_rng, unsigned char *output, size_t len)
532{
533 size_t i;
534
535 (void)p_rng;
536 for (i = 0; i < len; i++) {
537 output[i] = (char)i;
538 }
539
540 return 0;
541}
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200542#endif /* MCUBOOT_USE_PSA_CRYPTO */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300543#endif
544#endif /* defined(MCUBOOT_ENCRYPT_RSA) ||
545 defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS) */
Fabio Utzigba829042018-09-18 08:29:34 -0300546/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300547 * Decrypt an encryption key TLV.
548 *
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300549 * @param buf An encryption TLV read from flash (build time fixed length)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200550 * @param sz An encryption TLV buffer data size
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300551 * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300552 */
553int
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200554boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey, uint32_t sz, uint8_t *enciv)
Fabio Utzigba829042018-09-18 08:29:34 -0300555{
556#if defined(MCUBOOT_ENCRYPT_RSA)
557 mbedtls_rsa_context rsa;
558 uint8_t *cp;
559 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300560 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200561#endif
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900562#if defined(MCUBOOT_ENCRYPT_EC256)
563 bootutil_ecdh_p256_context ecdh_p256;
564#endif
565#if defined(MCUBOOT_ENCRYPT_X25519)
566 bootutil_ecdh_x25519_context ecdh_x25519;
567#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300568#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900569 bootutil_hmac_sha256_context hmac;
570 bootutil_aes_ctr_context aes_ctr;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200571 uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900572 uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200573 uint8_t info[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE] = "MCUBoot_ECIES_v1";
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300574 uint8_t shared[SHARED_KEY_LEN];
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200575 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 -0300576 uint8_t *cp;
577 uint8_t *cpend;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900578 uint8_t private_key[PRIV_KEY_LEN];
579 uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300580 uint16_t len;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200581 uint16_t out_len;
582 const uint8_t *my_salt = salt;
583 uint8_t *my_key_iv = counter;
584 uint8_t *my_counter = counter;
585#else
586 (void)sz;
587 (void)enciv;
Fabio Utzig4741c452019-12-19 15:32:41 -0300588#endif
589 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300590
Fabio Utzigba829042018-09-18 08:29:34 -0300591#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300592
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300593#if MBEDTLS_VERSION_NUMBER >= 0x03000000
594 mbedtls_rsa_init(&rsa);
595 mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
596#else
Fabio Utzig233af7d2019-08-26 12:06:16 -0300597 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300598#endif
Fabio Utzig233af7d2019-08-26 12:06:16 -0300599 cp = (uint8_t *)bootutil_enc_key.key;
600 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300601
Fabio Utzig5fde8322019-10-23 12:23:08 -0300602 rc = parse_rsa_enckey(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300603 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300604 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300605 return rc;
606 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300607#if MBEDTLS_VERSION_NUMBER >= 0x03000000
608 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, fake_rng, NULL,
609 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
610#else
Fabio Utzig233af7d2019-08-26 12:06:16 -0300611 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
612 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300613#endif
Fabio Utzig233af7d2019-08-26 12:06:16 -0300614 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300615
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300616#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
617
618#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300619
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300620 assert(*bootutil_enc_key.len == BOOT_ENC_KEY_SIZE);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300621 rc = key_unwrap(buf, enckey);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300622
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300623#endif /* defined(MCUBOOT_ENCRYPT_KW) */
624
625#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300626
627 cp = (uint8_t *)bootutil_enc_key.key;
628 cpend = cp + *bootutil_enc_key.len;
629
630 /*
631 * Load the stored EC256 decryption private key
632 */
633
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900634 rc = parse_ec256_enckey(&cp, cpend, private_key);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300635 if (rc) {
636 return rc;
637 }
638
Fabio Utzig5fde8322019-10-23 12:23:08 -0300639 /*
640 * First "element" in the TLV is the curve point (public key)
641 */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900642 bootutil_ecdh_p256_init(&ecdh_p256);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300643
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900644 rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200645
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900646 bootutil_ecdh_p256_drop(&ecdh_p256);
647 if (rc != 0) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300648 return -1;
649 }
650
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300651#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
652
653#if defined(MCUBOOT_ENCRYPT_X25519)
654
655 cp = (uint8_t *)bootutil_enc_key.key;
656 cpend = cp + *bootutil_enc_key.len;
657
658 /*
659 * Load the stored X25519 decryption private key
660 */
661
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900662 rc = parse_x25519_enckey(&cp, cpend, private_key);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300663 if (rc) {
664 return rc;
665 }
666
667 /*
668 * First "element" in the TLV is the curve point (public key)
669 */
670
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900671 bootutil_ecdh_x25519_init(&ecdh_x25519);
672
673 rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared);
674 bootutil_ecdh_x25519_drop(&ecdh_x25519);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300675 if (!rc) {
676 return -1;
677 }
678
679#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
680
681#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
682
Fabio Utzig5fde8322019-10-23 12:23:08 -0300683 /*
684 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
685 */
686
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200687 /* Prepare for default encryption scheme with zero salt and AES IVs */
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300688 (void)memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
689 (void)memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200690
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900691 len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200692
693 if (sz > EXPECTED_ENC_LEN) {
694 /* Use new enhanced encryption scheme with randomly generated salt and AES IVs */
695 len += BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE * 2;
696
697 my_salt = &buf[EXPECTED_ENC_LEN];
698
699 my_key_iv = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
700 BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
701
702 my_counter = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
703 BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE +
704 BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
705 }
706
707 out_len = len;
Roman Okhrimenko883cb5b2024-03-28 17:22:33 +0200708 rc = hkdf(shared, SHARED_KEY_LEN, info, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE,
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200709 my_salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, derived_key, &out_len);
710
711 if (rc != 0 || len != out_len) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300712 return -1;
713 }
714
715 /*
716 * HMAC the key and check that our received MAC matches the generated tag
717 */
718
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900719 bootutil_hmac_sha256_init(&hmac);
720
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300721 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 +0900722 if (rc != 0) {
723 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300724 return -1;
725 }
726
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300727 rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900728 if (rc != 0) {
729 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300730 return -1;
731 }
732
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200733 /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900734 rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
735 if (rc != 0) {
736 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300737 return -1;
738 }
739
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200740 if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) != 0) {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900741 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300742 return -1;
743 }
744
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900745 bootutil_hmac_sha256_drop(&hmac);
746
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200747 (void)memcpy(enciv, my_counter, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
748
Fabio Utzig5fde8322019-10-23 12:23:08 -0300749 /*
750 * Finally decrypt the received ciphered key
751 */
752
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900753 bootutil_aes_ctr_init(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300754
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900755 rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
756 if (rc != 0) {
757 bootutil_aes_ctr_drop(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300758 return -1;
759 }
760
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200761 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 +0900762 if (rc != 0) {
763 bootutil_aes_ctr_drop(&aes_ctr);
764 return -1;
765 }
766
767 bootutil_aes_ctr_drop(&aes_ctr);
768
Fabio Utzig5fde8322019-10-23 12:23:08 -0300769 rc = 0;
770
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300771#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300772
Fabio Utzigba829042018-09-18 08:29:34 -0300773 return rc;
774}
775
Fabio Utzig4741c452019-12-19 15:32:41 -0300776/*
777 * Load encryption key.
778 */
779int
780boot_enc_load(struct enc_key_data *enc_state, int image_index,
781 const struct image_header *hdr, const struct flash_area *fap,
782 struct boot_status *bs)
783{
784 uint32_t off;
785 uint16_t len;
786 struct image_tlv_iter it;
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300787#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
Fabio Utzig4741c452019-12-19 15:32:41 -0300788 uint8_t *buf;
789#else
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200790 uint8_t buf[EXPECTED_ENC_EXT_LEN];
Fabio Utzig4741c452019-12-19 15:32:41 -0300791#endif
792 uint8_t slot;
793 int rc;
794
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300795 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Fabio Utzig4741c452019-12-19 15:32:41 -0300796 if (rc < 0) {
797 return rc;
798 }
799 slot = rc;
800
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300801#ifndef MCUBOOT_ENC_IMAGES_XIP
Fabio Utzig4741c452019-12-19 15:32:41 -0300802 /* Already loaded... */
803 if (enc_state[slot].valid) {
804 return 1;
805 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300806#endif
Fabio Utzig4741c452019-12-19 15:32:41 -0300807
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900808 /* Initialize the AES context */
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300809 (void)boot_enc_init(enc_state, slot);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900810
Fabio Utzig4741c452019-12-19 15:32:41 -0300811 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
812 if (rc) {
813 return -1;
814 }
815
816 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
817 if (rc != 0) {
818 return rc;
819 }
820
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200821 if ((len < EXPECTED_ENC_LEN) || (len > EXPECTED_ENC_EXT_LEN)) {
Fabio Utzig4741c452019-12-19 15:32:41 -0300822 return -1;
823 }
824
Roman Okhrimenkodc0ca082023-06-21 20:49:51 +0300825#ifdef MCUBOOT_SWAP_SAVE_ENCTLV
Fabio Utzig4741c452019-12-19 15:32:41 -0300826 buf = bs->enctlv[slot];
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300827 (void)memset(buf, BOOT_UNINITIALIZED_TLV_FILL, BOOT_ENC_TLV_ALIGN_SIZE);
Fabio Utzig4741c452019-12-19 15:32:41 -0300828#endif
829
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200830 rc = flash_area_read(fap, off, buf, len);
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300831 if (rc != 0) {
Fabio Utzig4741c452019-12-19 15:32:41 -0300832 return -1;
833 }
834
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200835 return (boot_enc_decrypt(buf, bs->enckey[slot], len, enc_state[slot].aes_iv));
Fabio Utzig4741c452019-12-19 15:32:41 -0300836}
837
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100838bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300839boot_enc_valid(struct enc_key_data *enc_state, int image_index,
840 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300841{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100842 int rc;
843
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300844 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100845 if (rc < 0) {
846 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300847 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100848 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100849 }
850
851 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300852}
853
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300854int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300855boot_encrypt(struct enc_key_data *enc_state, int image_index,
856 const struct flash_area *fap, uint32_t off, uint32_t sz,
857 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300858{
859 struct enc_key_data *enc;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200860 uint8_t *nonce;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100861 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300862
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900863 /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
864 the TLVs. */
865 if (sz == 0) {
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300866 return 0;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900867 }
868
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300869#if MCUBOOT_SWAP_USING_SCRATCH
870/* in this case scratch area contains encrypted source block that was copied
871from secondary slot */
872 if (fap->fa_id == FLASH_AREA_IMAGE_SCRATCH) {
873 rc = 1;
874 }
875 else
876#endif
877 {
878 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
879 if (rc < 0) {
880 assert(0);
881 return rc;
882 }
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100883 }
884
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200885 enc = &enc_state[rc];
886 assert(enc->valid == 1);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200887
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200888 nonce = enc->aes_iv;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200889
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200890 off >>= 4;
891 nonce[12] = (uint8_t)(off >> 24);
892 nonce[13] = (uint8_t)(off >> 16);
893 nonce[14] = (uint8_t)(off >> 8);
894 nonce[15] = (uint8_t)off;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200895
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200896 return bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
Fabio Utzigba829042018-09-18 08:29:34 -0300897}
898
Fabio Utzig10ee6482019-08-01 12:04:52 -0300899/**
900 * Clears encrypted state after use.
901 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300902void
903boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300904{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900905 uint8_t slot;
906 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
907 (void)boot_enc_drop(enc_state, slot);
908 }
Roman Okhrimenko977b3752022-03-31 14:40:48 +0300909 (void)memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300910}
911
912#endif /* MCUBOOT_ENC_IMAGES */
INFINEON\DovhalA3b578f32024-11-29 01:06:04 +0200913
914/*
915 * Avoid warning from -pedantic. This is included
916 * because ISO C forbids an empty translation unit.
917 */
918typedef int encrypted_iso_c_forbids_empty_translation_units;