You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
115 lines
4.1 KiB
115 lines
4.1 KiB
use num_bigint::BigUint; |
|
|
|
use crate::common_types::{DnsSecAlgorithm, DnsSecAlgorithmKnown}; |
|
|
|
// ECC_GOST [RFC5933] |
|
|
|
// RFC5702 still confirms this |
|
const RSA_BITS_LIMIT: usize = 4096; |
|
const RSA_BYTES_LIMIT: usize = RSA_BITS_LIMIT / 8; |
|
|
|
fn parse_rsa(data: &[u8]) -> crate::errors::Result<PublicKey> { |
|
failure::ensure!(!data.is_empty(), "RSA public key must be non-empty"); |
|
|
|
let exp_len: usize; |
|
let offset: usize; |
|
if data[0] == 0 { |
|
failure::ensure!(data.len() >= 3, "RSA public key: unexpected end of data when decoding exponent length"); |
|
exp_len = (data[1] as usize) << 8 + (data[2] as usize); |
|
offset = 3; |
|
failure::ensure!(exp_len >= 256, "RSA public key: exponent length in long form but too small"); |
|
} else { |
|
exp_len = data[0] as usize; |
|
offset = 1; |
|
} |
|
|
|
assert!(exp_len > 0); // should be unreachable: 0 means two bytes, which are checked for >= 256 |
|
|
|
failure::ensure!(exp_len <= RSA_BYTES_LIMIT, "RSA public key: exponent too long (limit: {} bits)", RSA_BITS_LIMIT); |
|
|
|
failure::ensure!(data.len() >= offset + exp_len, "RSA public key: unexpected end of data when reading exponent"); |
|
failure::ensure!(data[offset] != 0, "RSA public key: leading zero in exponent"); |
|
let exponent = BigUint::from_bytes_be(&data[offset..][..exp_len]); |
|
|
|
let modulus_data = &data[offset..][exp_len..]; |
|
failure::ensure!(modulus_data.len() <= RSA_BYTES_LIMIT, "RSA public key: modulus too long (limit: {} bits)", RSA_BITS_LIMIT); |
|
failure::ensure!(!modulus_data.is_empty(), "RSA public key: modulus empty"); |
|
failure::ensure!(modulus_data[offset] != 0, "RSA public key: leading zero in modulus"); |
|
|
|
let modulus = BigUint::from_bytes_be(modulus_data); |
|
|
|
Ok(PublicKey::RSA { |
|
exponent, |
|
modulus, |
|
}) |
|
} |
|
|
|
#[allow(non_camel_case_types)] |
|
pub enum PublicKey { |
|
RSA { exponent: BigUint, modulus: BigUint }, |
|
ECDSAP256 { xy: Box<([u8; 32], [u8; 32])> }, |
|
ECDSAP384 { xy: Box<([u8; 48], [u8; 48])> }, |
|
ECC_GOST { xy: Box<([u8; 32], [u8; 32])> }, |
|
ED25519 { key: Box<[u8; 32]> }, |
|
ED448 { key: Box<[u8; 57]> }, |
|
} |
|
|
|
impl PublicKey { |
|
pub fn parse(algorithm: DnsSecAlgorithm, data: &[u8]) -> crate::errors::Result<Self> { |
|
use DnsSecAlgorithmKnown::*; |
|
|
|
let algorithm = algorithm.into_known().ok_or_else(|| failure::format_err!("Unknown algorithm"))?; |
|
match algorithm { |
|
DELETE|INDIRECT|PRIVATEDNS|PRIVATEOID => failure::bail!("Algorithm {:?} not used with actual key", algorithm), |
|
RSAMD5|RSASHA1|RSASHA1_NSEC3_SHA1|RSASHA256|RSASHA512 => parse_rsa(data), |
|
DH|DSA|DSA_NSEC3_SHA1 => failure::bail!("Algorithm {:?} not supported", algorithm), |
|
ECDSAP256SHA256 => { |
|
failure::ensure!(data.len() == 64, "Expected 64 bytes public key for ECDSAP256"); |
|
let mut x = [0u8; 32]; |
|
x.copy_from_slice(&data[..32]); |
|
let mut y = [0u8; 32]; |
|
y.copy_from_slice(&data[32..]); |
|
Ok(PublicKey::ECDSAP256 { xy: Box::new((x, y)) }) |
|
}, |
|
ECDSAP384SHA384 => { |
|
failure::ensure!(data.len() == 96, "Expected 96 bytes public key for ECDSAP384"); |
|
let mut x = [0u8; 48]; |
|
x.copy_from_slice(&data[..48]); |
|
let mut y = [0u8; 48]; |
|
y.copy_from_slice(&data[48..]); |
|
Ok(PublicKey::ECDSAP384 { xy: Box::new((x, y)) }) |
|
}, |
|
ECC_GOST => { |
|
failure::ensure!(data.len() == 64, "Expected 64 bytes public key for ECC_GOST"); |
|
let mut x = [0u8; 32]; |
|
x.copy_from_slice(&data[..32]); |
|
let mut y = [0u8; 32]; |
|
y.copy_from_slice(&data[32..]); |
|
Ok(PublicKey::ECC_GOST { xy: Box::new((x, y)) }) |
|
}, |
|
ED25519 => { |
|
failure::ensure!(data.len() == 32, "Expected 32 bytes public key for ED25519"); |
|
let mut key = [0u8; 32]; |
|
key.copy_from_slice(data); |
|
Ok(PublicKey::ED25519 { key: Box::new(key) }) |
|
}, |
|
ED448 => { |
|
failure::ensure!(data.len() == 57, "Expected 57 bytes public key for ED448"); |
|
let mut key = [0u8; 57]; |
|
key.copy_from_slice(data); |
|
Ok(PublicKey::ED448 { key: Box::new(key) }) |
|
}, |
|
} |
|
} |
|
|
|
pub fn bits(&self) -> Option<u32> { |
|
match self { |
|
PublicKey::RSA { modulus, .. } => Some(modulus.bits() as u32), |
|
PublicKey::ECDSAP256 { .. } => Some(32*8), |
|
PublicKey::ECDSAP384 { .. } => Some(48*8), |
|
PublicKey::ECC_GOST { .. } => Some(32*8), |
|
PublicKey::ED25519 { .. } => Some(32*8), |
|
PublicKey::ED448 { .. } => Some(57*8), |
|
} |
|
} |
|
}
|
|
|