-
Notifications
You must be signed in to change notification settings - Fork 177
Description
Some internals of the num-bigint-dig crate might panic under some conditions and rsa does not check for these. Therefore, users of the rsa crate experience panics.
I've stumbled upon this while implementing some jose stuff, so this examples uses a key in JsonWebKey format:
use base64ct::{Base64UrlUnpadded, Encoding};
use rsa::{BigUint, RsaPrivateKey};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let n = BigUint::from_bytes_be(&base64ct::Base64UrlUnpadded::decode_vec("w8XZRYEMzHbSMJXM6kSS2BGicmF5o9_cdlklKYXwey_HpWvI6XtRA9jq_SksGudyvhrLeyNr5P8mUoNPy9DiweXLoidv9kRbU33XLIvJkqbjIXKSwgk9RuQn-v8BoJj8e2uc7sH0eS3RVDtNZ1V1dRbyspC-e2zh9lgcgTRMUVM99pWijcrVD_Wt9hqYlFLM2HA_IoE-9gRrtqrRDwSOrISz_7pzRtJ3RFe3rVkh6MdZVUZ3bNa-D3A6acYmU74YFoVTyKlgSqNmuzFc9yOMM3z4amzLdvfeX_nUxWJdurK80M93vdTqw4-WIzlkkNkUOXq1LUjwZOvtke-t3y87JQ")?);
let e = BigUint::from_bytes_be(&Base64UrlUnpadded::decode_vec("AQAB")?);
let d = BigUint::from_bytes_be(&Base64UrlUnpadded::decode_vec("QThDVsVURzV6dpchKhZoOTU-wg45IN_uKTsvhzLI17EmOLS8vRPI_JgiSO6Tc-8RKcXxbfdx9VsPIEQArGzNbj0o5r9urEM_jYQJ0BxNrd6NIlJyE9RSJrDRpOuZVjBBRLioEl5pHImoCACtm7Q7qiNX_Sb9Xk76xD-8V0rd9eVJJBLXpoSV_b_Q80IB9YeZvE8VxzG9dzVjyowzn59SkvG-59G6SteOvLMb9i1in1dzXEKBzauYrExCOlT5t0skJenBVxgD-RNa9Bkjed_4QcNtO3x08F7j2ziqa8iNOtQWRThiArCd14iM2YhdHIZrzPeOYj9DmXIThOlacQ1NAQ")?);
// original p value
let p = BigUint::from_bytes_be(&Base64UrlUnpadded::decode_vec("11_iIv_gwowCkC32vALSm3Po9vfirnhX5jIyh2U2mzH9PvLx4OaUQ_O2WWyYRkpTNivSf0erFNjf9xz2efAhVrMX4Y11XPNpWAAsmuawA23Ptgjy6-PGSSHj8PJXXK6jTpoYe6uDtYIe509ODYdTeBU6KNg91T0EbNSV_A4K40E")?);
let q = BigUint::from_bytes_be(&Base64UrlUnpadded::decode_vec("6LNts0tPvK6J2XgLaWI9rvvztJNzKTznmA5WPDpkApPpKp9U2lDucAyjAIFYJxYuOPN4kJ6tBeFGJAKEU1rv7hW5gXbbkVt6r_v23lV_LQ841pEnsmwvdUEgw3gE7iEviI6ZuiaSQQ-yUSoiKQc0rXeXhdmyVck_y5s1JHl_cuU")?);
// malicious p
// when set to zero, it panics and the backtrace points to https://docs.rs/num-bigint-dig/latest/src/num_bigint_dig/algorithms/sub.rs.html#75-79
// when set to 1 it panics because of a divison by zero, probably because of https://docs.rs/rsa/latest/src/rsa/key.rs.html#344-345
let p = BigUint::from_bytes_be(&[0x0]);
// `precompute` in this method will panic
let private_key = RsaPrivateKey::from_components(n, e, d, vec![p, q]);
// it could be catched here (maybe, dont know tbh), but since it panics, there's
// no way
private_key.validate().unwrap();
Ok(())
}This can lead to denial of service attacks if untrusted keys are parsed and isn't mention in the docs at all.
I haven't tried malicious pem/der encoded keys, but it seems realistic that they suffer from the same problem.
I've also noticed that the sign method might loop if an incorrect parameter is used but that can probably be prevented by using RsaPrivateKey::validate.
Also, I really don't like the way primes are passed to RsaPrivateKey::from_components since passing an array with a length < 2 leads to panic because of out of bounds access and that isn't mention in the docs either.