blob: 6dcaa22f98b00a4a6e63ea8432b2c41356fa20ca [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
46#include "bootutil/image.h"
47#include "bootutil/enc_key.h"
48#include "bootutil/sign_key.h"
49
50#include "bootutil_priv.h"
51
52static struct enc_key_data enc_state[BOOT_NUM_SLOTS];
53
54#define TLV_ENC_RSA_SZ 256
55#define TLV_ENC_KW_SZ 24
56
Fabio Utzig38f5ffe2018-12-27 16:12:58 -020057#if defined(MCUBOOT_ENCRYPT_KW)
58#if defined(MCUBOOT_USE_MBED_TLS)
59int
60key_unwrap(uint8_t *wrapped, uint8_t *enckey)
61{
62 mbedtls_nist_kw_context kw;
63 int rc;
64 size_t olen;
65
66 mbedtls_nist_kw_init(&kw);
67
68 rc = mbedtls_nist_kw_setkey(&kw, MBEDTLS_CIPHER_ID_AES,
69 bootutil_enc_key.key, *bootutil_enc_key.len * 8, 0);
70 if (rc) {
71 goto done;
72 }
73
74 rc = mbedtls_nist_kw_unwrap(&kw, MBEDTLS_KW_MODE_KW, wrapped, TLV_ENC_KW_SZ,
75 enckey, &olen, BOOT_ENC_KEY_SIZE);
76
77done:
78 mbedtls_nist_kw_free(&kw);
79 return rc;
80}
81#else /* !MCUBOOT_USE_MBED_TLS */
82/*
83 * Implements AES key unwrapping following RFC-3394 section 2.2.2, using
84 * tinycrypt for AES-128 decryption.
85 */
86int
87key_unwrap(uint8_t *wrapped, uint8_t *enckey)
88{
89 struct tc_aes_key_sched_struct aes;
90 uint8_t A[8];
91 uint8_t B[16];
92 int8_t i, j, k;
93
94 if (tc_aes128_set_decrypt_key(&aes, bootutil_enc_key.key) == 0) {
95 return -1;
96 }
97
98 for (k = 0; k < 8; k++) {
99 A[k] = wrapped[k];
100 enckey[k] = wrapped[8 + k];
101 enckey[8 + k] = wrapped[16 + k];
102 }
103
104 for (j = 5; j >= 0; j--) {
105 for (i = 2; i > 0; i--) {
106 for (k = 0; k < 8; k++) {
107 B[k] = A[k];
108 B[8 + k] = enckey[((i-1) * 8) + k];
109 }
110 B[7] ^= 2 * j + i;
111 if (tc_aes_decrypt((uint8_t *)&B, (uint8_t *)&B, &aes) == 0) {
112 return -1;
113 }
114 for (k = 0; k < 8; k++) {
115 A[k] = B[k];
116 enckey[((i-1) * 8) + k] = B[8 + k];
117 }
118 }
119 }
120
121 for (i = 0, k = 0; i < 8; i++) {
122 k |= A[i] ^ 0xa6;
123 }
124 if (k) {
125 return -1;
126 }
127 return 0;
128}
129#endif /* MCUBOOT_USE_MBED_TLS */
130#endif /* MCUBOOT_ENCRYPT_KW */
131
Fabio Utzigba829042018-09-18 08:29:34 -0300132#if defined(MCUBOOT_ENCRYPT_RSA)
133static int
134parse_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
135{
136 int rc;
137 size_t len;
138
139 if ((rc = mbedtls_asn1_get_tag(p, end, &len,
140 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
141 return -1;
142 }
143
144 if (*p + len != end) {
145 return -2;
146 }
147
148 if ( /* version */
149 mbedtls_asn1_get_int(p, end, &ctx->ver) != 0 ||
150 /* public modulus */
151 mbedtls_asn1_get_mpi(p, end, &ctx->N) != 0 ||
152 /* public exponent */
153 mbedtls_asn1_get_mpi(p, end, &ctx->E) != 0 ||
154 /* private exponent */
155 mbedtls_asn1_get_mpi(p, end, &ctx->D) != 0 ||
156 /* primes */
157 mbedtls_asn1_get_mpi(p, end, &ctx->P) != 0 ||
158 mbedtls_asn1_get_mpi(p, end, &ctx->Q) != 0 ||
159 /* d mod (p-1) and d mod (q-1) */
160 mbedtls_asn1_get_mpi(p, end, &ctx->DP) != 0 ||
161 mbedtls_asn1_get_mpi(p, end, &ctx->DQ) != 0 ||
162 /* q ^ (-1) mod p */
163 mbedtls_asn1_get_mpi(p, end, &ctx->QP) != 0) {
164 return -3;
165 }
166
167 ctx->len = mbedtls_mpi_size(&ctx->N);
168
169 if (*p != end) {
170 return -4;
171 }
172
173 if (mbedtls_rsa_check_pubkey(ctx) != 0 ||
174 mbedtls_rsa_check_privkey(ctx) != 0) {
175 return -5;
176 }
177
178 return 0;
179}
180#endif
181
182int
183boot_enc_set_key(uint8_t slot, uint8_t *enckey)
184{
185 int rc;
186
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200187#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300188 mbedtls_aes_init(&enc_state[slot].aes);
189 rc = mbedtls_aes_setkey_enc(&enc_state[slot].aes, enckey, BOOT_ENC_KEY_SIZE_BITS);
190 if (rc) {
191 mbedtls_aes_free(&enc_state[slot].aes);
192 return -1;
193 }
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200194#else
195 (void)rc;
196
197 /* set_encrypt and set_decrypt do the same thing in tinycrypt */
198 tc_aes128_set_encrypt_key(&enc_state[slot].aes, enckey);
199#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300200
201 enc_state[slot].valid = 1;
202
203 return 0;
204}
205
206#if defined(MCUBOOT_ENCRYPT_RSA)
207# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_RSA2048
208# define EXPECTED_ENC_LEN TLV_ENC_RSA_SZ
209#elif defined(MCUBOOT_ENCRYPT_KW)
210# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
211# define EXPECTED_ENC_LEN TLV_ENC_KW_SZ
212#endif
213
214/*
215 * Load encryption key.
216 */
217int
218boot_enc_load(const struct image_header *hdr, const struct flash_area *fap,
219 uint8_t *enckey)
220{
221#if defined(MCUBOOT_ENCRYPT_RSA)
222 mbedtls_rsa_context rsa;
223 uint8_t *cp;
224 uint8_t *cpend;
Fabio Utzigba829042018-09-18 08:29:34 -0300225 size_t olen;
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200226#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300227 uint32_t off;
228 uint32_t end;
229 struct image_tlv_info info;
230 struct image_tlv tlv;
231 uint8_t buf[TLV_ENC_RSA_SZ];
232 uint8_t slot;
233 uint8_t enckey_type;
234 int rc;
235
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100236 rc = flash_area_id_to_image_slot(fap->fa_id);
237 if (rc < 0) {
238 return rc;
239 }
240 slot = rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300241
242 /* Already loaded... */
243 if (enc_state[slot].valid) {
244 return 1;
245 }
246
247 off = hdr->ih_img_size + hdr->ih_hdr_size;
248
249 rc = flash_area_read(fap, off, &info, sizeof(info));
250 if (rc) {
251 return rc;
252 }
253 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
254 return -1;
255 }
256 end = off + info.it_tlv_tot;
257 off += sizeof(info);
258
259 enckey_type = 0;
260 for (; off < end; off += sizeof(tlv) + tlv.it_len) {
261 rc = flash_area_read(fap, off, &tlv, sizeof tlv);
262 if (rc) {
263 return rc;
264 }
265
266 if (tlv.it_type == EXPECTED_ENC_TLV) {
267 if (tlv.it_len != EXPECTED_ENC_LEN) {
268 return -1;
269 }
270 rc = flash_area_read(fap, off + sizeof(tlv), buf, EXPECTED_ENC_LEN);
271 if (rc) {
272 return rc;
273 }
274 enckey_type = EXPECTED_ENC_TLV;
275 break;
276 }
277 }
278
279 if (enckey_type == 0) {
280 return -1;
281 }
282
283 if (enckey_type == EXPECTED_ENC_TLV) {
284#if defined(MCUBOOT_ENCRYPT_RSA)
285 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
286
287 cp = (uint8_t *)bootutil_enc_key.key;
288 cpend = cp + *bootutil_enc_key.len;
289
290 rc = parse_enckey(&rsa, &cp, cpend);
291 if (rc) {
292 mbedtls_rsa_free(&rsa);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200293 return rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300294 }
295
296 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
297 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
298 mbedtls_rsa_free(&rsa);
299
300#elif defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzigba829042018-09-18 08:29:34 -0300301 assert(*bootutil_enc_key.len == 16);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200302 rc = key_unwrap(buf, enckey);
Fabio Utzigba829042018-09-18 08:29:34 -0300303#endif
304 }
305
Fabio Utzigba829042018-09-18 08:29:34 -0300306 return rc;
307}
308
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100309bool
Fabio Utzigba829042018-09-18 08:29:34 -0300310boot_enc_valid(const struct flash_area *fap)
311{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100312 int rc;
313
314 rc = flash_area_id_to_image_slot(fap->fa_id);
315 if (rc < 0) {
316 /* can't get proper slot number - skip encryption, */
317 /* postpone the erro for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100318 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100319 }
320
321 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300322}
323
324void
David Vinczeba3bd602019-06-17 16:01:43 +0200325boot_enc_mark_keys_invalid(void)
326{
327 size_t slot;
328
329 for(slot = 0; slot < BOOT_NUM_SLOTS; ++slot) {
330 enc_state[slot].valid = 0;
331 }
332}
333
334void
Fabio Utzigba829042018-09-18 08:29:34 -0300335boot_encrypt(const struct flash_area *fap, uint32_t off, uint32_t sz,
336 uint32_t blk_off, uint8_t *buf)
337{
338 struct enc_key_data *enc;
339 uint32_t i, j;
340 uint8_t u8;
341 uint8_t nonce[16];
342 uint8_t blk[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100343 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300344
345 memset(nonce, 0, 12);
346 off >>= 4;
347 nonce[12] = (uint8_t)(off >> 24);
348 nonce[13] = (uint8_t)(off >> 16);
349 nonce[14] = (uint8_t)(off >> 8);
350 nonce[15] = (uint8_t)off;
351
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100352 rc = flash_area_id_to_image_slot(fap->fa_id);
353 if (rc < 0) {
354 assert(0);
355 return;
356 }
357
358 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300359 assert(enc->valid == 1);
360 for (i = 0; i < sz; i++) {
361 if (i == 0 || blk_off == 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200362#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300363 mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200364#else
365 tc_aes_encrypt(blk, nonce, &enc->aes);
366#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300367
368 for (j = 16; j > 0; --j) {
369 if (++nonce[j - 1] != 0) {
370 break;
371 }
372 }
373 }
374
375 u8 = *buf;
376 *buf++ = u8 ^ blk[blk_off];
377 blk_off = (blk_off + 1) & 0x0f;
378 }
379}
380
381void boot_enc_zeroize(void)
382{
383 memset(&enc_state, 0, sizeof(enc_state));
384}
385
386#endif /* MCUBOOT_ENC_IMAGES */