use std::sync::Arc;
use structured_asn1::{
Parser,
memory::{Memory, MemoryAccount},
};
use structured_cms::{ErrorCode, timestamp::Request};
fn request(optional: &[u8]) -> Vec<u8> {
let mut fields = vec![2, 1, 1, 0x30, 9, 0x30, 3, 6, 1, 42, 4, 2, 7, 8];
fields.extend(optional);
let mut bytes = vec![0x30, u8::try_from(fields.len()).unwrap()];
bytes.extend(fields);
bytes
}
#[test]
fn ordered_optional_fields_and_default_keep_original_views() {
let memory = Memory::new(Arc::new(MemoryAccount::new(65536, 65536)));
let parser = Parser::ber(memory.clone());
for (optional, cert_req) in [
(&[][..], false),
(&[6, 1, 43, 2, 1, 9, 1, 1, 0xff][..], true),
] {
let bytes = request(optional);
let mut parent = parser.read(&bytes, 400).unwrap();
let element = parent.next_element().unwrap().unwrap();
let parsed = Request::read(&parent, &element).unwrap();
assert_eq!(parsed.cert_req(), cert_req);
assert_eq!(
parsed.nonce().map(|n| n.as_u64().unwrap()),
if cert_req { Some(9) } else { None }
);
assert_eq!(
parsed.policy().map(structured_asn1::Oid::as_bytes),
if cert_req { Some(&[43][..]) } else { None }
);
assert!(parsed.same_session(&parent));
assert_eq!(parsed.imprint().hashed().as_one(), Some(&[7, 8][..]));
drop(parsed);
assert_eq!(memory.used(), 0);
}
}
#[test]
fn duplicate_and_out_of_order_request_fields_are_not_recovered() {
let parser = Parser::ber(Memory::new(Arc::new(MemoryAccount::new(65536, 65536))));
for (optional, code) in [
(&[2, 1, 9, 2, 1, 9][..], ErrorCode::DuplicateField),
(&[2, 1, 9, 6, 1, 43][..], ErrorCode::FieldOrder),
] {
let bytes = request(optional);
let mut parent = parser.read(&bytes, 400).unwrap();
let element = parent.next_element().unwrap().unwrap();
assert_eq!(Request::read(&parent, &element).unwrap_err().code(), code);
}
}
#[test]
fn request_version_requires_integer_tag_before_numeric_interpretation() {
let parser = Parser::ber(Memory::new(Arc::new(MemoryAccount::new(65536, 65536))));
let mut bytes = request(&[]);
bytes[2] = 6;
let mut parent = parser.read(&bytes, 400).unwrap();
let element = parent.next_element().unwrap().unwrap();
let error = Request::read(&parent, &element).unwrap_err();
assert_eq!(error.code(), ErrorCode::UnexpectedTag);
assert_eq!(error.offset(), 402);
}
#[test]
fn written_cert_req_false_is_ber_only_not_a_der_default() {
let bytes = request(&[1, 1, 0]);
let memory = Memory::new(Arc::new(MemoryAccount::new(65536, 65536)));
let ber = Parser::ber(memory.clone());
let der = Parser::der(memory);
let mut parent = ber.read(&bytes, 400).unwrap();
let element = parent.next_element().unwrap().unwrap();
assert!(!Request::read(&parent, &element).unwrap().cert_req());
let mut parent = der.read(&bytes, 400).unwrap();
let element = parent.next_element().unwrap().unwrap();
let error = Request::read(&parent, &element).unwrap_err();
assert_eq!(error.code(), ErrorCode::DefaultWritten);
assert_eq!(error.offset(), 416);
}
#[test]
fn nonce_policy_facts_use_original_sessions_and_current_token_work() {
use structured_cms::timestamp::{ImprintOperand, RequestFields, TokenInfo};
let memory = Memory::new(Arc::new(MemoryAccount::new(65536, 65536)));
let token_parser = Parser::ber(memory.clone());
let request_parser = Parser::ber(memory);
let asked = request(&[6, 1, 43, 2, 1, 9]);
let mut request_parent = request_parser.read(&asked, 900).unwrap();
let element = request_parent.next_element().unwrap().unwrap();
let requested = Request::read(&request_parent, &element).unwrap();
let mut fields = vec![
2, 1, 1, 6, 1, 43, 0x30, 9, 0x30, 3, 6, 1, 42, 4, 2, 7, 8, 2, 1, 7, 0x18, 15,
];
fields.extend(b"20260101000000Z");
fields.extend([2, 2, 0, 9]);
let mut bytes = vec![0x30, u8::try_from(fields.len()).unwrap()];
bytes.extend(fields);
let mut parent = token_parser.read(&bytes, 400).unwrap();
let element = parent.next_element().unwrap().unwrap();
let info = TokenInfo::read(&parent, &element).unwrap();
assert!(info.has_faults());
assert_eq!(
info.matches_request_fields(&requested, &parent, &request_parent)
.unwrap(),
RequestFields {
nonce: Some(true),
policy: Some(true)
}
);
let wrong = info
.matches_request_fields(&requested, &parent, &parent)
.unwrap_err();
assert_eq!(wrong.operand, ImprintOperand::Requested);
assert!(wrong.source.is_terminal());
let exhausted = Memory::new(Arc::new(MemoryAccount::new(65536, 0)));
let query = parent.with_execution(&exhausted);
let error = info
.matches_request_fields(&requested, &query, &request_parent)
.unwrap_err();
assert_eq!(error.operand, ImprintOperand::Token);
assert!(error.source.is_resource());
assert_eq!(error.source.offset(), 400);
}
#[test]
fn request_recognition_visits_noncritical_extensions_and_preserves_refusal() {
let members = [
0x30, 8, 6, 1, 42, 4, 3, 2, 1, 7, 0x30, 11, 6, 1, 43, 1, 1, 0xff, 4, 3, 2, 1, 8,
];
let mut extensions = vec![0xa0, u8::try_from(members.len()).unwrap()];
extensions.extend(members);
let bytes = request(&extensions);
let parser = Parser::ber(Memory::new(Arc::new(MemoryAccount::new(65536, 65536))));
let mut parent = parser.read(&bytes, 400).unwrap();
let element = parent.next_element().unwrap().unwrap();
let parsed = Request::read(&parent, &element).unwrap();
let mut calls = Vec::new();
let unknown = parsed
.unrecognized_extensions(&parent, |entry, _| {
calls.push(entry.kind().as_bytes()[0]);
Ok::<_, ()>(entry.is_critical())
})
.unwrap();
assert_eq!(calls, [42, 43]);
assert_eq!(unknown.len(), 1);
assert_eq!(unknown[0].as_bytes(), &[42]);
let error = parsed
.unrecognized_extensions(&parent, |_, _| Err::<bool, _>("capacity"))
.unwrap_err();
let structured_cms::timestamp::RecognitionError::Callback { source, span } = error else {
panic!("handler failure became unrecognized");
};
assert_eq!(source, "capacity");
assert!(span.start > parsed.span().start);
}