blob: b62a31ec1dc1c08590e894b6e689e8b99fc86c80 [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)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020022# if defined(MCUBOOT_USE_MBED_TLS)
23# include "mbedtls/nist_kw.h"
24# include "mbedtls/aes.h"
25# else
26# include "tinycrypt/aes.h"
27# endif
Fabio Utzigba829042018-09-18 08:29:34 -030028#endif
29
Fabio Utzig5fde8322019-10-23 12:23:08 -030030#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -030031#include "tinycrypt/ecc.h"
32#include "tinycrypt/ecc_dh.h"
Fabio Utzig6aec6ae2020-04-02 11:06:07 -030033#endif
34
35#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
36#include "tinycrypt/utils.h"
37#include "tinycrypt/constants.h"
Fabio Utzig5fde8322019-10-23 12:23:08 -030038#include "tinycrypt/ctr_mode.h"
39#include "tinycrypt/hmac.h"
40#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"
47
48#include "bootutil_priv.h"
49
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020050#if defined(MCUBOOT_ENCRYPT_KW)
51#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030052static int
Fabio Utzig4741c452019-12-19 15:32:41 -030053key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020054{
55 mbedtls_nist_kw_context kw;
56 int rc;
57 size_t olen;
58
59 mbedtls_nist_kw_init(&kw);
60
61 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES,
62 bootutil_enc_key.key, *bootutil_enc_key.len * 8, 0);
63 if (rc) {
64 goto done;
65 }
66
67 rc = mbedtls_nist_kw_unwrap(&kw, MBEDTLS_KW_MODE_KW, wrapped, TLV_ENC_KW_SZ,
68 enckey, &olen, BOOT_ENC_KEY_SIZE);
69
70done:
71 mbedtls_nist_kw_free(&kw);
72 return rc;
73}
74#else /* !MCUBOOT_USE_MBED_TLS */
75/*
76 * Implements AES key unwrapping following RFC-3394 section 2.2.2, using
77 * tinycrypt for AES-128 decryption.
78 */
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030079static int
Fabio Utzig4741c452019-12-19 15:32:41 -030080key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020081{
82 struct tc_aes_key_sched_struct aes;
83 uint8_t A[8];
84 uint8_t B[16];
85 int8_t i, j, k;
86
87 if (tc_aes128_set_decrypt_key(&aes, bootutil_enc_key.key) == 0) {
88 return -1;
89 }
90
91 for (k = 0; k < 8; k++) {
92 A[k] = wrapped[k];
93 enckey[k] = wrapped[8 + k];
94 enckey[8 + k] = wrapped[16 + k];
95 }
96
97 for (j = 5; j >= 0; j--) {
98 for (i = 2; i > 0; i--) {
99 for (k = 0; k < 8; k++) {
100 B[k] = A[k];
101 B[8 + k] = enckey[((i-1) * 8) + k];
102 }
103 B[7] ^= 2 * j + i;
104 if (tc_aes_decrypt((uint8_t *)&B, (uint8_t *)&B, &aes) == 0) {
105 return -1;
106 }
107 for (k = 0; k < 8; k++) {
108 A[k] = B[k];
109 enckey[((i-1) * 8) + k] = B[8 + k];
110 }
111 }
112 }
113
114 for (i = 0, k = 0; i < 8; i++) {
115 k |= A[i] ^ 0xa6;
116 }
117 if (k) {
118 return -1;
119 }
120 return 0;
121}
122#endif /* MCUBOOT_USE_MBED_TLS */
123#endif /* MCUBOOT_ENCRYPT_KW */
124
Fabio Utzigba829042018-09-18 08:29:34 -0300125#if defined(MCUBOOT_ENCRYPT_RSA)
126static int
Fabio Utzig5fde8322019-10-23 12:23:08 -0300127parse_rsa_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
Fabio Utzigba829042018-09-18 08:29:34 -0300128{
Fabio Utzigba829042018-09-18 08:29:34 -0300129 size_t len;
130
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300131 if (mbedtls_asn1_get_tag(p, end, &len,
132 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -0300133 return -1;
134 }
135
136 if (*p + len != end) {
137 return -2;
138 }
139
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300140 /* Non-optional fields. */
Fabio Utzigba829042018-09-18 08:29:34 -0300141 if ( /* version */
142 mbedtls_asn1_get_int(p, end, &ctx->ver) != 0 ||
143 /* public modulus */
144 mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0 ||
145 /* public exponent */
146 mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0 ||
147 /* private exponent */
148 mbedtls_asn1_get_mpi(p, end, &ctx->D) != 0 ||
149 /* primes */
150 mbedtls_asn1_get_mpi(p, end, &ctx->P) != 0 ||
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300151 mbedtls_asn1_get_mpi(p, end, &ctx->Q) != 0) {
152
Fabio Utzigba829042018-09-18 08:29:34 -0300153 return -3;
154 }
155
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300156#if !defined(MBEDTLS_RSA_NO_CRT)
157 /*
158 * DP/DQ/QP are only used inside mbedTLS if it was built with the
159 * Chinese Remainder Theorem enabled (default). In case it is disabled
160 * we parse, or if not available, we calculate those values.
161 */
162 if (*p < end) {
163 if ( /* d mod (p-1) and d mod (q-1) */
164 mbedtls_asn1_get_mpi(p, end, &ctx->DP) != 0 ||
165 mbedtls_asn1_get_mpi(p, end, &ctx->DQ) != 0 ||
166 /* q ^ (-1) mod p */
167 mbedtls_asn1_get_mpi(p, end, &ctx->QP) != 0) {
168
169 return -4;
170 }
171 } else {
172 if (mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
173 &ctx->DP, &ctx->DQ, &ctx->QP) != 0) {
174 return -5;
175 }
176 }
177#endif
178
Fabio Utzigba829042018-09-18 08:29:34 -0300179 ctx->len = mbedtls_mpi_size(&ctx->N);
180
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300181 if (mbedtls_rsa_check_privkey(ctx) != 0) {
182 return -6;
Fabio Utzigba829042018-09-18 08:29:34 -0300183 }
184
185 return 0;
186}
187#endif
188
Fabio Utzig5fde8322019-10-23 12:23:08 -0300189#if defined(MCUBOOT_ENCRYPT_EC256)
190static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
191static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
192
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300193#define SHARED_KEY_LEN NUM_ECC_BYTES
194#define PRIV_KEY_LEN NUM_ECC_BYTES
195
Fabio Utzig5fde8322019-10-23 12:23:08 -0300196/*
197 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
198 * curve keypair. See RFC5208 and RFC5915.
199 */
200static int
201parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
202{
203 int rc;
204 size_t len;
205 int version;
206 mbedtls_asn1_buf alg;
207 mbedtls_asn1_buf param;
208
209 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
210 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
211 return -1;
212 }
213
214 if (*p + len != end) {
215 return -2;
216 }
217
218 version = 0;
219 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
220 return -3;
221 }
222
223 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
224 return -5;
225 }
226
227 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
228 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
229 return -6;
230 }
231 if (param.len != sizeof(ec_secp256r1_oid) - 1 ||
232 memcmp(param.p, ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
233 return -7;
234 }
235
236 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
237 return -8;
238 }
239
240 /* RFC5915 - ECPrivateKey */
241
242 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
243 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
244 return -9;
245 }
246
247 version = 0;
248 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
249 return -10;
250 }
251
252 /* privateKey */
253
254 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
255 return -11;
256 }
257
258 if (len != NUM_ECC_BYTES) {
259 return -12;
260 }
261
262 memcpy(pk, *p, len);
263
264 /* publicKey usually follows but is not parsed here */
265
266 return 0;
267}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300268#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300269
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300270#if defined(MCUBOOT_ENCRYPT_X25519)
271#define X25519_OID "\x6e"
272static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
273 MBEDTLS_OID_ORG_GOV X25519_OID;
274
275extern int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
276 const uint8_t peer_public_value[32]);
277
278#define SHARED_KEY_LEN 32
279#define PRIV_KEY_LEN 32
280
281static int
282parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
283{
284 size_t len;
285 int version;
286 mbedtls_asn1_buf alg;
287 mbedtls_asn1_buf param;
288
289 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
290 MBEDTLS_ASN1_SEQUENCE) != 0) {
291 return -1;
292 }
293
294 if (*p + len != end) {
295 return -2;
296 }
297
298 version = 0;
299 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
300 return -3;
301 }
302
303 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
304 return -4;
305 }
306
307 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
308 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
309 return -5;
310 }
311
312 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
313 return -6;
314 }
315
316 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
317 return -7;
318 }
319
320 if (len != PRIV_KEY_LEN) {
321 return -8;
322 }
323
324 memcpy(pk, *p, PRIV_KEY_LEN);
325 return 0;
326}
327#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
328
329#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300330/*
331 * HKDF as described by RFC5869.
332 *
333 * @param ikm The input data to be derived.
334 * @param ikm_len Length of the input data.
335 * @param info An information tag.
336 * @param info_len Length of the information tag.
337 * @param okm Output of the KDF computation.
338 * @param okm_len On input the requested length; on output the generated length
339 */
340static int
341hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
342 uint8_t *okm, uint16_t *okm_len)
343{
344 struct tc_hmac_state_struct hmac;
345 uint8_t salt[TC_SHA256_DIGEST_SIZE];
346 uint8_t prk[TC_SHA256_DIGEST_SIZE];
347 uint8_t T[TC_SHA256_DIGEST_SIZE];
348 uint16_t off;
349 uint16_t len;
350 uint8_t counter;
351 bool first;
352 int rc;
353
354 /*
355 * Extract
356 */
357
358 if (ikm == NULL || okm == NULL || ikm_len == 0) {
359 return -1;
360 }
361
362 memset(salt, 0, TC_SHA256_DIGEST_SIZE);
363 rc = tc_hmac_set_key(&hmac, salt, TC_SHA256_DIGEST_SIZE);
364 if (rc != TC_CRYPTO_SUCCESS) {
365 return -1;
366 }
367
368 rc = tc_hmac_init(&hmac);
369 if (rc != TC_CRYPTO_SUCCESS) {
370 return -1;
371 }
372
373 rc = tc_hmac_update(&hmac, ikm, ikm_len);
374 if (rc != TC_CRYPTO_SUCCESS) {
375 return -1;
376 }
377
378 rc = tc_hmac_final(prk, TC_SHA256_DIGEST_SIZE, &hmac);
379 if (rc != TC_CRYPTO_SUCCESS) {
380 return -1;
381 }
382
383 /*
384 * Expand
385 */
386
387 len = *okm_len;
388 counter = 1;
389 first = true;
390 for (off = 0; len > 0; off += TC_SHA256_DIGEST_SIZE, ++counter) {
391 rc = tc_hmac_set_key(&hmac, prk, TC_SHA256_DIGEST_SIZE);
392 if (rc != TC_CRYPTO_SUCCESS) {
393 return -1;
394 }
395
396 rc = tc_hmac_init(&hmac);
397 if (rc != TC_CRYPTO_SUCCESS) {
398 return -1;
399 }
400
401 if (first) {
402 first = false;
403 } else {
404 rc = tc_hmac_update(&hmac, T, TC_SHA256_DIGEST_SIZE);
405 if (rc != TC_CRYPTO_SUCCESS) {
406 return -1;
407 }
408 }
409
410 rc = tc_hmac_update(&hmac, info, info_len);
411 if (rc != TC_CRYPTO_SUCCESS) {
412 return -1;
413 }
414
415 rc = tc_hmac_update(&hmac, &counter, 1);
416 if (rc != TC_CRYPTO_SUCCESS) {
417 return -1;
418 }
419
420 rc = tc_hmac_final(T, TC_SHA256_DIGEST_SIZE, &hmac);
421 if (rc != TC_CRYPTO_SUCCESS) {
422 return -1;
423 }
424
425 if (len > TC_SHA256_DIGEST_SIZE) {
426 memcpy(&okm[off], T, TC_SHA256_DIGEST_SIZE);
427 len -= TC_SHA256_DIGEST_SIZE;
428 } else {
429 memcpy(&okm[off], T, len);
430 len = 0;
431 }
432 }
433
434 return 0;
435}
436#endif
437
Fabio Utzigba829042018-09-18 08:29:34 -0300438int
Fabio Utzig4741c452019-12-19 15:32:41 -0300439boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
440 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300441{
442 int rc;
443
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200444#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300445 mbedtls_aes_init(&enc_state[slot].aes);
Fabio Utzig4741c452019-12-19 15:32:41 -0300446 rc = mbedtls_aes_setkey_enc(&enc_state[slot].aes, bs->enckey[slot],
447 BOOT_ENC_KEY_SIZE_BITS);
Fabio Utzigba829042018-09-18 08:29:34 -0300448 if (rc) {
449 mbedtls_aes_free(&enc_state[slot].aes);
450 return -1;
451 }
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200452#else
453 (void)rc;
454
455 /* set_encrypt and set_decrypt do the same thing in tinycrypt */
Fabio Utzig4741c452019-12-19 15:32:41 -0300456 tc_aes128_set_encrypt_key(&enc_state[slot].aes, bs->enckey[slot]);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200457#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300458
459 enc_state[slot].valid = 1;
460
461 return 0;
462}
463
Fabio Utzig4741c452019-12-19 15:32:41 -0300464#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
465
Fabio Utzigba829042018-09-18 08:29:34 -0300466#if defined(MCUBOOT_ENCRYPT_RSA)
467# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
Fabio Utzigba829042018-09-18 08:29:34 -0300468#elif defined(MCUBOOT_ENCRYPT_KW)
469# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
Fabio Utzig5fde8322019-10-23 12:23:08 -0300470#elif defined(MCUBOOT_ENCRYPT_EC256)
471# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
Fabio Utzig5fde8322019-10-23 12:23:08 -0300472# define EC_PUBK_INDEX (1)
473# define EC_TAG_INDEX (65)
474# define EC_CIPHERKEY_INDEX (65 + 32)
Fabio Utzig4741c452019-12-19 15:32:41 -0300475_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
476 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300477#elif defined(MCUBOOT_ENCRYPT_X25519)
478# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
479# define EC_PUBK_INDEX (0)
480# define EC_TAG_INDEX (32)
481# define EC_CIPHERKEY_INDEX (32 + 32)
482_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
483 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300484#endif
485
486/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300487 * Decrypt an encryption key TLV.
488 *
489 * @param buf An encryption TLV read from flash (build time fixed length)
490 * @param enckey An AES-128 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300491 */
492int
Fabio Utzig4741c452019-12-19 15:32:41 -0300493boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
Fabio Utzigba829042018-09-18 08:29:34 -0300494{
495#if defined(MCUBOOT_ENCRYPT_RSA)
496 mbedtls_rsa_context rsa;
497 uint8_t *cp;
498 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300499 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200500#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300501#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300502 struct tc_hmac_state_struct hmac;
503 struct tc_aes_key_sched_struct aes;
504 uint8_t tag[TC_SHA256_DIGEST_SIZE];
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300505 uint8_t shared[SHARED_KEY_LEN];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300506 uint8_t derived_key[TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE];
507 uint8_t *cp;
508 uint8_t *cpend;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300509 uint8_t pk[PRIV_KEY_LEN];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300510 uint8_t counter[TC_AES_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300511 uint16_t len;
Fabio Utzig4741c452019-12-19 15:32:41 -0300512#endif
513 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300514
Fabio Utzigba829042018-09-18 08:29:34 -0300515#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300516
Fabio Utzig233af7d2019-08-26 12:06:16 -0300517 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Fabio Utzigba829042018-09-18 08:29:34 -0300518
Fabio Utzig233af7d2019-08-26 12:06:16 -0300519 cp = (uint8_t *)bootutil_enc_key.key;
520 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300521
Fabio Utzig5fde8322019-10-23 12:23:08 -0300522 rc = parse_rsa_enckey(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300523 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300524 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300525 return rc;
526 }
527
528 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
529 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
530 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300531
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300532#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
533
534#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300535
Fabio Utzig233af7d2019-08-26 12:06:16 -0300536 assert(*bootutil_enc_key.len == 16);
537 rc = key_unwrap(buf, enckey);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300538
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300539#endif /* defined(MCUBOOT_ENCRYPT_KW) */
540
541#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300542
543 cp = (uint8_t *)bootutil_enc_key.key;
544 cpend = cp + *bootutil_enc_key.len;
545
546 /*
547 * Load the stored EC256 decryption private key
548 */
549
550 rc = parse_ec256_enckey(&cp, cpend, pk);
551 if (rc) {
552 return rc;
553 }
554
555 /* is EC point uncompressed? */
556 if (buf[0] != 0x04) {
557 return -1;
558 }
559
560 /*
561 * First "element" in the TLV is the curve point (public key)
562 */
563 rc = uECC_valid_public_key(&buf[EC_PUBK_INDEX], uECC_secp256r1());
564 if (rc != 0) {
565 return -1;
566 }
567
568 rc = uECC_shared_secret(&buf[EC_PUBK_INDEX], pk, shared, uECC_secp256r1());
569 if (rc != TC_CRYPTO_SUCCESS) {
570 return -1;
571 }
572
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300573#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
574
575#if defined(MCUBOOT_ENCRYPT_X25519)
576
577 cp = (uint8_t *)bootutil_enc_key.key;
578 cpend = cp + *bootutil_enc_key.len;
579
580 /*
581 * Load the stored X25519 decryption private key
582 */
583
584 rc = parse_x25519_enckey(&cp, cpend, pk);
585 if (rc) {
586 return rc;
587 }
588
589 /*
590 * First "element" in the TLV is the curve point (public key)
591 */
592
593 rc = X25519(shared, pk, &buf[EC_PUBK_INDEX]);
594 if (!rc) {
595 return -1;
596 }
597
598#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
599
600#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
601
Fabio Utzig5fde8322019-10-23 12:23:08 -0300602 /*
603 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
604 */
605
606 len = TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300607 rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
Fabio Utzig5fde8322019-10-23 12:23:08 -0300608 derived_key, &len);
609 if (rc != 0 || len != (TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE)) {
610 return -1;
611 }
612
613 /*
614 * HMAC the key and check that our received MAC matches the generated tag
615 */
616
617 rc = tc_hmac_set_key(&hmac, &derived_key[16], 32);
618 if (rc != TC_CRYPTO_SUCCESS) {
619 return -1;
620 }
621
622 rc = tc_hmac_init(&hmac);
623 if (rc != TC_CRYPTO_SUCCESS) {
624 return -1;
625 }
626
627 rc = tc_hmac_update(&hmac, &buf[EC_CIPHERKEY_INDEX], 16);
628 if (rc != TC_CRYPTO_SUCCESS) {
629 return -1;
630 }
631
632 /* Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes */
633 rc = tc_hmac_final(tag, TC_SHA256_DIGEST_SIZE, &hmac);
634 if (rc != TC_CRYPTO_SUCCESS) {
635 return -1;
636 }
637
638 if (_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
639 return -1;
640 }
641
642 /*
643 * Finally decrypt the received ciphered key
644 */
645
646 rc = tc_aes128_set_decrypt_key(&aes, derived_key);
647 if (rc != TC_CRYPTO_SUCCESS) {
648 return -1;
649 }
650
651 memset(counter, 0, TC_AES_BLOCK_SIZE);
652 rc = tc_ctr_mode(enckey, TC_AES_KEY_SIZE, &buf[EC_CIPHERKEY_INDEX],
653 TC_AES_KEY_SIZE, counter, &aes);
654 if (rc != TC_CRYPTO_SUCCESS) {
655 return -1;
656 }
657
658 rc = 0;
659
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300660#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300661
Fabio Utzigba829042018-09-18 08:29:34 -0300662 return rc;
663}
664
Fabio Utzig4741c452019-12-19 15:32:41 -0300665/*
666 * Load encryption key.
667 */
668int
669boot_enc_load(struct enc_key_data *enc_state, int image_index,
670 const struct image_header *hdr, const struct flash_area *fap,
671 struct boot_status *bs)
672{
673 uint32_t off;
674 uint16_t len;
675 struct image_tlv_iter it;
676#if MCUBOOT_SWAP_SAVE_ENCTLV
677 uint8_t *buf;
678#else
679 uint8_t buf[EXPECTED_ENC_LEN];
680#endif
681 uint8_t slot;
682 int rc;
683
684 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
685 if (rc < 0) {
686 return rc;
687 }
688 slot = rc;
689
690 /* Already loaded... */
691 if (enc_state[slot].valid) {
692 return 1;
693 }
694
695 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
696 if (rc) {
697 return -1;
698 }
699
700 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
701 if (rc != 0) {
702 return rc;
703 }
704
705 if (len != EXPECTED_ENC_LEN) {
706 return -1;
707 }
708
709#if MCUBOOT_SWAP_SAVE_ENCTLV
710 buf = bs->enctlv[slot];
711 memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
712#endif
713
714 rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
715 if (rc) {
716 return -1;
717 }
718
719 return boot_enc_decrypt(buf, bs->enckey[slot]);
720}
721
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100722bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300723boot_enc_valid(struct enc_key_data *enc_state, int image_index,
724 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300725{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100726 int rc;
727
Fabio Utzigb0f04732019-07-31 09:49:19 -0300728 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100729 if (rc < 0) {
730 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300731 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100732 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100733 }
734
735 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300736}
737
738void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300739boot_encrypt(struct enc_key_data *enc_state, int image_index,
740 const struct flash_area *fap, uint32_t off, uint32_t sz,
741 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300742{
743 struct enc_key_data *enc;
744 uint32_t i, j;
745 uint8_t u8;
746 uint8_t nonce[16];
747 uint8_t blk[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100748 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300749
750 memset(nonce, 0, 12);
751 off >>= 4;
752 nonce[12] = (uint8_t)(off >> 24);
753 nonce[13] = (uint8_t)(off >> 16);
754 nonce[14] = (uint8_t)(off >> 8);
755 nonce[15] = (uint8_t)off;
756
Fabio Utzigb0f04732019-07-31 09:49:19 -0300757 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100758 if (rc < 0) {
759 assert(0);
760 return;
761 }
762
763 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300764 assert(enc->valid == 1);
765 for (i = 0; i < sz; i++) {
766 if (i == 0 || blk_off == 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200767#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300768 mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200769#else
770 tc_aes_encrypt(blk, nonce, &enc->aes);
771#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300772
773 for (j = 16; j > 0; --j) {
774 if (++nonce[j - 1] != 0) {
775 break;
776 }
777 }
778 }
779
780 u8 = *buf;
781 *buf++ = u8 ^ blk[blk_off];
782 blk_off = (blk_off + 1) & 0x0f;
783 }
784}
785
Fabio Utzig10ee6482019-08-01 12:04:52 -0300786/**
787 * Clears encrypted state after use.
788 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300789void
790boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300791{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300792 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300793}
794
795#endif /* MCUBOOT_ENC_IMAGES */