-
-
Notifications
You must be signed in to change notification settings - Fork 9.8k
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 EVP_CIPHER_CTX_get_block_size() calls to check for -1. #23000
base: master
Are you sure you want to change the base?
Fix EVP_CIPHER_CTX_get_block_size() calls to check for -1. #23000
Conversation
Fix all the calls that assume it returns a size_t.
Needs tests |
…. Fix all the calls that assume it returns a size_t.
Nice to see this being tackled - I too saw that we would have some "fun" with this issue where we have had size_t logic get put in a few places incorrectly. |
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.
makes it more obvious that EVP_CIPHER_CTX_get_block_size() can return -1.
It's not currently clear to me why #22995 is making that change so that EVP_CIPHER_CTX_get_block_size() can suddenly return -1, where it doesn't seem to have done so before. This seems like a significant change in behaviour.
If we're assuming that the return value of this function can be safely cast to a size_t, then I'd say its a fair bet that applications are making the same assumption.
ssl/record/methods/dtls_meth.c
Outdated
blocksize = EVP_CIPHER_CTX_get_block_size(rl->enc_ctx); | ||
(EVP_CIPHER_CTX_get_mode(rl->enc_ctx) == EVP_CIPH_CBC_MODE)) { | ||
blksz = EVP_CIPHER_CTX_get_block_size(rl->enc_ctx); | ||
assert(blksz >= 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.
Shouldn't we instead propagate this error to the caller (there is only one)?
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.
Also a block size of 0 is really an error. Stream ciphers have block size of 1.
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.
Updated - the propagation required a few more changes
@mattcaswell this is sort of an interesting question - The documentation has never been clear on the return value of this call, save to say it returns the block size of the cipher. Given that the function is typed to return an int, it seems that a negative return code is feasible. Whats more, as @slontis has corrected here, we have a myriad of call points that treat the return code differently. Currently, our code base has 24 calls to EVP_CIPHER_CTX_get_block_size:
a) Some, like CMAC_CTX_copy check for a return values expressly less than 0 (treating a 0 return as valid) I think in my head, what should be done boils down to
If (1) is true and (2) is false, then we can safely just use 0 as an error return from this function, and fixup (a) and (b) and (c) above to coform to that. If that is the case then we should also consider modifying the EVP_CIPHER_CTX_get_block_size and EVP_CIPHER_get_block size to return a size_t or unsigned int accordingly. |
EVP_CIPHER_CTX_get_block_size() could already return -1 with the pre-existing code so yeah, this is a correct bug fix. |
…. Fix all the calls that assume it returns a size_t.
…. Fix all the calls that assume it returns a size_t.
Added some tests for the ones that I was able to.. |
…. Fix all the calls that assume it returns a size_t.
…. Fix all the calls that assume it returns a size_t.
…. Fix all the calls that assume it returns a size_t.
if (blocksz <= 0 || inlen % blocklen) { | ||
/* Invalid size */ | ||
return 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 would also put this if before the previous one. Funnily enough this newly added condition actually will never be evaluated for blocksz being negative as the blocklen value in the previous if
will be a huge number and thus the condition inlen < 2 * blocklen
will be true.
@@ -132,6 +132,8 @@ static int enc_read(BIO *b, char *out, int outl) | |||
} | |||
|
|||
blocksize = EVP_CIPHER_CTX_get_block_size(ctx->cipher); | |||
if (blocksize < 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 should be <=
as the 0 return is an error as well.
@@ -413,8 +413,10 @@ int EVP_Cipher(EVP_CIPHER_CTX *ctx, unsigned char *out, | |||
*/ | |||
int ret = -1; | |||
size_t outl = 0; | |||
size_t blocksize = EVP_CIPHER_CTX_get_block_size(ctx); | |||
int blocksize = EVP_CIPHER_CTX_get_block_size(ctx); |
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 is OK, however below in those ccipher/cupdate/cfinal calls you need to cast blocksize to size_t explicitly before adding inl as otherwise there can be an overflow. Rather theoretical one but...
@@ -37,13 +37,16 @@ unsigned char *PKCS12_pbe_crypt_ex(const X509_ALGOR *algor, | |||
algor->parameter, ctx, en_de, libctx, propq)) | |||
goto err; | |||
|
|||
blksz = EVP_CIPHER_CTX_get_block_size(ctx); | |||
if (blksz < 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.
<=
as 0 is also invalid.
/* Initialize input block */ | ||
blocksize = EVP_CIPHER_CTX_get_block_size(ctx); | ||
blksz = EVP_CIPHER_CTX_get_block_size(ctx); | ||
if (blksz < 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 PR is in a state where it requires action by @openssl/otc but the last update was 30 days ago |
This PR is in a state where it requires action by @openssl/otc but the last update was 61 days ago |
This PR is in a state where it requires action by @openssl/otc but the last update was 92 days ago |
This PR is in a state where it requires action by @openssl/otc but the last update was 123 days ago |
This PR is in a state where it requires action by @openssl/otc but the last update was 154 days ago |
EVP_CIPHER_CTX_get_block_size() returns an int which can be -1.
Fix all the calls that cast it to a size_t.
This is a follow on from reviewing #22995
which makes it more obvious that EVP_CIPHER_CTX_get_block_size() can return -1.
There are a couple of places in the code that already check for this, but the rest do bad things.
Checklist