Skip to content

Commit 7a9ebfd

Browse files
committed
bootutil/crypto: Add general-purpose HMAC and HKDF implementations
Using the currently configured crypto back end, this implements HMAC and HKDF. This implementation serves as a fallback solution for crypto back ends that do not provide these functions. As there are plans to remove TinyCrypt from MCUboot, no effort is made to use TinyCrypt when MCUBOOT_USE_TINYCRYPT is set. Instead, this configuration falls back on the general-purpose HMAC and HKDF implementations. Signed-off-by: kkrentz <konrad.krentz@gmail.com>
1 parent 8088674 commit 7a9ebfd

File tree

1 file changed

+148
-1
lines changed

1 file changed

+148
-1
lines changed

boot/bootutil/src/sha.c

Lines changed: 148 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
#if defined(MCUBOOT_USE_MBED_TLS)
1313
#include "mbedtls/hkdf.h"
1414
#include "mbedtls/md.h"
15-
#endif
15+
#else /* MCUBOOT_USE_MBED_TLS */
16+
#include <string.h>
17+
#endif /* MCUBOOT_USE_MBED_TLS */
1618

1719
int
1820
bootutil_sha(const uint8_t *const data, size_t data_len,
@@ -84,4 +86,149 @@ bootutil_sha_hkdf(const uint8_t *const salt, size_t salt_len,
8486
info, info_len,
8587
okm, okm_len);
8688
}
89+
#else /* MCUBOOT_USE_MBED_TLS */
90+
91+
#if defined(MCUBOOT_SHA512) || defined(MCUBOOT_SIGN_EC384)
92+
#define BLOCK_SIZE 128
93+
#else
94+
#define BLOCK_SIZE BOOTUTIL_CRYPTO_SHA256_BLOCK_SIZE
95+
#endif
96+
97+
struct hmac_context {
98+
bootutil_sha_context sha_ctx;
99+
uint8_t opad[BLOCK_SIZE];
100+
int status;
101+
};
102+
103+
static void
104+
hmac_init(struct hmac_context *const hmac_ctx,
105+
const uint8_t *key, size_t key_len)
106+
{
107+
uint8_t hashed_key[IMAGE_HASH_SIZE];
108+
uint_fast8_t i;
109+
uint8_t ipad[BLOCK_SIZE];
110+
111+
if (key_len > BLOCK_SIZE) {
112+
hmac_ctx->status = bootutil_sha(key, key_len, hashed_key);
113+
if (hmac_ctx->status) {
114+
return;
115+
}
116+
key_len = IMAGE_HASH_SIZE;
117+
key = hashed_key;
118+
} else {
119+
hmac_ctx->status = 0;
120+
}
121+
for (i = 0; i < key_len; i++) {
122+
ipad[i] = key[i] ^ 0x36;
123+
hmac_ctx->opad[i] = key[i] ^ 0x5c;
124+
}
125+
for (; i < BLOCK_SIZE; i++) {
126+
ipad[i] = 0x36;
127+
hmac_ctx->opad[i] = 0x5c;
128+
}
129+
bootutil_sha_init(&hmac_ctx->sha_ctx);
130+
bootutil_sha_update(&hmac_ctx->sha_ctx, ipad, sizeof(ipad));
131+
}
132+
133+
static void
134+
hmac_update(struct hmac_context *const hmac_ctx,
135+
const uint8_t *const data, size_t data_len)
136+
{
137+
if (hmac_ctx->status) {
138+
return;
139+
}
140+
bootutil_sha_update(&hmac_ctx->sha_ctx, data, data_len);
141+
}
142+
143+
static int
144+
hmac_finish(struct hmac_context *const hmac_ctx,
145+
uint8_t hmac[static IMAGE_HASH_SIZE])
146+
{
147+
if (hmac_ctx->status) {
148+
return hmac_ctx->status;
149+
}
150+
hmac_ctx->status = bootutil_sha_finish(&hmac_ctx->sha_ctx, hmac);
151+
bootutil_sha_drop(&hmac_ctx->sha_ctx);
152+
if (hmac_ctx->status) {
153+
return hmac_ctx->status;
154+
}
155+
bootutil_sha_init(&hmac_ctx->sha_ctx);
156+
bootutil_sha_update(&hmac_ctx->sha_ctx, hmac_ctx->opad, sizeof(hmac_ctx->opad));
157+
bootutil_sha_update(&hmac_ctx->sha_ctx, hmac, IMAGE_HASH_SIZE);
158+
hmac_ctx->status = bootutil_sha_finish(&hmac_ctx->sha_ctx, hmac);
159+
bootutil_sha_drop(&hmac_ctx->sha_ctx);
160+
return hmac_ctx->status;
161+
}
162+
163+
int
164+
bootutil_sha_hmac(const uint8_t *const key, size_t key_len,
165+
const uint8_t *const data, size_t data_len,
166+
uint8_t hmac[static IMAGE_HASH_SIZE])
167+
{
168+
struct hmac_context hmac_ctx;
169+
170+
hmac_init(&hmac_ctx, key, key_len);
171+
hmac_update(&hmac_ctx, data, data_len);
172+
return hmac_finish(&hmac_ctx, hmac);
173+
}
174+
175+
int
176+
bootutil_sha_hkdf_extract(const uint8_t *const salt, size_t salt_len,
177+
const uint8_t *const ikm, size_t ikm_len,
178+
uint8_t prk[static IMAGE_HASH_SIZE])
179+
{
180+
return bootutil_sha_hmac(salt, salt_len, ikm, ikm_len, prk);
181+
}
182+
183+
184+
int
185+
bootutil_sha_hkdf_expand(const uint8_t *const prk, size_t prk_len,
186+
const uint8_t *const info, size_t info_len,
187+
uint8_t *const okm, uint_fast16_t okm_len)
188+
{
189+
uint_fast8_t n;
190+
uint8_t i;
191+
struct hmac_context hmac_ctx;
192+
uint8_t t_i[IMAGE_HASH_SIZE];
193+
int rc;
194+
195+
if (okm_len > 255 * IMAGE_HASH_SIZE) {
196+
return 1;
197+
}
198+
n = okm_len / IMAGE_HASH_SIZE + (okm_len % IMAGE_HASH_SIZE ? 1 : 0);
199+
200+
for (i = 1; i <= n; i++) {
201+
hmac_init(&hmac_ctx, prk, prk_len);
202+
if (i != 1) {
203+
hmac_update(&hmac_ctx, t_i, sizeof(t_i));
204+
}
205+
hmac_update(&hmac_ctx, info, info_len);
206+
hmac_update(&hmac_ctx, &i, sizeof(i));
207+
rc = hmac_finish(&hmac_ctx, t_i);
208+
if (rc) {
209+
return rc;
210+
}
211+
memcpy(okm + ((i - 1) * IMAGE_HASH_SIZE),
212+
t_i,
213+
okm_len > IMAGE_HASH_SIZE ? okm_len : IMAGE_HASH_SIZE);
214+
okm_len -= IMAGE_HASH_SIZE;
215+
}
216+
return 0;
217+
}
218+
219+
int
220+
bootutil_sha_hkdf(const uint8_t *const salt, size_t salt_len,
221+
const uint8_t *const ikm, size_t ikm_len,
222+
const uint8_t *const info, size_t info_len,
223+
uint8_t *const okm, uint_fast16_t okm_len)
224+
{
225+
int rc;
226+
uint8_t prk[IMAGE_HASH_SIZE];
227+
228+
rc = bootutil_sha_hkdf_extract(salt, salt_len, ikm, ikm_len, prk);
229+
if (rc) {
230+
return rc;
231+
}
232+
return bootutil_sha_hkdf_expand(prk, sizeof(prk), info, info_len, okm, okm_len);
233+
}
87234
#endif /* MCUBOOT_USE_MBED_TLS */

0 commit comments

Comments
 (0)