openssl/openssl — pull request #179 by rwg (2014-09-22 21:24:57+00:00)
Title: Fix major bugs in AES Key Wrap code

`crypto/modes/wrap128.c` was heavily refactored to support AES Key Wrap with Padding, and four bugs were introduced into `CRYPTO_128_unwrap()` at that time:

* `crypto_128_unwrap_raw()`'s return value (`ret`) is checked incorrectly, and the function immediately returns `ret` in (almost) all cases. This makes the IV checking code later in the function unreachable, but callers think the IV check succeeded since `CRYPTO_128_unwrap()`'s return value is non-zero.

FIX: Return `0` (error) if `crypto_128_unwrap_raw()` returned `0` (error).

* `crypto_128_unwrap_raw()` writes the IV to the buffer pointed to by the `iv` parameter, not to the first 8 bytes of the output buffer (`out`) as the IV checking code expects. This makes the IV check fail.

FIX: Compare `iv` to `got_iv`, not `out`.

* The data written to the output buffer (`out`) is "cleansed" if the IV check fails, but the code passes `OPENSSL_cleanse()` the input buffer length (`inlen`) instead of the number of bytes that `crypto_128_unwrap_raw()` wrote to the output buffer (`ret`). This means that `OPENSSL_cleanse()` could potentially write past the end of `out`.

FIX: Change `inlen` to `ret` in the `OPENSSL_cleanse()` call.

* `CRYPTO_128_unwrap()` is returning the length of the input buffer (`inlen`) instead of the number of bytes written to the output buffer (`ret`). This could cause the caller to read past the end of `out`.

FIX: Return `ret` instead of `inlen` at the end of the function.

Also fix minor issues in the Doxygen comments in `crypto/modes/wrap128.c`.