blob: abc9fdd0d26eb5c9c1b16221e5c066500b844bf9 [file] [log] [blame]
Fabio Utzigba829042018-09-18 08:29:34 -03001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20#include "mcuboot_config/mcuboot_config.h"
21
22#if defined(MCUBOOT_ENC_IMAGES)
23#include <assert.h>
24#include <stddef.h>
25#include <inttypes.h>
26#include <string.h>
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020027#include <stdio.h>
Fabio Utzigba829042018-09-18 08:29:34 -030028
29#include "hal/hal_flash.h"
30
31#if defined(MCUBOOT_ENCRYPT_RSA)
32#include "mbedtls/rsa.h"
Fabio Utzig6f4d8f82019-12-12 18:46:06 -030033#include "mbedtls/rsa_internal.h"
Fabio Utzigba829042018-09-18 08:29:34 -030034#include "mbedtls/asn1.h"
35#endif
36
37#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020038# if defined(MCUBOOT_USE_MBED_TLS)
39# include "mbedtls/nist_kw.h"
40# include "mbedtls/aes.h"
41# else
42# include "tinycrypt/aes.h"
43# endif
Fabio Utzigba829042018-09-18 08:29:34 -030044#endif
45
Fabio Utzig5fde8322019-10-23 12:23:08 -030046#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -030047#include "tinycrypt/ecc.h"
48#include "tinycrypt/ecc_dh.h"
Fabio Utzig6aec6ae2020-04-02 11:06:07 -030049#endif
50
51#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
52#include "tinycrypt/utils.h"
53#include "tinycrypt/constants.h"
Fabio Utzig5fde8322019-10-23 12:23:08 -030054#include "tinycrypt/ctr_mode.h"
55#include "tinycrypt/hmac.h"
56#include "mbedtls/oid.h"
57#include "mbedtls/asn1.h"
58#endif
59
Fabio Utzigba829042018-09-18 08:29:34 -030060#include "bootutil/image.h"
61#include "bootutil/enc_key.h"
62#include "bootutil/sign_key.h"
63
64#include "bootutil_priv.h"
65
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020066#if defined(MCUBOOT_ENCRYPT_KW)
67#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030068static int
Fabio Utzig4741c452019-12-19 15:32:41 -030069key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020070{
71 mbedtls_nist_kw_context kw;
72 int rc;
73 size_t olen;
74
75 mbedtls_nist_kw_init(&kw);
76
77 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES,
78 bootutil_enc_key.key, *bootutil_enc_key.len * 8, 0);
79 if (rc) {
80 goto done;
81 }
82
83 rc = mbedtls_nist_kw_unwrap(&kw, MBEDTLS_KW_MODE_KW, wrapped, TLV_ENC_KW_SZ,
84 enckey, &olen, BOOT_ENC_KEY_SIZE);
85
86done:
87 mbedtls_nist_kw_free(&kw);
88 return rc;
89}
90#else /* !MCUBOOT_USE_MBED_TLS */
91/*
92 * Implements AES key unwrapping following RFC-3394 section 2.2.2, using
93 * tinycrypt for AES-128 decryption.
94 */
Fabio Utzig6ace9ee2019-08-19 11:11:07 -030095static int
Fabio Utzig4741c452019-12-19 15:32:41 -030096key_unwrap(const uint8_t *wrapped, uint8_t *enckey)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020097{
98 struct tc_aes_key_sched_struct aes;
99 uint8_t A[8];
100 uint8_t B[16];
101 int8_t i, j, k;
102
103 if (tc_aes128_set_decrypt_key(&aes, bootutil_enc_key.key) == 0) {
104 return -1;
105 }
106
107 for (k = 0; k < 8; k++) {
108 A[k] = wrapped[k];
109 enckey[k] = wrapped[8 + k];
110 enckey[8 + k] = wrapped[16 + k];
111 }
112
113 for (j = 5; j >= 0; j--) {
114 for (i = 2; i > 0; i--) {
115 for (k = 0; k < 8; k++) {
116 B[k] = A[k];
117 B[8 + k] = enckey[((i-1) * 8) + k];
118 }
119 B[7] ^= 2 * j + i;
120 if (tc_aes_decrypt((uint8_t *)&B, (uint8_t *)&B, &aes) == 0) {
121 return -1;
122 }
123 for (k = 0; k < 8; k++) {
124 A[k] = B[k];
125 enckey[((i-1) * 8) + k] = B[8 + k];
126 }
127 }
128 }
129
130 for (i = 0, k = 0; i < 8; i++) {
131 k |= A[i] ^ 0xa6;
132 }
133 if (k) {
134 return -1;
135 }
136 return 0;
137}
138#endif /* MCUBOOT_USE_MBED_TLS */
139#endif /* MCUBOOT_ENCRYPT_KW */
140
Fabio Utzigba829042018-09-18 08:29:34 -0300141#if defined(MCUBOOT_ENCRYPT_RSA)
142static int
Fabio Utzig5fde8322019-10-23 12:23:08 -0300143parse_rsa_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
Fabio Utzigba829042018-09-18 08:29:34 -0300144{
Fabio Utzigba829042018-09-18 08:29:34 -0300145 size_t len;
146
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300147 if (mbedtls_asn1_get_tag(p, end, &len,
148 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) != 0) {
Fabio Utzigba829042018-09-18 08:29:34 -0300149 return -1;
150 }
151
152 if (*p + len != end) {
153 return -2;
154 }
155
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300156 /* Non-optional fields. */
Fabio Utzigba829042018-09-18 08:29:34 -0300157 if ( /* version */
158 mbedtls_asn1_get_int(p, end, &ctx->ver) != 0 ||
159 /* public modulus */
160 mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0 ||
161 /* public exponent */
162 mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0 ||
163 /* private exponent */
164 mbedtls_asn1_get_mpi(p, end, &ctx->D) != 0 ||
165 /* primes */
166 mbedtls_asn1_get_mpi(p, end, &ctx->P) != 0 ||
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300167 mbedtls_asn1_get_mpi(p, end, &ctx->Q) != 0) {
168
Fabio Utzigba829042018-09-18 08:29:34 -0300169 return -3;
170 }
171
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300172#if !defined(MBEDTLS_RSA_NO_CRT)
173 /*
174 * DP/DQ/QP are only used inside mbedTLS if it was built with the
175 * Chinese Remainder Theorem enabled (default). In case it is disabled
176 * we parse, or if not available, we calculate those values.
177 */
178 if (*p < end) {
179 if ( /* d mod (p-1) and d mod (q-1) */
180 mbedtls_asn1_get_mpi(p, end, &ctx->DP) != 0 ||
181 mbedtls_asn1_get_mpi(p, end, &ctx->DQ) != 0 ||
182 /* q ^ (-1) mod p */
183 mbedtls_asn1_get_mpi(p, end, &ctx->QP) != 0) {
184
185 return -4;
186 }
187 } else {
188 if (mbedtls_rsa_deduce_crt(&ctx->P, &ctx->Q, &ctx->D,
189 &ctx->DP, &ctx->DQ, &ctx->QP) != 0) {
190 return -5;
191 }
192 }
193#endif
194
Fabio Utzigba829042018-09-18 08:29:34 -0300195 ctx->len = mbedtls_mpi_size(&ctx->N);
196
Fabio Utzig6f4d8f82019-12-12 18:46:06 -0300197 if (mbedtls_rsa_check_privkey(ctx) != 0) {
198 return -6;
Fabio Utzigba829042018-09-18 08:29:34 -0300199 }
200
201 return 0;
202}
203#endif
204
Fabio Utzig5fde8322019-10-23 12:23:08 -0300205#if defined(MCUBOOT_ENCRYPT_EC256)
206static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_EC_ALG_UNRESTRICTED;
207static const uint8_t ec_secp256r1_oid[] = MBEDTLS_OID_EC_GRP_SECP256R1;
208
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300209#define SHARED_KEY_LEN NUM_ECC_BYTES
210#define PRIV_KEY_LEN NUM_ECC_BYTES
211
Fabio Utzig5fde8322019-10-23 12:23:08 -0300212/*
213 * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
214 * curve keypair. See RFC5208 and RFC5915.
215 */
216static int
217parse_ec256_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
218{
219 int rc;
220 size_t len;
221 int version;
222 mbedtls_asn1_buf alg;
223 mbedtls_asn1_buf param;
224
225 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
226 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
227 return -1;
228 }
229
230 if (*p + len != end) {
231 return -2;
232 }
233
234 version = 0;
235 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
236 return -3;
237 }
238
239 if ((rc = mbedtls_asn1_get_alg(p, end, &alg, &param)) != 0) {
240 return -5;
241 }
242
243 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
244 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
245 return -6;
246 }
247 if (param.len != sizeof(ec_secp256r1_oid) - 1 ||
248 memcmp(param.p, ec_secp256r1_oid, sizeof(ec_secp256r1_oid) - 1)) {
249 return -7;
250 }
251
252 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
253 return -8;
254 }
255
256 /* RFC5915 - ECPrivateKey */
257
258 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
259 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
260 return -9;
261 }
262
263 version = 0;
264 if (mbedtls_asn1_get_int(p, end, &version) || version != 1) {
265 return -10;
266 }
267
268 /* privateKey */
269
270 if ((rc = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING)) != 0) {
271 return -11;
272 }
273
274 if (len != NUM_ECC_BYTES) {
275 return -12;
276 }
277
278 memcpy(pk, *p, len);
279
280 /* publicKey usually follows but is not parsed here */
281
282 return 0;
283}
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300284#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
Fabio Utzig5fde8322019-10-23 12:23:08 -0300285
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300286#if defined(MCUBOOT_ENCRYPT_X25519)
287#define X25519_OID "\x6e"
288static const uint8_t ec_pubkey_oid[] = MBEDTLS_OID_ISO_IDENTIFIED_ORG \
289 MBEDTLS_OID_ORG_GOV X25519_OID;
290
291extern int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
292 const uint8_t peer_public_value[32]);
293
294#define SHARED_KEY_LEN 32
295#define PRIV_KEY_LEN 32
296
297static int
298parse_x25519_enckey(uint8_t **p, uint8_t *end, uint8_t *pk)
299{
300 size_t len;
301 int version;
302 mbedtls_asn1_buf alg;
303 mbedtls_asn1_buf param;
304
305 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
306 MBEDTLS_ASN1_SEQUENCE) != 0) {
307 return -1;
308 }
309
310 if (*p + len != end) {
311 return -2;
312 }
313
314 version = 0;
315 if (mbedtls_asn1_get_int(p, end, &version) || version != 0) {
316 return -3;
317 }
318
319 if (mbedtls_asn1_get_alg(p, end, &alg, &param) != 0) {
320 return -4;
321 }
322
323 if (alg.len != sizeof(ec_pubkey_oid) - 1 ||
324 memcmp(alg.p, ec_pubkey_oid, sizeof(ec_pubkey_oid) - 1)) {
325 return -5;
326 }
327
328 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
329 return -6;
330 }
331
332 if (mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING) != 0) {
333 return -7;
334 }
335
336 if (len != PRIV_KEY_LEN) {
337 return -8;
338 }
339
340 memcpy(pk, *p, PRIV_KEY_LEN);
341 return 0;
342}
343#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
344
345#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300346/*
347 * HKDF as described by RFC5869.
348 *
349 * @param ikm The input data to be derived.
350 * @param ikm_len Length of the input data.
351 * @param info An information tag.
352 * @param info_len Length of the information tag.
353 * @param okm Output of the KDF computation.
354 * @param okm_len On input the requested length; on output the generated length
355 */
356static int
357hkdf(uint8_t *ikm, uint16_t ikm_len, uint8_t *info, uint16_t info_len,
358 uint8_t *okm, uint16_t *okm_len)
359{
360 struct tc_hmac_state_struct hmac;
361 uint8_t salt[TC_SHA256_DIGEST_SIZE];
362 uint8_t prk[TC_SHA256_DIGEST_SIZE];
363 uint8_t T[TC_SHA256_DIGEST_SIZE];
364 uint16_t off;
365 uint16_t len;
366 uint8_t counter;
367 bool first;
368 int rc;
369
370 /*
371 * Extract
372 */
373
374 if (ikm == NULL || okm == NULL || ikm_len == 0) {
375 return -1;
376 }
377
378 memset(salt, 0, TC_SHA256_DIGEST_SIZE);
379 rc = tc_hmac_set_key(&hmac, salt, TC_SHA256_DIGEST_SIZE);
380 if (rc != TC_CRYPTO_SUCCESS) {
381 return -1;
382 }
383
384 rc = tc_hmac_init(&hmac);
385 if (rc != TC_CRYPTO_SUCCESS) {
386 return -1;
387 }
388
389 rc = tc_hmac_update(&hmac, ikm, ikm_len);
390 if (rc != TC_CRYPTO_SUCCESS) {
391 return -1;
392 }
393
394 rc = tc_hmac_final(prk, TC_SHA256_DIGEST_SIZE, &hmac);
395 if (rc != TC_CRYPTO_SUCCESS) {
396 return -1;
397 }
398
399 /*
400 * Expand
401 */
402
403 len = *okm_len;
404 counter = 1;
405 first = true;
406 for (off = 0; len > 0; off += TC_SHA256_DIGEST_SIZE, ++counter) {
407 rc = tc_hmac_set_key(&hmac, prk, TC_SHA256_DIGEST_SIZE);
408 if (rc != TC_CRYPTO_SUCCESS) {
409 return -1;
410 }
411
412 rc = tc_hmac_init(&hmac);
413 if (rc != TC_CRYPTO_SUCCESS) {
414 return -1;
415 }
416
417 if (first) {
418 first = false;
419 } else {
420 rc = tc_hmac_update(&hmac, T, TC_SHA256_DIGEST_SIZE);
421 if (rc != TC_CRYPTO_SUCCESS) {
422 return -1;
423 }
424 }
425
426 rc = tc_hmac_update(&hmac, info, info_len);
427 if (rc != TC_CRYPTO_SUCCESS) {
428 return -1;
429 }
430
431 rc = tc_hmac_update(&hmac, &counter, 1);
432 if (rc != TC_CRYPTO_SUCCESS) {
433 return -1;
434 }
435
436 rc = tc_hmac_final(T, TC_SHA256_DIGEST_SIZE, &hmac);
437 if (rc != TC_CRYPTO_SUCCESS) {
438 return -1;
439 }
440
441 if (len > TC_SHA256_DIGEST_SIZE) {
442 memcpy(&okm[off], T, TC_SHA256_DIGEST_SIZE);
443 len -= TC_SHA256_DIGEST_SIZE;
444 } else {
445 memcpy(&okm[off], T, len);
446 len = 0;
447 }
448 }
449
450 return 0;
451}
452#endif
453
Fabio Utzigba829042018-09-18 08:29:34 -0300454int
Fabio Utzig4741c452019-12-19 15:32:41 -0300455boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot,
456 const struct boot_status *bs)
Fabio Utzigba829042018-09-18 08:29:34 -0300457{
458 int rc;
459
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200460#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300461 mbedtls_aes_init(&enc_state[slot].aes);
Fabio Utzig4741c452019-12-19 15:32:41 -0300462 rc = mbedtls_aes_setkey_enc(&enc_state[slot].aes, bs->enckey[slot],
463 BOOT_ENC_KEY_SIZE_BITS);
Fabio Utzigba829042018-09-18 08:29:34 -0300464 if (rc) {
465 mbedtls_aes_free(&enc_state[slot].aes);
466 return -1;
467 }
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200468#else
469 (void)rc;
470
471 /* set_encrypt and set_decrypt do the same thing in tinycrypt */
Fabio Utzig4741c452019-12-19 15:32:41 -0300472 tc_aes128_set_encrypt_key(&enc_state[slot].aes, bs->enckey[slot]);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200473#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300474
475 enc_state[slot].valid = 1;
476
477 return 0;
478}
479
Fabio Utzig4741c452019-12-19 15:32:41 -0300480#define EXPECTED_ENC_LEN BOOT_ENC_TLV_SIZE
481
Fabio Utzigba829042018-09-18 08:29:34 -0300482#if defined(MCUBOOT_ENCRYPT_RSA)
483# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
Fabio Utzigba829042018-09-18 08:29:34 -0300484#elif defined(MCUBOOT_ENCRYPT_KW)
485# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
Fabio Utzig5fde8322019-10-23 12:23:08 -0300486#elif defined(MCUBOOT_ENCRYPT_EC256)
487# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
Fabio Utzig5fde8322019-10-23 12:23:08 -0300488# define EC_PUBK_INDEX (1)
489# define EC_TAG_INDEX (65)
490# define EC_CIPHERKEY_INDEX (65 + 32)
Fabio Utzig4741c452019-12-19 15:32:41 -0300491_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
492 "Please fix ECIES-P256 component indexes");
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300493#elif defined(MCUBOOT_ENCRYPT_X25519)
494# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_X25519
495# define EC_PUBK_INDEX (0)
496# define EC_TAG_INDEX (32)
497# define EC_CIPHERKEY_INDEX (32 + 32)
498_Static_assert(EC_CIPHERKEY_INDEX + 16 == EXPECTED_ENC_LEN,
499 "Please fix ECIES-X25519 component indexes");
Fabio Utzigba829042018-09-18 08:29:34 -0300500#endif
501
502/*
Fabio Utzig4741c452019-12-19 15:32:41 -0300503 * Decrypt an encryption key TLV.
504 *
505 * @param buf An encryption TLV read from flash (build time fixed length)
506 * @param enckey An AES-128 key sized buffer to store to plain key.
Fabio Utzigba829042018-09-18 08:29:34 -0300507 */
508int
Fabio Utzig4741c452019-12-19 15:32:41 -0300509boot_enc_decrypt(const uint8_t *buf, uint8_t *enckey)
Fabio Utzigba829042018-09-18 08:29:34 -0300510{
511#if defined(MCUBOOT_ENCRYPT_RSA)
512 mbedtls_rsa_context rsa;
513 uint8_t *cp;
514 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300515 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200516#endif
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300517#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300518 struct tc_hmac_state_struct hmac;
519 struct tc_aes_key_sched_struct aes;
520 uint8_t tag[TC_SHA256_DIGEST_SIZE];
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300521 uint8_t shared[SHARED_KEY_LEN];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300522 uint8_t derived_key[TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE];
523 uint8_t *cp;
524 uint8_t *cpend;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300525 uint8_t pk[PRIV_KEY_LEN];
Fabio Utzig5fde8322019-10-23 12:23:08 -0300526 uint8_t counter[TC_AES_BLOCK_SIZE];
Fabio Utzig61fd8882019-09-14 20:00:20 -0300527 uint16_t len;
Fabio Utzig4741c452019-12-19 15:32:41 -0300528#endif
529 int rc = -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300530
Fabio Utzigba829042018-09-18 08:29:34 -0300531#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300532
Fabio Utzig233af7d2019-08-26 12:06:16 -0300533 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Fabio Utzigba829042018-09-18 08:29:34 -0300534
Fabio Utzig233af7d2019-08-26 12:06:16 -0300535 cp = (uint8_t *)bootutil_enc_key.key;
536 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300537
Fabio Utzig5fde8322019-10-23 12:23:08 -0300538 rc = parse_rsa_enckey(&rsa, &cp, cpend);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300539 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300540 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300541 return rc;
542 }
543
544 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
545 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
546 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300547
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300548#endif /* defined(MCUBOOT_ENCRYPT_RSA) */
549
550#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300551
Fabio Utzig233af7d2019-08-26 12:06:16 -0300552 assert(*bootutil_enc_key.len == 16);
553 rc = key_unwrap(buf, enckey);
Fabio Utzig5fde8322019-10-23 12:23:08 -0300554
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300555#endif /* defined(MCUBOOT_ENCRYPT_KW) */
556
557#if defined(MCUBOOT_ENCRYPT_EC256)
Fabio Utzig5fde8322019-10-23 12:23:08 -0300558
559 cp = (uint8_t *)bootutil_enc_key.key;
560 cpend = cp + *bootutil_enc_key.len;
561
562 /*
563 * Load the stored EC256 decryption private key
564 */
565
566 rc = parse_ec256_enckey(&cp, cpend, pk);
567 if (rc) {
568 return rc;
569 }
570
571 /* is EC point uncompressed? */
572 if (buf[0] != 0x04) {
573 return -1;
574 }
575
576 /*
577 * First "element" in the TLV is the curve point (public key)
578 */
579 rc = uECC_valid_public_key(&buf[EC_PUBK_INDEX], uECC_secp256r1());
580 if (rc != 0) {
581 return -1;
582 }
583
584 rc = uECC_shared_secret(&buf[EC_PUBK_INDEX], pk, shared, uECC_secp256r1());
585 if (rc != TC_CRYPTO_SUCCESS) {
586 return -1;
587 }
588
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300589#endif /* defined(MCUBOOT_ENCRYPT_EC256) */
590
591#if defined(MCUBOOT_ENCRYPT_X25519)
592
593 cp = (uint8_t *)bootutil_enc_key.key;
594 cpend = cp + *bootutil_enc_key.len;
595
596 /*
597 * Load the stored X25519 decryption private key
598 */
599
600 rc = parse_x25519_enckey(&cp, cpend, pk);
601 if (rc) {
602 return rc;
603 }
604
605 /*
606 * First "element" in the TLV is the curve point (public key)
607 */
608
609 rc = X25519(shared, pk, &buf[EC_PUBK_INDEX]);
610 if (!rc) {
611 return -1;
612 }
613
614#endif /* defined(MCUBOOT_ENCRYPT_X25519) */
615
616#if defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519)
617
Fabio Utzig5fde8322019-10-23 12:23:08 -0300618 /*
619 * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
620 */
621
622 len = TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE;
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300623 rc = hkdf(shared, SHARED_KEY_LEN, (uint8_t *)"MCUBoot_ECIES_v1", 16,
Fabio Utzig5fde8322019-10-23 12:23:08 -0300624 derived_key, &len);
625 if (rc != 0 || len != (TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE)) {
626 return -1;
627 }
628
629 /*
630 * HMAC the key and check that our received MAC matches the generated tag
631 */
632
633 rc = tc_hmac_set_key(&hmac, &derived_key[16], 32);
634 if (rc != TC_CRYPTO_SUCCESS) {
635 return -1;
636 }
637
638 rc = tc_hmac_init(&hmac);
639 if (rc != TC_CRYPTO_SUCCESS) {
640 return -1;
641 }
642
643 rc = tc_hmac_update(&hmac, &buf[EC_CIPHERKEY_INDEX], 16);
644 if (rc != TC_CRYPTO_SUCCESS) {
645 return -1;
646 }
647
648 /* Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes */
649 rc = tc_hmac_final(tag, TC_SHA256_DIGEST_SIZE, &hmac);
650 if (rc != TC_CRYPTO_SUCCESS) {
651 return -1;
652 }
653
654 if (_compare(tag, &buf[EC_TAG_INDEX], 32) != 0) {
655 return -1;
656 }
657
658 /*
659 * Finally decrypt the received ciphered key
660 */
661
662 rc = tc_aes128_set_decrypt_key(&aes, derived_key);
663 if (rc != TC_CRYPTO_SUCCESS) {
664 return -1;
665 }
666
667 memset(counter, 0, TC_AES_BLOCK_SIZE);
668 rc = tc_ctr_mode(enckey, TC_AES_KEY_SIZE, &buf[EC_CIPHERKEY_INDEX],
669 TC_AES_KEY_SIZE, counter, &aes);
670 if (rc != TC_CRYPTO_SUCCESS) {
671 return -1;
672 }
673
674 rc = 0;
675
Fabio Utzig6aec6ae2020-04-02 11:06:07 -0300676#endif /* defined(MCUBOOT_ENCRYPT_EC256) || defined(MCUBOOT_ENCRYPT_X25519) */
Fabio Utzigba829042018-09-18 08:29:34 -0300677
Fabio Utzigba829042018-09-18 08:29:34 -0300678 return rc;
679}
680
Fabio Utzig4741c452019-12-19 15:32:41 -0300681/*
682 * Load encryption key.
683 */
684int
685boot_enc_load(struct enc_key_data *enc_state, int image_index,
686 const struct image_header *hdr, const struct flash_area *fap,
687 struct boot_status *bs)
688{
689 uint32_t off;
690 uint16_t len;
691 struct image_tlv_iter it;
692#if MCUBOOT_SWAP_SAVE_ENCTLV
693 uint8_t *buf;
694#else
695 uint8_t buf[EXPECTED_ENC_LEN];
696#endif
697 uint8_t slot;
698 int rc;
699
700 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
701 if (rc < 0) {
702 return rc;
703 }
704 slot = rc;
705
706 /* Already loaded... */
707 if (enc_state[slot].valid) {
708 return 1;
709 }
710
711 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
712 if (rc) {
713 return -1;
714 }
715
716 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
717 if (rc != 0) {
718 return rc;
719 }
720
721 if (len != EXPECTED_ENC_LEN) {
722 return -1;
723 }
724
725#if MCUBOOT_SWAP_SAVE_ENCTLV
726 buf = bs->enctlv[slot];
727 memset(buf, 0xff, BOOT_ENC_TLV_ALIGN_SIZE);
728#endif
729
730 rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
731 if (rc) {
732 return -1;
733 }
734
735 return boot_enc_decrypt(buf, bs->enckey[slot]);
736}
737
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100738bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300739boot_enc_valid(struct enc_key_data *enc_state, int image_index,
740 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300741{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100742 int rc;
743
Fabio Utzigb0f04732019-07-31 09:49:19 -0300744 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100745 if (rc < 0) {
746 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300747 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100748 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100749 }
750
751 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300752}
753
754void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300755boot_encrypt(struct enc_key_data *enc_state, int image_index,
756 const struct flash_area *fap, uint32_t off, uint32_t sz,
757 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300758{
759 struct enc_key_data *enc;
760 uint32_t i, j;
761 uint8_t u8;
762 uint8_t nonce[16];
763 uint8_t blk[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100764 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300765
766 memset(nonce, 0, 12);
767 off >>= 4;
768 nonce[12] = (uint8_t)(off >> 24);
769 nonce[13] = (uint8_t)(off >> 16);
770 nonce[14] = (uint8_t)(off >> 8);
771 nonce[15] = (uint8_t)off;
772
Fabio Utzigb0f04732019-07-31 09:49:19 -0300773 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100774 if (rc < 0) {
775 assert(0);
776 return;
777 }
778
779 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300780 assert(enc->valid == 1);
781 for (i = 0; i < sz; i++) {
782 if (i == 0 || blk_off == 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200783#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300784 mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200785#else
786 tc_aes_encrypt(blk, nonce, &enc->aes);
787#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300788
789 for (j = 16; j > 0; --j) {
790 if (++nonce[j - 1] != 0) {
791 break;
792 }
793 }
794 }
795
796 u8 = *buf;
797 *buf++ = u8 ^ blk[blk_off];
798 blk_off = (blk_off + 1) & 0x0f;
799 }
800}
801
Fabio Utzig10ee6482019-08-01 12:04:52 -0300802/**
803 * Clears encrypted state after use.
804 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300805void
806boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300807{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300808 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300809}
810
811#endif /* MCUBOOT_ENC_IMAGES */