Skip to content

Commit

Permalink
const-oid: make ObjectIdentifier::as_bytes a const fn
Browse files Browse the repository at this point in the history
Also bumps MSRV to 1.71 due to the const use of `[u8]::split_at`.

Additionally makes the internal `Encoder` type const generic around the
size of the output buffer.
  • Loading branch information
tarcieri committed Jan 5, 2024
1 parent 09fcf93 commit 103c97b
Show file tree
Hide file tree
Showing 24 changed files with 104 additions and 95 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/const-oid.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
strategy:
matrix:
rust:
- 1.60.0 # MSRV
- 1.71.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand All @@ -47,7 +47,7 @@ jobs:
strategy:
matrix:
rust:
- 1.60.0 # MSRV
- 1.71.0 # MSRV
- stable
steps:
- uses: actions/checkout@v4
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/der.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand All @@ -51,7 +51,7 @@ jobs:
# 32-bit Linux
- targets: i686-unknown-linux-gnu
platform: ubuntu-latest
rust: 1.65.0 # MSRV
rust: 1.71.0 # MSRV
deps: sudo apt update && sudo apt install gcc-multilib
- targets: i686-unknown-linux-gnu
platform: ubuntu-latest
Expand All @@ -61,7 +61,7 @@ jobs:
# 64-bit Linux
- targets: x86_64-unknown-linux-gnu
platform: ubuntu-latest
rust: 1.65.0 # MSRV
rust: 1.71.0 # MSRV
- targets: x86_64-unknown-linux-gnu
platform: ubuntu-latest
rust: stable
Expand All @@ -70,7 +70,7 @@ jobs:
# 64-bit Windows
#- targets: x86_64-pc-windows-msvc
# platform: windows-latest
# rust: 1.65.0 # MSRV
# rust: 1.71.0 # MSRV
#- targets: x86_64-pc-windows-msvc
# platform: windows-latest
# rust: stable
Expand All @@ -90,7 +90,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pkcs1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand All @@ -52,7 +52,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pkcs5.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand All @@ -51,7 +51,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pkcs8.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand All @@ -53,7 +53,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/sec1.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
strategy:
matrix:
rust:
- 1.70.0 # MSRV
- 1.71.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand All @@ -52,7 +52,7 @@ jobs:
strategy:
matrix:
rust:
- 1.70.0 # MSRV
- 1.71.0 # MSRV
- stable
steps:
- uses: actions/checkout@v4
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/spki.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand All @@ -51,7 +51,7 @@ jobs:
strategy:
matrix:
rust:
- 1.65.0 # MSRV
- 1.71.0 # MSRV
- stable
steps:
- uses: actions/checkout@v4
Expand Down
2 changes: 1 addition & 1 deletion const-oid/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ categories = ["cryptography", "data-structures", "encoding", "no-std", "parser-i
keywords = ["iso", "iec", "itu", "oid"]
readme = "README.md"
edition = "2021"
rust-version = "1.60"
rust-version = "1.71"

[dependencies]
arbitrary = { version = "1.2", optional = true, features = ["derive"] }
Expand Down
4 changes: 2 additions & 2 deletions const-oid/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ well as a runtime OID library.

## Minimum Supported Rust Version

This crate requires **Rust 1.65** at a minimum.
This crate requires **Rust 1.71** at a minimum.

We may change the MSRV in the future, but it will be accompanied by a minor
version bump.
Expand All @@ -84,7 +84,7 @@ dual licensed as above, without any additional terms or conditions.
[docs-image]: https://docs.rs/const-oid/badge.svg
[docs-link]: https://docs.rs/const-oid/
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.65+-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.71+-blue.svg
[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg
[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/300570-formats
[build-image]: https://github.com/RustCrypto/formats/workflows/const-oid/badge.svg?branch=master&event=push
Expand Down
4 changes: 2 additions & 2 deletions const-oid/src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ pub struct Buffer<const SIZE: usize> {

impl<const SIZE: usize> Buffer<SIZE> {
/// Borrow the inner byte slice.
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[..self.length as usize]
pub const fn as_bytes(&self) -> &[u8] {
self.bytes.split_at(self.length as usize).0
}

/// Get the length of the BER message.
Expand Down
14 changes: 7 additions & 7 deletions const-oid/src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use crate::{

/// BER/DER encoder
#[derive(Debug)]
pub(crate) struct Encoder {
pub(crate) struct Encoder<const MAX_SIZE: usize> {
/// Current state
state: State,

/// Bytes of the OID being encoded in-progress
bytes: [u8; ObjectIdentifier::MAX_SIZE],
bytes: [u8; MAX_SIZE],

/// Current position within the byte buffer
cursor: usize,
Expand All @@ -31,18 +31,18 @@ enum State {
Body,
}

impl Encoder {
impl<const MAX_SIZE: usize> Encoder<MAX_SIZE> {
/// Create a new encoder initialized to an empty default state.
pub(crate) const fn new() -> Self {
Self {
state: State::Initial,
bytes: [0u8; ObjectIdentifier::MAX_SIZE],
bytes: [0u8; MAX_SIZE],
cursor: 0,
}
}

/// Extend an existing OID.
pub(crate) const fn extend(oid: ObjectIdentifier) -> Self {
pub(crate) const fn extend(oid: ObjectIdentifier<MAX_SIZE>) -> Self {
Self {
state: State::Body,
bytes: oid.buffer.bytes,
Expand Down Expand Up @@ -99,7 +99,7 @@ impl Encoder {
}

/// Finish encoding an OID.
pub(crate) const fn finish(self) -> Result<ObjectIdentifier> {
pub(crate) const fn finish(self) -> Result<ObjectIdentifier<MAX_SIZE>> {
if self.cursor >= 2 {
let bytes = Buffer {
bytes: self.bytes,
Expand Down Expand Up @@ -156,7 +156,7 @@ mod tests {

#[test]
fn encode() {
let encoder = Encoder::new();
let encoder = Encoder::<7>::new();
let encoder = encoder.arc(1).unwrap();
let encoder = encoder.arc(2).unwrap();
let encoder = encoder.arc(840).unwrap();
Expand Down
89 changes: 49 additions & 40 deletions const-oid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,50 +146,15 @@ impl ObjectIdentifier {

Ok(oid)
}

/// Get the parent OID of this one (if applicable).
pub fn parent(&self) -> Option<Self> {
let num_arcs = self.len().checked_sub(1)?;
Self::from_arcs(self.arcs().take(num_arcs)).ok()
}

/// Push an additional arc onto this OID, returning the child OID.
pub const fn push_arc(self, arc: Arc) -> Result<Self> {
// TODO(tarcieri): use `?` when stable in `const fn`
match Encoder::extend(self).arc(arc) {
Ok(encoder) => encoder.finish(),
Err(err) => Err(err),
}
}

/// Does this OID start with the other OID?
pub fn starts_with(&self, other: ObjectIdentifier) -> bool {
let mut self_arcs = self.arcs();

for other_arc in other.arcs() {
match self_arcs.next() {
Some(arc) => {
if arc != other_arc {
return false;
}
}
None => {
return false;
}
}
}

true
}
}

impl<const MAX_SIZE: usize> ObjectIdentifier<MAX_SIZE> {
/// Get the BER/DER serialization of this OID as bytes.
///
/// Note that this encoding omits the tag/length, and only contains the
/// value portion of the encoded OID.
pub fn as_bytes(&self) -> &[u8] {
self.buffer.as_ref()
/// Note that this encoding omits the tag/length, and only contains the value portion of the
/// encoded OID.
pub const fn as_bytes(&self) -> &[u8] {
self.buffer.as_bytes()
}

/// Return the arc with the given index, if it exists.
Expand All @@ -208,11 +173,55 @@ impl<const MAX_SIZE: usize> ObjectIdentifier<MAX_SIZE> {
pub fn len(&self) -> usize {
self.arcs().count()
}

/// Get the parent OID of this one (if applicable).
pub fn parent(&self) -> Option<Self> {
let num_arcs = self.len().checked_sub(1)?;
let mut encoder = Encoder::new();

for arc in self.arcs().take(num_arcs) {
encoder = encoder.arc(arc).ok()?;
}

encoder.finish().ok()
}

/// Push an additional arc onto this OID, returning the child OID.
pub const fn push_arc(self, arc: Arc) -> Result<Self> {
// TODO(tarcieri): use `?` when stable in `const fn`
match Encoder::extend(self).arc(arc) {
Ok(encoder) => encoder.finish(),
Err(err) => Err(err),
}
}

/// Does this OID start with the other OID?
pub const fn starts_with(&self, other: ObjectIdentifier) -> bool {
let len = other.as_bytes().len();

if self.as_bytes().len() < len {
return false;
}

let mut i = 0;
while i < len {
if self.as_bytes()[i] != other.as_bytes()[i] {
return false;
}

match i.checked_add(1) {
Some(succ) => i = succ,
None => return false,
}
}

true
}
}

impl<const MAX_SIZE: usize> AsRef<[u8]> for ObjectIdentifier<MAX_SIZE> {
fn as_ref(&self) -> &[u8] {
self.as_bytes()
self.buffer.as_bytes()
}
}

Expand Down
2 changes: 1 addition & 1 deletion const-oid/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) struct Parser {
current_arc: Arc,

/// BER/DER encoder
encoder: Encoder,
encoder: Encoder<{ ObjectIdentifier::MAX_SIZE }>,
}

impl Parser {
Expand Down
2 changes: 1 addition & 1 deletion der/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ categories = ["cryptography", "data-structures", "encoding", "no-std", "parser-i
keywords = ["asn1", "crypto", "itu", "pkcs"]
readme = "README.md"
edition = "2021"
rust-version = "1.65"
rust-version = "1.71"

[dependencies]
arbitrary = { version = "1.3", features = ["derive"], optional = true }
Expand Down
Loading

0 comments on commit 103c97b

Please sign in to comment.