1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
use crate::{ Asn1DerError, Source, Sink, error::ErrorChain };


/// A mod for ASN.1-length-coding
#[doc(hidden)]
pub mod length {
	use crate::{ Asn1DerError, Source, Sink, rust::mem };
	use crate::error::ErrorChain;
	
	/// The byte length of an `usize`
	const SIZE: usize = mem::size_of::<usize>();
	
	/// Tries to read the length or returns `None` if there are not enough bytes
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	#[cfg_attr(feature = "no_panic", inline(always))]
	pub fn decode<S: Source>(source: &mut S) -> Result<usize, Asn1DerError> {
		// Read first byte
		let first = source.read().propagate(e!("Failed to read length byte"))?;
		
		// Check if we have a simple or a complex length
		match first as usize {
			len if len < 0b1000_0000 => Ok(len),
			size if size & 0b0111_1111 > SIZE =>
				Err(eunsupported!("The object length is greater than `usize::max_value()`")),
			size => {
				// Prepare buffer
				let skip = SIZE - (size & 0b0111_1111);
				let mut buf = [0u8; SIZE];
				
				// Read the complex length bytes
				buf.iter_mut().skip(skip).try_for_each(|t| {
					let b = source.read().propagate(e!("Failed to read length"))?;
					Ok(*t = b)
				})?;
				
				// Validate the length
				match usize::from_be_bytes(buf) {
					len if len < 0b1000_0000 => Err(einval!("Encountered complex length < 128"))?,
					len => Ok(len)
				}
			}
		}
	}
	
	/// Encodes `len` to `sink` and returns the amount of
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	#[cfg_attr(feature = "no_panic", inline(always))]
	pub fn encode<S: Sink>(len: usize, sink: &mut S) -> Result<(), Asn1DerError> {
		match len {
			// Write simple length
			len if len < 128 => sink.write(len as u8).propagate(e!("Failed to write length byte")),
			// Encode complex length
			len => {
				// Compute the size of the length (without the complex length header byte)
				// #implicit_validation: Since the amount of leading zero bytes cannot be larger
				// than the amount of bytes in an `usize` (aka `SIZE`), both subtractions cannot
				// overflow so a `saturating_sub` is safe
				let size = SIZE.saturating_sub(len.leading_zeros() as usize / 8);
				let skip = SIZE.saturating_sub(size);
				
				// Write the length
				sink.write(0x80 | size as u8).propagate(e!("Failed to write length byte"))?;
				len.to_be_bytes().iter().skip(skip).try_for_each(|b| {
					sink.write(*b).propagate(e!("Failed to write length byte"))
				})
			}
		}
	}
}


/// An untyped DER object
#[derive(Copy, Clone)]
pub struct DerObject<'a> {
	raw: &'a[u8],
	header: &'a[u8],
	tag: u8,
	value: &'a[u8]
}
impl<'a> DerObject<'a> {
	/// Writes a new DER object with `tag` and `value` into `sink` and returns a view over it
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn new<S: Sink + Into<&'a[u8]>>(tag: u8, value: &[u8], sink: S)
		-> Result<Self, Asn1DerError>
	{
		Self::new_from_source(tag, value.len(), &mut value.iter(), sink)
	}
	/// Writes a new DER object with `tag`, `len` and `value` into `sink` and returns a view over it
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn new_from_source<A: Source, B: Sink + Into<&'a[u8]>>(tag: u8, len: usize, value: &mut A,
		mut sink: B) -> Result<Self, Asn1DerError>
	{
		Self::write(tag, len, value, &mut sink).propagate(e!("Failed to construct boolean"))?;
		DerObject::decode(sink.into()).propagate(e!("Failed to load constructed object"))
	}
	
	
	/// Decodes an object from `raw`
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn decode(raw: &'a[u8]) -> Result<Self, Asn1DerError> {
		Self::decode_at(raw, 0)
	}
	/// Decodes an object from `&raw[header_start..]`
	#[doc(hidden)]
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn decode_at(raw: &'a[u8], header_start: usize) -> Result<Self, Asn1DerError> {
		// Create iterator
		let mut value_start = header_start;
		let mut iter = raw.iter().skip(header_start).counting_source(&mut value_start);
		
		// Skip tag and read length
		let tag = iter.read().propagate(e!("Failed to read tag"))?;
		let len = length::decode(&mut iter).propagate(e!("Failed to decode length"))?;
		let value_end = match value_start.checked_add(len) {
			Some(value_end) => value_end,
			None => Err(eunsupported!("The object bounds would exceed `usize::max_value()`"))?
		};
		
		// Get the header slice
		let header = match raw.len() {
			len if len >= value_start => &raw[..value_start],
			_ => Err(eio!("The object is truncated"))?
		};
		let header = match header.len() {
			len if len >= header_start => &header[header_start..],
			_ => Err(eio!("The object is truncated"))?
		};
		
		// Get the value slice
		let value = match raw.len() {
			len if len >= value_end => &raw[..value_end],
			_ => Err(eio!("The object is truncated"))?
		};
		let value = match value.len() {
			len if len >= value_start => &value[value_start..],
			_ => Err(eio!("The object is truncated"))?
		};
		
		Ok(Self{ raw, header, tag, value })
	}
	/// Reads a DER-TLV structure from `source` by parsing the length field and copying the
	/// necessary bytes into `sink` and returns a view over it
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn decode_from_source<A: Source, B: Sink + Into<&'a[u8]>>(source: &mut A, mut sink: B)
		-> Result<Self, Asn1DerError>
	{
		// Create a copying iterator and copy the tag
		let mut source = source.copying_source(&mut sink);
		let _ = source.copy_next().propagate(e!("Failed to read tag"))?;
		
		// Read the length and copy the value
		let len = length::decode(&mut source).propagate(e!("Failed to decode length"))?;
		source.copy_n(len).propagate(e!("Failed to copy object value"))?;
		
		// Load the object
		Self::decode(sink.into()).propagate(e!("Failed to decode object"))
	}
	
	
	/// The underlying raw slice
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn raw(self) -> &'a[u8] {
		self.raw
	}
	/// The object header
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn header(self) -> &'a[u8] {
		self.header
	}
	/// The object tag
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn tag(self) -> u8 {
		self.tag
	}
	/// The object value
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn value(self) -> &'a[u8] {
		self.value
	}
	
	
	/// Encodes `self` to `sink`
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn encode<U: Sink>(&self, sink: &mut U) -> Result<(), Asn1DerError> {
		Self::write(self.tag, self.value.len(), &mut self.value.iter(), sink)
			.propagate(e!("Failed to write DER object"))
	}
	
	
	/// Writes a `tag`-`len`-`value` combination as DER-TLV structure into `sink`
	#[doc(hidden)]
	#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
	pub fn write<A: Source, B: Sink>(tag: u8, len: usize, value: &mut A, sink: &mut B)
		-> Result<(), Asn1DerError>
	{
		sink.write(tag).propagate(e!("Failed to write tag"))?;
		length::encode(len, sink).propagate(e!("Failed to write length"))?;
		value.copying_source(sink).copy_n(len).propagate(e!("Failed to write value"))
	}
}