1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
// Copyright 2023 Joseph Birr-Pixton.
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#![cfg(all(feature = "alloc", any(feature = "ring", feature = "aws-lc-rs")))]
use std::error::Error as StdError;
use core::time::Duration;
use pki_types::{CertificateDer, UnixTime};
use rcgen::{Certificate, ExtendedKeyUsagePurpose};
use webpki::{KeyUsage, RequiredEkuNotFoundContext, anchor_from_trusted_cert};
mod common;
use common::{make_end_entity, make_issuer};
#[test]
fn cert_with_no_eku_accepted_for_client_auth() {
let (ee, ca) = test_certs(vec![], "cert_with_no_eku_accepted_for_client_auth").unwrap();
assert_eq!(check_cert(ee.der(), ca.der()), Ok(()));
}
#[test]
fn cert_with_clientauth_eku_accepted_for_client_auth() {
let (ee, ca) = test_certs(
vec![ExtendedKeyUsagePurpose::ClientAuth],
"cert_with_clientauth_eku_accepted_for_client_auth",
)
.unwrap();
assert_eq!(check_cert(ee.der(), ca.der()), Ok(()));
}
#[test]
fn cert_with_both_ekus_accepted_for_client_auth() {
let (ee, ca) = test_certs(
vec![
ExtendedKeyUsagePurpose::ClientAuth,
ExtendedKeyUsagePurpose::ServerAuth,
],
"cert_with_both_ekus_accepted_for_client_auth",
)
.unwrap();
assert_eq!(check_cert(ee.der(), ca.der()), Ok(()));
}
#[test]
fn cert_with_serverauth_eku_rejected_for_client_auth() {
let (ee, ca) = test_certs(
vec![ExtendedKeyUsagePurpose::ServerAuth],
"cert_with_serverauth_eku_rejected_for_client_auth",
)
.unwrap();
let err = check_cert(ee.der(), ca.der()).unwrap_err();
assert_eq!(
err,
webpki::Error::RequiredEkuNotFoundContext(RequiredEkuNotFoundContext {
required: KeyUsage::client_auth(),
present: vec![vec![1, 3, 6, 1, 5, 5, 7, 3, 1]],
})
);
assert_eq!(
format!("{err}"),
"RequiredEkuNotFoundContext(RequiredEkuNotFoundContext { required: KeyPurposeId(1.3.6.1.5.5.7.3.2), present: [KeyPurposeId(1.3.6.1.5.5.7.3.1)] })"
)
}
fn check_cert(ee: &[u8], ca: &[u8]) -> Result<(), webpki::Error> {
let ca = CertificateDer::from(ca);
let anchors = &[anchor_from_trusted_cert(&ca).unwrap()];
let time = UnixTime::since_unix_epoch(Duration::from_secs(0x1fed_f00d));
let ee = CertificateDer::from(ee);
let cert = webpki::EndEntityCert::try_from(&ee).unwrap();
cert.verify_for_usage(
webpki::ALL_VERIFICATION_ALGS,
anchors,
&[],
time,
KeyUsage::client_auth(),
None,
None,
)
.map(|_| ())
}
fn test_certs(
ekus: Vec<ExtendedKeyUsagePurpose>,
name: &str,
) -> Result<(Certificate, Certificate), Box<dyn StdError>> {
let issuer = make_issuer(name)?;
let end_entity = make_end_entity(ekus, name, &issuer.cert, &issuer.key_pair)?;
Ok((end_entity.cert, issuer.cert))
}
|