136 lines
4.1 KiB
Rust
136 lines
4.1 KiB
Rust
use rpki::data_model::rc::{
|
|
Afi, AsIdentifierChoice, AsIdOrRange, AsResourceSet, IpAddressChoice, IpAddressOrRange,
|
|
IpResourceSet,
|
|
};
|
|
|
|
fn len_bytes(len: usize) -> Vec<u8> {
|
|
if len < 128 {
|
|
vec![len as u8]
|
|
} else {
|
|
let mut tmp = Vec::new();
|
|
let mut n = len;
|
|
while n > 0 {
|
|
tmp.push((n & 0xFF) as u8);
|
|
n >>= 8;
|
|
}
|
|
tmp.reverse();
|
|
let mut out = vec![0x80 | (tmp.len() as u8)];
|
|
out.extend(tmp);
|
|
out
|
|
}
|
|
}
|
|
|
|
fn tlv(tag: u8, content: &[u8]) -> Vec<u8> {
|
|
let mut out = vec![tag];
|
|
out.extend(len_bytes(content.len()));
|
|
out.extend_from_slice(content);
|
|
out
|
|
}
|
|
|
|
fn der_sequence(children: Vec<Vec<u8>>) -> Vec<u8> {
|
|
let mut content = Vec::new();
|
|
for c in children {
|
|
content.extend(c);
|
|
}
|
|
tlv(0x30, &content)
|
|
}
|
|
|
|
fn der_octet_string(bytes: &[u8]) -> Vec<u8> {
|
|
tlv(0x04, bytes)
|
|
}
|
|
|
|
fn der_null() -> Vec<u8> {
|
|
vec![0x05, 0x00]
|
|
}
|
|
|
|
fn der_integer_u64(v: u64) -> Vec<u8> {
|
|
let mut bytes = Vec::new();
|
|
let mut n = v;
|
|
if n == 0 {
|
|
bytes.push(0);
|
|
} else {
|
|
while n > 0 {
|
|
bytes.push((n & 0xFF) as u8);
|
|
n >>= 8;
|
|
}
|
|
bytes.reverse();
|
|
if bytes[0] & 0x80 != 0 {
|
|
bytes.insert(0, 0);
|
|
}
|
|
}
|
|
tlv(0x02, &bytes)
|
|
}
|
|
|
|
fn der_bit_string(unused: u8, bytes: &[u8]) -> Vec<u8> {
|
|
let mut content = vec![unused];
|
|
content.extend_from_slice(bytes);
|
|
tlv(0x03, &content)
|
|
}
|
|
|
|
fn cs_cons(tag_no: u8, inner_der: Vec<u8>) -> Vec<u8> {
|
|
tlv(0xA0 | (tag_no & 0x1F), &inner_der)
|
|
}
|
|
|
|
#[test]
|
|
fn ip_addr_blocks_decode_handles_inherit_and_range_endpoint_fill() {
|
|
// IPv6 family with one range:
|
|
// - min: 240a:a000::/32 (encoded as 32 bits)
|
|
// - max: 240a:a008::/31 (encoded as 31 bits, so fill-ones yields 240a:a009:ffff..)
|
|
let address_family = der_octet_string(&[0x00, 0x02]);
|
|
let min = der_bit_string(0, &[0x24, 0x0A, 0xA0, 0x00]);
|
|
let max = der_bit_string(1, &[0x24, 0x0A, 0xA0, 0x08]);
|
|
let range = der_sequence(vec![min, max]);
|
|
let choice = der_sequence(vec![range]);
|
|
let fam = der_sequence(vec![address_family, choice]);
|
|
let ip_addr_blocks = der_sequence(vec![fam]);
|
|
|
|
let decoded = IpResourceSet::decode_extn_value(&ip_addr_blocks).expect("decode ipAddrBlocks");
|
|
assert_eq!(decoded.families.len(), 1);
|
|
let fam = &decoded.families[0];
|
|
assert_eq!(fam.afi, Afi::Ipv6);
|
|
let IpAddressChoice::AddressesOrRanges(items) = &fam.choice else {
|
|
panic!("expected AddressesOrRanges");
|
|
};
|
|
let IpAddressOrRange::Range(r) = &items[0] else {
|
|
panic!("expected Range");
|
|
};
|
|
assert_eq!(r.min[..4], [0x24, 0x0A, 0xA0, 0x00]);
|
|
assert_eq!(r.max[..4], [0x24, 0x0A, 0xA0, 0x09]);
|
|
assert!(r.max[4..].iter().all(|&b| b == 0xFF));
|
|
|
|
// Inherit branch.
|
|
let fam_inherit = der_sequence(vec![der_octet_string(&[0x00, 0x01]), der_null()]);
|
|
let decoded = IpResourceSet::decode_extn_value(&der_sequence(vec![fam_inherit])).expect("decode inherit");
|
|
assert!(decoded.is_all_inherit());
|
|
}
|
|
|
|
#[test]
|
|
fn autonomous_sys_ids_decode_handles_inherit_ids_and_ranges() {
|
|
// ASIdentifiers with:
|
|
// - asnum [0] EXPLICIT asIdsOrRanges { id 64496, range 64500..64510 }
|
|
let as_id_or_ranges = der_sequence(vec![
|
|
der_integer_u64(64496),
|
|
der_sequence(vec![der_integer_u64(64500), der_integer_u64(64510)]),
|
|
]);
|
|
let asnum = cs_cons(0, as_id_or_ranges);
|
|
let as_identifiers = der_sequence(vec![asnum]);
|
|
|
|
let decoded = AsResourceSet::decode_extn_value(&as_identifiers).expect("decode asIdentifiers");
|
|
assert!(decoded.rdi.is_none());
|
|
let Some(asnum) = decoded.asnum else {
|
|
panic!("missing asnum");
|
|
};
|
|
let AsIdentifierChoice::AsIdsOrRanges(items) = asnum else {
|
|
panic!("expected AsIdsOrRanges");
|
|
};
|
|
assert_eq!(items.len(), 2);
|
|
assert!(matches!(items[0], AsIdOrRange::Id(64496)));
|
|
assert!(matches!(items[1], AsIdOrRange::Range { min: 64500, max: 64510 }));
|
|
|
|
// asnum inherit.
|
|
let asnum_inherit = cs_cons(0, der_null());
|
|
let decoded = AsResourceSet::decode_extn_value(&der_sequence(vec![asnum_inherit])).expect("decode inherit");
|
|
assert!(decoded.is_asnum_inherit());
|
|
}
|
|
|