Skip to content

Commit 413bb69

Browse files
authored
Merge pull request #395 from padelsbach/kbkdf-fixes
Misc kbkdf fixes
2 parents d8ae61d + a84b222 commit 413bb69

2 files changed

Lines changed: 153 additions & 10 deletions

File tree

src/wp_kbkdf.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -177,13 +177,15 @@ static int wp_kdf_kbkdf_set_ctx_params(wp_KbkdfCtx* ctx,
177177
if (!OSSL_PARAM_get_utf8_string_ptr(p, &mode)) {
178178
ok = 0;
179179
}
180-
if (ok) {
181-
if (XSTRCMP(mode, "FEEDBACK") == 0) {
182-
ctx->mode = WP_KDF_MODE_FEEDBACK;
183-
}
184-
else {
185-
ok = 0;
186-
}
180+
if (XSTRCMP(mode, "COUNTER") == 0) {
181+
ctx->mode = WP_KDF_MODE_COUNTER;
182+
}
183+
else if (XSTRCMP(mode, "FEEDBACK") == 0) {
184+
ctx->mode = WP_KDF_MODE_FEEDBACK;
185+
}
186+
else {
187+
WOLFPROV_MSG(WP_LOG_COMP_KDF, "Invalid KDF mode: %s", mode);
188+
ok = 0;
187189
}
188190
}
189191
}
@@ -355,7 +357,10 @@ static const OSSL_PARAM* wp_kdf_kbkdf_gettable_ctx_params(wp_KbkdfCtx* ctx,
355357
}
356358

357359
#ifdef WP_HAVE_HMAC
358-
#define WP_MAX_HASH_BLOCK_SIZE 128
360+
/* Must be large enough for the HMAC block size of every supported hash.
361+
* SHA3-224 has the largest HMAC block size of any currently supported
362+
* digest at 144 bytes. */
363+
#define WP_MAX_HASH_BLOCK_SIZE 144
359364

