This project contains known security vulnerabilities. Find detailed information at the bottom.

Crate sawtooth-sdk

Dependencies

(11 total, 6 outdated, 1 insecure, 2 possibly insecure)

CrateRequiredLatestStatus
 ctrlc^3.03.4.4up to date
 hex^0.30.4.3out of date
 libc^0.20.2.153up to date
 log^0.30.4.21out of date
 openssl ⚠️^0.100.10.64maybe insecure
 protobuf ⚠️^2.03.4.0out of date
 rand^0.4.20.8.5out of date
 rust-crypto ⚠️^0.2.360.2.36insecure
 sawtooth-zmq^0.8.2-dev50.0.2up to date
 secp256k1^0.7.10.28.2out of date
 uuid^0.51.8.0out of date

Dev dependencies

(1 total, 1 outdated)

CrateRequiredLatestStatus
 env_logger^0.30.11.3out of date

Security Vulnerabilities

protobuf: Out of Memory in stream::read_raw_bytes_into()

RUSTSEC-2019-0003

Affected versions of this crate called Vec::reserve() on user-supplied input.

This allows an attacker to cause an Out of Memory condition while calling the vulnerable method on untrusted data.

rust-crypto: Miscomputation when performing AES encryption in rust-crypto

RUSTSEC-2022-0011

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.

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:

     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.

openssl: `openssl` `X509VerifyParamRef::set_host` buffer over-read

RUSTSEC-2023-0044

When this function was passed an empty string, openssl would attempt to call strlen on it, reading arbitrary memory until it reached a NUL byte.