42
42
# endif
43
43
#endif
44
44
45
+ #if defined(MCUBOOT_ENCRYPT_EC256 )
46
+ #include "tinycrypt/utils.h"
47
+ #include "tinycrypt/constants.h"
48
+ #include "tinycrypt/ecc.h"
49
+ #include "tinycrypt/ecc_dh.h"
50
+ #include "tinycrypt/ctr_mode.h"
51
+ #include "tinycrypt/hmac.h"
52
+ #include "mbedtls/oid.h"
53
+ #include "mbedtls/asn1.h"
54
+ #endif
55
+
45
56
#include "bootutil/image.h"
46
57
#include "bootutil/enc_key.h"
47
58
#include "bootutil/sign_key.h"
@@ -128,7 +139,7 @@ key_unwrap(uint8_t *wrapped, uint8_t *enckey)
128
139
129
140
#if defined(MCUBOOT_ENCRYPT_RSA )
130
141
static int
131
- parse_enckey (mbedtls_rsa_context * ctx , uint8_t * * p , uint8_t * end )
142
+ parse_rsa_enckey (mbedtls_rsa_context * ctx , uint8_t * * p , uint8_t * end )
132
143
{
133
144
int rc ;
134
145
size_t len ;
@@ -176,6 +187,191 @@ parse_enckey(mbedtls_rsa_context *ctx, uint8_t **p, uint8_t *end)
176
187
}
177
188
#endif
178
189
190
+ #if defined(MCUBOOT_ENCRYPT_EC256 )
191
+ static const uint8_t ec_pubkey_oid [] = MBEDTLS_OID_EC_ALG_UNRESTRICTED ;
192
+ static const uint8_t ec_secp256r1_oid [] = MBEDTLS_OID_EC_GRP_SECP256R1 ;
193
+
194
+ /*
195
+ * Parses the output of `imgtool keygen`, which produces a PKCS#8 elliptic
196
+ * curve keypair. See RFC5208 and RFC5915.
197
+ */
198
+ static int
199
+ parse_ec256_enckey (uint8_t * * p , uint8_t * end , uint8_t * pk )
200
+ {
201
+ int rc ;
202
+ size_t len ;
203
+ int version ;
204
+ mbedtls_asn1_buf alg ;
205
+ mbedtls_asn1_buf param ;
206
+
207
+ if ((rc = mbedtls_asn1_get_tag (p , end , & len ,
208
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE )) != 0 ) {
209
+ return -1 ;
210
+ }
211
+
212
+ if (* p + len != end ) {
213
+ return -2 ;
214
+ }
215
+
216
+ version = 0 ;
217
+ if (mbedtls_asn1_get_int (p , end , & version ) || version != 0 ) {
218
+ return -3 ;
219
+ }
220
+
221
+ if ((rc = mbedtls_asn1_get_alg (p , end , & alg , & param )) != 0 ) {
222
+ return -5 ;
223
+ }
224
+
225
+ if (alg .len != sizeof (ec_pubkey_oid ) - 1 ||
226
+ memcmp (alg .p , ec_pubkey_oid , sizeof (ec_pubkey_oid ) - 1 )) {
227
+ return -6 ;
228
+ }
229
+ if (param .len != sizeof (ec_secp256r1_oid ) - 1 ||
230
+ memcmp (param .p , ec_secp256r1_oid , sizeof (ec_secp256r1_oid ) - 1 )) {
231
+ return -7 ;
232
+ }
233
+
234
+ if ((rc = mbedtls_asn1_get_tag (p , end , & len , MBEDTLS_ASN1_OCTET_STRING )) != 0 ) {
235
+ return -8 ;
236
+ }
237
+
238
+ /* RFC5915 - ECPrivateKey */
239
+
240
+ if ((rc = mbedtls_asn1_get_tag (p , end , & len ,
241
+ MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE )) != 0 ) {
242
+ return -9 ;
243
+ }
244
+
245
+ version = 0 ;
246
+ if (mbedtls_asn1_get_int (p , end , & version ) || version != 1 ) {
247
+ return -10 ;
248
+ }
249
+
250
+ /* privateKey */
251
+
252
+ if ((rc = mbedtls_asn1_get_tag (p , end , & len , MBEDTLS_ASN1_OCTET_STRING )) != 0 ) {
253
+ return -11 ;
254
+ }
255
+
256
+ if (len != NUM_ECC_BYTES ) {
257
+ return -12 ;
258
+ }
259
+
260
+ memcpy (pk , * p , len );
261
+
262
+ /* publicKey usually follows but is not parsed here */
263
+
264
+ return 0 ;
265
+ }
266
+
267
+ /*
268
+ * HKDF as described by RFC5869.
269
+ *
270
+ * @param ikm The input data to be derived.
271
+ * @param ikm_len Length of the input data.
272
+ * @param info An information tag.
273
+ * @param info_len Length of the information tag.
274
+ * @param okm Output of the KDF computation.
275
+ * @param okm_len On input the requested length; on output the generated length
276
+ */
277
+ static int
278
+ hkdf (uint8_t * ikm , uint16_t ikm_len , uint8_t * info , uint16_t info_len ,
279
+ uint8_t * okm , uint16_t * okm_len )
280
+ {
281
+ struct tc_hmac_state_struct hmac ;
282
+ uint8_t salt [TC_SHA256_DIGEST_SIZE ];
283
+ uint8_t prk [TC_SHA256_DIGEST_SIZE ];
284
+ uint8_t T [TC_SHA256_DIGEST_SIZE ];
285
+ uint16_t off ;
286
+ uint16_t len ;
287
+ uint8_t counter ;
288
+ bool first ;
289
+ int rc ;
290
+
291
+ /*
292
+ * Extract
293
+ */
294
+
295
+ if (ikm == NULL || okm == NULL || ikm_len == 0 ) {
296
+ return -1 ;
297
+ }
298
+
299
+ memset (salt , 0 , TC_SHA256_DIGEST_SIZE );
300
+ rc = tc_hmac_set_key (& hmac , salt , TC_SHA256_DIGEST_SIZE );
301
+ if (rc != TC_CRYPTO_SUCCESS ) {
302
+ return -1 ;
303
+ }
304
+
305
+ rc = tc_hmac_init (& hmac );
306
+ if (rc != TC_CRYPTO_SUCCESS ) {
307
+ return -1 ;
308
+ }
309
+
310
+ rc = tc_hmac_update (& hmac , ikm , ikm_len );
311
+ if (rc != TC_CRYPTO_SUCCESS ) {
312
+ return -1 ;
313
+ }
314
+
315
+ rc = tc_hmac_final (prk , TC_SHA256_DIGEST_SIZE , & hmac );
316
+ if (rc != TC_CRYPTO_SUCCESS ) {
317
+ return -1 ;
318
+ }
319
+
320
+ /*
321
+ * Expand
322
+ */
323
+
324
+ len = * okm_len ;
325
+ counter = 1 ;
326
+ first = true;
327
+ for (off = 0 ; len > 0 ; off += TC_SHA256_DIGEST_SIZE , ++ counter ) {
328
+ rc = tc_hmac_set_key (& hmac , prk , TC_SHA256_DIGEST_SIZE );
329
+ if (rc != TC_CRYPTO_SUCCESS ) {
330
+ return -1 ;
331
+ }
332
+
333
+ rc = tc_hmac_init (& hmac );
334
+ if (rc != TC_CRYPTO_SUCCESS ) {
335
+ return -1 ;
336
+ }
337
+
338
+ if (first ) {
339
+ first = false;
340
+ } else {
341
+ rc = tc_hmac_update (& hmac , T , TC_SHA256_DIGEST_SIZE );
342
+ if (rc != TC_CRYPTO_SUCCESS ) {
343
+ return -1 ;
344
+ }
345
+ }
346
+
347
+ rc = tc_hmac_update (& hmac , info , info_len );
348
+ if (rc != TC_CRYPTO_SUCCESS ) {
349
+ return -1 ;
350
+ }
351
+
352
+ rc = tc_hmac_update (& hmac , & counter , 1 );
353
+ if (rc != TC_CRYPTO_SUCCESS ) {
354
+ return -1 ;
355
+ }
356
+
357
+ rc = tc_hmac_final (T , TC_SHA256_DIGEST_SIZE , & hmac );
358
+ if (rc != TC_CRYPTO_SUCCESS ) {
359
+ return -1 ;
360
+ }
361
+
362
+ if (len > TC_SHA256_DIGEST_SIZE ) {
363
+ memcpy (& okm [off ], T , TC_SHA256_DIGEST_SIZE );
364
+ len -= TC_SHA256_DIGEST_SIZE ;
365
+ } else {
366
+ memcpy (& okm [off ], T , len );
367
+ len = 0 ;
368
+ }
369
+ }
370
+
371
+ return 0 ;
372
+ }
373
+ #endif
374
+
179
375
int
180
376
boot_enc_set_key (struct enc_key_data * enc_state , uint8_t slot , uint8_t * enckey )
181
377
{
@@ -206,6 +402,12 @@ boot_enc_set_key(struct enc_key_data *enc_state, uint8_t slot, uint8_t *enckey)
206
402
#elif defined(MCUBOOT_ENCRYPT_KW )
207
403
# define EXPECTED_ENC_TLV IMAGE_TLV_ENC_KW128
208
404
# define EXPECTED_ENC_LEN TLV_ENC_KW_SZ
405
+ #elif defined(MCUBOOT_ENCRYPT_EC256 )
406
+ # define EXPECTED_ENC_TLV IMAGE_TLV_ENC_EC256
407
+ # define EXPECTED_ENC_LEN (65 + 32 + 16)
408
+ # define EC_PUBK_INDEX (1)
409
+ # define EC_TAG_INDEX (65)
410
+ # define EC_CIPHERKEY_INDEX (65 + 32)
209
411
#endif
210
412
211
413
/*
@@ -221,11 +423,22 @@ boot_enc_load(struct enc_key_data *enc_state, int image_index,
221
423
uint8_t * cp ;
222
424
uint8_t * cpend ;
223
425
size_t olen ;
426
+ #endif
427
+ #if defined(MCUBOOT_ENCRYPT_EC256 )
428
+ struct tc_hmac_state_struct hmac ;
429
+ struct tc_aes_key_sched_struct aes ;
430
+ uint8_t tag [TC_SHA256_DIGEST_SIZE ];
431
+ uint8_t shared [NUM_ECC_BYTES ];
432
+ uint8_t derived_key [TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE ];
433
+ uint8_t * cp ;
434
+ uint8_t * cpend ;
435
+ uint8_t pk [NUM_ECC_BYTES ];
436
+ uint8_t counter [TC_AES_BLOCK_SIZE ];
224
437
#endif
225
438
uint32_t off ;
226
439
uint16_t len ;
227
440
struct image_tlv_iter it ;
228
- uint8_t buf [TLV_ENC_RSA_SZ ];
441
+ uint8_t buf [EXPECTED_ENC_LEN ];
229
442
uint8_t slot ;
230
443
int rc ;
231
444
@@ -260,12 +473,13 @@ boot_enc_load(struct enc_key_data *enc_state, int image_index,
260
473
}
261
474
262
475
#if defined(MCUBOOT_ENCRYPT_RSA )
476
+
263
477
mbedtls_rsa_init (& rsa , MBEDTLS_RSA_PKCS_V21 , MBEDTLS_MD_SHA256 );
264
478
265
479
cp = (uint8_t * )bootutil_enc_key .key ;
266
480
cpend = cp + * bootutil_enc_key .len ;
267
481
268
- rc = parse_enckey (& rsa , & cp , cpend );
482
+ rc = parse_rsa_enckey (& rsa , & cp , cpend );
269
483
if (rc ) {
270
484
mbedtls_rsa_free (& rsa );
271
485
return rc ;
@@ -276,8 +490,100 @@ boot_enc_load(struct enc_key_data *enc_state, int image_index,
276
490
mbedtls_rsa_free (& rsa );
277
491
278
492
#elif defined(MCUBOOT_ENCRYPT_KW )
493
+
279
494
assert (* bootutil_enc_key .len == 16 );
280
495
rc = key_unwrap (buf , enckey );
496
+
497
+ #elif defined(MCUBOOT_ENCRYPT_EC256 )
498
+
499
+ cp = (uint8_t * )bootutil_enc_key .key ;
500
+ cpend = cp + * bootutil_enc_key .len ;
501
+
502
+ /*
503
+ * Load the stored EC256 decryption private key
504
+ */
505
+
506
+ rc = parse_ec256_enckey (& cp , cpend , pk );
507
+ if (rc ) {
508
+ return rc ;
509
+ }
510
+
511
+ /* is EC point uncompressed? */
512
+ if (buf [0 ] != 0x04 ) {
513
+ return -1 ;
514
+ }
515
+
516
+ /*
517
+ * First "element" in the TLV is the curve point (public key)
518
+ */
519
+ rc = uECC_valid_public_key (& buf [EC_PUBK_INDEX ], uECC_secp256r1 ());
520
+ if (rc != 0 ) {
521
+ return -1 ;
522
+ }
523
+
524
+ rc = uECC_shared_secret (& buf [EC_PUBK_INDEX ], pk , shared , uECC_secp256r1 ());
525
+ if (rc != TC_CRYPTO_SUCCESS ) {
526
+ return -1 ;
527
+ }
528
+
529
+ /*
530
+ * Expand shared secret to create keys for AES-128-CTR + HMAC-SHA256
531
+ */
532
+
533
+ len = TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE ;
534
+ rc = hkdf (shared , TC_SHA256_DIGEST_SIZE , (uint8_t * )"MCUBoot_ECIES_v1" , 16 ,
535
+ derived_key , & len );
536
+ if (rc != 0 || len != (TC_AES_KEY_SIZE + TC_SHA256_DIGEST_SIZE )) {
537
+ return -1 ;
538
+ }
539
+
540
+ /*
541
+ * HMAC the key and check that our received MAC matches the generated tag
542
+ */
543
+
544
+ rc = tc_hmac_set_key (& hmac , & derived_key [16 ], 32 );
545
+ if (rc != TC_CRYPTO_SUCCESS ) {
546
+ return -1 ;
547
+ }
548
+
549
+ rc = tc_hmac_init (& hmac );
550
+ if (rc != TC_CRYPTO_SUCCESS ) {
551
+ return -1 ;
552
+ }
553
+
554
+ rc = tc_hmac_update (& hmac , & buf [EC_CIPHERKEY_INDEX ], 16 );
555
+ if (rc != TC_CRYPTO_SUCCESS ) {
556
+ return -1 ;
557
+ }
558
+
559
+ /* Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes */
560
+ rc = tc_hmac_final (tag , TC_SHA256_DIGEST_SIZE , & hmac );
561
+ if (rc != TC_CRYPTO_SUCCESS ) {
562
+ return -1 ;
563
+ }
564
+
565
+ if (_compare (tag , & buf [EC_TAG_INDEX ], 32 ) != 0 ) {
566
+ return -1 ;
567
+ }
568
+
569
+ /*
570
+ * Finally decrypt the received ciphered key
571
+ */
572
+
573
+ rc = tc_aes128_set_decrypt_key (& aes , derived_key );
574
+ if (rc != TC_CRYPTO_SUCCESS ) {
575
+ return -1 ;
576
+ }
577
+
578
+ memset (counter , 0 , TC_AES_BLOCK_SIZE );
579
+ rc = tc_ctr_mode (enckey , TC_AES_KEY_SIZE , & buf [EC_CIPHERKEY_INDEX ],
580
+ TC_AES_KEY_SIZE , counter , & aes );
581
+ if (rc != TC_CRYPTO_SUCCESS ) {
582
+ return -1 ;
583
+ }
584
+
585
+ rc = 0 ;
586
+
281
587
#endif
282
588
283
589
return rc ;
0 commit comments