Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions const-oid/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,20 @@ pub use crate::{
use crate::encoder::Encoder;
use core::{borrow::Borrow, fmt, ops::Deref, str::FromStr};

/// Default maximum size.
/// Default maximum size: the largest BER/DER contents RFC 5280 Appendix B
/// requires implementations to accept.
///
/// Makes `ObjectIdentifier` 40-bytes total w\ 1-byte length.
const DEFAULT_MAX_SIZE: usize = 39;
/// Appendix B mandates support for OIDs with at most 20 arcs, every arc below
/// 2^28, whose dotted-decimal string is at most 100 bytes. The 100-byte string
/// is the binding limit: the leading `1.2.` packs the first two arcs into a
/// single octet (the second arc is 0..=39 under X.660), and every further
/// 4-octet arc costs at least 8 string bytes to spell (values in
/// 2^21..=2^28-1 start at 7 digits), so 96 remaining bytes buy at most
/// twelve of them: 1 + 12 * 4 = 49 contents octets, reached by twelve arcs
/// of 9999999 below 1.2 (a 99-byte string).
///
/// Makes `ObjectIdentifier` 50-bytes total w\ 1-byte length.
const DEFAULT_MAX_SIZE: usize = 49;

/// Object identifier (OID).
///
Expand All @@ -60,7 +70,7 @@ const DEFAULT_MAX_SIZE: usize = 39;
/// - The OID MUST have at least 3 arcs
/// - The first arc MUST be within the range 0-2
/// - The second arc MUST be within the range 0-39
/// - The BER/DER encoding of the OID MUST be shorter than
/// - The BER/DER encoding of the OID MUST be no longer than
/// [`ObjectIdentifier::MAX_SIZE`]
#[derive(Clone, Copy, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub struct ObjectIdentifier<const MAX_SIZE: usize = DEFAULT_MAX_SIZE> {
Expand Down
42 changes: 42 additions & 0 deletions const-oid/tests/oid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,3 +316,45 @@ fn starts_with() {
assert!(!child.starts_with(oid("2.2.3")));
assert!(!child.starts_with(oid("1.2.3.4.5.6")));
}

/// Worst case RFC 5280 Appendix B mandates support for: at most 20 arcs,
/// every arc below 2^28, dotted-decimal string at most 100 bytes.
/// Twelve 7-digit arcs below 1.2 spell a 99-byte string that encodes to
/// 49 contents octets, the ceiling for any Appendix B-conformant OID.
#[test]
fn rfc5280_appendix_b_worst_case_fits() {
let oid_str = "1.2.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999";
assert_eq!(oid_str.len(), 99);

let oid = ObjectIdentifier::new(oid_str).unwrap();
assert_eq!(oid.as_bytes().len(), 49);
assert_eq!(oid.to_string(), oid_str);

let round_trip = ObjectIdentifier::from_bytes(oid.as_bytes()).unwrap();
assert_eq!(round_trip, oid);
}

/// 100-byte dotted string from #2485 encoding to 40 contents octets.
#[test]
fn rfc5280_appendix_b_100_byte_40_octet_oid_fits() {
let oid_str = "1.3.268435455.268435455.268435455.268435455.268435455.268435455.268435455.268435455.268435455.123456";
assert_eq!(oid_str.len(), 100);

let oid = ObjectIdentifier::new(oid_str).unwrap();
assert_eq!(oid.as_bytes().len(), 40);
assert_eq!(oid.to_string(), oid_str);

let round_trip = ObjectIdentifier::from_bytes(oid.as_bytes()).unwrap();
assert_eq!(round_trip, oid);
}

/// The default capacity is what grows with this change: an explicitly
/// smaller capacity still rejects OIDs that do not fit it.
#[test]
fn explicit_smaller_capacity_still_rejects() {
let oid_str = "1.2.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999.9999999";
let oid = ObjectIdentifier::new(oid_str).unwrap();
let ber = oid.as_bytes();
assert_eq!(ber.len(), 49);
assert!(ObjectIdentifier::<39>::from_bytes_sized(ber).is_err());
}
Loading