1 /*
2  * This module provides a thin abstraction over some of the crypto
3  * primitives to make it easier to swap out the used crypto library.
4  *
5  * At this point, there are two choices: MCUBOOT_USE_MBED_TLS, or
6  * MCUBOOT_USE_TINYCRYPT.  It is a compile error there is not exactly
7  * one of these defined.
8  */
9 
10 #ifndef __BOOTUTIL_CRYPTO_AES_KW_H_
11 #define __BOOTUTIL_CRYPTO_AES_KW_H_
12 
13 #include "mcuboot_config/mcuboot_config.h"
14 
15 #if (defined(MCUBOOT_USE_MBED_TLS) + \
16      defined(MCUBOOT_USE_TINYCRYPT)) != 1
17     #error "One crypto backend must be defined: either MBED_TLS or TINYCRYPT"
18 #endif
19 
20 #if defined(MCUBOOT_USE_MBED_TLS)
21     #include <mbedtls/aes.h>
22     #include <mbedtls/nist_kw.h>
23 #endif /* MCUBOOT_USE_MBED_TLS */
24 
25 #if defined(MCUBOOT_USE_TINYCRYPT)
26     #if defined(MCUBOOT_AES_256)
27         #error "Cannot use AES-256 for encryption with Tinycrypt library."
28     #endif
29     #include <tinycrypt/aes.h>
30     #include <tinycrypt/constants.h>
31 #endif /* MCUBOOT_USE_TINYCRYPT */
32 
33 #include <stdint.h>
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 #if defined(MCUBOOT_USE_MBED_TLS)
40 typedef mbedtls_nist_kw_context bootutil_aes_kw_context;
bootutil_aes_kw_init(bootutil_aes_kw_context * ctx)41 static inline void bootutil_aes_kw_init(bootutil_aes_kw_context *ctx)
42 {
43     (void)mbedtls_nist_kw_init(ctx);
44 }
45 
bootutil_aes_kw_drop(bootutil_aes_kw_context * ctx)46 static inline void bootutil_aes_kw_drop(bootutil_aes_kw_context *ctx)
47 {
48     mbedtls_nist_kw_free(ctx);
49 }
50 
bootutil_aes_kw_set_unwrap_key(bootutil_aes_kw_context * ctx,const uint8_t * k,uint32_t klen)51 static inline int bootutil_aes_kw_set_unwrap_key(bootutil_aes_kw_context *ctx, const uint8_t *k, uint32_t klen)
52 {
53     return mbedtls_nist_kw_setkey(ctx, MBEDTLS_CIPHER_ID_AES, k, klen * 8, 0);
54 }
55 
bootutil_aes_kw_unwrap(bootutil_aes_kw_context * ctx,const uint8_t * wrapped_key,uint32_t wrapped_key_len,uint8_t * key,uint32_t key_len)56 static inline int bootutil_aes_kw_unwrap(bootutil_aes_kw_context *ctx, const uint8_t *wrapped_key, uint32_t wrapped_key_len, uint8_t *key, uint32_t key_len)
57 {
58     size_t olen;
59     return mbedtls_nist_kw_unwrap(ctx, MBEDTLS_KW_MODE_KW, wrapped_key, wrapped_key_len, key, &olen, key_len);
60 }
61 #endif /* MCUBOOT_USE_MBED_TLS */
62 
63 #if defined(MCUBOOT_USE_TINYCRYPT)
64 typedef struct tc_aes_key_sched_struct bootutil_aes_kw_context;
bootutil_aes_kw_init(bootutil_aes_kw_context * ctx)65 static inline void bootutil_aes_kw_init(bootutil_aes_kw_context *ctx)
66 {
67     (void)ctx;
68 }
69 
bootutil_aes_kw_drop(bootutil_aes_kw_context * ctx)70 static inline void bootutil_aes_kw_drop(bootutil_aes_kw_context *ctx)
71 {
72     (void)ctx;
73 }
74 
bootutil_aes_kw_set_unwrap_key(bootutil_aes_kw_context * ctx,const uint8_t * k,uint32_t klen)75 static inline int bootutil_aes_kw_set_unwrap_key(bootutil_aes_kw_context *ctx, const uint8_t *k, uint32_t klen)
76 {
77     int rc;
78 
79     if (klen != 16) {
80         return -1;
81     }
82 
83     rc = tc_aes128_set_decrypt_key(ctx, k);
84     if (rc != TC_CRYPTO_SUCCESS) {
85         return -1;
86     }
87     return 0;
88 }
89 
90 /*
91  * Implements AES key unwrapping following RFC-3394 section 2.2.2, using
92  * tinycrypt for AES-128 decryption.
93  */
bootutil_aes_kw_unwrap(bootutil_aes_kw_context * ctx,const uint8_t * wrapped_key,uint32_t wrapped_key_len,uint8_t * key,uint32_t key_len)94 static int bootutil_aes_kw_unwrap(bootutil_aes_kw_context *ctx, const uint8_t *wrapped_key, uint32_t wrapped_key_len, uint8_t *key, uint32_t key_len)
95 {
96     uint8_t A[8];
97     uint8_t B[16];
98     int8_t i, j, k;
99 
100     if (wrapped_key_len != 24 || key_len != 16) {
101         return -1;
102     }
103 
104     for (k = 0; k < 8; k++) {
105         A[k]       = wrapped_key[k];
106         key[k]     = wrapped_key[8 + k];
107         key[8 + k] = wrapped_key[16 + k];
108     }
109 
110     for (j = 5; j >= 0; j--) {
111         for (i = 2; i > 0; i--) {
112             for (k = 0; k < 8; k++) {
113                 B[k] = A[k];
114                 B[8 + k] = key[((i-1) * 8) + k];
115             }
116             B[7] ^= 2 * j + i;
117             if (tc_aes_decrypt((uint8_t *)&B, (uint8_t *)&B, ctx) != TC_CRYPTO_SUCCESS) {
118                 return -1;
119             }
120             for (k = 0; k < 8; k++) {
121                 A[k] = B[k];
122                 key[((i-1) * 8) + k] = B[8 + k];
123             }
124         }
125     }
126 
127     for (i = 0, k = 0; i < 8; i++) {
128         k |= A[i] ^ 0xa6;
129     }
130     if (k) {
131         return -1;
132     }
133 
134     return 0;
135 }
136 #endif /* MCUBOOT_USE_TINYCRYPT */
137 
138 #ifdef __cplusplus
139 }
140 #endif
141 
142 #endif /* __BOOTUTIL_CRYPTO_AES_KW_H_ */
143