chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

39
vendor/asn1-rs/doc/DEBUG.md vendored Normal file
View File

@@ -0,0 +1,39 @@
# Debugging
To debug parsing errors, the `debug` feature can be used to print any error on stderr:
```shell
$ ./fail_debug
asn1_rs::asn1_types::sequence::Sequence ↯ Parsing failed at location:
00000000 30 81 04 00 00 0<>...
asn1_rs::asn1_types::sequence::Sequence ↯ T::from_der failed: Parsing requires 2 bytes/chars
```
In the above example, the parser tries to read a `Sequence` but input is incomplete (missing at least 2 bytes).
The `debug` feature will print errors. To add the full trace of all parsing functions, use the `trace` feature:
```shell
$ ./fail_trace
u32 ⤷ T::from_der
u32 ⤷ input (len=3, type=asn1_rs::asn1_types::any::Any)
u32 ⤶ Parsed 3 bytes, 0 remaining
u32 ⤷ Conversion to uint
u32 ↯ T::from_der failed: Parsing Error: UnexpectedTag { expected: Some(Tag(2)), actual: Tag(1) }
bool ↯ T::from_der failed: Parsing Error: DerConstraintFailed(InvalidBoolean)
```
In this example, the parser tries to read an `u32`. It is first read as `Any` with sucess, however the conversion to `u32` fails because of a wrong tag. See below for details on how to interpret output.
Note that the `trace` feature is very verbose, and can generate a huge amount of logs on large inputs.
## Interpretating output
When interpreting the trace output, knowing how `asn1-rs` works is useful. For most types, the following operations are done when parsing type `T`:
- first, the object is parsed as `Any`: this is a very quick step, header is parsed, and object length is tested
- next, DER constraint are tested for type `T` (if parsing DER)
- finally, object is converted using `T::try_from(any)`. Other type-depdendant checks are done during this step.
## Examples and
When writing a crate, the feature can be activated without changing the `Cargo.toml` file.
For example, if you want to run `example/print-cert` with trace enabled:
```shell
$ cargo run --features=asn1-rs/trace --example=print-cert -- ./assets/certificate.der
```

354
vendor/asn1-rs/doc/DERIVE.md vendored Normal file
View File

