File: client_auth.rs

package info (click to toggle)
rust-rustls-webpki 0.103.4-2
  • links: PTS, VCS
  • area: main
  • in suites: experimental, sid
  • size: 10,632 kB
  • sloc: python: 2,278; sh: 61; makefile: 12
file content (105 lines) | stat: -rw-r--r-- 3,555 bytes parent folder | download | duplicates (2)
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))
}