blob: 72e1481583bdc43cca3e161f6d6ec389fc6d33ac [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;
226 uint32_t end;
227 struct image_tlv_info info;
228 struct image_tlv tlv;
229 uint8_t buf[TLV_ENC_RSA_SZ];
230 uint8_t slot;
231 uint8_t enckey_type;
232 int rc;
233
Fabio Utzigb0f04732019-07-31 09:49:19 -0300234 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100235 if (rc < 0) {
236 return rc;
237 }
238 slot = rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300239
240 /* Already loaded... */
241 if (enc_state[slot].valid) {
242 return 1;
243 }
244
Fabio Utzigc9621352019-08-08 12:15:51 -0300245 off = BOOT_TLV_OFF(hdr);
Fabio Utzigba829042018-09-18 08:29:34 -0300246
247 rc = flash_area_read(fap, off, &info, sizeof(info));
248 if (rc) {
249 return rc;
250 }
251 if (info.it_magic != IMAGE_TLV_INFO_MAGIC) {
252 return -1;
253 }
254 end = off + info.it_tlv_tot;
255 off += sizeof(info);
256
257 enckey_type = 0;
258 for (; off < end; off += sizeof(tlv) + tlv.it_len) {
259 rc = flash_area_read(fap, off, &tlv, sizeof tlv);
260 if (rc) {
261 return rc;
262 }
263
264 if (tlv.it_type == EXPECTED_ENC_TLV) {
265 if (tlv.it_len != EXPECTED_ENC_LEN) {
266 return -1;
267 }
268 rc = flash_area_read(fap, off + sizeof(tlv), buf, EXPECTED_ENC_LEN);
269 if (rc) {
270 return rc;
271 }
272 enckey_type = EXPECTED_ENC_TLV;
273 break;
274 }
275 }
276
277 if (enckey_type == 0) {
278 return -1;
279 }
280
281 if (enckey_type == EXPECTED_ENC_TLV) {
282#if defined(MCUBOOT_ENCRYPT_RSA)
283 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
284
285 cp = (uint8_t *)bootutil_enc_key.key;
286 cpend = cp + *bootutil_enc_key.len;
287
288 rc = parse_enckey(&rsa, &cp, cpend);
289 if (rc) {
290 mbedtls_rsa_free(&rsa);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200291 return rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300292 }
293
294 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
295 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
296 mbedtls_rsa_free(&rsa);
297
298#elif defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzigba829042018-09-18 08:29:34 -0300299 assert(*bootutil_enc_key.len == 16);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200300 rc = key_unwrap(buf, enckey);
Fabio Utzigba829042018-09-18 08:29:34 -0300301#endif
302 }
303
Fabio Utzigba829042018-09-18 08:29:34 -0300304 return rc;
305}
306
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100307bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300308boot_enc_valid(struct enc_key_data *enc_state, int image_index,
309 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300310{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100311 int rc;
312
Fabio Utzigb0f04732019-07-31 09:49:19 -0300313 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100314 if (rc < 0) {
315 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300316 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100317 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100318 }
319
320 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300321}
322
323void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300324boot_encrypt(struct enc_key_data *enc_state, int image_index,
325 const struct flash_area *fap, uint32_t off, uint32_t sz,
326 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300327{
328 struct enc_key_data *enc;
329 uint32_t i, j;
330 uint8_t u8;
331 uint8_t nonce[16];
332 uint8_t blk[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100333 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300334
335 memset(nonce, 0, 12);
336 off >>= 4;
337 nonce[12] = (uint8_t)(off >> 24);
338 nonce[13] = (uint8_t)(off >> 16);
339 nonce[14] = (uint8_t)(off >> 8);
340 nonce[15] = (uint8_t)off;
341
Fabio Utzigb0f04732019-07-31 09:49:19 -0300342 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100343 if (rc < 0) {
344 assert(0);
345 return;
346 }
347
348 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300349 assert(enc->valid == 1);
350 for (i = 0; i < sz; i++) {
351 if (i == 0 || blk_off == 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200352#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300353 mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200354#else
355 tc_aes_encrypt(blk, nonce, &enc->aes);
356#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300357
358 for (j = 16; j > 0; --j) {
359 if (++nonce[j - 1] != 0) {
360 break;
361 }
362 }
363 }
364
365 u8 = *buf;
366 *buf++ = u8 ^ blk[blk_off];
367 blk_off = (blk_off + 1) & 0x0f;
368 }
369}
370
Fabio Utzig10ee6482019-08-01 12:04:52 -0300371/**
372 * Clears encrypted state after use.
373 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300374void
375boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300376{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300377 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300378}
379
380#endif /* MCUBOOT_ENC_IMAGES */