@@ -0,0 +1,354 @@
# BER/DER Custom Derive Attributes
## BER/DER Sequence parsers
### `BER`
To derive a BER `SEQUENCE` parser, add the [`BerSequence`] derive attribute to an existing struct. Parsers will be derived automatically for all fields, which must implement the [`FromBer`] trait.
For ex:
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, BerSequence)]
pub struct S {
a: u32,
b: u16,
c: u16,
}
# let parser = |input| -> Result<(), Error> {
let (rest, result) = S::from_ber(input)?;
# Ok(()) };
```
After parsing b, any bytes that were leftover and not used to fill val will be returned in `rest`.
When parsing a `SEQUENCE` into a struct, any trailing elements of the `SEQUENCE` that do
not have matching fields in val will not be included in `rest`, as these are considered
valid elements of the `SEQUENCE` and not trailing data.
### `DER`
To derive a `DER` parser, use the [`DerSequence`] custom attribute.
*Note: the `DerSequence` attributes derive both `BER` and `DER` parsers.*
## Tagged values
### `EXPLICIT`
There are several ways of parsing tagged values: either using types like [`TaggedExplicit`], or using custom annotations.
Using `TaggedExplicit` works as usual. The only drawback is that the type is visible in the structure, so accessing the value must be done using `.as_ref()` or `.into_inner()`:
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, DerSequence)]
pub struct S2 {
a: u16,
}
// test with EXPLICIT Vec
#[derive(Debug, PartialEq, DerSequence)]
pub struct S {
// a INTEGER
a: u32,
// b INTEGER
b: u16,
// c [0] EXPLICIT SEQUENCE OF S2
c: TaggedExplicit<Vec<S2>, Error, 0>,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_ber(input)?;
// Get a reference on c (type is &Vec<S2>)
let ref_c = result.c.as_ref();
# Ok(()) };
```
*Note: tags are context-specific by default. To specify other kind of tags (like `APPLICATION`) use [`TaggedValue`].*
### `tag_explicit`
To "hide" the tag from the parser, the `tag_explicit` attribute is provided. This attribute must specify the tag value (as an integer), and will automatically wrap reading the value with the specified tag.
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, DerSequence)]
pub struct S {
// a [0] EXPLICIT INTEGER
#[tag_explicit(0)]
a: u16,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_ber(input)?;
# Ok(()) };
```
This method handles transparently the encapsulation and the read of the tagged value.
*Note: tags are context-specific by default. To specify other kind of tags (like `APPLICATION`) add the tag class before the value in the `tag_explicit` attribute.*
For ex: `tag_explicit(APPLICATION 0)` or `tag_explicit(PRIVATE 2)`.
### Tagged optional values
The `optional` custom attribute can be used in addition of `tag_explicit` to specify that the value is `OPTIONAL`.
The type of the annotated field member must be resolvable to `Option`.
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, DerSequence)]
pub struct S {
// a [0] EXPLICIT INTEGER OPTIONAL
#[tag_explicit(0)]
#[optional]
a: Option<u16>,
// b INTEGER
b: u16,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_ber(input)?;
# Ok(()) };
```
### `IMPLICIT`
Tagged `IMPLICIT` values are handled similarly as for `EXPLICIT`, and can be parsed either using the [`TaggedImplicit`] type, or using the `tag_implicit` custom attribute.
For ex:
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, DerSequence)]
pub struct S {
// a [0] IMPLICIT INTEGER OPTIONAL
#[tag_implicit(0)]
#[optional]
a: Option<u16>,
// b INTEGER
b: u16,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_ber(input)?;
# Ok(()) };
```
## `OPTIONAL` values (not tagged)
The `optional` custom attribute can be specified to indicate the value is `OPTIONAL`.
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, DerSequence)]
pub struct S {
// a INTEGER
a: u16,
// b INTEGER OPTIONAL
#[optional]
b: Option<u16>,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_ber(input)?;
# Ok(()) };
```
**Important**: there are several limitations to this attribute.
In particular, the parser is eager: when an `OPTIONAL` value of some type is followed by another value (not `OPTIONAL`) of the same type, this can create problem.
If only one value is present, the parser will affect it to the first field, and then raise an error because the second is absent.
Note that this does not concern tagged optional values (unless they have the same tag).
## `DEFAULT`
The `default` custom attribute can be specified to indicate the value has a `DEFAULT` attribute. The value can also be marked as
`OPTIONAL`, but this can be omitted.
Since the value can always be obtained, the type should not be `Option<T>`, but should use `T` directly.
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, DerSequence)]
#[debug_derive]
pub struct S {
// a INTEGER
a: u16,
// b INTEGER DEFAULT 0
#[default(0_u16)]
b: u16,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_ber(input)?;
# Ok(()) };
```
Limitations are the same as for `OPTIONAL` attribute.
## Debugging
To help debugging the generated code, the `#[debug_derive]` attribute has been added.
When this attribute is specified, the generated code will be printed to `stderr` during compilation.
Example:
```rust
use asn1_rs::*;
#[derive(BerSequence)]
#[debug_derive]
struct S {
a: u32,
}
```
## BER/DER Set parsers
Parsing BER/DER `SET` objects is very similar to `SEQUENCE`. Use the [`BerSet`] and [`DerSet`] custom derive attributes on the structure, and everything else is exactly the same as for sequences (see above for documentation).
Example:
```rust
# use asn1_rs::*;
use std::collections::BTreeSet;
// `Ord` is needed because we will parse as a `BTreeSet` later
#[derive(Debug, DerSet, PartialEq, Eq, PartialOrd, Ord)]
pub struct S2 {
a: u16,
}
// test with EXPLICIT Vec
#[derive(Debug, PartialEq, DerSet)]
pub struct S {
// a INTEGER
a: u32,
// b INTEGER
b: u16,
// c [0] EXPLICIT SET OF S2
c: TaggedExplicit<BTreeSet<S2>, Error, 0>,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_ber(input)?;
// Get a reference on c (type is &BTreeSet<S2>)
let ref_c = result.c.as_ref();
# Ok(()) };
```
# Advanced
## Custom errors
Derived parsers can use the `error` attribute to specify the error type of the parser.
The custom error type must implement `From<Error>`, so the derived parsers will transparently convert errors using the [`Into`] trait.
Example:
```rust
# use asn1_rs::*;
#
#[derive(Debug, PartialEq)]
pub enum MyError {
NotYetImplemented,
}
impl From<asn1_rs::Error> for MyError {
fn from(_: asn1_rs::Error) -> Self {
MyError::NotYetImplemented
}
}
#[derive(DerSequence)]
#[error(MyError)]
pub struct T2 {
pub a: u32,
}
```
## Mapping errors
Sometimes, it is necessary to map the returned error to another type, for example when a subparser returns a different error type than the parser's, and the [`Into`] trait cannot be implemented. This is often used in combination with the `error` attribute, but can also be used alone.
The `map_err` attribute can be used to specify a function or closure to map errors. The function signature is `fn (e1: E1) -> E2`.
Example:
```rust
# use asn1_rs::*;
#
#[derive(Debug, PartialEq)]
pub enum MyError {
NotYetImplemented,
}
impl From<asn1_rs::Error> for MyError {
fn from(_: asn1_rs::Error) -> Self {
MyError::NotYetImplemented
}
}
#[derive(DerSequence)]
#[error(MyError)]
pub struct T2 {
pub a: u32,
}
// subparser returns an error of type MyError,
// which is mapped to `Error`
#[derive(DerSequence)]
pub struct T4 {
#[map_err(|_| Error::BerTypeError)]
pub a: T2,
}
```
*Note*: when deriving BER and DER parsers, errors paths are different (`TryFrom` returns the error type, while [`FromDer`] returns a [`ParseResult`]). Some code will be inserted by the `map_err` attribute to handle this transparently and keep the same function signature.
# Serialization
## BER/DER Sequence serialization
To serialize a struct to a DER `SEQUENCE`, add the [`ToDerSequence`] derive attribute to an existing struct.
Serialization will be derived automatically for all fields, which must implement the [`ToDer`] trait.
Some parser traits may be required, so also deriving parsers using [`DerSequence`] may be required.
*Note*: serialization to BER is currently not available. In most cases, DER serialization should be enough.
For ex:
```rust
# use asn1_rs::*;
#[derive(Debug, PartialEq, DerSequence, ToDerSequence)]
pub struct S {
a: u32,
b: u16,
c: u16,
}
let s = S { a: 1, b: 2, c: 3 };
let output = s.to_der_vec().expect("serialization failed");
let (_rest, result) = S::from_ber(&output).expect("parsing failed");
assert_eq!(s, result);
```
[`FromBer`]: crate::FromBer
[`FromDer`]: crate::FromDer
[`ToDer`]: crate::ToDer
[`BerSequence`]: crate::BerSequence
[`DerSequence`]: crate::DerSequence
[`BerSet`]: crate::BerSet
[`DerSet`]: crate::DerSet
[`ToDerSequence`]: crate::ToDerSequence
[`ParseResult`]: crate::ParseResult
[`TaggedExplicit`]: crate::TaggedExplicit
[`TaggedImplicit`]: crate::TaggedImplicit
[`TaggedValue`]: crate::TaggedValue

238
vendor/asn1-rs/doc/RECIPES.md vendored Normal file
View File

@@ -0,0 +1,238 @@
# Documentation: BER/DER parsing recipes
## Builtin types
Most builtin types can be parsed by calling the `from_der` or `from_der` functions (see `FromBer` and `FromDer` traits for documentation).
For ex:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = <u32>::from_der(input)?;
# Ok(()) };
```
Note: this crates makes extensive use of types annotation and turbofish operator, for example `<Type>::from_der()` or `TaggedExplicit::<u32, Error, 0>::from_der()`.
See table B-3 in <https://doc.rust-lang.org/book/appendix-02-operators.html> for reference on syntax.
## `SEQUENCE` and `SET`
The `SEQUENCE` and `SET` types are handled very similarly, so recipes will be given for `SEQUENCE`, but can be adapted to `SET` by replacing words.
### Parsing `SEQUENCE`
Usually, the sequence envelope does not need to be stored, so it just needs to be parsed to get the sequence content and parse it.
The methods [`from_ber_and_then`](crate::Sequence::from_ber_and_then()) and [`from_der_and_then`](crate::Sequence::from_der_and_then()) provide helpers for that:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = Sequence::from_ber_and_then(input, |i| {
// first item is INTEGER
let (rem, a) = u32::from_der(input)?;
// second item is OCTET STRING
let (rem, b) = <&[u8]>::from_der(input)?;
Ok((rem, (a, b)))
})?;
// result has type (u32, &[u8])
assert_eq!(result.0, 0);
assert_eq!(result.1, b"\x00\x01");
# Ok(()) };
```
### Automatically deriving sequence parsers
The [`BerSequence`](crate::BerSequence) and [`DerSequence`](crate::DerSequence)
custom derive provide attributes to automatically derive a parser for a sequence.
For ex:
```rust
# use asn1_rs::*;
#[derive(DerSequence)]
pub struct S {
a: u32,
b: u16,
c: u16,
}
# let parser = |input| -> Result<(), Error> {
let (rem, result) = S::from_der(input)?;
# Ok(()) };
```
This will work for any field type that implements [`FromBer`](crate::FromBer) or [`FromDer`](crate::FromDer), respectively.
See [`derive`](mod@derive) documentation for more examples and documentation.
### Parsing `SEQUENCE OF`
`SEQUENCE OF T` can be parsed using either type `SequenceOf<T>` or `Vec<T>`:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = SequenceOf::<u32>::from_der(input)?;
# Ok(()) };
```
or
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = <Vec<u32>>::from_der(input)?;
# Ok(()) };
```
`SET OF T` can be parsed using either `SetOf<T>`, `BTreeSet<T>` or `HashSet<T>`.
## `EXPLICIT` tagged values
### Parsing `EXPLICIT`, expecting a known tag
If you expect only a specific tag, use `TaggedExplicit`.
For ex, to parse a `[3] EXPLICIT INTEGER`:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = TaggedExplicit::<u32, Error, 0>::from_der(input)?;
// result has type TaggedValue. Use `.as_ref()` or `.into_inner()`
// to access content
let tag = result.tag();
let class = result.class();
assert_eq!(result.as_ref(), &0);
# Ok(()) };
```
### Specifying the class
`TaggedExplicit` does not check the class, and accepts any class. It expects you to check the class after reading the value.
To specify the class in the parser, use `TaggedValue`:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
// Note: the strange notation (using braces) is required by the compiler to use
// a constant instead of the numeric value.
let (rem, result) = TaggedValue::<u32, Error, Explicit, {Class::CONTEXT_SPECIFIC}, 0>::from_der(input)?;
# Ok(()) };
```
Note that `TaggedExplicit` is a type alias to `TaggedValue`, so the objects are the same.
### Accepting any `EXPLICIT` tag
To parse a value, accepting any class or tag, use `TaggedParser`.
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = TaggedParser::<Explicit, u32>::from_der(input)?;
// result has type TaggedParser. Use `.as_ref()` or `.into_inner()`
// to access content
let tag = result.tag();
let class = result.class();
assert_eq!(result.as_ref(), &0);
# Ok(()) };
```
### Optional tagged values
To parse optional tagged values, `Option<TaggedExplicit<...>>` can be used:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = Option::<TaggedExplicit::<u32, Error, 0>>::from_der(input)?;
# Ok(()) };
```
The type `OptTaggedExplicit` is also provided as an alias:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = OptTaggedExplicit::<u32, Error, 0>::from_der(input)?;
# Ok(()) };
```
## `IMPLICIT` tagged values
### Parsing `IMPLICIT`, expecting a known tag
If you expect only a specific tag, use `TaggedImplicit`.
For ex, to parse a `[3] EXPLICIT INTEGER`:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = TaggedExplicit::<u32, Error, 0>::from_der(input)?;
// result has type TaggedValue. Use `.as_ref()` or `.into_inner()`
// to access content
let tag = result.tag();
let class = result.class();
assert_eq!(result.as_ref(), &0);
# Ok(()) };
```
### Specifying the class
`TaggedImplicit` does not check the class, and accepts any class. It expects you to check the class after reading the value.
To specify the class in the parser, use `TaggedValue`:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
// Note: the strange notation (using braces) is required by the compiler to use
// a constant instead of the numeric value.
let (rem, result) = TaggedValue::<u32, Error, Implicit, { Class::CONTEXT_SPECIFIC }, 1>::from_der(input)?;
# Ok(()) };
```
Note that `TaggedImplicit` is a type alias to `TaggedValue`, so the objects are the same.
### Accepting any `IMPLICIT` tag
To parse a value, accepting any class or tag, use `TaggedParser`.
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = TaggedParser::<Implicit, u32>::from_der(input)?;
// result has type TaggedParser. Use `.as_ref()` or `.into_inner()`
// to access content
let tag = result.tag();
let class = result.class();
assert_eq!(result.as_ref(), &0);
# Ok(()) };
```
### Optional tagged values
To parse optional tagged values, `Option<TaggedImplicit<...>>` can be used:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = Option::<TaggedImplicit::<u32, Error, 0>>::from_der(input)?;
# Ok(()) };
```
The type `OptTaggedImplicit` is also provided as an alias:
```rust
# use asn1_rs::*;
# let parser = |input| -> Result<(), Error> {
let (rem, result) = OptTaggedImplicit::<u32, Error, 0>::from_der(input)?;
# Ok(()) };
```