-
Notifications
You must be signed in to change notification settings - Fork 698
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
Make caller enforce invariants when setting AES encryption key #702
Make caller enforce invariants when setting AES encryption key #702
Conversation
crypto/fipsmodule/cipher/e_aes.c
Outdated
// anyway. | ||
GFp_AES_set_encrypt_key(key, (unsigned)key_len * 8, &ks); | ||
unsigned bits = key_len * 8; | ||
if (bits != 128 && bits != 256) { |
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.
Instead, let's compare key_len != 16 && key_len != 32
so we don't have to worry about any overflow issues with the multiplication.
crypto/fipsmodule/aes/aes.c
Outdated
} | ||
rk += 4; | ||
} | ||
} | ||
|
||
rk[4] = from_be_u32_ptr(key + 16); | ||
rk[5] = from_be_u32_ptr(key + 20); | ||
rk[6] = from_be_u32_ptr(key + 24); | ||
rk[7] = from_be_u32_ptr(key + 28); | ||
if (bits == 256) { |
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.
Remove the if (bits == 256) {
here and do this unconditionally.
If/when this gets merged, the equivalent error handling code should be removed from the assembly implementations. Also, 192-bit key support was removed from the vectorized AES implementation but not the one using AES-NI. I can open new issues for these if you like. |
crypto/fipsmodule/aes/aes.c
Outdated
} | ||
rk += 4; | ||
} | ||
} | ||
|
||
// bits == 256 |
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 should be assert(bits == 256);
. That is, we prefer checked (at debug time at least) assertions to unchecked assertions.
@@ -172,8 +174,8 @@ mod tests { | |||
} | |||
|
|||
extern "C" { | |||
fn GFp_AES_set_encrypt_key(key: *const u8, bits: usize, |
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.
We should have done this change as a separate commit. But, OK.
LGTM! Thanks! Please squash these commits together, change the comment to an |
@ecstatic-morse Are you still interested in this? It would be great if you could make the small changes I requested in the PR soon. I want to refactor the C code (or, if you want, you can do so, in another PR!) to remove the duplication between the 128-bit case and the 256-bit case, and to replace the weird loop constructions with straightforward |
2ec35ef
to
69a6be1
Compare
Sorry, life got in the way last week. I made the changes and squashed. My plan was to start working on #660 and #705 tonight. Refactoring AES round key generation would be a nice warm up. On a more meta note, I'm trying to get accustomed to the programming style here before I tackle more involved issues. If you have any suggestions for next steps, I'd love to hear them. |
I refactored the C AES key expansion routines. I'll submit a PR when this gets merged. |
crypto/fipsmodule/cipher/e_aes.c
Outdated
#if defined(HWAES) | ||
if (hwaes_capable()) { | ||
return GFp_aes_hw_set_encrypt_key(user_key, bits, key); | ||
GFp_aes_hw_set_encrypt_key(user_key, bits, key); |
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.
Please prefix this with (void)
to make it clear we're ignoring the return value intentionally.
crypto/fipsmodule/cipher/e_aes.c
Outdated
@@ -149,14 +153,15 @@ int GFp_AES_set_encrypt_key(const uint8_t *user_key, unsigned bits, | |||
#error "BSAES and VPAES are enabled at the same time, unexpectedly." | |||
#endif | |||
if (vpaes_capable()) { | |||
return GFp_vpaes_set_encrypt_key(user_key, bits, key); | |||
GFp_vpaes_set_encrypt_key(user_key, bits, key); |
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.
Ditto: prefix with (void)
.
Thanks for the quick turnaround @ecstatic-morse. I was just about to merge this but I noticed a couple of things: (1) We are missing a couple places where we should be using |
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.
See the previous comment for the changes requested.
`GFp_AES_set_encrypt_key` can fail if and only if the following invariants are violated. * All pointer arguments must be non-null. * The key size must be either 128 or 256 bits (192 bit keys aren't supported). The first invariant should not be checked at runtime (except via assertion) as it is the responsibility of the caller. The second could be expressed statically by accepting an enum with the valid key lengths, but enums don't provide any type safety in C. Instead, we document the acceptable key lengths and make them the responsibility of the caller. As a result of these changes, `GFp_AES_set_encrypt_key` (as well as `GFp_aes_c_set_encrypt_key`) no longer needs to return an error code. The assembly functions still return an error code and do input validation. This commit also corrects the signature of `GFp_AES_set_encrypt_key`. I agree to license my contributions to each file under the terms given at the top of each file I changed.
69a6be1
to
38d54b9
Compare
Whoops, sorry about that. I added the disclaimer to the commit message and made the requested changes. Is the use |
Thanks! No, I guess it isn't mentioned in the style guide. One reason is that it is unusual for us to ignore return values in the first place. We're only doing so here temporarily until the types of those functions change to be FWIW, I'd normally write |
Resolves #113.
GFp_AES_set_encrypt_key
can fail if and only if the following invariants are violated.The first invariant should not be checked at runtime (except via assertion) as it is the responsibility of the caller.
The second could be expressed statically by accepting an enum with the valid key lengths, but enums don't provide any type safety in C. Instead, we document the acceptable key lengths and make them the responsibility of the caller.
As a result of these changes,
GFp_AES_set_encrypt_key
(as well asGFp_aes_c_set_encrypt_key
) no longer needs to return an error code. The assembly functions still return an error code and do input validation.