mirror of
https://github.com/OMGeeky/advisory-db.git
synced 2026-02-15 22:04:38 +01:00
134 lines
3.9 KiB
Markdown
134 lines
3.9 KiB
Markdown
```toml
|
|
[advisory]
|
|
id = "RUSTSEC-2022-0011"
|
|
|
|
package = "rust-crypto"
|
|
|
|
date = "2022-02-28"
|
|
|
|
categories = ["crypto-failure"]
|
|
|
|
keywords = ["aesni"]
|
|
aliases = ["GHSA-jp3w-3q88-34cf"]
|
|
|
|
[versions]
|
|
patched = []
|
|
```
|
|
|
|
# Miscomputation when performing AES encryption in rust-crypto
|
|
|
|
The following Rust program demonstrates some strangeness in AES encryption - if you have an immutable key slice and then operate on that slice, you get different encryption output than if you operate on a copy of that key.
|
|
|
|
For these functions, we expect that extending a 16 byte key to a 32 byte key by repeating it gives the same encrypted data, because the underlying rust-crypto functions repeat key data up to the necessary key size for the cipher.
|
|
|
|
```rust
|
|
use crypto::{
|
|
aes, blockmodes, buffer,
|
|
buffer::{BufferResult, ReadBuffer, WriteBuffer},
|
|
symmetriccipher,
|
|
};
|
|
|
|
fn encrypt(
|
|
key: &[u8],
|
|
iv: &[u8],
|
|
data: &str,
|
|
) -> Result<String, symmetriccipher::SymmetricCipherError> {
|
|
let mut encryptor =
|
|
aes::cbc_encryptor(aes::KeySize::KeySize256, key, iv, blockmodes::PkcsPadding);
|
|
|
|
let mut encrypted_data = Vec::<u8>::new();
|
|
let mut read_buffer = buffer::RefReadBuffer::new(data.as_bytes());
|
|
let mut buffer = [0; 4096];
|
|
let mut write_buffer = buffer::RefWriteBuffer::new(&mut buffer);
|
|
|
|
loop {
|
|
let result = encryptor.encrypt(&mut read_buffer, &mut write_buffer, true)?;
|
|
|
|
encrypted_data.extend(
|
|
write_buffer
|
|
.take_read_buffer()
|
|
.take_remaining()
|
|
.iter()
|
|
.copied(),
|
|
);
|
|
|
|
match result {
|
|
BufferResult::BufferUnderflow => break,
|
|
BufferResult::BufferOverflow => {}
|
|
}
|
|
}
|
|
|
|
Ok(hex::encode(encrypted_data))
|
|
}
|
|
|
|
fn working() {
|
|
let data = "data";
|
|
let iv = [
|
|
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE,
|
|
0xFF,
|
|
];
|
|
let key = [
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
|
|
0x0F,
|
|
];
|
|
// The copy here makes the code work.
|
|
let key_copy = key;
|
|
let key2: Vec<u8> = key_copy.iter().cycle().take(32).copied().collect();
|
|
println!("key1:{} key2: {}", hex::encode(&key), hex::encode(&key2));
|
|
|
|
let x1 = encrypt(&key, &iv, data).unwrap();
|
|
println!("X1: {}", x1);
|
|
|
|
let x2 = encrypt(&key2, &iv, data).unwrap();
|
|
println!("X2: {}", x2);
|
|
|
|
assert_eq!(x1, x2);
|
|
}
|
|
|
|
fn broken() {
|
|
let data = "data";
|
|
let iv = [
|
|
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE,
|
|
0xFF,
|
|
];
|
|
let key = [
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
|
|
0x0F,
|
|
];
|
|
// This operation shouldn't affect the contents of key at all.
|
|
let key2: Vec<u8> = key.iter().cycle().take(32).copied().collect();
|
|
println!("key1:{} key2: {}", hex::encode(&key), hex::encode(&key2));
|
|
|
|
let x1 = encrypt(&key, &iv, data).unwrap();
|
|
println!("X1: {}", x1);
|
|
|
|
let x2 = encrypt(&key2, &iv, data).unwrap();
|
|
println!("X2: {}", x2);
|
|
|
|
assert_eq!(x1, x2);
|
|
}
|
|
|
|
fn main() {
|
|
working();
|
|
broken();
|
|
}
|
|
```
|
|
|
|
The output from this program:
|
|
|
|
```shell
|
|
Running `target/host/debug/rust-crypto-test`
|
|
key1:000102030405060708090a0b0c0d0e0f key2: 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
|
X1: 90462bbe32965c8e7ea0addbbed4cddb
|
|
X2: 90462bbe32965c8e7ea0addbbed4cddb
|
|
key1:000102030405060708090a0b0c0d0e0f key2: 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
|
|
X1: 26e847e5e7df1947bf82a650548a7d5b
|
|
X2: 90462bbe32965c8e7ea0addbbed4cddb
|
|
thread 'main' panicked at 'assertion failed: `(left == right)`
|
|
left: `"26e847e5e7df1947bf82a650548a7d5b"`,
|
|
right: `"90462bbe32965c8e7ea0addbbed4cddb"`', src/main.rs:83:5
|
|
```
|
|
|
|
Notably, the X1 key in the `broken()` test changes every time after rerunning the program.
|
|
|