Coverage Report

Created: 2024-12-17 06:15

/rust/registry/src/index.crates.io-6f17d22bba15001f/x509-parser-0.16.0/src/extensions/keyusage.rs
Line
Count
Source (jump to first uncovered line)
1
use crate::error::{X509Error, X509Result};
2
use asn1_rs::FromDer;
3
use der_parser::der::*;
4
use der_parser::error::BerError;
5
use der_parser::{oid, oid::Oid};
6
use nom::{Err, IResult};
7
use std::fmt;
8
9
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10
pub struct KeyUsage {
11
    pub flags: u16,
12
}
13
14
impl KeyUsage {
15
0
    pub fn digital_signature(&self) -> bool {
16
0
        self.flags & 1 == 1
17
0
    }
18
0
    pub fn non_repudiation(&self) -> bool {
19
0
        (self.flags >> 1) & 1u16 == 1
20
0
    }
21
0
    pub fn key_encipherment(&self) -> bool {
22
0
        (self.flags >> 2) & 1u16 == 1
23
0
    }
24
0
    pub fn data_encipherment(&self) -> bool {
25
0
        (self.flags >> 3) & 1u16 == 1
26
0
    }
27
0
    pub fn key_agreement(&self) -> bool {
28
0
        (self.flags >> 4) & 1u16 == 1
29
0
    }
30
0
    pub fn key_cert_sign(&self) -> bool {
31
0
        (self.flags >> 5) & 1u16 == 1
32
0
    }
33
0
    pub fn crl_sign(&self) -> bool {
34
0
        (self.flags >> 6) & 1u16 == 1
35
0
    }
36
0
    pub fn encipher_only(&self) -> bool {
37
0
        (self.flags >> 7) & 1u16 == 1
38
0
    }
39
0
    pub fn decipher_only(&self) -> bool {
40
0
        (self.flags >> 8) & 1u16 == 1
41
0
    }
42
}
43
44
// This list must have the same order as KeyUsage flags declaration (4.2.1.3)
45
const KEY_USAGE_FLAGS: &[&str] = &[
46
    "Digital Signature",
47
    "Non Repudiation",
48
    "Key Encipherment",
49
    "Data Encipherment",
50
    "Key Agreement",
51
    "Key Cert Sign",
52
    "CRL Sign",
53
    "Encipher Only",
54
    "Decipher Only",
55
];
56
57
impl fmt::Display for KeyUsage {
58
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59
0
        let mut s = KEY_USAGE_FLAGS
60
0
            .iter()
61
0
            .enumerate()
62
0
            .fold(String::new(), |acc, (idx, s)| {
63
0
                if self.flags >> idx & 1 != 0 {
64
0
                    acc + s + ", "
65
                } else {
66
0
                    acc
67
                }
68
0
            });
69
0
        s.pop();
70
0
        s.pop();
71
0
        f.write_str(&s)
72
0
    }
73
}
74
75
impl<'a> FromDer<'a, X509Error> for KeyUsage {
76
0
    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
77
0
        parse_keyusage(i).map_err(Err::convert)
78
0
    }
79
}
80
81
#[derive(Clone, Debug, PartialEq, Eq)]
82
pub struct ExtendedKeyUsage<'a> {
83
    pub any: bool,
84
    pub server_auth: bool,
85
    pub client_auth: bool,
86
    pub code_signing: bool,
87
    pub email_protection: bool,
88
    pub time_stamping: bool,
89
    pub ocsp_signing: bool,
90
    pub other: Vec<Oid<'a>>,
91
}
92
93
impl<'a> FromDer<'a, X509Error> for ExtendedKeyUsage<'a> {
94
0
    fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
95
0
        parse_extendedkeyusage(i).map_err(Err::convert)
96
0
    }
97
}
98
99
0
pub(crate) fn parse_keyusage(i: &[u8]) -> IResult<&[u8], KeyUsage, BerError> {
100
0
    let (rest, obj) = parse_der_bitstring(i)?;
101
0
    let bitstring = obj
102
0
        .content
103
0
        .as_bitstring()
104
0
        .or(Err(Err::Error(BerError::BerTypeError)))?;
105
0
    let flags = bitstring
106
0
        .data
107
0
        .iter()
108
0
        .rev()
109
0
        .fold(0, |acc, x| acc << 8 | (x.reverse_bits() as u16));
110
0
    Ok((rest, KeyUsage { flags }))
111
0
}
112
113
0
pub(crate) fn parse_extendedkeyusage(i: &[u8]) -> IResult<&[u8], ExtendedKeyUsage, BerError> {
114
0
    let (ret, seq) = <Vec<Oid>>::from_der(i)?;
115
0
    let mut seen = std::collections::HashSet::new();
116
0
    let mut eku = ExtendedKeyUsage {
117
0
        any: false,
118
0
        server_auth: false,
119
0
        client_auth: false,
120
0
        code_signing: false,
121
0
        email_protection: false,
122
0
        time_stamping: false,
123
0
        ocsp_signing: false,
124
0
        other: Vec::new(),
125
0
    };
126
0
    for oid in &seq {
127
0
        if !seen.insert(oid.clone()) {
128
0
            continue;
129
0
        }
130
0
        let asn1 = oid.as_bytes();
131
0
        if asn1 == oid!(raw 2.5.29.37.0) {
132
0
            eku.any = true;
133
0
        } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.1) {
134
0
            eku.server_auth = true;
135
0
        } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.2) {
136
0
            eku.client_auth = true;
137
0
        } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.3) {
138
0
            eku.code_signing = true;
139
0
        } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.4) {
140
0
            eku.email_protection = true;
141
0
        } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.8) {
142
0
            eku.time_stamping = true;
143
0
        } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.9) {
144
0
            eku.ocsp_signing = true;
145
0
        } else {
146
0
            eku.other.push(oid.clone());
147
0
        }
148
    }
149
0
    Ok((ret, eku))
150
0
}