From c33291b244cd17e3720cac0d173ffdb316847d83 Mon Sep 17 00:00:00 2001 From: Harris Kaufmann Date: Sun, 3 Aug 2025 00:02:50 +0200 Subject: [PATCH 1/3] der: add `new` and derives to SequenceRef --- der/src/asn1/sequence.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/der/src/asn1/sequence.rs b/der/src/asn1/sequence.rs index 9b7c8a70b..2013a5660 100644 --- a/der/src/asn1/sequence.rs +++ b/der/src/asn1/sequence.rs @@ -2,8 +2,8 @@ //! `SEQUENCE`s to Rust structs. use crate::{ - BytesRef, DecodeValue, EncodeValue, Error, FixedTag, Header, Length, Reader, Result, Tag, - Writer, + BytesRef, DecodeValue, EncodeValue, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, + Tag, Writer, }; #[cfg(feature = "alloc")] @@ -28,12 +28,20 @@ impl<'a, T> Sequence<'a> for Box where T: Sequence<'a> {} /// DER-encoded `SEQUENCE`. /// /// This is a zero-copy reference type which borrows from the input data. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] pub struct SequenceRef<'a> { /// Body of the `SEQUENCE`. body: &'a BytesRef, } impl<'a> SequenceRef<'a> { + /// Create a new [`SequenceRef`] from the provided DER bytes. + pub fn new(slice: &'a [u8]) -> Result { + BytesRef::new(slice) + .map(|body| Self { body }) + .map_err(|_| ErrorKind::Length { tag: Self::TAG }.into()) + } + /// Borrow the inner byte slice. pub fn as_bytes(&self) -> &'a [u8] { self.body.as_slice() From 3ac2a6b218f4255c5bbbeb831f1ff7c203721643 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Fri, 22 Aug 2025 13:31:06 +0200 Subject: [PATCH 2/3] der: add test for derive Sequence with IMPLICIT SequenceRef --- der/tests/derive.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/der/tests/derive.rs b/der/tests/derive.rs index b94748b26..def6d7c52 100644 --- a/der/tests/derive.rs +++ b/der/tests/derive.rs @@ -278,7 +278,7 @@ mod sequence { use core::marker::PhantomData; use der::{ Decode, Encode, Sequence, ValueOrd, - asn1::{AnyRef, ObjectIdentifier, SetOf}, + asn1::{AnyRef, ObjectIdentifier, SequenceRef, SetOf}, }; use hex_literal::hex; @@ -723,6 +723,28 @@ mod sequence { algorithm_identifier.to_der().unwrap() ); } + + #[derive(Debug, Sequence)] + pub struct OidAndImplicitSequence<'a> { + pub oid: ObjectIdentifier, + #[asn1(context_specific = "0", tag_mode = "IMPLICIT")] + pub data: SequenceRef<'a>, + } + + #[test] + fn roundtrip_oid_and_implicit_sequence() { + let obj_data: &[u8] = &hex!( + "30 09" // SEQUENCE + "06 03" // OBJECT IDENTIFIER + "29 01 01" // oid "1.1.1.1" + "A0 02" // CONTEXT-SPECIFIC [0] (constructed) + "AA BB" + ); + let obj = OidAndImplicitSequence::from_der(obj_data).unwrap(); + + assert_eq!(obj.data.as_bytes(), &hex!("AA BB")); + assert_eq!(obj_data, &obj.to_der().unwrap()); + } } /// Custom derive test cases for the `EncodeValue` macro. From 88ebffbd976e0bb4f3e5e72c414e2b962ba2d125 Mon Sep 17 00:00:00 2001 From: dishmaker <141624503+dishmaker@users.noreply.github.com> Date: Sun, 24 Aug 2025 12:52:27 +0200 Subject: [PATCH 3/3] der: docs: SequenceRef::new --- der/src/asn1/sequence.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/der/src/asn1/sequence.rs b/der/src/asn1/sequence.rs index 2013a5660..62d160d02 100644 --- a/der/src/asn1/sequence.rs +++ b/der/src/asn1/sequence.rs @@ -35,7 +35,7 @@ pub struct SequenceRef<'a> { } impl<'a> SequenceRef<'a> { - /// Create a new [`SequenceRef`] from the provided DER bytes. + /// Create a new [`SequenceRef`] from the DER bytes of the inner value. pub fn new(slice: &'a [u8]) -> Result { BytesRef::new(slice) .map(|body| Self { body })