/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 | } |