blob: 12c0a9c41829630baba60d3d6d2088f1c5e76b0b [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
5 * Copyright (c) 2019 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"
Fabio Utzig6f4d8f82019-12-12 18:46:06 -030017#include "mbedtls/rsa_internal.h"
Fabio Utzigba829042018-09-18 08:29:34 -030018#include "mbedtls/asn1.h"
19#endif
20
21#if defined(MCUBOOT_ENCRYPT_KW)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090022#include "bootutil/crypto/aes_kw.h"
Fabio Utzigba829042018-09-18 08:29:34 -030023#endif
24
Fabio Utzig5fde8322019-10-23 12:23:08 -030025#if defined(MCUBOOT_ENCRYPT_EC256)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090026#include "bootutil/crypto/ecdh_p256.h"
27#endif
28
29#if defined(MCUBOOT_ENCRYPT_X25519)
30#include "bootutil/crypto/ecdh_x25519.h"
Fabio Utzig6aec6ae2020-04-02 11:06:07 -030031#endif
32
33#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090034#include "bootutil/crypto/sha256.h"
35#include "bootutil/crypto/hmac_sha256.h"
Fabio Utzig5fde8322019-10-23 12:23:08 -030036#include "mbedtls/oid.h"
37#include "mbedtls/asn1.h"
38#endif
39
Fabio Utzigba829042018-09-18 08:29:34 -030040#include "bootutil/image.h"
41#include "bootutil/enc_key.h"
42#include "bootutil/sign_key.h"
43
44#include "bootutil_priv.h"
45
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090046#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
47#if defined(_compare)
48static inline int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
49{
50 return _compare(a, b, size);
51}
52#else
53static int bootutil_constant_time_compare(const uint8_t *a, const uint8_t *b, size_t size)
54{
55 const uint8_t *tempa = a;
56 const uint8_t *tempb = b;
57 uint8_t result = 0;
58 unsigned int i;
59
60 for (i = 0; i < size; i++) {
61 result |= tempa[i] ^ tempb[i];
62 }
63 return result;
64}
65#endif
66#endif
67
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020068#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030069static int
Fabio Utzig4741c452019-12-19 15:32:41 -030070key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020071{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090072 bootutil_aes_kw_context aes_kw;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020073 int rc;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020074
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090075 bootutil_aes_kw_init(&aes_kw);
76 rc = bootutil_aes_kw_set_unwrap_key(&aes_kw, bootutil_enc_key.key, *bootutil_enc_key.len);
77 if (rc != 0) {
78 goto done;
79 }
80 rc = bootutil_aes_kw_unwrap(&aes_kw, wrapped, TLV_ENC_KW_SZ, enckey, BOOT_ENC_KEY_SIZE);
81 if (rc != 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020082 goto done;
83 }
84
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020085done:
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +090086 bootutil_aes_kw_drop(&aes_kw);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020087 return rc;
88}
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020089#endif /* MCUBOOT_ENCRYPT_KW */
90
Fabio Utzigba829042018-09-18 08:29:34 -030091#if defined(MCUBOOT_ENCRYPT_RSA)
92static int
Fabio Utzig5fde8322019-10-23 12:23:08 -030093parse_rsa_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
Fabio Utzigba829042018-09-18 08:29:34 -030094{
Fabio Utzigba829042018-09-18 08:29:34 -030095 size_t len;
96
Fabio Utzig6f4d8f82019-12-12 18:46:06 -030097 if (mbedtls_asn1_get_tag(p, end, &len,
98 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -030099 return -1;
100 }
101
102 if (*p + len != end) {
103 return -2;
104 }
105
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300106 /* Non-optional fields. */
Fabio Utzigba829042018-09-18 08:29:34 -0300107 if ( /* version */
108 mbedtls_asn1_get_int(p, end, &ctx->ver) != 0 ||
109 /* public modulus */
110 mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0 ||
111 /* public exponent */
112 mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0 ||
113 /* private exponent */
114 mbedtls_asn1_get_mpi(p, end, &ctx->D) != 0 ||
115 /* primes */
116 mbedtls_asn1_get_mpi(p, end, &ctx->P) != 0 ||
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300117 mbedtls_asn1_get_mpi(p, end, &ctx->Q) != 0) {
118
Fabio Utzigba829042018-09-18 08:29:34 -0300119 return -3;
120 }
121
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300122#if !defined(MBEDTLS_RSA_NO_CRT)
123 /*
124 * DP/DQ/QP are only used inside mbedTLS if it was built with the
125 * Chinese Remainder Theorem enabled (default). In case it is disabled
126 * we parse, or if not available, we calculate those values.
127 */
128 if (*p < end) {
129 if ( /* d mod (p-1) and d mod (q-1) */
130 mbedtls_asn1_get_mpi(p, end, &ctx->DP) != 0 ||
131 mbedtls_asn1_get_mpi(p, end, &ctx->DQ) != 0 ||
132 /* q ^ (-1) mod p */
133 mbedtls_asn1_get_mpi(p, end, &ctx->QP) != 0) {
134
135 return -4;
136 }
137 } else {
138 if (mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
139 &ctx->DP, &ctx->DQ, &ctx->QP) != 0) {
140 return -5;
141 }
142 }
143#endif
144
Fabio Utzigba829042018-09-18 08:29:34 -0300145 ctx->len = mbedtls_mpi_size(&ctx->N);
146
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300147 if (mbedtls_rsa_check_privkey(ctx) != 0) {
148 return -6;
Fabio Utzigba829042018-09-18 08:29:34 -0300149 }
150
151 return 0;
152}
153#endif
154
Fabio Utzig5fde8322019-10-23 12:23:08 -0300155#if defined(MCUBOOT_ENCRYPT_EC256)
156static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
157static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
158
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300159#define SHARED_KEY_LEN NUM_ECC_BYTES
160#define PRIV_KEY_LEN NUM_ECC_BYTES
161
Fabio Utzig5fde8322019-10-23 12:23:08 -0300162/*
163 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
164 * curve keypair. See RFC5208 and RFC5915.
165 */
166static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900167parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300168{
169 int rc;
170 size_t len;
171 int version;
172 mbedtls_asn1_buf alg;
173 mbedtls_asn1_buf param;
174
175 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
176 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
177 return -1;
178 }
179
180 if (*p + len != end) {
181 return -2;
182 }
183
184 version = 0;
185 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
186 return -3;
187 }
188
189 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
190 return -5;
191 }
192
193 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
194 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
195 return -6;
196 }
197 if (param.len != sizeof(ec_secp256r1_oid) - 1 ||
198 memcmp(param.p, ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
199 return -7;
200 }
201
202 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
203 return -8;
204 }
205
206 /* RFC5915 - ECPrivateKey */
207
208 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
209 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
210 return -9;
211 }
212
213 version = 0;
214 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
215 return -10;
216 }
217
218 /* privateKey */
219
220 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
221 return -11;
222 }
223
224 if (len != NUM_ECC_BYTES) {
225 return -12;
226 }
227
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900228 memcpy(private_key, *p, len);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300229
230 /* publicKey usually follows but is not parsed here */
231
232 return 0;
233}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300234#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300235
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300236#if defined(MCUBOOT_ENCRYPT_X25519)
237#define X25519_OID "\x6e"
238static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
239 MBEDTLS_OID_ORG_GOV X25519_OID;
240
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300241#define SHARED_KEY_LEN 32
242#define PRIV_KEY_LEN 32
243
244static int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900245parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *private_key)
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300246{
247 size_t len;
248 int version;
249 mbedtls_asn1_buf alg;
250 mbedtls_asn1_buf param;
251
252 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
253 MBEDTLS_ASN1_SEQUENCE) != 0) {
254 return -1;
255 }
256
257 if (*p + len != end) {
258 return -2;
259 }
260
261 version = 0;
262 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
263 return -3;
264 }
265
266 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
267 return -4;
268 }
269
270 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
271 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
272 return -5;
273 }
274
275 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
276 return -6;
277 }
278
279 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
280 return -7;
281 }
282
283 if (len != PRIV_KEY_LEN) {
284 return -8;
285 }
286
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900287 memcpy(private_key, *p, PRIV_KEY_LEN);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300288 return 0;
289}
290#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
291
292#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300293/*
294 * HKDF as described by RFC5869.
295 *
296 * @param ikm The input data to be derived.
297 * @param ikm_len Length of the input data.
298 * @param info An information tag.
299 * @param info_len Length of the information tag.
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200300 * @param salt An salt tag.
301 * @param salt_len Length of the salt tag.
Fabio Utzig5fde8322019-10-23 12:23:08 -0300302 * @param okm Output of the KDF computation.
303 * @param okm_len On input the requested length; on output the generated length
304 */
305static int
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200306hkdf(const uint8_t *ikm, uint16_t ikm_len, const uint8_t *info, uint16_t info_len,
307 const uint8_t *salt, uint16_t salt_len, uint8_t *okm, uint16_t *okm_len)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300308{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900309 bootutil_hmac_sha256_context hmac;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900310 uint8_t prk[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
311 uint8_t T[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300312 uint16_t off;
313 uint16_t len;
314 uint8_t counter;
315 bool first;
316 int rc;
317
318 /*
319 * Extract
320 */
321
322 if (ikm == NULL || okm == NULL || ikm_len == 0) {
323 return -1;
324 }
325
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900326 bootutil_hmac_sha256_init(&hmac);
327
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200328 rc = bootutil_hmac_sha256_set_key(&hmac, salt, salt_len);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900329 if (rc != 0) {
330 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300331 }
332
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900333 rc = bootutil_hmac_sha256_update(&hmac, ikm, ikm_len);
334 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_finish(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
339 if (rc != 0) {
340 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300341 }
342
343 /*
344 * Expand
345 */
346
347 len = *okm_len;
348 counter = 1;
349 first = true;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900350 for (off = 0; len > 0; off += BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, ++counter) {
351 bootutil_hmac_sha256_init(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300352
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900353 rc = bootutil_hmac_sha256_set_key(&hmac, prk, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
354 if (rc != 0) {
355 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300356 }
357
358 if (first) {
359 first = false;
360 } else {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900361 rc = bootutil_hmac_sha256_update(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
362 if (rc != 0) {
363 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300364 }
365 }
366
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900367 rc = bootutil_hmac_sha256_update(&hmac, info, info_len);
368 if (rc != 0) {
369 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300370 }
371
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900372 rc = bootutil_hmac_sha256_update(&hmac, &counter, 1);
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_finish(&hmac, T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
378 if (rc != 0) {
379 goto error;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300380 }
381
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900382 if (len > BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) {
383 memcpy(&okm[off], T, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
384 len -= BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300385 } else {
386 memcpy(&okm[off], T, len);
387 len = 0;
388 }
389 }
390
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900391 bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300392 return 0;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900393
394error:
395 bootutil_hmac_sha256_drop(&hmac);
396 return -1;
Fabio Utzig5fde8322019-10-23 12:23:08 -0300397}
398#endif
399
Fabio Utzigba829042018-09-18 08:29:34 -0300400int
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900401boot_enc_init(struct enc_key_data *enc_state, uint8_t slot)
402{
403 bootutil_aes_ctr_init(&enc_state[slot].aes_ctr);
404 return 0;
405}
406
407int
408boot_enc_drop(struct enc_key_data *enc_state, uint8_t slot)
409{
410 bootutil_aes_ctr_drop(&enc_state[slot].aes_ctr);
411 return 0;
412}
413
414int
Fabio Utzig4741c452019-12-19 15:32:41 -0300415boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
416 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300417{
418 int rc;
419
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900420 rc = bootutil_aes_ctr_set_key(&enc_state[slot].aes_ctr, bs->enckey[slot]);
421 if (rc != 0) {
422 boot_enc_drop(enc_state, slot);
423 enc_state[slot].valid = 0;
Fabio Utzigba829042018-09-18 08:29:34 -0300424 return -1;
425 }
426
427 enc_state[slot].valid = 1;
428
429 return 0;
430}
431
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200432#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
Fabio Utzig4741c452019-12-19 15:32:41 -0300433
Fabio Utzigba829042018-09-18 08:29:34 -0300434#if defined(MCUBOOT_ENCRYPT_RSA)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200435# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
436# define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_TLV
Fabio Utzigba829042018-09-18 08:29:34 -0300437#elif defined(MCUBOOT_ENCRYPT_KW)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200438# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
439# define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_TLV
Fabio Utzig5fde8322019-10-23 12:23:08 -0300440#elif defined(MCUBOOT_ENCRYPT_EC256)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200441# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
442# define EXPECTED_ENC_EXT_LEN (EXPECTED_ENC_LEN + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE)
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200443# define EC_PUBK_INDEX (0)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300444# define EC_TAG_INDEX (65)
445# define EC_CIPHERKEY_INDEX (65 + 32)
Fabio Utzig4741c452019-12-19 15:32:41 -0300446_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
447 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300448#elif defined(MCUBOOT_ENCRYPT_X25519)
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200449# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
450# define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_TLV
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300451# define EC_PUBK_INDEX (0)
452# define EC_TAG_INDEX (32)
453# define EC_CIPHERKEY_INDEX (32 + 32)
454_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
455 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300456#endif
457
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200458#ifndef EXPECTED_ENC_EXT_LEN
459#define EXPECTED_ENC_EXT_LEN EXPECTED_ENC_LEN
460#endif
461
Fabio Utzigba829042018-09-18 08:29:34 -0300462/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300463 * Decrypt an encryption key TLV.
464 *
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200465 * @param buf An encryption TLV buffer red from flash
466 * @param sz An encryption TLV buffer data size
Fabio Utzig4741c452019-12-19 15:32:41 -0300467 * @param enckey An AES-128 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300468 */
469int
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200470boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey, uint32_t sz, uint8_t *enciv)
Fabio Utzigba829042018-09-18 08:29:34 -0300471{
472#if defined(MCUBOOT_ENCRYPT_RSA)
473 mbedtls_rsa_context rsa;
474 uint8_t *cp;
475 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300476 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200477#endif
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900478#if defined(MCUBOOT_ENCRYPT_EC256)
479 bootutil_ecdh_p256_context ecdh_p256;
480#endif
481#if defined(MCUBOOT_ENCRYPT_X25519)
482 bootutil_ecdh_x25519_context ecdh_x25519;
483#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300484#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900485 bootutil_hmac_sha256_context hmac;
486 bootutil_aes_ctr_context aes_ctr;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200487 uint8_t salt[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900488 uint8_t tag[BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300489 uint8_t shared[SHARED_KEY_LEN];
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200490 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 -0300491 uint8_t *cp;
492 uint8_t *cpend;
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900493 uint8_t private_key[PRIV_KEY_LEN];
494 uint8_t counter[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300495 uint16_t len;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200496 uint16_t out_len;
497 const uint8_t *my_salt = salt;
498 uint8_t *my_key_iv = counter;
499 uint8_t *my_counter = counter;
500#else
501 (void)sz;
502 (void)enciv;
Fabio Utzig4741c452019-12-19 15:32:41 -0300503#endif
504 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300505
Fabio Utzigba829042018-09-18 08:29:34 -0300506#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300507
Fabio Utzig233af7d2019-08-26 12:06:16 -0300508 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Fabio Utzigba829042018-09-18 08:29:34 -0300509
Fabio Utzig233af7d2019-08-26 12:06:16 -0300510 cp = (uint8_t *)bootutil_enc_key.key;
511 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300512
Fabio Utzig5fde8322019-10-23 12:23:08 -0300513 rc = parse_rsa_enckey(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300514 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300515 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300516 return rc;
517 }
518
519 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
520 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
521 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300522
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300523#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
524
525#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300526
Fabio Utzig233af7d2019-08-26 12:06:16 -0300527 assert(*bootutil_enc_key.len == 16);
528 rc = key_unwrap(buf, enckey);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300529
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300530#endif /* defined(MCUBOOT_ENCRYPT_KW) */
531
532#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300533
534 cp = (uint8_t *)bootutil_enc_key.key;
535 cpend = cp + *bootutil_enc_key.len;
536
537 /*
538 * Load the stored EC256 decryption private key
539 */
540
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900541 rc = parse_ec256_enckey(&cp, cpend, private_key);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300542 if (rc) {
543 return rc;
544 }
545
Fabio Utzig5fde8322019-10-23 12:23:08 -0300546 /*
547 * First "element" in the TLV is the curve point (public key)
548 */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900549 bootutil_ecdh_p256_init(&ecdh_p256);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300550
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900551 rc = bootutil_ecdh_p256_shared_secret(&ecdh_p256, &buf[EC_PUBK_INDEX], private_key, shared);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200552
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900553 bootutil_ecdh_p256_drop(&ecdh_p256);
554 if (rc != 0) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300555 return -1;
556 }
557
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300558#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
559
560#if defined(MCUBOOT_ENCRYPT_X25519)
561
562 cp = (uint8_t *)bootutil_enc_key.key;
563 cpend = cp + *bootutil_enc_key.len;
564
565 /*
566 * Load the stored X25519 decryption private key
567 */
568
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900569 rc = parse_x25519_enckey(&cp, cpend, private_key);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300570 if (rc) {
571 return rc;
572 }
573
574 /*
575 * First "element" in the TLV is the curve point (public key)
576 */
577
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900578 bootutil_ecdh_x25519_init(&ecdh_x25519);
579
580 rc = bootutil_ecdh_x25519_shared_secret(&ecdh_x25519, &buf[EC_PUBK_INDEX], private_key, shared);
581 bootutil_ecdh_x25519_drop(&ecdh_x25519);
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300582 if (!rc) {
583 return -1;
584 }
585
586#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
587
588#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
589
Fabio Utzig5fde8322019-10-23 12:23:08 -0300590 /*
591 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
592 */
593
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200594 /* Prepare for default encryption scheme with zero salt and AES IVs */
595 memset(counter, 0, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
596 memset(salt, 0, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
597
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900598 len = BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE + BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200599
600 if (sz > EXPECTED_ENC_LEN) {
601 /* Use new enhanced encryption scheme with randomly generated salt and AES IVs */
602 len += BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE * 2;
603
604 my_salt = &buf[EXPECTED_ENC_LEN];
605
606 my_key_iv = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
607 BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE];
608
609 my_counter = &derived_key[BOOTUTIL_CRYPTO_AES_CTR_KEY_SIZE +
610 BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE +
611 BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE];
612 }
613
614 out_len = len;
615 rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE,
616 my_salt, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE, derived_key, &out_len);
617
618 if (rc != 0 || len != out_len) {
Fabio Utzig5fde8322019-10-23 12:23:08 -0300619 return -1;
620 }
621
622 /*
623 * HMAC the key and check that our received MAC matches the generated tag
624 */
625
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900626 bootutil_hmac_sha256_init(&hmac);
627
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200628 rc = bootutil_hmac_sha256_set_key(&hmac, &derived_key[BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE], BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900629 if (rc != 0) {
630 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300631 return -1;
632 }
633
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200634 rc = bootutil_hmac_sha256_update(&hmac, &buf[EC_CIPHERKEY_INDEX], BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900635 if (rc != 0) {
636 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300637 return -1;
638 }
639
Bohdan Kovalchuk25c7a0f2020-11-30 21:32:14 +0200640 /* Assumes the tag buffer is at least sizeof(hmac_tag_size(state)) bytes */
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900641 rc = bootutil_hmac_sha256_finish(&hmac, tag, BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE);
642 if (rc != 0) {
643 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300644 return -1;
645 }
646
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200647 if (bootutil_constant_time_compare(tag, &buf[EC_TAG_INDEX], BOOTUTIL_CRYPTO_SHA256_DIGEST_SIZE) != 0) {
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900648 (void)bootutil_hmac_sha256_drop(&hmac);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300649 return -1;
650 }
651
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900652 bootutil_hmac_sha256_drop(&hmac);
653
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200654 (void)memcpy(enciv, my_counter, BOOTUTIL_CRYPTO_AES_CTR_BLOCK_SIZE);
655
Fabio Utzig5fde8322019-10-23 12:23:08 -0300656 /*
657 * Finally decrypt the received ciphered key
658 */
659
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900660 bootutil_aes_ctr_init(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300661
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900662 rc = bootutil_aes_ctr_set_key(&aes_ctr, derived_key);
663 if (rc != 0) {
664 bootutil_aes_ctr_drop(&aes_ctr);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300665 return -1;
666 }
667
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200668 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 +0900669 if (rc != 0) {
670 bootutil_aes_ctr_drop(&aes_ctr);
671 return -1;
672 }
673
674 bootutil_aes_ctr_drop(&aes_ctr);
675
Fabio Utzig5fde8322019-10-23 12:23:08 -0300676 rc = 0;
677
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300678#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300679
Fabio Utzigba829042018-09-18 08:29:34 -0300680 return rc;
681}
682
Fabio Utzig4741c452019-12-19 15:32:41 -0300683/*
684 * Load encryption key.
685 */
686int
687boot_enc_load(struct enc_key_data *enc_state, int image_index,
688 const struct image_header *hdr, const struct flash_area *fap,
689 struct boot_status *bs)
690{
691 uint32_t off;
692 uint16_t len;
693 struct image_tlv_iter it;
694#if MCUBOOT_SWAP_SAVE_ENCTLV
695 uint8_t *buf;
696#else
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200697 uint8_t buf[EXPECTED_ENC_EXT_LEN];
Fabio Utzig4741c452019-12-19 15:32:41 -0300698#endif
699 uint8_t slot;
700 int rc;
701
702 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
703 if (rc < 0) {
704 return rc;
705 }
706 slot = rc;
707
708 /* Already loaded... */
709 if (enc_state[slot].valid) {
710 return 1;
711 }
712
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900713 /* Initialize the AES context */
714 boot_enc_init(enc_state, slot);
715
Fabio Utzig4741c452019-12-19 15:32:41 -0300716 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
717 if (rc) {
718 return -1;
719 }
720
721 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
722 if (rc != 0) {
723 return rc;
724 }
725
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200726 if ((len < EXPECTED_ENC_LEN) || (len > EXPECTED_ENC_EXT_LEN)) {
Fabio Utzig4741c452019-12-19 15:32:41 -0300727 return -1;
728 }
729
730#if MCUBOOT_SWAP_SAVE_ENCTLV
731 buf = bs->enctlv[slot];
732 memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
733#endif
734
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200735 rc = flash_area_read(fap, off, buf, len);
Fabio Utzig4741c452019-12-19 15:32:41 -0300736 if (rc) {
737 return -1;
738 }
739
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200740 return (boot_enc_decrypt(buf, bs->enckey[slot], len, enc_state[slot].aes_iv));
Fabio Utzig4741c452019-12-19 15:32:41 -0300741}
742
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100743bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300744boot_enc_valid(struct enc_key_data *enc_state, int image_index,
745 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300746{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100747 int rc;
748
Fabio Utzigb0f04732019-07-31 09:49:19 -0300749 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100750 if (rc < 0) {
751 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300752 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100753 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100754 }
755
756 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300757}
758
759void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300760boot_encrypt(struct enc_key_data *enc_state, int image_index,
761 const struct flash_area *fap, uint32_t off, uint32_t sz,
762 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300763{
764 struct enc_key_data *enc;
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200765 uint8_t *nonce;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100766 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300767
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900768 /* boot_copy_region will call boot_encrypt with sz = 0 when skipping over
769 the TLVs. */
770 if (sz == 0) {
771 return;
772 }
773
Fabio Utzigb0f04732019-07-31 09:49:19 -0300774 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100775 if (rc < 0) {
776 assert(0);
777 return;
778 }
779
780 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300781 assert(enc->valid == 1);
Roman Okhrimenko13f79ed2021-03-11 19:05:41 +0200782
783 nonce = enc->aes_iv;
784
785 off >>= 4;
786 nonce[12] = (uint8_t)(off >> 24);
787 nonce[13] = (uint8_t)(off >> 16);
788 nonce[14] = (uint8_t)(off >> 8);
789 nonce[15] = (uint8_t)off;
790
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900791 bootutil_aes_ctr_encrypt(&enc->aes_ctr, nonce, buf, sz, blk_off, buf);
Fabio Utzigba829042018-09-18 08:29:34 -0300792}
793
Fabio Utzig10ee6482019-08-01 12:04:52 -0300794/**
795 * Clears encrypted state after use.
796 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300797void
798boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300799{
Blaž Hrastnik4f4833d2020-09-14 13:53:31 +0900800 uint8_t slot;
801 for (slot = 0; slot < BOOT_NUM_SLOTS; slot++) {
802 (void)boot_enc_drop(enc_state, slot);
803 }
Fabio Utzig10ee6482019-08-01 12:04:52 -0300804 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300805}
806
807#endif /* MCUBOOT_ENC_IMAGES */