360365
static int wp_kbkdf_init_hmac(wp_KbkdfCtx* ctx, unsigned char* key,
361366
size_t keyLen)
@@ -368,14 +373,18 @@ static int wp_kbkdf_init_hmac(wp_KbkdfCtx* ctx, unsigned char* key,
368373

369374
WOLFPROV_ENTER(WP_LOG_COMP_KDF, "wp_kbkdf_init_hmac");
370375

371-
if (keyLen < blockSize) {
376+
if (blockSize > sizeof(localKey) || keyLen > sizeof(localKey)) {
377+
ok = 0;
378+
}
379+
380+
if (ok && keyLen < blockSize) {
372381
/* wolfSSL FIPS needs a key that is at least block size in length with
373382
* the unused parts zeroed out.
374383
*/
375384
XMEMSET(localKey + keyLen, 0, blockSize - keyLen);
376385
localKeyLen = blockSize;
377386
}
378-
else {
387+
else if (ok) {
379388
localKeyLen = (word32)keyLen;
380389
}
381390

test/test_kbkdf.c

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,97 @@ static int test_kbkdf_feedback_compare(OSSL_LIB_CTX* osslCtx, OSSL_LIB_CTX* wpCt
124124
return err;
125125
}
126126

127+
static int test_kbkdf_counter_explicit_ex(OSSL_LIB_CTX* libctx,
128+
const unsigned char* key, size_t keyLen, unsigned char* out, size_t outLen)
129+
{
130+
int err = 0;
131+
EVP_KDF *kdf = NULL;
132+
EVP_KDF_CTX *kctx = NULL;
133+
OSSL_PARAM params[7], *p = params;
134+
unsigned char label[] = {
135+
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18
136+
};
137+
unsigned char context[] = {
138+
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28
139+
};
140+
char counter[] = "COUNTER";
141+
char cmac[] = "CMAC";
142+
char cipher[13];
143+
144+
if (keyLen == 16) {
145+
XSTRNCPY(cipher, "AES-128-CBC", sizeof(cipher));
146+
}
147+
else if (keyLen == 32) {
148+
XSTRNCPY(cipher, "AES-256-CBC", sizeof(cipher));
149+
}
150+
else {
151+
PRINT_MSG("Invalid key length");
152+
return 1;
153+
}
154+
155+
kdf = EVP_KDF_fetch(libctx, "KBKDF", NULL);
156+
if (!kdf) {
157+
PRINT_MSG("Failed to fetch KBKDF");
158+
err = 1;
159+
goto done;
160+
}
161+
162+
kctx = EVP_KDF_CTX_new(kdf);
163+
if (!kctx) {
164+
PRINT_MSG("Failed to create KBKDF context");
165+
err = 1;
166+
goto done;
167+
}
168+
169+
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MODE,
170+
counter, 0);
171+
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_MAC,
172+
cmac, 0);
173+
*p++ = OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_CIPHER,
174+
cipher, 0);
175+
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY,
176+
(void*)key, keyLen);
177+
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT,
178+
label, sizeof(label));
179+
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_INFO,
180+
context, sizeof(context));
181+
*p = OSSL_PARAM_construct_end();
182+
183+
if (EVP_KDF_derive(kctx, out, outLen, params) <= 0) {
184+
PRINT_MSG("KBKDF derive with explicit COUNTER mode failed");
185+
err = 1;
186+
goto done;
187+
}
188+
189+
done:
190+
EVP_KDF_free(kdf);
191+
EVP_KDF_CTX_free(kctx);
192+
return err;
193+
}
194+
195+
static int test_kbkdf_counter_explicit_compare(OSSL_LIB_CTX* osslCtx,
196+
OSSL_LIB_CTX* wpCtx, const unsigned char* key, size_t keyLen)
197+
{
198+
int err = 0;
199+
unsigned char osslOut[32];
200+
unsigned char wpOut[32];
201+
202+
PRINT_MSG("Test KBKDF with explicit COUNTER mode string");
203+
204+
err = test_kbkdf_counter_explicit_ex(osslCtx, key, keyLen, osslOut, keyLen);
205+
if (err == 0) {
206+
err = test_kbkdf_counter_explicit_ex(wpCtx, key, keyLen, wpOut, keyLen);
207+
if (err == 0) {
208+
if (XMEMCMP(osslOut, wpOut, keyLen) != 0) {
209+
PRINT_MSG("KBKDF derived keys do not match!");
210+
err = 1;
211+
}
212+
}
213+
}
214+
215+
return err;
216+
}
217+
127218
static int test_kbkdf_hmac_ex(OSSL_LIB_CTX* libctx, const unsigned char* key,
128219
size_t keyLen, const char* digest, unsigned char* out, size_t outLen)
129220
{
@@ -242,6 +333,46 @@ static int test_kbkdf_feedback(void)
242333
err = test_kbkdf_hmac_compare(osslLibCtx, wpLibCtx, key256, sizeof(key256), "SHA384");
243334
}
244335
}
336+
/* SHA3-224 (144 byte HMAC block) and SHA3-256 (136 byte block) both
337+
* exceed the legacy 128-byte localKey buffer in wp_kbkdf_init_hmac;
338+
* exercising them here guards against the stack overflow regressing. */
339+
if (err == 0) {
340+
err = test_kbkdf_hmac_compare(osslLibCtx, wpLibCtx, key128, sizeof(key128), "SHA3-224");
341+
if (err == 0) {
342+
err = test_kbkdf_hmac_compare(osslLibCtx, wpLibCtx, key256, sizeof(key256), "SHA3-224");
343+
}
344+
}
345+
if (err == 0) {
346+
err = test_kbkdf_hmac_compare(osslLibCtx, wpLibCtx, key128, sizeof(key128), "SHA3-256");
347+
if (err == 0) {
348+
err = test_kbkdf_hmac_compare(osslLibCtx, wpLibCtx, key256, sizeof(key256), "SHA3-256");
349+
}
350+
}
351+
352+
return err;
353+
}
354+
355+
static int test_kbkdf_counter(void)
356+
{
357+
int err;
358+
unsigned char key128[] = {
359+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
360+
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10
361+
};
362+
unsigned char key256[] = {
363+
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
364+
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
365+
0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
366+
0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20
367+
};
368+
369+
PRINT_MSG("\nTesting KBKDF with explicit COUNTER mode:");
370+
err = test_kbkdf_counter_explicit_compare(osslLibCtx, wpLibCtx, key128,
371+
sizeof(key128));
372+
if (err == 0) {
373+
err = test_kbkdf_counter_explicit_compare(osslLibCtx, wpLibCtx, key256,
374+
sizeof(key256));
375+
}
245376

246377
return err;
247378
}
@@ -252,6 +383,9 @@ int test_kbkdf(void *data)
252383
(void)data;
253384

254385
err = test_kbkdf_feedback();
386+
if (err == 0) {
387+
err = test_kbkdf_counter();
388+
}
255389

256390
return err;
257391
}

0 commit comments

Comments
 (0)