x509_parser/extensions/
keyusage.rs1use crate::error::{X509Error, X509Result};
2use asn1_rs::FromDer;
3use der_parser::der::*;
4use der_parser::error::BerError;
5use der_parser::{oid, oid::Oid};
6use nom::{Err, IResult};
7use std::fmt;
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub struct KeyUsage {
11 pub flags: u16,
12}
13
14impl KeyUsage {
15 pub fn digital_signature(&self) -> bool {
16 self.flags & 1 == 1
17 }
18 pub fn non_repudiation(&self) -> bool {
19 (self.flags >> 1) & 1u16 == 1
20 }
21 pub fn key_encipherment(&self) -> bool {
22 (self.flags >> 2) & 1u16 == 1
23 }
24 pub fn data_encipherment(&self) -> bool {
25 (self.flags >> 3) & 1u16 == 1
26 }
27 pub fn key_agreement(&self) -> bool {
28 (self.flags >> 4) & 1u16 == 1
29 }
30 pub fn key_cert_sign(&self) -> bool {
31 (self.flags >> 5) & 1u16 == 1
32 }
33 pub fn crl_sign(&self) -> bool {
34 (self.flags >> 6) & 1u16 == 1
35 }
36 pub fn encipher_only(&self) -> bool {
37 (self.flags >> 7) & 1u16 == 1
38 }
39 pub fn decipher_only(&self) -> bool {
40 (self.flags >> 8) & 1u16 == 1
41 }
42}
43
44const 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
57impl fmt::Display for KeyUsage {
58 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
59 let mut s = KEY_USAGE_FLAGS
60 .iter()
61 .enumerate()
62 .fold(String::new(), |acc, (idx, s)| {
63 if (self.flags >> idx) & 1 != 0 {
64 acc + s + ", "
65 } else {
66 acc
67 }
68 });
69 s.pop();
70 s.pop();
71 f.write_str(&s)
72 }
73}
74
75impl<'a> FromDer<'a, X509Error> for KeyUsage {
76 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
77 parse_keyusage(i).map_err(Err::convert)
78 }
79}
80
81#[derive(Clone, Debug, PartialEq, Eq)]
82pub 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
93impl<'a> FromDer<'a, X509Error> for ExtendedKeyUsage<'a> {
94 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
95 parse_extendedkeyusage(i).map_err(Err::convert)
96 }
97}
98
99pub(crate) fn parse_keyusage(i: &[u8]) -> IResult<&[u8], KeyUsage, BerError> {
100 let (rest, obj) = parse_der_bitstring(i)?;
101 let bitstring = obj
102 .content
103 .as_bitstring()
104 .or(Err(Err::Error(BerError::BerTypeError)))?;
105 let flags = bitstring
106 .data
107 .iter()
108 .rev()
109 .fold(0, |acc, x| (acc << 8) | (x.reverse_bits() as u16));
110 Ok((rest, KeyUsage { flags }))
111}
112
113pub(crate) fn parse_extendedkeyusage(i: &[u8]) -> IResult<&[u8], ExtendedKeyUsage, BerError> {
114 let (ret, seq) = <Vec<Oid>>::from_der(i)?;
115 let mut seen = std::collections::HashSet::new();
116 let mut eku = ExtendedKeyUsage {
117 any: false,
118 server_auth: false,
119 client_auth: false,
120 code_signing: false,
121 email_protection: false,
122 time_stamping: false,
123 ocsp_signing: false,
124 other: Vec::new(),
125 };
126 for oid in &seq {
127 if !seen.insert(oid.clone()) {
128 continue;
129 }
130 let asn1 = oid.as_bytes();
131 if asn1 == oid!(raw 2.5.29.37.0) {
132 eku.any = true;
133 } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.1) {
134 eku.server_auth = true;
135 } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.2) {
136 eku.client_auth = true;
137 } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.3) {
138 eku.code_signing = true;
139 } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.4) {
140 eku.email_protection = true;
141 } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.8) {
142 eku.time_stamping = true;
143 } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.9) {
144 eku.ocsp_signing = true;
145 } else {
146 eku.other.push(oid.clone());
147 }
148 }
149 Ok((ret, eku))
150}