Unix-like operating systems may segfault due to dereferencing a dangling pointer in specific circumstances. This requires an environment variable to be set in a different thread than the affected functions. This may occur without the user's knowledge, notably in a third-party library.
Due to a non-constant-time implementation, information about the private key is leaked through timing information which is observable over the network. An attacker may be able to use that information to recover the key.
Patches
No patch is yet available, however work is underway to migrate to a fully constant-time implementation.
Workarounds
The only currently available workaround is to avoid using the rsa crate in settings where attackers are able to observe timing information, e.g. local use on a non-compromised computer is fine.
References
This vulnerability was discovered as part of the "Marvin Attack", which revealed several implementations of RSA including OpenSSL had not properly mitigated timing sidechannel attacks.
aes-gcm: Plaintext exposed in decrypt_in_place_detached even on tag verification failure
In the AES GCM implementation of decrypt_in_place_detached,
the decrypted ciphertext (i.e. the correct plaintext) is
exposed even if tag verification fails.
Impact
If a program using the aes-gcm crate's decrypt_in_place*
APIs accesses the buffer after decryption failure, it will
contain a decryption of an unauthenticated input. Depending
on the specific nature of the program this may enable
Chosen Ciphertext Attacks (CCAs) which can cause a
catastrophic breakage of the cipher including full
plaintext recovery.
Details
As seen in the implementation of decrypt_in_place_detached for
AES GCM, if the tag verification fails, an error is returned.
Because the decryption of the ciphertext is done in place,
the plaintext contents are now exposed via buffer.
This should ideally not be the case - as noted in page 17 of
NIST's publication Recommendation for Block Cipher Modes of
Operation: Galois/Counter Mode (GCM) and GMAC:
In Step 8, the result of Step 7 is compared with the
authentication tag that was received as an input: if
they are identical, then the plaintext is returned;
otherwise,FAIL is returned.
This is seems correctly addressed in the AES GCM SIV
implementation, where the decrypted buffer is encrypted
again before the error is returned - this fix is
straightforward to implement in AES GCM. To ensure that
these types of cases are covered during testing, it
would be valuable to add test cases like 23, 24 etc
from project wycheproof to ensure that when a bad tag
is used, there is an error on decryption and that the
plaintext value is not exposed.
PoC
To reproduce this issue, I'm using test case 23 from
project wycheproof.
let key = GenericArray::from_slice(&hex!("000102030405060708090a0b0c0d0e0f"));
let nonce = GenericArray::from_slice(&hex!("505152535455565758595a5b"));
let tag = GenericArray::from_slice(&hex!("d9847dbc326a06e988c77ad3863e6083")); // bad tag
let mut ct = hex!("eb156d081ed6b6b55f4612f021d87b39");
let msg = hex!("202122232425262728292a2b2c2d2e2f");
let aad = hex!("");
let cipher = Aes128Gcm::new(&key);
let _plaintext = cipher.decrypt_in_place_detached(&nonce, &aad, &mut ct, &tag);
assert_eq!(ct, msg);
rustls: `rustls::ConnectionCommon::complete_io` could fall into an infinite loop based on network input
A bug introduced in rustls 0.23.13 leads to a panic if the received
TLS ClientHello is fragmented. Only servers that use
rustls::server::Acceptor::accept() are affected.
Servers that use tokio-rustls's LazyConfigAcceptor API are affected.
Servers that use tokio-rustls's TlsAcceptor API are not affected.
Servers that use rustls-ffi's rustls_acceptor_accept API are affected.
fast-float: Segmentation fault due to lack of bound check
In this case, the "fast_float::common::AsciiStr::first" method within the "AsciiStr" struct
uses the unsafe keyword to reading from memory without performing bounds checking.
Specifically, it directly dereferences a pointer offset by "self.ptr".
Because of the above reason, the method accesses invalid memory address when it takes an empty string as its input.
This approach violates Rust’s memory safety guarantees, as it can lead to invalid memory access if empty buffer is provided.
No patched version for fast-float crate has been released, but a patch is available in the fast-float2 fork.
ring: Some AES functions may panic when overflow checking is enabled.
ring::aead::quic::HeaderProtectionKey::new_mask() may panic when overflow
checking is enabled. In the QUIC protocol, an attacker can induce this panic by
sending a specially-crafted packet. Even unintentionally it is likely to occur
in 1 out of every 2**32 packets sent and/or received.
On 64-bit targets operations using ring::aead::{AES_128_GCM, AES_256_GCM} may
panic when overflow checking is enabled, when encrypting/decrypting approximately
68,719,476,700 bytes (about 64 gigabytes) of data in a single chunk. Protocols
like TLS and SSH are not affected by this because those protocols break large
amounts of data into small chunks. Similarly, most applications will not
attempt to encrypt/decrypt 64GB of data in one chunk.
Overflow checking is not enabled in release mode by default, but
RUSTFLAGS="-C overflow-checks" or overflow-checks = true in the Cargo.toml
profile can override this. Overflow checking is usually enabled by default in
debug mode.
sequoia-openpgp: Underflow in aes_key_unwrap function
The aes_key_unwrap function would panic if passed a ciphertext
that was too short. In a debug build, it would panic due to a
subtraction underflow. In a release build, it would use the
small negative quantity to allocate a vector. Since the
allocator expects an unsigned quantity, the negative value would
be interpreted as a huge allocation. The allocator would then
fail to allocate the memory and panic.
An attacker could trigger this panic by sending a victim an
encrypted message whose PKESK or SKESK packet has been specially
modified. When the victim decrypts the message, the program
would crash.
rkyv: Potential Undefined Behaviors in `Arc<T>`/`Rc<T>` impls of `from_value` on OOM
The SharedPointer::alloc implementation for sync::Arc<T> and rc::Rc<T> in rkyv/src/impls/alloc/rc/atomic.rs (and rc.rs) does not check if the allocator returns a null pointer on OOM (Out of Memory).
This null pointer can flow through to SharedPointer::from_value, which calls Box::from_raw(ptr) with the null pointer. This triggers undefined behavior when utilizing safe deserialization APIs (such as rkyv::from_bytes or rkyv::deserialize_using) if an OOM condition occurs during the allocation of the shared pointer.
The issue is reachable through safe code and violates Rust's safety guarantees.
In the unique reclaim path of BytesMut::reserve, the condition
if v_capacity >= new_cap + offset
uses an unchecked addition. When new_cap + offset overflows usize in release builds, this condition may incorrectly pass, causing self.cap to be set to a value that exceeds the actual allocated capacity. Subsequent APIs such as spare_capacity_mut() then trust this corrupted cap value and may create out-of-bounds slices, leading to UB.
This behavior is observable in release builds (integer overflow wraps), whereas debug builds panic due to overflow checks.
PoC
use bytes::*;
fn main() {
let mut a = BytesMut::from(&b"hello world"[..]);
let mut b = a.split_off(5);
// Ensure b becomes the unique owner of the backing storage
drop(a);
// Trigger overflow in new_cap + offset inside reserve
b.reserve(usize::MAX - 6);
// This call relies on the corrupted cap and may cause UB & HBO
b.put_u8(b'h');
}
Workarounds
Users of BytesMut::reserve are only affected if integer overflow checks are configured to wrap. When integer overflow is configured to panic, this issue does not apply.