#![cfg(test)]
use super::*;
#[test]
fn request_round_trips_and_proves_possession_of_the_identity_key() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let verified = verify_certificate_request(&der).unwrap();
assert_eq!(
verified.subject_public_key(),
&identity.public_key_bytes(),
"the verified request must carry the identity's own key"
);
assert_eq!(verified.common_name(), "agent-noor");
}
#[test]
fn substituting_the_subject_key_breaks_proof_of_possession() {
let identity = test_identity();
let attacker = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let forged = patch_first(
&der,
&identity.public_key_bytes(),
&attacker.public_key_bytes(),
);
let error = verify_certificate_request(&forged).unwrap_err();
match error {
TrustError::CertificateVerification { reason } => {
assert!(
reason.contains("proof of possession failed"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a verification failure, got {other:?}"),
}
}
#[test]
fn tampering_with_the_requested_name_breaks_proof_of_possession() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let forged = patch_first(&der, b"agent-noor", b"agent-root");
let error = verify_certificate_request(&forged).unwrap_err();
assert!(matches!(error, TrustError::CertificateVerification { .. }));
}
#[test]
fn a_small_order_subject_key_is_rejected() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let forged = patch_first(&der, &identity.public_key_bytes(), &[0u8; 32]);
let error = verify_certificate_request(&forged).unwrap_err();
match error {
TrustError::CertificateVerification { reason } => {
assert!(
reason.contains("proof of possession failed")
|| reason.contains("not a valid Ed25519 point"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a verification failure, got {other:?}"),
}
}
#[test]
fn trailing_bytes_after_the_request_are_rejected() {
let identity = test_identity();
let mut der = create_certificate_request(&identity, "agent-noor").unwrap();
der.push(0x00);
let error = verify_certificate_request(&der).unwrap_err();
match error {
TrustError::CertificateParsing { reason } => {
assert!(reason.contains("trailing"), "unexpected reason: {reason}");
}
other => panic!("expected a parsing failure, got {other:?}"),
}
}
#[test]
fn a_non_ed25519_signature_algorithm_is_rejected() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let forged = patch_last(&der, &ED25519_OID_DER, &ED448_OID_DER);
let error = verify_certificate_request(&forged).unwrap_err();
match error {
TrustError::CertificateParsing { reason } => {
assert!(
reason.contains("signature algorithm is not Ed25519"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a parsing failure, got {other:?}"),
}
}
#[test]
fn a_non_ed25519_subject_key_algorithm_is_rejected() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let forged = patch_first(&der, &ED25519_OID_DER, &ED448_OID_DER);
let error = verify_certificate_request(&forged).unwrap_err();
match error {
TrustError::CertificateParsing { reason } => {
assert!(
reason.contains("subject key algorithm is not Ed25519"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a parsing failure, got {other:?}"),
}
}
#[test]
fn requested_extensions_are_refused_rather_than_stripped() {
let identity = test_identity();
let mut params = CertificateParams::new(vec!["agent-noor.example".to_string()]).unwrap();
params.distinguished_name = distinguished_name("agent-noor");
params
.subject_alt_names
.push(SanType::DnsName("other.example".try_into().unwrap()));
let der = request_with_params(&identity, ¶ms);
let error = verify_certificate_request(&der).unwrap_err();
match error {
TrustError::CertificateParsing { reason } => {
assert!(
reason.contains("requested extensions"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a parsing failure, got {other:?}"),
}
}
#[test]
fn our_own_requests_carry_no_requested_extensions() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
verify_certificate_request(&der).expect("our own request must be acceptable");
}
#[test]
fn more_than_one_common_name_is_rejected() {
let identity = test_identity();
let mut params = CertificateParams::new(Vec::<String>::new()).unwrap();
let mut dn = rcgen::DistinguishedName::new();
dn.push(DnType::CommonName, "agent-noor");
dn.push(DnType::CountryName, "AU");
params.distinguished_name = dn;
let der = request_with_params(&identity, ¶ms);
let forged = patch_first(&der, &COUNTRY_OID_DER, &CN_OID_DER);
let error = verify_certificate_request(&forged).unwrap_err();
match error {
TrustError::CertificateParsing { reason } => {
assert!(
reason.contains("more than one common name"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a parsing failure, got {other:?}"),
}
}
#[test]
fn a_request_with_no_common_name_is_rejected() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let forged = patch_first(&der, &CN_OID_DER, &COUNTRY_OID_DER);
let error = verify_certificate_request(&forged).unwrap_err();
match error {
TrustError::CertificateParsing { reason } => {
assert!(
reason.contains("no common name"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a parsing failure, got {other:?}"),
}
}
#[test]
fn a_whitespace_only_common_name_is_rejected() {
let identity = test_identity();
let der = create_certificate_request(&identity, "agent-noor").unwrap();
let forged = patch_first(&der, b"agent-noor", b" ");
let error = verify_certificate_request(&forged).unwrap_err();
match error {
TrustError::CertificateParsing { reason } => {
assert!(
reason.contains("must not be empty"),
"unexpected reason: {reason}"
);
}
other => panic!("expected a parsing failure, got {other:?}"),
}
}
#[test]
fn creating_a_request_for_an_empty_subject_is_refused() {
let identity = test_identity();
for subject in ["", " "] {
let error = create_certificate_request(&identity, subject).unwrap_err();
assert!(matches!(error, TrustError::CertificateGeneration { .. }));
}
}