diff options
author | Matt Caswell <matt@openssl.org> | 2015-03-12 15:59:07 +0000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2015-03-17 13:39:53 +0000 |
commit | 3475c7a1854977e290ab44deb16551f6d55ad9a7 (patch) | |
tree | 10b41868ffb2d87bb51463ac9c070cbe340addf4 /crypto/modes | |
parent | dfef52f6f277327e118fdd0fe34486852c2789b6 (diff) |
Fix unintended sign extension
The function CRYPTO_128_unwrap_pad uses an 8 byte AIV (Alternative Initial
Value). The least significant 4 bytes of this is placed into the local
variable |ptext_len|. This is done as follows:
ptext_len = (aiv[4] << 24) | (aiv[5] << 16) | (aiv[6] << 8) | aiv[7];
aiv[4] is an unsigned char, but (aiv[4] << 24) is promoted to a *signed*
int - therefore we could end up shifting into the sign bit and end up with
a negative value. |ptext_len| is a size_t (typically 64-bits). If the
result of the shifts is negative then the upper bits of |ptext_len| will
all be 1.
This commit fixes the issue by explicitly casting to an unsigned int.
Reviewed-by: Richard Levitte <levitte@openssl.org>
Diffstat (limited to 'crypto/modes')
-rw-r--r-- | crypto/modes/wrap128.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/crypto/modes/wrap128.c b/crypto/modes/wrap128.c index ccb58c5a0b..73718ae59f 100644 --- a/crypto/modes/wrap128.c +++ b/crypto/modes/wrap128.c @@ -350,7 +350,10 @@ size_t CRYPTO_128_unwrap_pad(void *key, const unsigned char *icv, * LSB(32,AIV). */ - ptext_len = (aiv[4] << 24) | (aiv[5] << 16) | (aiv[6] << 8) | aiv[7]; + ptext_len = ((unsigned int)aiv[4] << 24) + | ((unsigned int)aiv[5] << 16) + | ((unsigned int)aiv[6] << 8) + | (unsigned int)aiv[7]; if (8 * (n - 1) >= ptext_len || ptext_len > 8 * n) { OPENSSL_cleanse(out, inlen); return 0; |