Check for record data length upon creation. (#169)

This commit changes the new function of the following record types to check
whether the wire format representation of the record data is too long and
thus returns a result: Tsig<_, _>, Dnskey<_>, Rrsig<_, _>, Ds<_>,
Cdnskey<_>, Cds<_>. In addition, it changes the Null::new to
Null::from_octets.
This commit is contained in:
Martin Hoffmann
2023-02-06 16:54:27 +01:00
committed by GitHub
parent d36bd1d1c4
commit a3b33a4237
11 changed files with 686 additions and 329 deletions
+8 -1
View File
@@ -114,6 +114,9 @@ impl Opt<[u8]> {
/// Checks that the slice contains acceptable OPT record data.
fn check_slice(slice: &[u8]) -> Result<(), ParseError> {
if slice.len() > usize::from(u16::MAX) {
return Err(FormError::new("long record data").into());
}
let mut parser = Parser::from_ref(slice);
while parser.remaining() > 0 {
parser.advance(2)?;
@@ -126,11 +129,15 @@ impl Opt<[u8]> {
impl<Octs: AsRef<[u8]> + ?Sized> Opt<Octs> {
/// Returns the length of the OPT record data.
#[allow(clippy::len_without_is_empty)] // never empty.
pub fn len(&self) -> usize {
self.octets.as_ref().len()
}
/// Returns whether the OPT record data is empty.
pub fn is_empty(&self) -> bool {
self.octets.as_ref().is_empty()
}
/// Returns an iterator over options of a given type.
///
/// The returned iterator will return only options represented by type
+17 -6
View File
@@ -243,11 +243,8 @@ impl<Octs> UnknownRecordData<Octs> {
where
Octs: AsRef<[u8]>,
{
if data.as_ref().len() > 0xFFFF {
Err(LongRecordData())
} else {
Ok(UnknownRecordData { rtype, data })
}
LongRecordData::check_len(data.as_ref().len())?;
Ok(UnknownRecordData { rtype, data })
}
/// Returns the record type this data is for.
@@ -450,9 +447,23 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for UnknownRecordData<Octs> {
#[derive(Clone, Copy, Debug)]
pub struct LongRecordData();
impl LongRecordData {
pub fn as_str(self) -> &'static str {
"record data too long"
}
pub fn check_len(len: usize) -> Result<(), Self> {
if len > usize::from(u16::MAX) {
Err(LongRecordData())
} else {
Ok(())
}
}
}
impl fmt::Display for LongRecordData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("record data too long")
f.write_str(self.as_str())
}
}
+1 -1
View File
@@ -75,7 +75,7 @@ macro_rules! rdata_types {
Unknown($crate::base::rdata::UnknownRecordData<O>),
}
impl<Octets: AsRef<[u8]>, Name> ZoneRecordData<Octets, Name> {
impl<Octets: AsRef<[u8]>, Name: ToDname> ZoneRecordData<Octets, Name> {
/// Scans a value of the given rtype.
///
/// If the record data is given via the notation for unknown
+157 -78
View File
@@ -9,14 +9,16 @@ use crate::base::cmp::CanonicalOrd;
use crate::base::iana::Rtype;
use crate::base::name::{Dname, ParsedDname, PushError, ToDname};
use crate::base::net::Ipv4Addr;
use crate::base::rdata::{ComposeRecordData, ParseRecordData, RecordData};
use crate::base::rdata::{
ComposeRecordData, LongRecordData, ParseRecordData, RecordData
};
use crate::base::scan::{Scan, Scanner, ScannerError, Symbol};
use crate::base::serial::Serial;
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::base::wire::{Compose, Composer, FormError, Parse, ParseError};
#[cfg(feature = "bytes")]
use bytes::BytesMut;
use core::cmp::Ordering;
use core::convert::Infallible;
use core::convert::{Infallible, TryFrom};
use core::str::FromStr;
use core::{fmt, hash, ops, str};
use octseq::builder::{
@@ -937,7 +939,7 @@ dname_type_well_known! {
/// The Null record type is defined in RFC 1035, section 3.3.10.
#[derive(Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Null<Octs> {
pub struct Null<Octs: ?Sized> {
#[cfg_attr(
feature = "serde",
serde(
@@ -953,21 +955,54 @@ pub struct Null<Octs> {
}
impl<Octs> Null<Octs> {
/// Creates new, empty owned Null record data.
pub fn new(data: Octs) -> Self {
Null { data }
/// Creates new NULL record data from the given octets.
///
/// The function will fail if `data` is longer than 65,535 octets.
pub fn from_octets(data: Octs) -> Result<Self, LongRecordData>
where Octs: AsRef<[u8]> {
Null::check_slice(data.as_ref())?;
Ok(unsafe { Self::from_octets_unchecked(data) })
}
/// Creates new NULL record data without checking.
///
/// # Safety
///
/// The caller has to ensure that `data` is at most 65,535 octets long.
pub unsafe fn from_octets_unchecked(data: Octs) -> Self {
Null { data }
}
}
impl Null<[u8]> {
/// Creates new NULL record data from an octets slice.
///
/// The function will fail if `data` is longer than 65,535 octets.
pub fn from_slice(data: &[u8]) -> Result<&Self, LongRecordData> {
Self::check_slice(data)?;
Ok(unsafe { Self::from_slice_unchecked(data) })
}
/// Creates new NULL record from an octets slice data without checking.
///
/// # Safety
///
/// The caller has to ensure that `data` is at most 65,535 octets long.
pub unsafe fn from_slice_unchecked(data: &[u8]) -> &Self {
&*(data as *const [u8] as *const Self)
}
/// Checks that a slice can be used for NULL record data.
fn check_slice(slice: &[u8]) -> Result<(), LongRecordData> {
LongRecordData::check_len(slice.len())
}
}
impl<Octs: ?Sized> Null<Octs> {
/// The raw content of the record.
pub fn data(&self) -> &Octs {
&self.data
}
pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
self,
) -> Result<Null<Target>, Target::Error> {
Ok(Null::new(self.data.try_octets_into()?))
}
}
impl<Octs: AsRef<[u8]>> Null<Octs> {
@@ -980,12 +1015,24 @@ impl<Octs: AsRef<[u8]>> Null<Octs> {
}
}
impl<Octs> Null<Octs> {
pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
self,
) -> Result<Null<Target>, Target::Error> {
Ok(unsafe {
Null::from_octets_unchecked(self.data.try_octets_into()?)
})
}
}
impl<Octs> Null<Octs> {
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
parser: &mut Parser<'a, Src>,
) -> Result<Self, ParseError> {
let len = parser.remaining();
parser.parse_octets(len).map(Self::new).map_err(Into::into)
parser.parse_octets(len).map(|res| {
unsafe { Self::from_octets_unchecked(res) }
}).map_err(Into::into)
}
}
@@ -994,15 +1041,11 @@ impl<SrcOcts> Null<SrcOcts> {
where
Octs: OctetsFrom<SrcOcts>,
{
Ok(Null::new(self.data.try_octets_into().map_err(Into::into)?))
}
}
//--- From
impl<Octs> From<Octs> for Null<Octs> {
fn from(data: Octs) -> Self {
Self::new(data)
Ok(unsafe {
Null::from_octets_unchecked(
self.data.try_octets_into().map_err(Into::into)?
)
})
}
}
@@ -1015,7 +1058,9 @@ where
type Error = Octs::Error;
fn try_octets_from(source: Null<SrcOcts>) -> Result<Self, Self::Error> {
Octs::try_octets_from(source.data).map(Self::new)
Octs::try_octets_from(source.data).map(|res| {
unsafe { Self::from_octets_unchecked(res) }
})
}
}
@@ -1023,22 +1068,22 @@ where
impl<Octs, Other> PartialEq<Null<Other>> for Null<Octs>
where
Octs: AsRef<[u8]>,
Other: AsRef<[u8]>,
Octs: AsRef<[u8]> + ?Sized,
Other: AsRef<[u8]> + ?Sized,
{
fn eq(&self, other: &Null<Other>) -> bool {
self.data.as_ref().eq(other.data.as_ref())
}
}
impl<Octs: AsRef<[u8]>> Eq for Null<Octs> {}
impl<Octs: AsRef<[u8]> + ?Sized> Eq for Null<Octs> {}
//--- PartialOrd, CanonicalOrd, and Ord
impl<Octs, Other> PartialOrd<Null<Other>> for Null<Octs>
where
Octs: AsRef<[u8]>,
Other: AsRef<[u8]>,
Octs: AsRef<[u8]> + ?Sized,
Other: AsRef<[u8]> + ?Sized,
{
fn partial_cmp(&self, other: &Null<Other>) -> Option<Ordering> {
self.data.as_ref().partial_cmp(other.data.as_ref())
@@ -1047,15 +1092,15 @@ where
impl<Octs, Other> CanonicalOrd<Null<Other>> for Null<Octs>
where
Octs: AsRef<[u8]>,
Other: AsRef<[u8]>,
Octs: AsRef<[u8]> + ?Sized,
Other: AsRef<[u8]> + ?Sized,
{
fn canonical_cmp(&self, other: &Null<Other>) -> Ordering {
self.data.as_ref().cmp(other.data.as_ref())
}
}
impl<Octs: AsRef<[u8]>> Ord for Null<Octs> {
impl<Octs: AsRef<[u8]> + ?Sized> Ord for Null<Octs> {
fn cmp(&self, other: &Self) -> Ordering {
self.data.as_ref().cmp(other.data.as_ref())
}
@@ -1063,7 +1108,7 @@ impl<Octs: AsRef<[u8]>> Ord for Null<Octs> {
//--- Hash
impl<Octs: AsRef<[u8]>> hash::Hash for Null<Octs> {
impl<Octs: AsRef<[u8]> + ?Sized> hash::Hash for Null<Octs> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.data.as_ref().hash(state)
}
@@ -1071,7 +1116,7 @@ impl<Octs: AsRef<[u8]>> hash::Hash for Null<Octs> {
//--- RecordData, ParseRecordData, ComposeRecordData
impl<Octs> RecordData for Null<Octs> {
impl<Octs: ?Sized> RecordData for Null<Octs> {
fn rtype(&self) -> Rtype {
Rtype::Null
}
@@ -1093,7 +1138,7 @@ where
}
}
impl<Octs: AsRef<[u8]>> ComposeRecordData for Null<Octs> {
impl<Octs: AsRef<[u8]> + ?Sized> ComposeRecordData for Null<Octs> {
fn rdlen(&self, _compress: bool) -> Option<u16> {
Some(
u16::try_from(self.data.as_ref().len()).expect("long NULL rdata"),
@@ -1115,16 +1160,6 @@ impl<Octs: AsRef<[u8]>> ComposeRecordData for Null<Octs> {
}
}
//--- Deref
impl<Octs> ops::Deref for Null<Octs> {
type Target = Octs;
fn deref(&self) -> &Self::Target {
&self.data
}
}
//--- AsRef
impl<Octs: AsRef<Other>, Other> AsRef<Other> for Null<Octs> {
@@ -1570,7 +1605,7 @@ impl<Octs: FromBuilder> Txt<Octs> {
impl<Octs> Txt<Octs> {
/// Creates new TXT record data from its encoded content.
pub fn from_octets(octets: Octs) -> Result<Self, CharStrError>
pub fn from_octets(octets: Octs) -> Result<Self, TxtError>
where
Octs: AsRef<[u8]>
{
@@ -1587,7 +1622,40 @@ impl<Octs> Txt<Octs> {
unsafe fn from_octets_unchecked(octets: Octs) -> Self {
Txt(octets)
}
}
impl Txt<[u8]> {
/// Creates new TXT record data on an octets slice.
pub fn from_slice(slice: &[u8]) -> Result<&Self, TxtError> {
Txt::check_slice(slice)?;
Ok(unsafe { Txt::from_slice_unchecked(slice) })
}
/// Creates new TXT record data on an octets slice without checking.
///
/// # Safety
///
/// The passed octets must contain correctly encoded TXT record data,
/// that is a sequence of encoded character strings.
unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
unsafe { &*(slice as *const [u8] as *const Self) }
}
/// Checks that a slice contains correctly encoded TXT data.
fn check_slice(mut slice: &[u8]) -> Result<(), TxtError> {
LongRecordData::check_len(slice.len())?;
while let Some(&len) = slice.first() {
let len = usize::from(len);
if slice.len() <= len {
return Err(TxtError(TxtErrorInner::ShortInput));
}
slice = &slice[len + 1..];
}
Ok(())
}
}
impl<Octs> Txt<Octs> {
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
parser: &mut Parser<'a, Src>,
) -> Result<Self, ParseError>
@@ -1608,36 +1676,6 @@ impl<Octs> Txt<Octs> {
}
}
impl Txt<[u8]> {
/// Creates new TXT record data on an octets slice.
pub fn from_slice(slice: &[u8]) -> Result<&Self, CharStrError> {
Txt::check_slice(slice)?;
Ok(unsafe { Txt::from_slice_unchecked(slice) })
}
/// Creates new TXT record data on an octets slice without checking.
///
/// # Safety
///
/// The passed octets must contain correctly encoded TXT record data,
/// that is a sequence of encoded character strings.
unsafe fn from_slice_unchecked(slice: &[u8]) -> &Self {
unsafe { &*(slice as *const [u8] as *const Self) }
}
/// Checks that a slice contains correctly encoded TXT data.
fn check_slice(mut slice: &[u8]) -> Result<(), CharStrError> {
while let Some(&len) = slice.first() {
let len = usize::from(len);
if slice.len() <= len {
return Err(CharStrError);
}
slice = &slice[len + 1..];
}
Ok(())
}
}
impl<Octs: AsRef<[u8]> + ?Sized> Txt<Octs> {
/// Returns an iterator over the text items.
///
@@ -2176,7 +2214,48 @@ impl<Builder: OctetsBuilder + EmptyBuilder> Default for TxtBuilder<Builder> {
}
}
//============ Testing ======================================================
//============ Error Types ===================================================
//------------ TxtError ------------------------------------------------------
/// An octets sequence does not form valid TXT record data.
#[derive(Clone, Copy, Debug)]
pub struct TxtError(TxtErrorInner);
#[derive(Clone, Copy, Debug)]
enum TxtErrorInner {
Long(LongRecordData),
ShortInput,
}
impl TxtError {
pub fn as_str(self) -> &'static str {
match self.0 {
TxtErrorInner::Long(err) => err.as_str(),
TxtErrorInner::ShortInput => "short input",
}
}
}
impl From<LongRecordData> for TxtError {
fn from(err: LongRecordData) -> TxtError {
TxtError(TxtErrorInner::Long(err))
}
}
impl From<TxtError> for FormError {
fn from(err: TxtError) -> FormError {
FormError::new(err.as_str())
}
}
impl fmt::Display for TxtError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.as_str())
}
}
//============ Testing =======================================================
#[cfg(test)]
#[cfg(all(feature = "std", feature = "bytes"))]
@@ -2276,7 +2355,7 @@ mod test {
#[test]
fn null_compose_parse_scan() {
let rdata = Null::new("foo");
let rdata = Null::from_octets("foo").unwrap();
test_rdlen(&rdata);
test_compose_parse(&rdata, |parser| Null::parse(parser));
}
+82 -45
View File
@@ -7,7 +7,9 @@
use crate::base::cmp::CanonicalOrd;
use crate::base::iana::{Rtype, TsigRcode};
use crate::base::name::{Dname, ParsedDname, PushError, ToDname};
use crate::base::rdata::{ComposeRecordData, ParseRecordData, RecordData};
use crate::base::rdata::{
ComposeRecordData, LongRecordData, ParseRecordData, RecordData
};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::utils::base64;
use core::cmp::Ordering;
@@ -77,14 +79,11 @@ pub struct Tsig<Octs, Name> {
}
impl<O, N> Tsig<O, N> {
/// Creates a new TSIG record from its components.
/// Creates new TSIG record data from its components.
///
/// See the access methods for an explanation of these components.
///
/// # Panics
///
/// Since `time_signed` is actually a 48 bit integer, the function will
/// panic of the upper 16 bits are not all 0.
/// See the access methods for an explanation of these components. The
/// function will return an error if the wire format length of the record
/// would exceed 65,535 octets.
pub fn new(
algorithm: N,
time_signed: Time48,
@@ -93,6 +92,42 @@ impl<O, N> Tsig<O, N> {
original_id: u16,
error: TsigRcode,
other: O,
) -> Result<Self, LongRecordData>
where O: AsRef<[u8]>, N: ToDname {
LongRecordData::check_len(
6 // time_signed
+ 2 // fudge
+ 2 // MAC length
+ 2 // original ID
+ 2 // error
+ 2 // other length
+ usize::from(algorithm.compose_len()).checked_add(
mac.as_ref().len()
).expect("long MAC").checked_add(
other.as_ref().len()
).expect("long TSIG")
)?;
Ok(unsafe {
Tsig::new_unchecked(
algorithm, time_signed, fudge, mac, original_id, error, other,
)
})
}
/// Creates new TSIG record data without checking.
///
/// # Safety
///
/// The caller needs to ensure that the wire format length of the
/// created record will not exceed 65,535 octets.
pub unsafe fn new_unchecked(
algorithm: N,
time_signed: Time48,
fudge: u16,
mac: O,
original_id: u16,
error: TsigRcode,
other: O,
) -> Self {
Tsig {
algorithm,
@@ -214,15 +249,17 @@ impl<O, N> Tsig<O, N> {
TOcts: OctetsFrom<O>,
TName: OctetsFrom<N, Error = TOcts::Error>,
{
Ok(Tsig::new(
self.algorithm.try_octets_into()?,
self.time_signed,
self.fudge,
self.mac.try_octets_into()?,
self.original_id,
self.error,
self.other.try_octets_into()?,
))
Ok(unsafe {
Tsig::new_unchecked(
self.algorithm.try_octets_into()?,
self.time_signed,
self.fudge,
self.mac.try_octets_into()?,
self.original_id,
self.error,
self.other.try_octets_into()?,
)
})
}
}
@@ -246,15 +283,17 @@ impl<Octs, NOcts> Tsig<Octs, ParsedDname<NOcts>> {
other,
} = self;
Ok(Tsig::new(
algorithm.flatten_into()?,
time_signed,
fudge,
mac.try_octets_into().map_err(Into::into)?,
original_id,
error,
other.try_octets_into().map_err(Into::into)?,
))
Ok(unsafe {
Tsig::new_unchecked(
algorithm.flatten_into()?,
time_signed,
fudge,
mac.try_octets_into().map_err(Into::into)?,
original_id,
error,
other.try_octets_into().map_err(Into::into)?,
)
})
}
}
@@ -271,14 +310,10 @@ impl<Octs> Tsig<Octs, ParsedDname<Octs>> {
let error = TsigRcode::parse(parser)?;
let other_len = u16::parse(parser)?;
let other = parser.parse_octets(other_len as usize)?;
Ok(Tsig {
algorithm,
time_signed,
fudge,
mac,
original_id,
error,
other,
Ok(unsafe {
Tsig::new_unchecked(
algorithm, time_signed, fudge, mac, original_id, error, other,
)
})
}
}
@@ -297,15 +332,17 @@ where
fn try_octets_from(
source: Tsig<SrcOctets, SrcName>,
) -> Result<Self, Self::Error> {
Ok(Tsig::new(
Name::try_octets_from(source.algorithm)?,
source.time_signed,
source.fudge,
Octs::try_octets_from(source.mac)?,
source.original_id,
source.error,
Octs::try_octets_from(source.other)?,
))
Ok(unsafe {
Tsig::new_unchecked(
Name::try_octets_from(source.algorithm)?,
source.time_signed,
source.fudge,
Octs::try_octets_from(source.mac)?,
source.original_id,
source.error,
Octs::try_octets_from(source.other)?,
)
})
}
}
@@ -666,7 +703,7 @@ impl fmt::Display for Time48 {
}
}
//============ Testing ======================================================
//============ Testing =======================================================
#[cfg(test)]
#[cfg(all(feature = "std", feature = "bytes"))]
@@ -687,7 +724,7 @@ mod test {
13,
TsigRcode::BadCookie,
"",
);
).unwrap();
test_rdlen(&rdata);
test_compose_parse(&rdata, |parser| Tsig::parse(parser));
}
+252 -111
View File
@@ -7,7 +7,9 @@
use crate::base::cmp::CanonicalOrd;
use crate::base::iana::{DigestAlg, Rtype, SecAlg};
use crate::base::name::{Dname, ParsedDname, PushError, ToDname};
use crate::base::rdata::{ComposeRecordData, ParseRecordData, RecordData};
use crate::base::rdata::{
ComposeRecordData, LongRecordData, ParseRecordData, RecordData
};
use crate::base::scan::{Scan, Scanner, ScannerError};
use crate::base::serial::Serial;
use crate::base::wire::{Compose, Composer, FormError, Parse, ParseError};
@@ -59,6 +61,36 @@ impl<Octs> Dnskey<Octs> {
protocol: u8,
algorithm: SecAlg,
public_key: Octs,
) -> Result<Self, LongRecordData>
where
Octs: AsRef<[u8]>,
{
LongRecordData::check_len(
usize::from(
u16::COMPOSE_LEN + u8::COMPOSE_LEN + SecAlg::COMPOSE_LEN
).checked_add(
public_key.as_ref().len()
).expect("long key")
)?;
Ok(Dnskey {
flags,
protocol,
algorithm,
public_key,
})
}
/// Creates new DNSKEY record data without checking.
///
/// # Safety
///
/// The caller needs to ensure that wire format representation of the
/// record data is at most 65,535 octets long.
pub unsafe fn new_unchecked(
flags: u16,
protocol: u8,
algorithm: SecAlg,
public_key: Octs,
) -> Self {
Dnskey {
flags,
@@ -176,12 +208,14 @@ impl<Octs> Dnskey<Octs> {
pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
self,
) -> Result<Dnskey<Target>, Target::Error> {
Ok(Dnskey::new(
self.flags,
self.protocol,
self.algorithm,
self.public_key.try_octets_into()?,
))
Ok(unsafe {
Dnskey::new_unchecked(
self.flags,
self.protocol,
self.algorithm,
self.public_key.try_octets_into()?,
)
})
}
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
@@ -191,23 +225,26 @@ impl<Octs> Dnskey<Octs> {
Some(len) => len,
None => return Err(ParseError::ShortInput),
};
Ok(Self::new(
u16::parse(parser)?,
u8::parse(parser)?,
SecAlg::parse(parser)?,
parser.parse_octets(len)?,
))
Ok(unsafe {
Self::new_unchecked(
u16::parse(parser)?,
u8::parse(parser)?,
SecAlg::parse(parser)?,
parser.parse_octets(len)?,
)
})
}
pub fn scan<S: Scanner<Octets = Octs>>(
scanner: &mut S,
) -> Result<Self, S::Error> {
Ok(Self::new(
) -> Result<Self, S::Error>
where Octs: AsRef<[u8]> {
Self::new(
u16::scan(scanner)?,
u8::scan(scanner)?,
SecAlg::scan(scanner)?,
scanner.convert_entry(base64::SymbolConverter::new())?,
))
).map_err(|err| S::Error::custom(err.as_str()))
}
}
@@ -223,12 +260,14 @@ impl<SrcOcts> Dnskey<SrcOcts> {
public_key,
} = self;
Ok(Dnskey::new(
flags,
protocol,
algorithm,
public_key.try_octets_into().map_err(Into::into)?,
))
Ok(unsafe {
Dnskey::new_unchecked(
flags,
protocol,
algorithm,
public_key.try_octets_into().map_err(Into::into)?,
)
})
}
}
@@ -241,12 +280,14 @@ where
type Error = Octs::Error;
fn try_octets_from(source: Dnskey<SrcOcts>) -> Result<Self, Self::Error> {
Ok(Dnskey::new(
source.flags,
source.protocol,
source.algorithm,
Octs::try_octets_from(source.public_key)?,
))
Ok(unsafe {
Dnskey::new_unchecked(
source.flags,
source.protocol,
source.algorithm,
Octs::try_octets_from(source.public_key)?,
)
})
}
}
@@ -433,7 +474,10 @@ impl<Name> ProtoRrsig<Name> {
}
}
pub fn into_rrsig<Octs>(self, signature: Octs) -> Rrsig<Octs, Name> {
pub fn into_rrsig<Octs: AsRef<[u8]>>(
self, signature: Octs
) -> Result<Rrsig<Octs, Name>, LongRecordData>
where Name: ToDname {
Rrsig::new(
self.type_covered,
self.algorithm,
@@ -595,6 +639,55 @@ impl<Octs, Name> Rrsig<Octs, Name> {
key_tag: u16,
signer_name: Name,
signature: Octs,
) -> Result<Self, LongRecordData>
where Octs: AsRef<[u8]>, Name: ToDname {
LongRecordData::check_len(
usize::from(
Rtype::COMPOSE_LEN
+ SecAlg::COMPOSE_LEN
+ u8::COMPOSE_LEN
+ u32::COMPOSE_LEN
+ Serial::COMPOSE_LEN
+ Serial::COMPOSE_LEN
+ u16::COMPOSE_LEN
+ signer_name.compose_len()
).checked_add(
signature.as_ref().len()
)
.expect("long signature")
)?;
Ok(unsafe {
Rrsig::new_unchecked(
type_covered,
algorithm,
labels,
original_ttl,
expiration,
inception,
key_tag,
signer_name,
signature,
)
})
}
/// Creates new RRSIG record data without checking.
///
/// # Safety
///
/// The caller needs to ensure that wire format representation of the
/// record data is at most 65,535 octets long.
#[allow(clippy::too_many_arguments)] // XXX Consider changing.
pub unsafe fn new_unchecked(
type_covered: Rtype,
algorithm: SecAlg,
labels: u8,
original_ttl: u32,
expiration: Serial,
inception: Serial,
key_tag: u16,
signer_name: Name,
signature: Octs,
) -> Self {
Rrsig {
type_covered,
@@ -656,23 +749,29 @@ impl<Octs, Name> Rrsig<Octs, Name> {
TOcts: OctetsFrom<Octs>,
TName: OctetsFrom<Name, Error = TOcts::Error>,
{
Ok(Rrsig::new(
self.type_covered,
self.algorithm,
self.labels,
self.original_ttl,
self.expiration,
self.inception,
self.key_tag,
TName::try_octets_from(self.signer_name)?,
TOcts::try_octets_from(self.signature)?,
))
Ok(unsafe {
Rrsig::new_unchecked(
self.type_covered,
self.algorithm,
self.labels,
self.original_ttl,
self.expiration,
self.inception,
self.key_tag,
TName::try_octets_from(self.signer_name)?,
TOcts::try_octets_from(self.signature)?,
)
})
}
pub fn scan<S: Scanner<Octets = Octs, Dname = Name>>(
scanner: &mut S,
) -> Result<Self, S::Error> {
Ok(Self::new(
) -> Result<Self, S::Error>
where
Octs: AsRef<[u8]>,
Name: ToDname,
{
Self::new(
Rtype::scan(scanner)?,
SecAlg::scan(scanner)?,
u8::scan(scanner)?,
@@ -682,7 +781,7 @@ impl<Octs, Name> Rrsig<Octs, Name> {
u16::scan(scanner)?,
scanner.scan_dname()?,
scanner.convert_entry(base64::SymbolConverter::new())?,
))
).map_err(|err| S::Error::custom(err.as_str()))
}
}
@@ -709,17 +808,19 @@ impl<Octs, NOcts> Rrsig<Octs, ParsedDname<NOcts>> {
signature,
} = self;
Ok(Rrsig::new(
type_covered,
algorithm,
labels,
original_ttl,
expiration,
inception,
key_tag,
signer_name.flatten_into()?,
Target::try_octets_from(signature).map_err(Into::into)?,
))
Ok(unsafe {
Rrsig::new_unchecked(
type_covered,
algorithm,
labels,
original_ttl,
expiration,
inception,
key_tag,
signer_name.flatten_into()?,
Target::try_octets_from(signature).map_err(Into::into)?,
)
})
}
}
@@ -737,17 +838,19 @@ impl<Octs> Rrsig<Octs, ParsedDname<Octs>> {
let signer_name = ParsedDname::parse(parser)?;
let len = parser.remaining();
let signature = parser.parse_octets(len)?;
Ok(Self::new(
type_covered,
algorithm,
labels,
original_ttl,
expiration,
inception,
key_tag,
signer_name,
signature,
))
Ok(unsafe {
Self::new_unchecked(
type_covered,
algorithm,
labels,
original_ttl,
expiration,
inception,
key_tag,
signer_name,
signature,
)
})
}
}
@@ -765,17 +868,19 @@ where
fn try_octets_from(
source: Rrsig<SrcOcts, SrcName>,
) -> Result<Self, Self::Error> {
Ok(Rrsig::new(
source.type_covered,
source.algorithm,
source.labels,
source.original_ttl,
source.expiration,
source.inception,
source.key_tag,
Name::try_octets_from(source.signer_name)?,
Octs::try_octets_from(source.signature)?,
))
Ok(unsafe {
Rrsig::new_unchecked(
source.type_covered,
source.algorithm,
source.labels,
source.original_ttl,
source.expiration,
source.inception,
source.key_tag,
Name::try_octets_from(source.signer_name)?,
Octs::try_octets_from(source.signature)?,
)
})
}
}
@@ -1353,6 +1458,30 @@ impl<Octs> Ds<Octs> {
algorithm: SecAlg,
digest_type: DigestAlg,
digest: Octs,
) -> Result<Self, LongRecordData>
where Octs: AsRef<[u8]> {
LongRecordData::check_len(
usize::from(
u16::COMPOSE_LEN + SecAlg::COMPOSE_LEN + DigestAlg::COMPOSE_LEN
).checked_add(digest.as_ref().len()).expect("long digest")
)?;
Ok(unsafe {
Ds::new_unchecked(key_tag, algorithm, digest_type, digest)
})
}
/// Creates new DS record data without checking.
///
/// # Safety
///
/// The caller needs to ensure that wire format representation of the
/// record data is at most 65,535 octets long.
pub unsafe fn new_unchecked(
key_tag: u16,
algorithm: SecAlg,
digest_type: DigestAlg,
digest: Octs,
) -> Self {
Ds {
key_tag,
@@ -1385,12 +1514,14 @@ impl<Octs> Ds<Octs> {
pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
self,
) -> Result<Ds<Target>, Target::Error> {
Ok(Ds::new(
self.key_tag,
self.algorithm,
self.digest_type,
self.digest.try_octets_into()?,
))
Ok(unsafe {
Ds::new_unchecked(
self.key_tag,
self.algorithm,
self.digest_type,
self.digest.try_octets_into()?,
)
})
}
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
@@ -1400,23 +1531,26 @@ impl<Octs> Ds<Octs> {
Some(len) => len,
None => return Err(ParseError::ShortInput),
};
Ok(Self::new(
u16::parse(parser)?,
SecAlg::parse(parser)?,
DigestAlg::parse(parser)?,
parser.parse_octets(len)?,
))
Ok(unsafe {
Self::new_unchecked(
u16::parse(parser)?,
SecAlg::parse(parser)?,
DigestAlg::parse(parser)?,
parser.parse_octets(len)?,
)
})
}
pub fn scan<S: Scanner<Octets = Octs>>(
scanner: &mut S,
) -> Result<Self, S::Error> {
Ok(Self::new(
) -> Result<Self, S::Error>
where Octs: AsRef<[u8]> {
Self::new(
u16::scan(scanner)?,
SecAlg::scan(scanner)?,
DigestAlg::scan(scanner)?,
scanner.convert_entry(base16::SymbolConverter::new())?,
))
).map_err(|err| S::Error::custom(err.as_str()))
}
}
@@ -1431,12 +1565,14 @@ impl<SrcOcts> Ds<SrcOcts> {
digest_type,
digest,
} = self;
Ok(Ds::new(
key_tag,
algorithm,
digest_type,
digest.try_octets_into().map_err(Into::into)?,
))
Ok(unsafe {
Ds::new_unchecked(
key_tag,
algorithm,
digest_type,
digest.try_octets_into().map_err(Into::into)?,
)
})
}
}
@@ -1449,12 +1585,14 @@ where
type Error = Octs::Error;
fn try_octets_from(source: Ds<SrcOcts>) -> Result<Self, Self::Error> {
Ok(Ds::new(
source.key_tag,
source.algorithm,
source.digest_type,
Octs::try_octets_from(source.digest)?,
))
Ok(unsafe {
Ds::new_unchecked(
source.key_tag,
source.algorithm,
source.digest_type,
Octs::try_octets_from(source.digest)?,
)
})
}
}
@@ -2281,7 +2419,7 @@ mod test {
#[test]
fn dnskey_compose_parse_scan() {
let rdata = Dnskey::new(10, 11, SecAlg::RsaSha1, b"key");
let rdata = Dnskey::new(10, 11, SecAlg::RsaSha1, b"key").unwrap();
test_rdlen(&rdata);
test_compose_parse(&rdata, |parser| Dnskey::parse(parser));
test_scan(&["10", "11", "RSASHA1", "a2V5"], Dnskey::scan, &rdata);
@@ -2301,7 +2439,7 @@ mod test {
15,
Dname::<Vec<u8>>::from_str("example.com.").unwrap(),
b"key",
);
).unwrap();
test_rdlen(&rdata);
test_compose_parse(&rdata, |parser| Rrsig::parse(parser));
test_scan(
@@ -2341,7 +2479,9 @@ mod test {
#[test]
fn ds_compose_parse_scan() {
let rdata = Ds::new(10, SecAlg::RsaSha1, DigestAlg::Sha256, b"key");
let rdata = Ds::new(
10, SecAlg::RsaSha1, DigestAlg::Sha256, b"key"
).unwrap();
test_rdlen(&rdata);
test_compose_parse(&rdata, |parser| Ds::parse(parser));
test_scan(&["10", "RSASHA1", "2", "6b6579"], Ds::scan, &rdata);
@@ -2440,7 +2580,7 @@ mod test {
KLZ02cRWXqM="
)
.unwrap()
)
).unwrap()
.key_tag(),
59944
);
@@ -2460,7 +2600,7 @@ mod test {
9555KrUB5qihylGa8subX2Nn6UwNR1AkUTV74bU="
)
.unwrap()
)
).unwrap()
.key_tag(),
20326
);
@@ -2476,7 +2616,7 @@ mod test {
C+7Eoi12SqybMTicD3Ezwa9XbG1iPjmjhbMrLh7MSQpX"
)
.unwrap()
)
).unwrap()
.key_tag(),
18698
);
@@ -2484,8 +2624,9 @@ mod test {
#[test]
fn dnskey_flags() {
let dnskey =
Dnskey::new(257, 3, SecAlg::RsaSha256, bytes::Bytes::new());
let dnskey = Dnskey::new(
257, 3, SecAlg::RsaSha256, bytes::Bytes::new()
).unwrap();
assert!(dnskey.is_zsk());
assert!(dnskey.is_secure_entry_point());
assert!(!dnskey.is_revoked());
+126 -64
View File
@@ -4,8 +4,10 @@
use crate::base::cmp::CanonicalOrd;
use crate::base::iana::{DigestAlg, Rtype, SecAlg};
use crate::base::name::PushError;
use crate::base::rdata::{ComposeRecordData, ParseRecordData, RecordData};
use crate::base::scan::{Scan, Scanner};
use crate::base::rdata::{
ComposeRecordData, LongRecordData, ParseRecordData, RecordData
};
use crate::base::scan::{Scan, Scanner, ScannerError};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::utils::{base16, base64};
use core::cmp::Ordering;
@@ -50,6 +52,29 @@ impl<Octs> Cdnskey<Octs> {
protocol: u8,
algorithm: SecAlg,
public_key: Octs,
) -> Result<Self, LongRecordData>
where Octs: AsRef<[u8]> {
LongRecordData::check_len(
usize::from(
u16::COMPOSE_LEN + u8::COMPOSE_LEN + SecAlg::COMPOSE_LEN
).checked_add(public_key.as_ref().len()).expect("long key")
)?;
Ok(unsafe {
Cdnskey::new_unchecked(flags, protocol, algorithm, public_key)
})
}
/// Creates new CDNSKEY record data without checking.
///
/// # Safety
///
/// The caller needs to ensure that wire format representation of the
/// record data is at most 65,535 octets long.
pub unsafe fn new_unchecked(
flags: u16,
protocol: u8,
algorithm: SecAlg,
public_key: Octs,
) -> Self {
Cdnskey {
flags,
@@ -78,12 +103,14 @@ impl<Octs> Cdnskey<Octs> {
pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
self,
) -> Result<Cdnskey<Target>, Target::Error> {
Ok(Cdnskey::new(
self.flags,
self.protocol,
self.algorithm,
self.public_key.try_octets_into()?,
))
Ok(unsafe {
Cdnskey::new_unchecked(
self.flags,
self.protocol,
self.algorithm,
self.public_key.try_octets_into()?,
)
})
}
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
@@ -93,23 +120,26 @@ impl<Octs> Cdnskey<Octs> {
Some(len) => len,
None => return Err(ParseError::ShortInput),
};
Ok(Self::new(
u16::parse(parser)?,
u8::parse(parser)?,
SecAlg::parse(parser)?,
parser.parse_octets(len)?,
))
Ok(unsafe {
Self::new_unchecked(
u16::parse(parser)?,
u8::parse(parser)?,
SecAlg::parse(parser)?,
parser.parse_octets(len)?,
)
})
}
pub fn scan<S: Scanner<Octets = Octs>>(
scanner: &mut S,
) -> Result<Self, S::Error> {
Ok(Self::new(
) -> Result<Self, S::Error>
where Octs: AsRef<[u8]> {
Self::new(
u16::scan(scanner)?,
u8::scan(scanner)?,
SecAlg::scan(scanner)?,
scanner.convert_entry(base64::SymbolConverter::new())?,
))
).map_err(|err| S::Error::custom(err.as_str()))
}
}
@@ -124,12 +154,14 @@ impl<SrcOcts> Cdnskey<SrcOcts> {
algorithm,
public_key,
} = self;
Ok(Cdnskey::new(
flags,
protocol,
algorithm,
public_key.try_octets_into().map_err(Into::into)?,
))
Ok(unsafe {
Cdnskey::new_unchecked(
flags,
protocol,
algorithm,
public_key.try_octets_into().map_err(Into::into)?,
)
})
}
}
@@ -144,12 +176,14 @@ where
fn try_octets_from(
source: Cdnskey<SrcOcts>,
) -> Result<Self, Self::Error> {
Ok(Cdnskey::new(
source.flags,
source.protocol,
source.algorithm,
Octs::try_octets_from(source.public_key)?,
))
Ok(unsafe {
Cdnskey::new_unchecked(
source.flags,
source.protocol,
source.algorithm,
Octs::try_octets_from(source.public_key)?,
)
})
}
}
@@ -334,6 +368,29 @@ impl<Octs> Cds<Octs> {
algorithm: SecAlg,
digest_type: DigestAlg,
digest: Octs,
) -> Result<Self, LongRecordData>
where Octs: AsRef<[u8]> {
LongRecordData::check_len(
usize::from(
u16::COMPOSE_LEN + SecAlg::COMPOSE_LEN + DigestAlg::COMPOSE_LEN
).checked_add(digest.as_ref().len()).expect("long digest")
)?;
Ok(unsafe {
Cds::new_unchecked(key_tag, algorithm, digest_type, digest)
})
}
/// Creates new CDS record data without checking.
///
/// # Safety
///
/// The caller needs to ensure that wire format representation of the
/// record data is at most 65,535 octets long.
pub unsafe fn new_unchecked(
key_tag: u16,
algorithm: SecAlg,
digest_type: DigestAlg,
digest: Octs,
) -> Self {
Cds {
key_tag,
@@ -366,12 +423,14 @@ impl<Octs> Cds<Octs> {
pub(super) fn convert_octets<Target: OctetsFrom<Octs>>(
self,
) -> Result<Cds<Target>, Target::Error> {
Ok(Cds::new(
self.key_tag,
self.algorithm,
self.digest_type,
self.digest.try_octets_into()?,
))
Ok(unsafe {
Cds::new_unchecked(
self.key_tag,
self.algorithm,
self.digest_type,
self.digest.try_octets_into()?,
)
})
}
pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized>(
@@ -381,23 +440,26 @@ impl<Octs> Cds<Octs> {
Some(len) => len,
None => return Err(ParseError::ShortInput),
};
Ok(Self::new(
u16::parse(parser)?,
SecAlg::parse(parser)?,
DigestAlg::parse(parser)?,
parser.parse_octets(len)?,
))
Ok(unsafe {
Self::new_unchecked(
u16::parse(parser)?,
SecAlg::parse(parser)?,
DigestAlg::parse(parser)?,
parser.parse_octets(len)?,
)
})
}
pub fn scan<S: Scanner<Octets = Octs>>(
scanner: &mut S,
) -> Result<Self, S::Error> {
Ok(Self::new(
) -> Result<Self, S::Error>
where Octs: AsRef<[u8]> {
Self::new(
u16::scan(scanner)?,
SecAlg::scan(scanner)?,
DigestAlg::scan(scanner)?,
scanner.convert_entry(base16::SymbolConverter::new())?,
))
).map_err(|err| S::Error::custom(err.as_str()))
}
}
@@ -406,18 +468,14 @@ impl<SrcOcts> Cds<SrcOcts> {
where
Octs: OctetsFrom<SrcOcts>,
{
let Self {
key_tag,
algorithm,
digest_type,
digest,
} = self;
Ok(Cds::new(
key_tag,
algorithm,
digest_type,
digest.try_octets_into().map_err(Into::into)?,
))
Ok(unsafe {
Cds::new_unchecked(
self.key_tag,
self.algorithm,
self.digest_type,
self.digest.try_octets_into().map_err(Into::into)?,
)
})
}
}
@@ -430,12 +488,14 @@ where
type Error = Octs::Error;
fn try_octets_from(source: Cds<SrcOcts>) -> Result<Self, Self::Error> {
Ok(Cds::new(
source.key_tag,
source.algorithm,
source.digest_type,
Octs::try_octets_from(source.digest)?,
))
Ok(unsafe {
Cds::new_unchecked(
source.key_tag,
source.algorithm,
source.digest_type,
Octs::try_octets_from(source.digest)?,
)
})
}
}
@@ -623,7 +683,7 @@ mod test {
#[test]
fn cdnskey_compose_parse_scan() {
let rdata = Cdnskey::new(10, 11, SecAlg::RsaSha1, b"key");
let rdata = Cdnskey::new(10, 11, SecAlg::RsaSha1, b"key").unwrap();
test_rdlen(&rdata);
test_compose_parse(&rdata, |parser| Cdnskey::parse(parser));
test_scan(&["10", "11", "RSASHA1", "a2V5"], Cdnskey::scan, &rdata);
@@ -633,7 +693,9 @@ mod test {
#[test]
fn cds_compose_parse_scan() {
let rdata = Cds::new(10, SecAlg::RsaSha1, DigestAlg::Sha256, b"key");
let rdata = Cds::new(
10, SecAlg::RsaSha1, DigestAlg::Sha256, b"key"
).unwrap();
test_rdlen(&rdata);
test_compose_parse(&rdata, |parser| Cds::parse(parser));
test_scan(&["10", "RSASHA1", "2", "6b6579"], Cds::scan, &rdata);
+4 -2
View File
@@ -74,7 +74,7 @@ impl<N, D> SortedRecords<N, D> {
N: ToDname + Clone,
D: RecordData + ComposeRecordData,
Key: SigningKey,
Octets: From<Key::Signature>,
Octets: From<Key::Signature> + AsRef<[u8]>,
ApexName: ToDname + Clone,
{
let mut res = Vec::new();
@@ -154,7 +154,9 @@ impl<N, D> SortedRecords<N, D> {
name.owner().clone(),
name.class(),
rrset.ttl(),
rrsig.into_rrsig(key.sign(&buf)?.into()),
rrsig
.into_rrsig(key.sign(&buf)?.into())
.expect("long signature"),
));
}
}
+4 -2
View File
@@ -52,7 +52,8 @@ impl<'a> Key<'a> {
3,
SecAlg::EcdsaP256Sha256,
public_key,
),
)
.expect("long key"),
key: RingKey::Ecdsa(keypair),
rng,
})
@@ -82,7 +83,8 @@ impl<'a> SigningKey for Key<'a> {
self.dnskey.algorithm(),
DigestAlg::Sha256,
digest,
))
)
.expect("long digest"))
}
fn sign(&self, msg: &[u8]) -> Result<Self::Signature, Self::Error> {
+8 -2
View File
@@ -1406,6 +1406,9 @@ impl Variables {
key.name.clone(),
Class::Any,
0,
// The only reason creating TSIG record data can fail here is
// that the hmac is unreasonable large. Since we control its
// creation, panicing in this case is fine.
Tsig::new(
key.algorithm().to_dname(),
self.time_signed,
@@ -1414,7 +1417,8 @@ impl Variables {
original_id,
self.error,
other,
),
)
.expect("long MAC"),
))
}
@@ -1656,6 +1660,7 @@ impl<K: AsRef<Key>> ServerError<K> {
tsig.owner(),
tsig.class(),
tsig.ttl(),
// The TSIG record data can never ever be to long.
Tsig::new(
tsig.data().algorithm(),
tsig.data().time_signed(),
@@ -1664,7 +1669,8 @@ impl<K: AsRef<Key>> ServerError<K> {
msg.header().id(),
error,
b"",
),
)
.expect("long record data"),
))?;
}
ServerErrorInner::Signed { context, variables } => {
+27 -17
View File
@@ -382,8 +382,8 @@ mod test {
)
.unwrap();
(
Dnskey::new(257, 3, SecAlg::RsaSha256, ksk),
Dnskey::new(256, 3, SecAlg::RsaSha256, zsk),
Dnskey::new(257, 3, SecAlg::RsaSha256, ksk).unwrap(),
Dnskey::new(256, 3, SecAlg::RsaSha256, zsk).unwrap(),
)
}
@@ -398,8 +398,8 @@ mod test {
)
.unwrap();
(
Dnskey::new(257, 3, SecAlg::RsaSha256, ksk),
Dnskey::new(256, 3, SecAlg::RsaSha256, zsk),
Dnskey::new(257, 3, SecAlg::RsaSha256, ksk).unwrap(),
Dnskey::new(256, 3, SecAlg::RsaSha256, zsk).unwrap(),
)
}
@@ -415,7 +415,8 @@ mod test {
"4G1EuAuPHTmpXAsNfGXQhFjogECbvGg0VxBCN8f47I0=",
)
.unwrap(),
);
)
.unwrap();
assert_eq!(
dnskey.digest(&owner, DigestAlg::Sha256).unwrap().as_ref(),
expected.digest()
@@ -474,7 +475,7 @@ mod test {
"otBkINZAQu7AvPKjr/xWIEE7+SoZtKgF8bzVynX6bfJMJuPay8jPvNmwXkZOdSoYlvFp0bk9JWJKCh8y5uoNfMFkN6OSrDkr3t0E+c8c0Mnmwkk5CETH3Gqxthi0yyRX5T4VlHU06/Ks4zI+XAgl3FBpOc554ivdzez8YCjAIGx7XgzzooEb7heMSlLc7S7/HNjw51TPRs4RxrAVcezieKCzPPpeWBhjE6R3oiSwrl0SBD4/yplrDlr7UHs/Atcm3MSgemdyr2sOoOUkVQCVpcj3SQQezoD2tCM7861CXEQdg5fjeHDtz285xHt5HJpA5cOcctRo4ihybfow/+V7AQ==",
)
.unwrap()
);
).unwrap();
rrsig_verify_dnskey(ksk, zsk, rrsig);
// Test 1024b long key
@@ -492,7 +493,7 @@ mod test {
"j1s1IPMoZd0mbmelNVvcbYNe2tFCdLsLpNCnQ8xW6d91ujwPZ2yDlc3lU3hb+Jq3sPoj+5lVgB7fZzXQUQTPFWLF7zvW49da8pWuqzxFtg6EjXRBIWH5rpEhOcr+y3QolJcPOTx+/utCqt2tBKUUy3LfM6WgvopdSGaryWdwFJPW7qKHjyyLYxIGx5AEuLfzsA5XZf8CmpUheSRH99GRZoIB+sQzHuelWGMQ5A42DPvOVZFmTpIwiT2QaIpid4nJ7jNfahfwFrCoS+hvqjK9vktc5/6E/Mt7DwCQDaPt5cqDfYltUitQy+YA5YP5sOhINChYadZe+2N80OA+RKz0mA==",
)
.unwrap()
);
).unwrap();
rrsig_verify_dnskey(ksk, zsk, rrsig.clone());
// Test that 512b short RSA DNSKEY is not supported (too short)
@@ -501,7 +502,7 @@ mod test {
)
.unwrap();
let short_key = Dnskey::new(256, 3, SecAlg::RsaSha256, data);
let short_key = Dnskey::new(256, 3, SecAlg::RsaSha256, data).unwrap();
let err = rrsig
.verify_signed_data(&short_key, &vec![0; 100])
.unwrap_err();
@@ -520,7 +521,8 @@ mod test {
F+KkxLbxILfDLUT0rAK9iUzy1L53eKGQ==",
)
.unwrap(),
),
)
.unwrap(),
Dnskey::new(
256,
3,
@@ -530,7 +532,8 @@ mod test {
d8KqXXFJkqmVfRvMGPmM1x8fGAa2XhSA==",
)
.unwrap(),
),
)
.unwrap(),
);
let owner = Dname::from_str("cloudflare.com.").unwrap();
@@ -548,7 +551,8 @@ mod test {
zcJBLvRmofYFDAhju21p1uTfLaYHrg==",
)
.unwrap(),
);
)
.unwrap();
rrsig_verify_dnskey(ksk, zsk, rrsig);
}
@@ -563,7 +567,8 @@ mod test {
"m1NELLVVQKl4fHVn/KKdeNO0PrYKGT3IGbYseT8XcKo=",
)
.unwrap(),
),
)
.unwrap(),
Dnskey::new(
256,
3,
@@ -572,7 +577,8 @@ mod test {
"2tstZAjgmlDTePn0NVXrAHBJmg84LoaFVxzLl1anjGI=",
)
.unwrap(),
),
)
.unwrap(),
);
let owner =
@@ -592,7 +598,8 @@ mod test {
QdtgPXja7YkTaqzrYUbYk01J8ICsAA==",
)
.unwrap(),
);
)
.unwrap();
rrsig_verify_dnskey(ksk, zsk, rrsig);
}
@@ -617,7 +624,8 @@ mod test {
dg5fjeHDtz285xHt5HJpA5cOcctRo4ihybfow/+V7AQ==",
)
.unwrap(),
);
)
.unwrap();
let mut records: Vec<Record<Dname, ZoneRecordData<Vec<u8>, Dname>>> =
[&ksk, &zsk]
@@ -656,7 +664,8 @@ mod test {
vh0z2542lzMKR4Dh8uZffQ==",
)
.unwrap(),
);
)
.unwrap();
let rrsig = Rrsig::new(
Rtype::Mx,
SecAlg::RsaSha1,
@@ -673,7 +682,8 @@ mod test {
36SR5xBni8vHI=",
)
.unwrap(),
);
)
.unwrap();
let record = Record::new(
Dname::from_str("a.z.w.example.").unwrap(),
Class::In,