blob: b4c57275456aeda7f17dc7a520f14e1806f6b08a [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;
Fabio Utzigba829042018-09-18 08:29:34 -0300227 struct image_tlv tlv;
228 uint8_t buf[TLV_ENC_RSA_SZ];
229 uint8_t slot;
230 uint8_t enckey_type;
231 int rc;
232
Fabio Utzigb0f04732019-07-31 09:49:19 -0300233 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100234 if (rc < 0) {
235 return rc;
236 }
237 slot = rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300238
239 /* Already loaded... */
240 if (enc_state[slot].valid) {
241 return 1;
242 }
243
Fabio Utzig233af7d2019-08-26 12:06:16 -0300244 rc = boot_find_tlv_offs(hdr, fap, &off, &end);
Fabio Utzigba829042018-09-18 08:29:34 -0300245 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300246 return -1;
247 }
Fabio Utzigba829042018-09-18 08:29:34 -0300248
Fabio Utzig233af7d2019-08-26 12:06:16 -0300249 for (enckey_type = 0; off < end; off += sizeof(tlv) + tlv.it_len) {
Fabio Utzigba829042018-09-18 08:29:34 -0300250 rc = flash_area_read(fap, off, &tlv, sizeof tlv);
251 if (rc) {
252 return rc;
253 }
254
255 if (tlv.it_type == EXPECTED_ENC_TLV) {
256 if (tlv.it_len != EXPECTED_ENC_LEN) {
257 return -1;
258 }
259 rc = flash_area_read(fap, off + sizeof(tlv), buf, EXPECTED_ENC_LEN);
260 if (rc) {
Fabio Utzig233af7d2019-08-26 12:06:16 -0300261 return -1;
Fabio Utzigba829042018-09-18 08:29:34 -0300262 }
263 enckey_type = EXPECTED_ENC_TLV;
264 break;
265 }
266 }
267
268 if (enckey_type == 0) {
269 return -1;
Fabio Utzig233af7d2019-08-26 12:06:16 -0300270 } else if (enckey_type != EXPECTED_ENC_TLV) {
271 return 0;
Fabio Utzigba829042018-09-18 08:29:34 -0300272 }
273
Fabio Utzigba829042018-09-18 08:29:34 -0300274#if defined(MCUBOOT_ENCRYPT_RSA)
Fabio Utzig233af7d2019-08-26 12:06:16 -0300275 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
Fabio Utzigba829042018-09-18 08:29:34 -0300276
Fabio Utzig233af7d2019-08-26 12:06:16 -0300277 cp = (uint8_t *)bootutil_enc_key.key;
278 cpend = cp + *bootutil_enc_key.len;
Fabio Utzigba829042018-09-18 08:29:34 -0300279
Fabio Utzig233af7d2019-08-26 12:06:16 -0300280 rc = parse_enckey(&rsa, &cp, cpend);
281 if (rc) {
Fabio Utzigba829042018-09-18 08:29:34 -0300282 mbedtls_rsa_free(&rsa);
Fabio Utzig233af7d2019-08-26 12:06:16 -0300283 return rc;
284 }
285
286 rc = mbedtls_rsa_rsaes_oaep_decrypt(&rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE,
287 NULL, 0, &olen, buf, enckey, BOOT_ENC_KEY_SIZE);
288 mbedtls_rsa_free(&rsa);
Fabio Utzigba829042018-09-18 08:29:34 -0300289
290#elif defined(MCUBOOT_ENCRYPT_KW)
Fabio Utzig233af7d2019-08-26 12:06:16 -0300291 assert(*bootutil_enc_key.len == 16);
292 rc = key_unwrap(buf, enckey);
Fabio Utzigba829042018-09-18 08:29:34 -0300293#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300294
Fabio Utzigba829042018-09-18 08:29:34 -0300295 return rc;
296}
297
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100298bool
Fabio Utzig10ee6482019-08-01 12:04:52 -0300299boot_enc_valid(struct enc_key_data *enc_state, int image_index,
300 const struct flash_area *fap)
Fabio Utzigba829042018-09-18 08:29:34 -0300301{
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100302 int rc;
303
Fabio Utzigb0f04732019-07-31 09:49:19 -0300304 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100305 if (rc < 0) {
306 /* can't get proper slot number - skip encryption, */
Fabio Utzigb0f04732019-07-31 09:49:19 -0300307 /* postpone the error for a upper layer */
Andrzej Puzdrowskicf97dd02019-03-14 15:10:10 +0100308 return false;
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100309 }
310
311 return enc_state[rc].valid;
Fabio Utzigba829042018-09-18 08:29:34 -0300312}
313
314void
Fabio Utzig10ee6482019-08-01 12:04:52 -0300315boot_encrypt(struct enc_key_data *enc_state, int image_index,
316 const struct flash_area *fap, uint32_t off, uint32_t sz,
317 uint32_t blk_off, uint8_t *buf)
Fabio Utzigba829042018-09-18 08:29:34 -0300318{
319 struct enc_key_data *enc;
320 uint32_t i, j;
321 uint8_t u8;
322 uint8_t nonce[16];
323 uint8_t blk[16];
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100324 int rc;
Fabio Utzigba829042018-09-18 08:29:34 -0300325
326 memset(nonce, 0, 12);
327 off >>= 4;
328 nonce[12] = (uint8_t)(off >> 24);
329 nonce[13] = (uint8_t)(off >> 16);
330 nonce[14] = (uint8_t)(off >> 8);
331 nonce[15] = (uint8_t)off;
332
Fabio Utzigb0f04732019-07-31 09:49:19 -0300333 rc = flash_area_id_to_multi_image_slot(image_index, fap->fa_id);
Andrzej Puzdrowskie575fe92019-03-14 12:20:19 +0100334 if (rc < 0) {
335 assert(0);
336 return;
337 }
338
339 enc = &enc_state[rc];
Fabio Utzigba829042018-09-18 08:29:34 -0300340 assert(enc->valid == 1);
341 for (i = 0; i < sz; i++) {
342 if (i == 0 || blk_off == 0) {
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200343#if defined(MCUBOOT_USE_MBED_TLS)
Fabio Utzigba829042018-09-18 08:29:34 -0300344 mbedtls_aes_crypt_ecb(&enc->aes, MBEDTLS_AES_ENCRYPT, nonce, blk);
Fabio Utzig38f5ffe2018-12-27 16:12:58 -0200345#else
346 tc_aes_encrypt(blk, nonce, &enc->aes);
347#endif
Fabio Utzigba829042018-09-18 08:29:34 -0300348
349 for (j = 16; j > 0; --j) {
350 if (++nonce[j - 1] != 0) {
351 break;
352 }
353 }
354 }
355
356 u8 = *buf;
357 *buf++ = u8 ^ blk[blk_off];
358 blk_off = (blk_off + 1) & 0x0f;
359 }
360}
361
Fabio Utzig10ee6482019-08-01 12:04:52 -0300362/**
363 * Clears encrypted state after use.
364 */
Fabio Utzigb63d9952019-08-19 14:20:52 -0300365void
366boot_enc_zeroize(struct enc_key_data *enc_state)
Fabio Utzigba829042018-09-18 08:29:34 -0300367{
Fabio Utzig10ee6482019-08-01 12:04:52 -0300368 memset(enc_state, 0, sizeof(struct enc_key_data) * BOOT_NUM_SLOTS);
Fabio Utzigba829042018-09-18 08:29:34 -0300369}
370
371#endif /* MCUBOOT_ENC_IMAGES */