blob: 032b46b9b17d52999bed9d14d90e76726845de63 [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"
33#include "mbedtls/asn1.h"
34#endif
35
36#if defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020037# if defined(MCUBOOT_USE_MBED_TLS)
38# include "mbedtls/nist_kw.h"
39# include "mbedtls/aes.h"
40# else
41# include "tinycrypt/aes.h"
42# endif
Fabio Utzigba829042018-09-18 08:29:34 -030043#endif
44
Fabio Utzigba829042018-09-18 08:29:34 -030045#include "bootutil/image.h"
46#include "bootutil/enc_key.h"
47#include "bootutil/sign_key.h"
48
49#include "bootutil_priv.h"
50
Fabio Utzigba829042018-09-18 08:29:34 -030051#define TLV_ENC_RSA_SZ 256
52#define TLV_ENC_KW_SZ 24
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 Utzig38f5ffe2018-12-27 16:12:58 -020057key_unwrap(uint8_t *wrapped, uint8_t *enckey)
58{
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 Utzig38f5ffe2018-12-27 16:12:58 -020084key_unwrap(uint8_t *wrapped, uint8_t *enckey)
85{
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
131parse_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
132{
133 int rc;
134 size_t len;
135
136 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
137 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
138 return -1;
139 }
140
141 if (*p + len != end) {
142 return -2;
143 }
144
145 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 ||
155 mbedtls_asn1_get_mpi(p, end, &ctx->Q) != 0 ||
156 /* d mod (p-1) and d mod (q-1) */
157 mbedtls_asn1_get_mpi(p, end, &ctx->DP) != 0 ||
158 mbedtls_asn1_get_mpi(p, end, &ctx->DQ) != 0 ||
159 /* q ^ (-1) mod p */
160 mbedtls_asn1_get_mpi(p, end, &ctx->QP) != 0) {
161 return -3;
162 }
163
164 ctx->len = mbedtls_mpi_size(&ctx->N);
165
166 if (*p != end) {
167 return -4;
168 }
169
170 if (mbedtls_rsa_check_pubkey(ctx) != 0 ||
171 mbedtls_rsa_check_privkey(ctx) != 0) {
172 return -5;
173 }
174
175 return 0;
176}
177#endif
178
179int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300180boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, uint8_t *enckey)
Fabio Utzigba829042018-09-18 08:29:34 -0300181{
182 int rc;
183
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200184#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300185 mbedtls_aes_init(&enc_state[slot].aes);
186 rc = mbedtls_aes_setkey_enc(&enc_state[slot].aes, enckey, BOOT_ENC_KEY_SIZE_BITS);
187 if (rc) {
188 mbedtls_aes_free(&enc_state[slot].aes);
189 return -1;
190 }
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200191#else
192 (void)rc;
193
194 /* set_encrypt and set_decrypt do the same thing in tinycrypt */
195 tc_aes128_set_encrypt_key(&enc_state[slot].aes, enckey);
196#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300197
198 enc_state[slot].valid = 1;
199
200 return 0;
201}
202
203#if defined(MCUBOOT_ENCRYPT_RSA)
204# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
205# define EXPECTED_ENC_LEN TLV_ENC_RSA_SZ
206#elif defined(MCUBOOT_ENCRYPT_KW)
207# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
208# define EXPECTED_ENC_LEN TLV_ENC_KW_SZ
209#endif
210
211/*
212 * Load encryption key.
213 */
214int
Fabio Utzig10ee6482019-08-01 12:04:52 -0300215boot_enc_load(struct enc_key_data *enc_state, int image_index,
216 const struct image_header *hdr, const struct flash_area *fap,
217 uint8_t *enckey)
Fabio Utzigba829042018-09-18 08:29:34 -0300218{
219#if defined(MCUBOOT_ENCRYPT_RSA)
220 mbedtls_rsa_context rsa;
221 uint8_t *cp;
222 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300223 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200224#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300225 uint32_t off;
Fabio Utzig61fd8882019-09-14 20:00:20 -0300226 uint16_t len;
227 struct image_tlv_iter it;
Fabio Utzigba829042018-09-18 08:29:34 -0300228 uint8_t buf[TLV_ENC_RSA_SZ];
229 uint8_t slot;
Fabio Utzigba829042018-09-18 08:29:34 -0300230 int rc;
231
Fabio Utzigb0f04732019-07-31 09:49:19 -0300232 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100233 if (rc < 0) {
234 return rc;
235 }
236 slot = rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300237
238 /* Already loaded... */
239 if (enc_state[slot].valid) {
240 return 1;
241 }
242
Fabio Utzig61fd8882019-09-14 20:00:20 -0300243 rc = bootutil_tlv_iter_begin(&it, hdr, fap, EXPECTED_ENC_TLV, false);
Fabio Utzigba829042018-09-18 08:29:34 -0300244 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300245 return -1;
246 }
Fabio Utzigba829042018-09-18 08:29:34 -0300247
Fabio Utzig61fd8882019-09-14 20:00:20 -0300248 rc = bootutil_tlv_iter_next(&it, &off, &len, NULL);
249 if (rc != 0) {
250 return rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300251 }
252
Fabio Utzig61fd8882019-09-14 20:00:20 -0300253 if (len != EXPECTED_ENC_LEN) {
Fabio Utzigba829042018-09-18 08:29:34 -0300254 return -1;
Fabio Utzig61fd8882019-09-14 20:00:20 -0300255 }
256
257 rc = flash_area_read(fap, off, buf, EXPECTED_ENC_LEN);
258 if (rc) {
259 return -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300260 }
261
Fabio Utzigba829042018-09-18 08:29:34 -0300262#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig233af7d2019-08-26 12:06:16 -0300263 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Fabio Utzigba829042018-09-18 08:29:34 -0300264
Fabio Utzig233af7d2019-08-26 12:06:16 -0300265 cp = (uint8_t *)bootutil_enc_key.key;
266 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300267
Fabio Utzig233af7d2019-08-26 12:06:16 -0300268 rc = parse_enckey(&rsa, &cp, cpend);
269 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300270 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300271 return rc;
272 }
273
274 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
275 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
276 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300277
278#elif defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig233af7d2019-08-26 12:06:16 -0300279 assert(*bootutil_enc_key.len == 16);
280 rc = key_unwrap(buf, enckey);
Fabio Utzigba829042018-09-18 08:29:34 -0300281#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300282
Fabio Utzigba829042018-09-18 08:29:34 -0300283 return rc;
284}
285
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100286bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300287boot_enc_valid(struct enc_key_data *enc_state, int image_index,
288 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300289{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100290 int rc;
291
Fabio Utzigb0f04732019-07-31 09:49:19 -0300292 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100293 if (rc < 0) {
294 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300295 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100296 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100297 }
298
299 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300300}
301
302void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300303boot_encrypt(struct enc_key_data *enc_state, int image_index,
304 const struct flash_area *fap, uint32_t off, uint32_t sz,
305 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300306{
307 struct enc_key_data *enc;
308 uint32_t i, j;
309 uint8_t u8;
310 uint8_t nonce[16];
311 uint8_t blk[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100312 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300313
314 memset(nonce, 0, 12);
315 off >>= 4;
316 nonce[12] = (uint8_t)(off >> 24);
317 nonce[13] = (uint8_t)(off >> 16);
318 nonce[14] = (uint8_t)(off >> 8);
319 nonce[15] = (uint8_t)off;
320
Fabio Utzigb0f04732019-07-31 09:49:19 -0300321 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100322 if (rc < 0) {
323 assert(0);
324 return;
325 }
326
327 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300328 assert(enc->valid == 1);
329 for (i = 0; i < sz; i++) {
330 if (i == 0 || blk_off == 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200331#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300332 mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200333#else
334 tc_aes_encrypt(blk, nonce, &enc->aes);
335#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300336
337 for (j = 16; j > 0; --j) {
338 if (++nonce[j - 1] != 0) {
339 break;
340 }
341 }
342 }
343
344 u8 = *buf;
345 *buf++ = u8 ^ blk[blk_off];
346 blk_off = (blk_off + 1) & 0x0f;
347 }
348}
349
Fabio Utzig10ee6482019-08-01 12:04:52 -0300350/**
351 * Clears encrypted state after use.
352 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300353void
354boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300355{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300356 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300357}
358
359#endif /* MCUBOOT_ENC_IMAGES */