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 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
#![no_std] pub use heapless_bytes::{consts, ArrayLength, Bytes}; const CONSTRUCTED: u8 = 1 << 5; // const CONTEXT_SPECIFIC: u8 = 2 << 6; /// ASN.1 Tags #[derive(Debug, Clone, Copy, PartialEq)] #[repr(u8)] pub enum Tag { // Eoc = 0x00, // Boolean = 0x01, Integer = 0x02, // BitString = 0x03, // OctetString = 0x04, // Null = 0x05, // Oid = 0x06, Sequence = CONSTRUCTED | 0x10, // UtcTime = 0x17, // GeneralizedTime = 0x18, // ContextSpecificConstructed0 = CONTEXT_SPECIFIC | CONSTRUCTED | 0, // ContextSpecificConstructed1 = CONTEXT_SPECIFIC | CONSTRUCTED | 1, // ContextSpecificConstructed2 = CONTEXT_SPECIFIC | CONSTRUCTED | 2, // ContextSpecificConstructed3 = CONTEXT_SPECIFIC | CONSTRUCTED | 3, } impl From<Tag> for usize { fn from(tag: Tag) -> Self { tag as Self } } impl From<Tag> for u8 { fn from(tag: Tag) -> Self { tag as Self } } // the only error is buffer overflow type Result = core::result::Result<(), ()>; /// DER writer #[derive(Debug)] pub struct Der<N>(Bytes<N>) where N: ArrayLength<u8>; impl<N: ArrayLength<u8>> Default for Der<N> { fn default() -> Self { Self::new() } } impl<N: ArrayLength<u8>> core::ops::Deref for Der<N> { type Target = Bytes<N>; fn deref(&self) -> &Self::Target { &self.0 } } impl<N: ArrayLength<u8>> core::ops::DerefMut for Der<N> { fn deref_mut(&mut self) -> &mut Bytes<N> { &mut self.0 } } impl<N: ArrayLength<u8>> Der<N> { /// Create a new `Der` structure that writes values to the given buffer pub fn new() -> Self { Der(Bytes::new()) } // // equivalent of method in std::io::Write // fn write_all(&mut self, data: &[u8]) -> Result { // self.0.extend_from_slice(data) // } /// Return underlying buffer pub fn into_inner(self) -> Bytes<N> { self.0 } // https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-encoded-length-and-value-bytes fn write_length_field(&mut self, length: usize) -> Result { if length < 0x80 { // values under 128: write length directly as u8 self.extend_from_slice(&[length as u8]) } else { // values at least 128: // - write number of bytes needed as u8, setting bit 7 // - write l as big-endian bytes representation, with minimal length let mut repr = &length.to_be_bytes()[..]; while repr[0] == 0 { repr = &repr[1..]; } self.extend_from_slice(&[0x80 | repr.len() as u8])?; self.extend_from_slice(repr) } } // // /// Write a `NULL` tag. // // pub fn null(&mut self) -> Result { // // self.0.extend_from_slice(&[Tag::Null as u8, 0])?; // // Ok(()) // // } /// Write an arbitrary tag-length-value pub fn raw_tlv(&mut self, tag: Tag, value: &[u8]) -> Result { self.extend_from_slice(&[tag as u8])?; self.write_length_field(value.len())?; self.extend_from_slice(value) } /// Write the given input as integer. /// /// Assumes `input` is the big-endian representation of a non-negative `Integer` /// /// Not sure about good references, maybe: /// https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-integer /// /// From: https://docs.rs/ecdsa/0.3.0/src/ecdsa/convert.rs.html#205-219 /// Compute ASN.1 DER encoded length for the provided scalar. /// The ASN.1 encoding is signed, so its leading bit must have value 0; /// it must also be of minimal length (so leading bytes of value 0 must be /// removed, except if that would contradict the rule about the sign bit). pub fn non_negative_integer(&mut self, mut integer: &[u8]) -> Result { self.extend_from_slice(&[Tag::Integer as u8])?; // strip leading zero bytes while !integer.is_empty() && integer[0] == 0 { integer = &integer[1..]; } if integer.is_empty() || integer[0] >= 0x80 { self.write_length_field(integer.len() + 1)?; self.extend_from_slice(&[0x00])?; } else { self.write_length_field(integer.len())?; } self.extend_from_slice(integer) } /// Write a nested structure by passing in a handling function that writes /// the serialized intermediate structure. fn nested<F>(&mut self, tag: Tag, f: F) -> Result where F: FnOnce(&mut Der<N>) -> Result, { let before = self.len(); // serialize the nested structure f(self)?; let written = self.len() - before; // generate Tag-Length prefix // 1 for tag, 1 for length prefix, 4 or 8 for usize itself // // could try something like: type PrefixSize =<consts::U2 as core::ops::Add<consts::U8>>::Output; // but not couldn't find a consts::Usize type; type PrefixSize = consts::U12; let mut prefix = Der::<PrefixSize>::new(); // generate prefix consisting of "tag" and length of nested structure prefix.extend_from_slice(&[tag as u8])?; prefix.write_length_field(written)?; self.insert_slice_at(&prefix, before) } /// Write a `SEQUENCE` by passing in a handling function that writes to an intermediate `Vec` /// before writing the whole sequence to `self`. pub fn sequence<F>(&mut self, f: F) -> Result where F: FnOnce(&mut Der<N>) -> Result, { self.nested(Tag::Sequence, f) } } #[cfg(test)] mod test { use super::*; // #[test] // fn max_prefix() { // let mut u32_buf = [0u8; core::mem::size_of::<u32>() + 2]; // let mut prefix = Der::new(&mut u32_buf); // prefix.0.extend_from_slice(&[0u8]).unwrap(); // assert!(prefix.write_length_field(u32::max_value() as usize).is_ok()); // assert_eq!([0u8, 132, 255, 255, 255, 255], prefix.as_ref()); // let mut u64_buf = [0u8; core::mem::size_of::<u64>() + 2]; // let mut prefix = Der::new(&mut u64_buf); // prefix.0.extend_from_slice(&[0u8]).unwrap(); // assert!(prefix.write_length_field(u64::max_value() as usize).is_ok()); // assert_eq!([0, 136, 255, 255, 255, 255, 255, 255, 255, 255], prefix.as_ref()); // } #[test] fn write_asn1_der_ecdsa_signature() { let r = [ 167u8, 156, 58, 251, 253, 197, 176, 208, 165, 146, 155, 16, 217, 152, 192, 243, 206, 76, 214, 207, 207, 180, 237, 8, 156, 160, 64, 32, 147, 82, 213, 158, ]; let s = [ 184, 156, 136, 100, 87, 142, 84, 61, 235, 27, 193, 223, 254, 97, 11, 111, 80, 37, 46, 150, 121, 96, 165, 96, 65, 242, 211, 180, 175, 91, 158, 88, ]; // let mut buf = [0u8; 1024]; let mut der = Der::<consts::U1024>::new(); der.sequence(|der| { der.non_negative_integer(&r)?; der.non_negative_integer(&s) }) .unwrap(); #[rustfmt::skip] let expected = [ 48u8, 70, 2, 33, 0, 167, 156, 58, 251, 253, 197, 176, 208, 165, 146, 155, 16, 217, 152, 192, 243, 206, 76, 214, 207, 207, 180, 237, 8, 156, 160, 64, 32, 147, 82, 213, 158, 2, 33, 0, 184, 156, 136, 100, 87, 142, 84, 61, 235, 27, 193, 223, 254, 97, 11, 111, 80, 37, 46, 150, 121, 96, 165, 96, 65, 242, 211, 180, 175, 91, 158, 88, ]; assert_eq!(der.len(), expected.len()); assert_eq!( Bytes::<consts::U72>::try_from_slice(&der).unwrap(), Bytes::<consts::U72>::try_from_slice(&expected).unwrap(), ); // assert_eq!(&got[..32], &expected[..32]); // assert_eq!(&got[32..64], &expected[32..64]); // assert_eq!(&got[64..], &expected[64..]); } } //// let mut der = Der::new(&mut buf); //// der.sequence(|der| { //// der.positive_integer(n)?; //// der.positive_integer(e) //// }) //// .unwrap(); //// /// Write an `OBJECT IDENTIFIER`. //// pub fn oid(&mut self, input: &[u8]) -> Result<()> { //// self.writer.0.extend_from_slice(&[Tag::Oid as u8])?; //// self.write_length_field(input.len())?; //// self.writer.0.extend_from_slice(&input)?; //// Ok(()) //// } //// /// Write raw bytes to `self`. This does not calculate length or apply. This should only be used //// /// when you know you are dealing with bytes that are already DER encoded. //// pub fn raw(&mut self, input: &[u8]) -> Result<()> { //// Ok(self.writer.0.extend_from_slice(input)?) //// } //// /// Write a `BIT STRING`. //// pub fn bit_string(&mut self, unused_bits: u8, bit_string: &[u8]) -> Result<()> { //// self.writer.0.extend_from_slice(&[Tag::BitString as u8])?; //// self.write_length_field(bit_string.len() + 1)?; //// self.writer.0.extend_from_slice(&[unused_bits])?; //// self.writer.0.extend_from_slice(&bit_string)?; //// Ok(()) //// } //// /// Write an `OCTET STRING`. //// pub fn octet_string(&mut self, octet_string: &[u8]) -> Result<()> { //// self.writer.0.extend_from_slice(&[Tag::OctetString as u8])?; //// self.write_length_field(octet_string.len())?; //// self.writer.0.extend_from_slice(&octet_string)?; //// Ok(()) //// } //// } //// #[cfg(test)] //// mod test { //// use super::*; //// use untrusted::Input; //// use Error; //// static RSA_2048_PKCS1: &'static [u8] = include_bytes!("../tests/rsa-2048.pkcs1.der"); //// #[test] //// fn write_pkcs1() { //// let input = Input::from(RSA_2048_PKCS1); //// let (n, e) = input //// .read_all(Error::Read, |input| { //// der::nested(input, Tag::Sequence, |input| { //// let n = der::positive_integer(input)?; //// let e = der::positive_integer(input)?; //// Ok((n.as_slice_less_safe(), e.as_slice_less_safe())) //// }) //// }) //// .unwrap(); //// let mut buf = Vec::new(); //// { //// let mut der = Der::new(&mut buf); //// der.sequence(|der| { //// der.positive_integer(n)?; //// der.positive_integer(e) //// }) //// .unwrap(); //// } //// assert_eq!(buf.as_slice(), RSA_2048_PKCS1); //// } //// #[test] //// fn write_octet_string() { //// let mut buf = Vec::new(); //// { //// let mut der = Der::new(&mut buf); //// der.octet_string(&[]).unwrap(); //// } //// assert_eq!(&buf, &[0x04, 0x00]); //// let mut buf = Vec::new(); //// { //// let mut der = Der::new(&mut buf); //// der.octet_string(&[0x0a, 0x0b, 0x0c]).unwrap(); //// } //// assert_eq!(&buf, &[0x04, 0x03, 0x0a, 0x0b, 0x0c]); //// } //// }