#![no_std]
pub use heapless_bytes::{consts, ArrayLength, Bytes};
const CONSTRUCTED: u8 = 1 << 5;
#[derive(Debug, Clone, Copy, PartialEq)]
#[repr(u8)]
pub enum Tag {
Integer = 0x02,
Sequence = CONSTRUCTED | 0x10,
}
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
}
}
type Result = core::result::Result<(), ()>;
#[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> {
pub fn new() -> Self {
Der(Bytes::new())
}
pub fn into_inner(self) -> Bytes<N> {
self.0
}
fn write_length_field(&mut self, length: usize) -> Result {
if length < 0x80 {
self.extend_from_slice(&[length as u8])
} else {
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)
}
}
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)
}
pub fn non_negative_integer(&mut self, mut integer: &[u8]) -> Result {
self.extend_from_slice(&[Tag::Integer as u8])?;
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)
}
fn nested<F>(&mut self, tag: Tag, f: F) -> Result
where
F: FnOnce(&mut Der<N>) -> Result,
{
let before = self.len();
f(self)?;
let written = self.len() - before;
type PrefixSize = consts::U12;
let mut prefix = Der::<PrefixSize>::new();
prefix.extend_from_slice(&[tag as u8])?;
prefix.write_length_field(written)?;
self.insert_slice_at(&prefix, before)
}
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 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 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(),
);
}
}