Skip to content

Commit 0bf450e

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 7e66dd3 commit 0bf450e

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
@@ -14,7 +14,9 @@
1414
#include "mbedtls/hkdf.h"
1515
#endif /* MBEDTLS_HKDF_C */
1616
#include "mbedtls/md.h"
17-
#endif
17+
#else /* MCUBOOT_USE_MBED_TLS */
18+
#include <string.h>
19+
#endif /* MCUBOOT_USE_MBED_TLS */
1820

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

0 commit comments

Comments
 (0)