blob: 6104397de0b44d4cf7b71427d2d55b41bc466ac2 [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)
11#include <assert.h>
12#include <stddef.h>
13#include <inttypes.h>
14#include <string.h>
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020015#include <stdio.h>
Fabio Utzigba829042018-09-18 08:29:34 -030016
17#include "hal/hal_flash.h"
18
19#if defined(MCUBOOT_ENCRYPT_RSA)
20#include "mbedtls/rsa.h"
Fabio Utzig6f4d8f82019-12-12 18:46:06 -030021#include "mbedtls/rsa_internal.h"
Fabio Utzigba829042018-09-18 08:29:34 -030022#include "mbedtls/asn1.h"
23#endif
24
25#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020026# if defined(MCUBOOT_USE_MBED_TLS)
27# include "mbedtls/nist_kw.h"
28# include "mbedtls/aes.h"
29# else
30# include "tinycrypt/aes.h"
31# endif
Fabio Utzigba829042018-09-18 08:29:34 -030032#endif
33
Fabio Utzig5fde8322019-10-23 12:23:08 -030034#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -030035#include "tinycrypt/ecc.h"
36#include "tinycrypt/ecc_dh.h"
Fabio Utzig6aec6ae2020-04-02 11:06:07 -030037#endif
38
39#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
40#include "tinycrypt/utils.h"
41#include "tinycrypt/constants.h"
Fabio Utzig5fde8322019-10-23 12:23:08 -030042#include "tinycrypt/ctr_mode.h"
43#include "tinycrypt/hmac.h"
44#include "mbedtls/oid.h"
45#include "mbedtls/asn1.h"
46#endif
47
Fabio Utzigba829042018-09-18 08:29:34 -030048#include "bootutil/image.h"
49#include "bootutil/enc_key.h"
50#include "bootutil/sign_key.h"
51
52#include "bootutil_priv.h"
53
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020054#if defined(MCUBOOT_ENCRYPT_KW)
55#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030056static int
Fabio Utzig4741c452019-12-19 15:32:41 -030057key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020058{
59 mbedtls_nist_kw_context kw;
60 int rc;
61 size_t olen;
62
63 mbedtls_nist_kw_init(&kw);
64
65 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES,
66 bootutil_enc_key.key, *bootutil_enc_key.len * 8, 0);
67 if (rc) {
68 goto done;
69 }
70
71 rc = mbedtls_nist_kw_unwrap(&kw, MBEDTLS_KW_MODE_KW, wrapped, TLV_ENC_KW_SZ,
72 enckey, &olen, BOOT_ENC_KEY_SIZE);
73
74done:
75 mbedtls_nist_kw_free(&kw);
76 return rc;
77}
78#else /* !MCUBOOT_USE_MBED_TLS */
79/*
80 * Implements AES key unwrapping following RFC-3394 section 2.2.2, using
81 * tinycrypt for AES-128 decryption.
82 */
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030083static int
Fabio Utzig4741c452019-12-19 15:32:41 -030084key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020085{
86 struct tc_aes_key_sched_struct aes;
87 uint8_t A[8];
88 uint8_t B[16];
89 int8_t i, j, k;
90
91 if (tc_aes128_set_decrypt_key(&aes, bootutil_enc_key.key) == 0) {
92 return -1;
93 }
94
95 for (k = 0; k < 8; k++) {
96 A[k] = wrapped[k];
97 enckey[k] = wrapped[8 + k];
98 enckey[8 + k] = wrapped[16 + k];
99 }
100
101 for (j = 5; j >= 0; j--) {
102 for (i = 2; i > 0; i--) {
103 for (k = 0; k < 8; k++) {
104 B[k] = A[k];
105 B[8 + k] = enckey[((i-1) * 8) + k];
106 }
107 B[7] ^= 2 * j + i;
108 if (tc_aes_decrypt((uint8_t *)&B, (uint8_t *)&B, &aes) == 0) {
109 return -1;
110 }
111 for (k = 0; k < 8; k++) {
112 A[k] = B[k];
113 enckey[((i-1) * 8) + k] = B[8 + k];
114 }
115 }
116 }
117
118 for (i = 0, k = 0; i < 8; i++) {
119 k |= A[i] ^ 0xa6;
120 }
121 if (k) {
122 return -1;
123 }
124 return 0;
125}
126#endif /* MCUBOOT_USE_MBED_TLS */
127#endif /* MCUBOOT_ENCRYPT_KW */
128
Fabio Utzigba829042018-09-18 08:29:34 -0300129#if defined(MCUBOOT_ENCRYPT_RSA)
130static int
Fabio Utzig5fde8322019-10-23 12:23:08 -0300131parse_rsa_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
Fabio Utzigba829042018-09-18 08:29:34 -0300132{
Fabio Utzigba829042018-09-18 08:29:34 -0300133 size_t len;
134
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300135 if (mbedtls_asn1_get_tag(p, end, &len,
136 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -0300137 return -1;
138 }
139
140 if (*p + len != end) {
141 return -2;
142 }
143
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300144 /* Non-optional fields. */
Fabio Utzigba829042018-09-18 08:29:34 -0300145 if ( /* version */
146 mbedtls_asn1_get_int(p, end, &ctx->ver) != 0 ||
147 /* public modulus */
148 mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0 ||
149 /* public exponent */
150 mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0 ||
151 /* private exponent */
152 mbedtls_asn1_get_mpi(p, end, &ctx->D) != 0 ||
153 /* primes */
154 mbedtls_asn1_get_mpi(p, end, &ctx->P) != 0 ||
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300155 mbedtls_asn1_get_mpi(p, end, &ctx->Q) != 0) {
156
Fabio Utzigba829042018-09-18 08:29:34 -0300157 return -3;
158 }
159
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300160#if !defined(MBEDTLS_RSA_NO_CRT)
161 /*
162 * DP/DQ/QP are only used inside mbedTLS if it was built with the
163 * Chinese Remainder Theorem enabled (default). In case it is disabled
164 * we parse, or if not available, we calculate those values.
165 */
166 if (*p < end) {
167 if ( /* d mod (p-1) and d mod (q-1) */
168 mbedtls_asn1_get_mpi(p, end, &ctx->DP) != 0 ||
169 mbedtls_asn1_get_mpi(p, end, &ctx->DQ) != 0 ||
170 /* q ^ (-1) mod p */
171 mbedtls_asn1_get_mpi(p, end, &ctx->QP) != 0) {
172
173 return -4;
174 }
175 } else {
176 if (mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
177 &ctx->DP, &ctx->DQ, &ctx->QP) != 0) {
178 return -5;
179 }
180 }
181#endif
182
Fabio Utzigba829042018-09-18 08:29:34 -0300183 ctx->len = mbedtls_mpi_size(&ctx->N);
184
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300185 if (mbedtls_rsa_check_privkey(ctx) != 0) {
186 return -6;
Fabio Utzigba829042018-09-18 08:29:34 -0300187 }
188
189 return 0;
190}
191#endif
192
Fabio Utzig5fde8322019-10-23 12:23:08 -0300193#if defined(MCUBOOT_ENCRYPT_EC256)
194static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
195static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
196
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300197#define SHARED_KEY_LEN NUM_ECC_BYTES
198#define PRIV_KEY_LEN NUM_ECC_BYTES
199
Fabio Utzig5fde8322019-10-23 12:23:08 -0300200/*
201 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
202 * curve keypair. See RFC5208 and RFC5915.
203 */
204static int
205parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
206{
207 int rc;
208 size_t len;
209 int version;
210 mbedtls_asn1_buf alg;
211 mbedtls_asn1_buf param;
212
213 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
214 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
215 return -1;
216 }
217
218 if (*p + len != end) {
219 return -2;
220 }
221
222 version = 0;
223 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
224 return -3;
225 }
226
227 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
228 return -5;
229 }
230
231 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
232 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
233 return -6;
234 }
235 if (param.len != sizeof(ec_secp256r1_oid) - 1 ||
236 memcmp(param.p, ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
237 return -7;
238 }
239
240 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
241 return -8;
242 }
243
244 /* RFC5915 - ECPrivateKey */
245
246 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
247 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
248 return -9;
249 }
250
251 version = 0;
252 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
253 return -10;
254 }
255
256 /* privateKey */
257
258 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
259 return -11;
260 }
261
262 if (len != NUM_ECC_BYTES) {
263 return -12;
264 }
265
266 memcpy(pk, *p, len);
267
268 /* publicKey usually follows but is not parsed here */
269
270 return 0;
271}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300272#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300273
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300274#if defined(MCUBOOT_ENCRYPT_X25519)
275#define X25519_OID "\x6e"
276static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
277 MBEDTLS_OID_ORG_GOV X25519_OID;
278
279extern int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
280 const uint8_t peer_public_value[32]);
281
282#define SHARED_KEY_LEN 32
283#define PRIV_KEY_LEN 32
284
285static int
286parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
287{
288 size_t len;
289 int version;
290 mbedtls_asn1_buf alg;
291 mbedtls_asn1_buf param;
292
293 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
294 MBEDTLS_ASN1_SEQUENCE) != 0) {
295 return -1;
296 }
297
298 if (*p + len != end) {
299 return -2;
300 }
301
302 version = 0;
303 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
304 return -3;
305 }
306
307 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
308 return -4;
309 }
310
311 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
312 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
313 return -5;
314 }
315
316 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
317 return -6;
318 }
319
320 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
321 return -7;
322 }
323
324 if (len != PRIV_KEY_LEN) {
325 return -8;
326 }
327
328 memcpy(pk, *p, PRIV_KEY_LEN);
329 return 0;
330}
331#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
332
333#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300334/*
335 * HKDF as described by RFC5869.
336 *
337 * @param ikm The input data to be derived.
338 * @param ikm_len Length of the input data.
339 * @param info An information tag.
340 * @param info_len Length of the information tag.
341 * @param okm Output of the KDF computation.
342 * @param okm_len On input the requested length; on output the generated length
343 */
344static int
345hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
346 uint8_t *okm, uint16_t *okm_len)
347{
348 struct tc_hmac_state_struct hmac;
349 uint8_t salt[TC_SHA256_DIGEST_SIZE];
350 uint8_t prk[TC_SHA256_DIGEST_SIZE];
351 uint8_t T[TC_SHA256_DIGEST_SIZE];
352 uint16_t off;
353 uint16_t len;
354 uint8_t counter;
355 bool first;
356 int rc;
357
358 /*
359 * Extract
360 */
361
362 if (ikm == NULL || okm == NULL || ikm_len == 0) {
363 return -1;
364 }
365
366 memset(salt, 0, TC_SHA256_DIGEST_SIZE);
367 rc = tc_hmac_set_key(&hmac, salt, TC_SHA256_DIGEST_SIZE);
368 if (rc != TC_CRYPTO_SUCCESS) {
369 return -1;
370 }
371
372 rc = tc_hmac_init(&hmac);
373 if (rc != TC_CRYPTO_SUCCESS) {
374 return -1;
375 }
376
377 rc = tc_hmac_update(&hmac, ikm, ikm_len);
378 if (rc != TC_CRYPTO_SUCCESS) {
379 return -1;
380 }
381
382 rc = tc_hmac_final(prk, TC_SHA256_DIGEST_SIZE, &hmac);
383 if (rc != TC_CRYPTO_SUCCESS) {
384 return -1;
385 }
386
387 /*
388 * Expand
389 */
390
391 len = *okm_len;
392 counter = 1;
393 first = true;
394 for (off = 0; len > 0; off += TC_SHA256_DIGEST_SIZE, ++counter) {
395 rc = tc_hmac_set_key(&hmac, prk, TC_SHA256_DIGEST_SIZE);
396 if (rc != TC_CRYPTO_SUCCESS) {
397 return -1;
398 }
399
400 rc = tc_hmac_init(&hmac);
401 if (rc != TC_CRYPTO_SUCCESS) {
402 return -1;
403 }
404
405 if (first) {
406 first = false;
407 } else {
408 rc = tc_hmac_update(&hmac, T, TC_SHA256_DIGEST_SIZE);
409 if (rc != TC_CRYPTO_SUCCESS) {
410 return -1;
411 }
412 }
413
414 rc = tc_hmac_update(&hmac, info, info_len);
415 if (rc != TC_CRYPTO_SUCCESS) {
416 return -1;
417 }
418
419 rc = tc_hmac_update(&hmac, &counter, 1);
420 if (rc != TC_CRYPTO_SUCCESS) {
421 return -1;
422 }
423
424 rc = tc_hmac_final(T, TC_SHA256_DIGEST_SIZE, &hmac);
425 if (rc != TC_CRYPTO_SUCCESS) {
426 return -1;
427 }
428
429 if (len > TC_SHA256_DIGEST_SIZE) {
430 memcpy(&okm[off], T, TC_SHA256_DIGEST_SIZE);
431 len -= TC_SHA256_DIGEST_SIZE;
432 } else {
433 memcpy(&okm[off], T, len);
434 len = 0;
435 }
436 }
437
438 return 0;
439}
440#endif
441
Fabio Utzigba829042018-09-18 08:29:34 -0300442int
Fabio Utzig4741c452019-12-19 15:32:41 -0300443boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
444 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300445{
446 int rc;
447
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200448#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300449 mbedtls_aes_init(&enc_state[slot].aes);
Fabio Utzig4741c452019-12-19 15:32:41 -0300450 rc = mbedtls_aes_setkey_enc(&enc_state[slot].aes, bs->enckey[slot],
451 BOOT_ENC_KEY_SIZE_BITS);
Fabio Utzigba829042018-09-18 08:29:34 -0300452 if (rc) {
453 mbedtls_aes_free(&enc_state[slot].aes);
454 return -1;
455 }
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200456#else
457 (void)rc;
458
459 /* set_encrypt and set_decrypt do the same thing in tinycrypt */
Fabio Utzig4741c452019-12-19 15:32:41 -0300460 tc_aes128_set_encrypt_key(&enc_state[slot].aes, bs->enckey[slot]);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200461#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300462
463 enc_state[slot].valid = 1;
464
465 return 0;
466}
467
Fabio Utzig4741c452019-12-19 15:32:41 -0300468#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
469
Fabio Utzigba829042018-09-18 08:29:34 -0300470#if defined(MCUBOOT_ENCRYPT_RSA)
471# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
Fabio Utzigba829042018-09-18 08:29:34 -0300472#elif defined(MCUBOOT_ENCRYPT_KW)
473# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
Fabio Utzig5fde8322019-10-23 12:23:08 -0300474#elif defined(MCUBOOT_ENCRYPT_EC256)
475# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
Fabio Utzig5fde8322019-10-23 12:23:08 -0300476# define EC_PUBK_INDEX (1)
477# define EC_TAG_INDEX (65)
478# define EC_CIPHERKEY_INDEX (65 + 32)
Fabio Utzig4741c452019-12-19 15:32:41 -0300479_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
480 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300481#elif defined(MCUBOOT_ENCRYPT_X25519)
482# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
483# define EC_PUBK_INDEX (0)
484# define EC_TAG_INDEX (32)
485# define EC_CIPHERKEY_INDEX (32 + 32)
486_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
487 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300488#endif
489
490/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300491 * Decrypt an encryption key TLV.
492 *
493 * @param buf An encryption TLV read from flash (build time fixed length)
494 * @param enckey An AES-128 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300495 */
496int
Fabio Utzig4741c452019-12-19 15:32:41 -0300497boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
Fabio Utzigba829042018-09-18 08:29:34 -0300498{
499#if defined(MCUBOOT_ENCRYPT_RSA)
500 mbedtls_rsa_context rsa;
501 uint8_t *cp;
502 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300503 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200504#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300505#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300506 struct tc_hmac_state_struct hmac;
507 struct tc_aes_key_sched_struct aes;
508 uint8_t tag[TC_SHA256_DIGEST_SIZE];
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300509 uint8_t shared[SHARED_KEY_LEN];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300510 uint8_t derived_key[TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE];
511 uint8_t *cp;
512 uint8_t *cpend;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300513 uint8_t pk[PRIV_KEY_LEN];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300514 uint8_t counter[TC_AES_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300515 uint16_t len;
Fabio Utzig4741c452019-12-19 15:32:41 -0300516#endif
517 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300518
Fabio Utzigba829042018-09-18 08:29:34 -0300519#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300520
Fabio Utzig233af7d2019-08-26 12:06:16 -0300521 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Fabio Utzigba829042018-09-18 08:29:34 -0300522
Fabio Utzig233af7d2019-08-26 12:06:16 -0300523 cp = (uint8_t *)bootutil_enc_key.key;
524 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300525
Fabio Utzig5fde8322019-10-23 12:23:08 -0300526 rc = parse_rsa_enckey(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300527 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300528 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300529 return rc;
530 }
531
532 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
533 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
534 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300535
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300536#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
537
538#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300539
Fabio Utzig233af7d2019-08-26 12:06:16 -0300540 assert(*bootutil_enc_key.len == 16);
541 rc = key_unwrap(buf, enckey);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300542
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300543#endif /* defined(MCUBOOT_ENCRYPT_KW) */
544
545#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300546
547 cp = (uint8_t *)bootutil_enc_key.key;
548 cpend = cp + *bootutil_enc_key.len;
549
550 /*
551 * Load the stored EC256 decryption private key
552 */
553
554 rc = parse_ec256_enckey(&cp, cpend, pk);
555 if (rc) {
556 return rc;
557 }
558
559 /* is EC point uncompressed? */
560 if (buf[0] != 0x04) {
561 return -1;
562 }
563
564 /*
565 * First "element" in the TLV is the curve point (public key)
566 */
567 rc = uECC_valid_public_key(&buf[EC_PUBK_INDEX], uECC_secp256r1());
568 if (rc != 0) {
569 return -1;
570 }
571
572 rc = uECC_shared_secret(&buf[EC_PUBK_INDEX], pk, shared, uECC_secp256r1());
573 if (rc != TC_CRYPTO_SUCCESS) {
574 return -1;
575 }
576
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300577#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
578
579#if defined(MCUBOOT_ENCRYPT_X25519)
580
581 cp = (uint8_t *)bootutil_enc_key.key;
582 cpend = cp + *bootutil_enc_key.len;
583
584 /*
585 * Load the stored X25519 decryption private key
586 */
587
588 rc = parse_x25519_enckey(&cp, cpend, pk);
589 if (rc) {
590 return rc;
591 }
592
593 /*
594 * First "element" in the TLV is the curve point (public key)
595 */
596
597 rc = X25519(shared, pk, &buf[EC_PUBK_INDEX]);
598 if (!rc) {
599 return -1;
600 }
601
602#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
603
604#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
605
Fabio Utzig5fde8322019-10-23 12:23:08 -0300606 /*
607 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
608 */
609
610 len = TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300611 rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
Fabio Utzig5fde8322019-10-23 12:23:08 -0300612 derived_key, &len);
613 if (rc != 0 || len != (TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE)) {
614 return -1;
615 }
616
617 /*
618 * HMAC the key and check that our received MAC matches the generated tag
619 */
620
621 rc = tc_hmac_set_key(&hmac, &derived_key[16], 32);
622 if (rc != TC_CRYPTO_SUCCESS) {
623 return -1;
624 }
625
626 rc = tc_hmac_init(&hmac);
627 if (rc != TC_CRYPTO_SUCCESS) {
628 return -1;
629 }
630
631 rc = tc_hmac_update(&hmac, &buf[EC_CIPHERKEY_INDEX], 16);
632 if (rc != TC_CRYPTO_SUCCESS) {
633 return -1;
634 }
635
636 /* Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes */
637 rc = tc_hmac_final(tag, TC_SHA256_DIGEST_SIZE, &hmac);
638 if (rc != TC_CRYPTO_SUCCESS) {
639 return -1;
640 }
641
642 if (_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
643 return -1;
644 }
645
646 /*
647 * Finally decrypt the received ciphered key
648 */
649
650 rc = tc_aes128_set_decrypt_key(&aes, derived_key);
651 if (rc != TC_CRYPTO_SUCCESS) {
652 return -1;
653 }
654
655 memset(counter, 0, TC_AES_BLOCK_SIZE);
656 rc = tc_ctr_mode(enckey, TC_AES_KEY_SIZE, &buf[EC_CIPHERKEY_INDEX],
657 TC_AES_KEY_SIZE, counter, &aes);
658 if (rc != TC_CRYPTO_SUCCESS) {
659 return -1;
660 }
661
662 rc = 0;
663
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300664#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300665
Fabio Utzigba829042018-09-18 08:29:34 -0300666 return rc;
667}
668
Fabio Utzig4741c452019-12-19 15:32:41 -0300669/*
670 * Load encryption key.
671 */
672int
673boot_enc_load(struct enc_key_data *enc_state, int image_index,
674 const struct image_header *hdr, const struct flash_area *fap,
675 struct boot_status *bs)
676{
677 uint32_t off;
678 uint16_t len;
679 struct image_tlv_iter it;
680#if MCUBOOT_SWAP_SAVE_ENCTLV
681 uint8_t *buf;
682#else
683 uint8_t buf[EXPECTED_ENC_LEN];
684#endif
685 uint8_t slot;
686 int rc;
687
688 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
689 if (rc < 0) {
690 return rc;
691 }
692 slot = rc;
693
694 /* Already loaded... */
695 if (enc_state[slot].valid) {
696 return 1;
697 }
698
699 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
700 if (rc) {
701 return -1;
702 }
703
704 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
705 if (rc != 0) {
706 return rc;
707 }
708
709 if (len != EXPECTED_ENC_LEN) {
710 return -1;
711 }
712
713#if MCUBOOT_SWAP_SAVE_ENCTLV
714 buf = bs->enctlv[slot];
715 memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
716#endif
717
718 rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
719 if (rc) {
720 return -1;
721 }
722
723 return boot_enc_decrypt(buf, bs->enckey[slot]);
724}
725
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100726bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300727boot_enc_valid(struct enc_key_data *enc_state, int image_index,
728 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300729{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100730 int rc;
731
Fabio Utzigb0f04732019-07-31 09:49:19 -0300732 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100733 if (rc < 0) {
734 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300735 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100736 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100737 }
738
739 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300740}
741
742void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300743boot_encrypt(struct enc_key_data *enc_state, int image_index,
744 const struct flash_area *fap, uint32_t off, uint32_t sz,
745 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300746{
747 struct enc_key_data *enc;
748 uint32_t i, j;
749 uint8_t u8;
750 uint8_t nonce[16];
751 uint8_t blk[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100752 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300753
754 memset(nonce, 0, 12);
755 off >>= 4;
756 nonce[12] = (uint8_t)(off >> 24);
757 nonce[13] = (uint8_t)(off >> 16);
758 nonce[14] = (uint8_t)(off >> 8);
759 nonce[15] = (uint8_t)off;
760
Fabio Utzigb0f04732019-07-31 09:49:19 -0300761 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100762 if (rc < 0) {
763 assert(0);
764 return;
765 }
766
767 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300768 assert(enc->valid == 1);
769 for (i = 0; i < sz; i++) {
770 if (i == 0 || blk_off == 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200771#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300772 mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200773#else
774 tc_aes_encrypt(blk, nonce, &enc->aes);
775#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300776
777 for (j = 16; j > 0; --j) {
778 if (++nonce[j - 1] != 0) {
779 break;
780 }
781 }
782 }
783
784 u8 = *buf;
785 *buf++ = u8 ^ blk[blk_off];
786 blk_off = (blk_off + 1) & 0x0f;
787 }
788}
789
Fabio Utzig10ee6482019-08-01 12:04:52 -0300790/**
791 * Clears encrypted state after use.
792 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300793void
794boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300795{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300796 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300797}
798
799#endif /* MCUBOOT_ENC_IMAGES */