blob: fdd98524cbe15f10db2fdee7a25a09b0bbb385d2 [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
Salome Thirot0f641972021-05-14 11:19:55 +01005 * 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"
Sherry Zhangb111f982021-07-13 17:11:47 +080017#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"
Sherry Zhangb111f982021-07-13 17:11:47 +080021#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"
Sherry Zhangb111f982021-07-13 17:11:47 +080047#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);
82 if (rc != 0) {
83 goto done;
84 }
85 rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE);
86 if (rc != 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020087 goto done;
88 }
89
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020090done:
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 */
Sherry Zhangb111f982021-07-13 17:11:47 +0800113 mbedtls_asn1_get_int(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(ver)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300114 /* public modulus */
Sherry Zhangb111f982021-07-13 17:11:47 +0800115 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(N)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300116 /* public exponent */
Sherry Zhangb111f982021-07-13 17:11:47 +0800117 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(E)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300118 /* private exponent */
Sherry Zhangb111f982021-07-13 17:11:47 +0800119 mbedtls_asn1_get_mpi(p, end, &ctx->MBEDTLS_CONTEXT_MEMBER(D)) != 0 ||
Fabio Utzigba829042018-09-18 08:29:34 -0300120 /* primes */
Sherry Zhangb111f982021-07-13 17:11:47 +0800121 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) */
Sherry Zhangb111f982021-07-13 17:11:47 +0800135 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 */
Sherry Zhangb111f982021-07-13 17:11:47 +0800138 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 {
Sherry Zhangb111f982021-07-13 17:11:47 +0800143 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
Sherry Zhangb111f982021-07-13 17:11:47 +0800154 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)
165static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
166static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
167
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300168#define SHARED_KEY_LEN NUM_ECC_BYTES
169#define PRIV_KEY_LEN NUM_ECC_BYTES
170
Fabio Utzig5fde8322019-10-23 12:23:08 -0300171/*
172 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
173 * curve keypair. See RFC5208 and RFC5915.
174 */
175static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900176parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300177{
178 int rc;
179 size_t len;
180 int version;
181 mbedtls_asn1_buf alg;
182 mbedtls_asn1_buf param;
183
184 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
185 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
186 return -1;
187 }
188
189 if (*p + len != end) {
190 return -2;
191 }
192
193 version = 0;
194 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
195 return -3;
196 }
197
198 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
199 return -5;
200 }
201
Sherry Zhangb111f982021-07-13 17:11:47 +0800202 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
203 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300204 return -6;
205 }
Sherry Zhangb111f982021-07-13 17:11:47 +0800206 if (param.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_secp256r1_oid) - 1 ||
207 memcmp(param.MBEDTLS_CONTEXT_MEMBER(p), ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300208 return -7;
209 }
210
211 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
212 return -8;
213 }
214
215 /* RFC5915 - ECPrivateKey */
216
217 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
218 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
219 return -9;
220 }
221
222 version = 0;
223 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
224 return -10;
225 }
226
227 /* privateKey */
228
229 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
230 return -11;
231 }
232
233 if (len != NUM_ECC_BYTES) {
234 return -12;
235 }
236
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900237 memcpy(private_key, *p, len);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300238
239 /* publicKey usually follows but is not parsed here */
240
241 return 0;
242}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300243#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300244
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300245#if defined(MCUBOOT_ENCRYPT_X25519)
246#define X25519_OID "\x6e"
247static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
248 MBEDTLS_OID_ORG_GOV X25519_OID;
249
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300250#define SHARED_KEY_LEN 32
251#define PRIV_KEY_LEN 32
252
253static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900254parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300255{
256 size_t len;
257 int version;
258 mbedtls_asn1_buf alg;
259 mbedtls_asn1_buf param;
260
261 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
262 MBEDTLS_ASN1_SEQUENCE) != 0) {
263 return -1;
264 }
265
266 if (*p + len != end) {
267 return -2;
268 }
269
270 version = 0;
271 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
272 return -3;
273 }
274
275 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
276 return -4;
277 }
278
Sherry Zhangb111f982021-07-13 17:11:47 +0800279 if (alg.MBEDTLS_CONTEXT_MEMBER(len) != sizeof(ec_pubkey_oid) - 1 ||
280 memcmp(alg.MBEDTLS_CONTEXT_MEMBER(p), ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300281 return -5;
282 }
283
284 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
285 return -6;
286 }
287
288 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
289 return -7;
290 }
291
292 if (len != PRIV_KEY_LEN) {
293 return -8;
294 }
295
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900296 memcpy(private_key, *p, PRIV_KEY_LEN);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300297 return 0;
298}
299#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
300
301#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300302/*
303 * HKDF as described by RFC5869.
304 *
305 * @param ikm The input data to be derived.
306 * @param ikm_len Length of the input data.
307 * @param info An information tag.
308 * @param info_len Length of the information tag.
309 * @param okm Output of the KDF computation.
310 * @param okm_len On input the requested length; on output the generated length
311 */
312static int
313hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
314 uint8_t *okm, uint16_t *okm_len)
315{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900316 bootutil_hmac_sha256_context hmac;
317 uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
318 uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
319 uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300320 uint16_t off;
321 uint16_t len;
322 uint8_t counter;
323 bool first;
324 int rc;
325
326 /*
327 * Extract
328 */
329
330 if (ikm == NULL || okm == NULL || ikm_len == 0) {
331 return -1;
332 }
333
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900334 bootutil_hmac_sha256_init(&hmac);
335
336 memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
337 rc = bootutil_hmac_sha256_set_key(&hmac, salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
338 if (rc != 0) {
339 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300340 }
341
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900342 rc = bootutil_hmac_sha256_update(&hmac, ikm, ikm_len);
343 if (rc != 0) {
344 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300345 }
346
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900347 rc = bootutil_hmac_sha256_finish(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
348 if (rc != 0) {
349 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300350 }
351
352 /*
353 * Expand
354 */
355
356 len = *okm_len;
357 counter = 1;
358 first = true;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900359 for (off = 0; len > 0; off += BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, ++counter) {
360 bootutil_hmac_sha256_init(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300361
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900362 rc = bootutil_hmac_sha256_set_key(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
363 if (rc != 0) {
364 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300365 }
366
367 if (first) {
368 first = false;
369 } else {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900370 rc = bootutil_hmac_sha256_update(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
371 if (rc != 0) {
372 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300373 }
374 }
375
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900376 rc = bootutil_hmac_sha256_update(&hmac, info, info_len);
377 if (rc != 0) {
378 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300379 }
380
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900381 rc = bootutil_hmac_sha256_update(&hmac, &counter, 1);
382 if (rc != 0) {
383 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300384 }
385
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900386 rc = bootutil_hmac_sha256_finish(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
387 if (rc != 0) {
388 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300389 }
390
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900391 if (len > BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) {
392 memcpy(&okm[off], T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
393 len -= BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300394 } else {
395 memcpy(&okm[off], T, len);
396 len = 0;
397 }
398 }
399
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900400 bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300401 return 0;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900402
403error:
404 bootutil_hmac_sha256_drop(&hmac);
405 return -1;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300406}
407#endif
408
Fabio Utzigba829042018-09-18 08:29:34 -0300409int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900410boot_enc_init(struct enc_key_data *enc_state, uint8_t slot)
411{
412 bootutil_aes_ctr_init(&enc_state[slot].aes_ctr);
413 return 0;
414}
415
416int
417boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot)
418{
419 bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr);
420 return 0;
421}
422
423int
Fabio Utzig4741c452019-12-19 15:32:41 -0300424boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
425 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300426{
427 int rc;
428
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900429 rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]);
430 if (rc != 0) {
431 boot_enc_drop(enc_state, slot);
432 enc_state[slot].valid = 0;
Fabio Utzigba829042018-09-18 08:29:34 -0300433 return -1;
434 }
435
436 enc_state[slot].valid = 1;
437
438 return 0;
439}
440
Fabio Utzig4741c452019-12-19 15:32:41 -0300441#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
442
Fabio Utzigba829042018-09-18 08:29:34 -0300443#if defined(MCUBOOT_ENCRYPT_RSA)
444# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
Fabio Utzigba829042018-09-18 08:29:34 -0300445#elif defined(MCUBOOT_ENCRYPT_KW)
Salome Thirot0f641972021-05-14 11:19:55 +0100446# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW
Fabio Utzig5fde8322019-10-23 12:23:08 -0300447#elif defined(MCUBOOT_ENCRYPT_EC256)
448# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200449# define EC_PUBK_INDEX (0)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300450# define EC_TAG_INDEX (65)
451# define EC_CIPHERKEY_INDEX (65 + 32)
Salome Thirot0f641972021-05-14 11:19:55 +0100452_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig4741c452019-12-19 15:32:41 -0300453 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300454#elif defined(MCUBOOT_ENCRYPT_X25519)
455# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
456# define EC_PUBK_INDEX (0)
457# define EC_TAG_INDEX (32)
458# define EC_CIPHERKEY_INDEX (32 + 32)
Salome Thirot0f641972021-05-14 11:19:55 +0100459_Static_assert(EC_CIPHERKEY_INDEX + BOOT_ENC_KEY_SIZE == EXPECTED_ENC_LEN,
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300460 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300461#endif
462
Sherry Zhangb111f982021-07-13 17:11:47 +0800463#if defined(MCUBOOT_ENCRYPT_RSA) || \
464 (defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS))
465#if MBEDTLS_VERSION_NUMBER >= 0x03000000
466static int fake_rng(void *p_rng, unsigned char *output, size_t len)
467{
468 size_t i;
469
470 (void)p_rng;
471 for (i = 0; i < len; i++) {
472 output[i] = (char)i;
473 }
474
475 return 0;
476}
477#endif
478#endif /* defined(MCUBOOT_ENCRYPT_RSA) ||
479 defined(MCUBOOT_ENCRYPT_EC256) && defined(MCUBOOT_USE_MBED_TLS) */
480
Fabio Utzigba829042018-09-18 08:29:34 -0300481/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300482 * Decrypt an encryption key TLV.
483 *
484 * @param buf An encryption TLV read from flash (build time fixed length)
Salome Thirot0f641972021-05-14 11:19:55 +0100485 * @param enckey An AES-128 or AES-256 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300486 */
487int
Fabio Utzig4741c452019-12-19 15:32:41 -0300488boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
Fabio Utzigba829042018-09-18 08:29:34 -0300489{
490#if defined(MCUBOOT_ENCRYPT_RSA)
491 mbedtls_rsa_context rsa;
492 uint8_t *cp;
493 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300494 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200495#endif
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900496#if defined(MCUBOOT_ENCRYPT_EC256)
497 bootutil_ecdh_p256_context ecdh_p256;
498#endif
499#if defined(MCUBOOT_ENCRYPT_X25519)
500 bootutil_ecdh_x25519_context ecdh_x25519;
501#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300502#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900503 bootutil_hmac_sha256_context hmac;
504 bootutil_aes_ctr_context aes_ctr;
505 uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300506 uint8_t shared[SHARED_KEY_LEN];
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900507 uint8_t derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300508 uint8_t *cp;
509 uint8_t *cpend;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900510 uint8_t private_key[PRIV_KEY_LEN];
511 uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300512 uint16_t len;
Fabio Utzig4741c452019-12-19 15:32:41 -0300513#endif
514 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300515
Fabio Utzigba829042018-09-18 08:29:34 -0300516#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300517
Sherry Zhangb111f982021-07-13 17:11:47 +0800518#if MBEDTLS_VERSION_NUMBER >= 0x03000000
519 mbedtls_rsa_init(&rsa);
520 mbedtls_rsa_set_padding(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
521#else
Fabio Utzig233af7d2019-08-26 12:06:16 -0300522 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Sherry Zhangb111f982021-07-13 17:11:47 +0800523#endif
Fabio Utzig233af7d2019-08-26 12:06:16 -0300524 cp = (uint8_t *)bootutil_enc_key.key;
525 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300526
Fabio Utzig5fde8322019-10-23 12:23:08 -0300527 rc = parse_rsa_enckey(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300528 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300529 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300530 return rc;
531 }
Sherry Zhangb111f982021-07-13 17:11:47 +0800532#if MBEDTLS_VERSION_NUMBER >= 0x03000000
533 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, fake_rng, NULL,
534 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
535#else
Fabio Utzig233af7d2019-08-26 12:06:16 -0300536 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
537 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
Sherry Zhangb111f982021-07-13 17:11:47 +0800538#endif
Fabio Utzig233af7d2019-08-26 12:06:16 -0300539 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300540
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300541#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
542
543#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300544
Salome Thirot0f641972021-05-14 11:19:55 +0100545 assert(*bootutil_enc_key.len == BOOT_ENC_KEY_SIZE);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300546 rc = key_unwrap(buf, enckey);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300547
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300548#endif /* defined(MCUBOOT_ENCRYPT_KW) */
549
550#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300551
552 cp = (uint8_t *)bootutil_enc_key.key;
553 cpend = cp + *bootutil_enc_key.len;
554
555 /*
556 * Load the stored EC256 decryption private key
557 */
558
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900559 rc = parse_ec256_enckey(&cp, cpend, private_key);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300560 if (rc) {
561 return rc;
562 }
563
Fabio Utzig5fde8322019-10-23 12:23:08 -0300564 /*
565 * First "element" in the TLV is the curve point (public key)
566 */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900567 bootutil_ecdh_p256_init(&ecdh_p256);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300568
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900569 rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
570 bootutil_ecdh_p256_drop(&ecdh_p256);
571 if (rc != 0) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300572 return -1;
573 }
574
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300575#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
576
577#if defined(MCUBOOT_ENCRYPT_X25519)
578
579 cp = (uint8_t *)bootutil_enc_key.key;
580 cpend = cp + *bootutil_enc_key.len;
581
582 /*
583 * Load the stored X25519 decryption private key
584 */
585
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900586 rc = parse_x25519_enckey(&cp, cpend, private_key);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300587 if (rc) {
588 return rc;
589 }
590
591 /*
592 * First "element" in the TLV is the curve point (public key)
593 */
594
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900595 bootutil_ecdh_x25519_init(&ecdh_x25519);
596
597 rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared);
598 bootutil_ecdh_x25519_drop(&ecdh_x25519);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300599 if (!rc) {
600 return -1;
601 }
602
603#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
604
605#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
606
Fabio Utzig5fde8322019-10-23 12:23:08 -0300607 /*
608 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
609 */
610
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900611 len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300612 rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
Fabio Utzig5fde8322019-10-23 12:23:08 -0300613 derived_key, &len);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900614 if (rc != 0 || len != (BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300615 return -1;
616 }
617
618 /*
619 * HMAC the key and check that our received MAC matches the generated tag
620 */
621
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900622 bootutil_hmac_sha256_init(&hmac);
623
Salome Thirot0f641972021-05-14 11:19:55 +0100624 rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOT_ENC_KEY_SIZE], 32);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900625 if (rc != 0) {
626 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300627 return -1;
628 }
629
Salome Thirot0f641972021-05-14 11:19:55 +0100630 rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], BOOT_ENC_KEY_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900631 if (rc != 0) {
632 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300633 return -1;
634 }
635
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200636 /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900637 rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
638 if (rc != 0) {
639 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300640 return -1;
641 }
642
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900643 if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
644 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300645 return -1;
646 }
647
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900648 bootutil_hmac_sha256_drop(&hmac);
649
Fabio Utzig5fde8322019-10-23 12:23:08 -0300650 /*
651 * Finally decrypt the received ciphered key
652 */
653
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900654 bootutil_aes_ctr_init(&aes_ctr);
655 if (rc != 0) {
656 bootutil_aes_ctr_drop(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300657 return -1;
658 }
659
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900660 rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
661 if (rc != 0) {
662 bootutil_aes_ctr_drop(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300663 return -1;
664 }
665
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900666 memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
667 rc = bootutil_aes_ctr_decrypt(&aes_ctr, counter, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE, 0, enckey);
668 if (rc != 0) {
669 bootutil_aes_ctr_drop(&aes_ctr);
670 return -1;
671 }
672
673 bootutil_aes_ctr_drop(&aes_ctr);
674
Fabio Utzig5fde8322019-10-23 12:23:08 -0300675 rc = 0;
676
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300677#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300678
Fabio Utzigba829042018-09-18 08:29:34 -0300679 return rc;
680}
681
Fabio Utzig4741c452019-12-19 15:32:41 -0300682/*
683 * Load encryption key.
684 */
685int
686boot_enc_load(struct enc_key_data *enc_state, int image_index,
687 const struct image_header *hdr, const struct flash_area *fap,
688 struct boot_status *bs)
689{
690 uint32_t off;
691 uint16_t len;
692 struct image_tlv_iter it;
693#if MCUBOOT_SWAP_SAVE_ENCTLV
694 uint8_t *buf;
695#else
696 uint8_t buf[EXPECTED_ENC_LEN];
697#endif
698 uint8_t slot;
699 int rc;
700
Dominik Ermel260ae092021-04-23 05:38:45 +0000701 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Fabio Utzig4741c452019-12-19 15:32:41 -0300702 if (rc < 0) {
703 return rc;
704 }
705 slot = rc;
706
707 /* Already loaded... */
708 if (enc_state[slot].valid) {
709 return 1;
710 }
711
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900712 /* Initialize the AES context */
713 boot_enc_init(enc_state, slot);
714
Fabio Utzig4741c452019-12-19 15:32:41 -0300715 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
716 if (rc) {
717 return -1;
718 }
719
720 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
721 if (rc != 0) {
722 return rc;
723 }
724
725 if (len != EXPECTED_ENC_LEN) {
726 return -1;
727 }
728
729#if MCUBOOT_SWAP_SAVE_ENCTLV
730 buf = bs->enctlv[slot];
731 memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
732#endif
733
734 rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
735 if (rc) {
736 return -1;
737 }
738
739 return boot_enc_decrypt(buf, bs->enckey[slot]);
740}
741
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100742bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300743boot_enc_valid(struct enc_key_data *enc_state, int image_index,
744 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300745{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100746 int rc;
747
Dominik Ermel260ae092021-04-23 05:38:45 +0000748 rc = flash_area_id_to_multi_image_slot(image_index, flash_area_get_id(fap));
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100749 if (rc < 0) {
750 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300751 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100752 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100753 }
754
755 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300756}
757
758void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300759boot_encrypt(struct enc_key_data *enc_state, int image_index,
760 const struct flash_area *fap, uint32_t off, uint32_t sz,
761 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300762{
763 struct enc_key_data *enc;
Fabio Utzigba829042018-09-18 08:29:34 -0300764 uint8_t nonce[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100765 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300766
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900767 /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
768 the TLVs. */
769 if (sz == 0) {
770 return;
771 }
772
Fabio Utzigba829042018-09-18 08:29:34 -0300773 memset(nonce, 0, 12);
774 off >>= 4;
775 nonce[12] = (uint8_t)(off >> 24);
776 nonce[13] = (uint8_t)(off >> 16);
777 nonce[14] = (uint8_t)(off >> 8);
778 nonce[15] = (uint8_t)off;
779
Dominik Ermel260ae092021-04-23 05:38:45 +0000780 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 assert(0);
783 return;
784 }
785
786 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300787 assert(enc->valid == 1);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900788 bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
Fabio Utzigba829042018-09-18 08:29:34 -0300789}
790
Fabio Utzig10ee6482019-08-01 12:04:52 -0300791/**
792 * Clears encrypted state after use.
793 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300794void
795boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300796{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900797 uint8_t slot;
798 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
799 (void)boot_enc_drop(enc_state, slot);
800 }
Fabio Utzig10ee6482019-08-01 12:04:52 -0300801 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300802}
803
804#endif /* MCUBOOT_ENC_IMAGES */