blob: 5f6a31dd8b395cec6a048cbfcacefe44611398df [file] [log] [blame]
//! Helper for writing ASN.1
use ring;
use std::io::{self, Write};
use untrusted::Input;
use der::Tag;
pub struct Asn1<'a, W: Write + 'a> {
writer: &'a mut W,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Error;
impl From<ring::error::Unspecified> for Error {
fn from(_: ring::error::Unspecified) -> Error {
Error
}
}
impl From<io::Error> for Error {
fn from(_: io::Error) -> Error {
Error
}
}
impl<'a, W: Write> Asn1<'a, W> {
pub fn new(writer: &'a mut W) -> Self {
Asn1 { writer: writer }
}
fn length_of_length(len: usize) -> u8 {
let mut i = len;
let mut num_bytes = 1;
while i > 255 {
num_bytes += 1;
i >>= 8;
}
num_bytes
}
fn write_len(&mut self, len: usize) -> Result<(), Error> {
if len >= 128 {
let n = Self::length_of_length(len);
self.writer.write_all(&[0x80 | n])?;
for i in (1..n + 1).rev() {
self.writer.write_all(&[(len >> ((i - 1) * 8)) as u8])?;
}
} else {
self.writer.write_all(&[len as u8])?;
}
Ok(())
}
pub fn write_integer(&mut self, input: Input) -> Result<(), Error> {
self.writer.write_all(&[Tag::Integer as u8])?;
let mut buf = Vec::new();
input.read_all(Error, |read| {
while let Ok(byte) = read.read_byte() {
buf.push(byte);
}
Ok(())
})?;
self.write_len(buf.len())?;
Ok(self.writer.write_all(&mut buf)?)
}
pub fn write_sequence<F: FnOnce(&mut Asn1<Vec<u8>>) -> Result<(), Error>>
(&mut self,
func: F)
-> Result<(), Error> {
self.writer.write_all(&[Tag::Sequence as u8])?;
let mut buf = Vec::new();
{
let mut inner = Asn1::new(&mut buf);
func(&mut inner)?;
}
self.write_len(buf.len())?;
Ok(self.writer.write_all(&buf)?)
}
}