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