-
-
Notifications
You must be signed in to change notification settings - Fork 10.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix API to allow zero-length secret for EVP_KDF #12826
Conversation
It's like #11920 all over again... |
I think that there might be a better fix for this. There is an issue where I suspect changing |
Scratch that, fixing malloc causes test failures... in kdf code |
Is this behavior what we really want - or should it have caused an error? |
I'm not going to make a call either way. If it should have caused an error then this should have been generated when the API was called, not left to a malloc failure later. Also if you prefer to fail on a zero-length secret then maybe you should also fail on any insecure secret length? I doubt a one-byte secret is providing much authentication. |
Are you just doing negative testing or is this a use case you actually need? |
This is an edge-case test. I can't see a specific use case. |
I think we do see empty-keyed HMAC pop up in some protocol edge cases, though most of the examples that are coming to mind are using a block of zeros rather than a true empty key. The original report to me that prompted #11920 was definitely for HMAC; something QUIC-related IIRC. |
Would a zero length secret be permitted by NIST for a module integrity check? I'm sure there are plenty of examples of this in the wild 😞 |
24 hours has passed since 'approval: done' was set, but as this PR has been updated in that time the label 'approval: ready to merge' is not being automatically set. Please review the updates and set the label manually. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we are going to allow this then there at least needs to be a test for it.
Some tests added. It seems that the initial bug reported in #12409 is no longer a problem. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks jon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great 😁
@@ -205,6 +205,12 @@ static int kbkdf_derive(void *vctx, unsigned char *key, size_t keylen) | |||
return 0; | |||
} | |||
|
|||
/* Fail if the output length is zero */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting that KBKDF gets this comment but not HKDF or tls1_prf.
static int test_kdf_tls1_prf(void) | ||
{ | ||
int ret; | ||
EVP_KDF_CTX *kctx = NULL; | ||
unsigned char out[16]; | ||
OSSL_PARAM params[4], *p = params; | ||
OSSL_PARAM *params; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically every other test in this file uses stack-allocated OSSL_PARAM
arrays; I didn't see discussion of why this one should allocate on the heap. (It's not wrong per se, just surprising.)
You can keep the helper function and just pass in a pointer to the start of the (stack-allocated) array, if you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm ambivalent either way. A comment might be beneficial to explain the change of style. However, there are plenty of cases where two different styles are used (param construct vs param_bld e.g.). One minor point in favour of the status quo is that construct_tls1_prf_params
is returning a filled out param array, so doing it dynamically like this provides some future proofing against needing more params at some point (it's pretty weak).
EVP_KDF_CTX_free(kctx); | ||
OPENSSL_free(params); | ||
return ret; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's vaguely plausible that some of these tls-prf tests could be refactored consolidated into an ADD_ALL_TESTS
(vs ADD_TEST
) invocation, but I didn't do the work to check and won't insist that anyone else do the work.
test/evp_kdf_test.c
Outdated
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, | ||
salt, strlen(salt)); | ||
*p++ = OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_KEY, | ||
(unsigned char*)key, keylen); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we have to make any other changes I'd suggest reordering these to match the order of the function parameters. It's purely cosmetic, though, so not critical.
EVP_KDF_CTX_free(kctx); | ||
OPENSSL_free(params); | ||
return ret; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[same coment about consolidating/refactoring]
|| !TEST_true(EVP_KDF_CTX_set_params(kctx, params)) | ||
/* A key length that is too small should fail */ | ||
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, 112 / 8 - 1), 0) | ||
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, 112 / 8 - 1), 0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume there's not an appropriate #define
for 112 here.
OSSL_PARAM *params; | ||
|
||
if (sizeof(len) > 32) | ||
len = SIZE_MAX; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems incorrect/bizzare (but is unchanged from the old code). len
is a size_t
, which is not really of variable size (and 256-bit integers are not really a thing, let alone bigger ones!).
|
||
/* If the "pkcs5" mode is disabled then the derive will now fail */ | ||
if (!TEST_true(EVP_KDF_CTX_set_params(kctx, mode_params)) | ||
|| !TEST_int_eq(EVP_KDF_derive(kctx, out, sizeof(out)), 0)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This actually raises a potentially interesting question: should EVP_KDF_derive()
be a one-shot operation on a given EVP_KDF_CTX
?
(That's a +0 from me; I read the whole thing and there are no critical flaws, and I'm okay with it proceeding as-is with the other reviews if that's desired.) |
@kaduk, does this mean another review is required or does your earlier stand as enough of a positive for this to go in? |
@paulidale oops, I seem to have misread the preexisting approval count. Mine would have been enough for it to go in, I think, but Tim has short-circuited the issue in the time it took me to check my email. |
@kaduk, it was your final +0 comment that threw me. I didn't want to assume that your approval stood as a +1. |
Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from #12826)
Also add more test cases Reviewed-by: Tim Hudson <tjh@openssl.org> Reviewed-by: Ben Kaduk <kaduk@mit.edu> Reviewed-by: Paul Dale <paul.dale@oracle.com> (Merged from #12826)
Merged to master after removing some end of line spaces. Thanks. |
The behaviour of EVP_KDF_CTX_set_params changed between alpha4 and current, so that one of our tests started to fail. The test results in this API call:
Where:
secret = pointer to blank buffer
secretlen = 0
The KDF is OSSL_KDF_NAME_TLS1_PRF.
This started to fail recently with a change to the HMAC code (which is used internally in the KDF):
3fddbb2
The code added to allocate a copy of the HMAC key is not zero-length aware so the OPENSSL_secure_malloc fails. The KDF code to store the secret is already zero-length aware.
This PR also goes some way to fixing #8531 although the secret buffer is still checked for NULL so the user would have to provide a non-null buffer even with a length of zero.