Skip to main content

Crate structured_asn1

Crate structured_asn1 

Source
Expand description

A streaming BER/DER reader for the certificate, CMS and timestamp parsers.

What this is for, and what it deliberately is not: it reads the structure of an encoding and hands back the bytes each element occupies. It does not decide what those elements mean. A schema layer above does that, and keeping the two apart is what lets a signature be checked over the bytes as they arrived rather than over a re-encoding of what somebody understood.

Three things shape the design.

Nothing is copied. Elements borrow from the document and carry the range they occupy in it, so a caller holding one gigabyte does not become a caller holding two.

Nothing recurses. Depth is bounded by a budget the caller sets, not by the thread’s stack, so a deeply nested document is refused rather than fatal.

A refusal to finish is not a verdict about the document. Running out of budget reports ErrorCode::LimitExceeded, which is distinct from every code that says the bytes are malformed, because telling somebody their document is broken when the truth is that this device gave up is a different statement and a worse one.

use std::sync::Arc;
use structured_asn1::{Parser, Tag, universal};
use structured_asn1::memory::{Memory, MemoryAccount};

// SEQUENCE { INTEGER 1 }
let document = [0x30, 0x03, 0x02, 0x01, 0x01];

let memory = Memory::new(Arc::new(MemoryAccount::new(1024, 1024)));
let parser = Parser::der(memory);
let mut reader = parser.read(&document, 0)?;

let sequence = reader.expect(Tag::constructed(universal::SEQUENCE))?;
let mut inside = reader.enter(&sequence)?;

let integer = inside.expect(Tag::primitive(universal::INTEGER))?;
assert_eq!(integer.contents(), &[0x01]);

// The range the value occupies in the document, for a signature to cover.
assert_eq!(integer.span().start, 2);
assert_eq!(integer.span().length, 3);

Re-exports§

pub use error::Error;
pub use error::ErrorCode;
pub use error::Limit;
pub use error::Path;
pub use error::Result;
pub use length::Encoding;
pub use length::Length;
pub use limits::Limits;
pub use reader::Element;
pub use reader::IntegerReading;
pub use reader::Parser;
pub use reader::Reader;
pub use reader::Span;
pub use tag::Class;
pub use tag::Tag;
pub use tag::universal;
pub use value::Arcs;
pub use value::BitString;
pub use value::Integer;
pub use value::Oid;
pub use value::OwnedOid;

Modules§

error
What went wrong, where, and under which element.
length
Length octets, in both the definite and the indefinite form.
limits
What the caller is willing to spend on one parse.
memory
Shared storage accounting for independently owned results.
reader
Reading elements in sequence, and descending into the constructed ones.
tag
Identifier octets: the class, whether the element is constructed, and the number.
value
The contents of primitive elements, read without copying them.