summaryrefslogtreecommitdiffstats
path: root/rust/vendor/x509-parser/src/extensions/keyusage.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/vendor/x509-parser/src/extensions/keyusage.rs')
-rw-r--r--rust/vendor/x509-parser/src/extensions/keyusage.rs150
1 files changed, 150 insertions, 0 deletions
diff --git a/rust/vendor/x509-parser/src/extensions/keyusage.rs b/rust/vendor/x509-parser/src/extensions/keyusage.rs
new file mode 100644
index 0000000..81a07f1
--- /dev/null
+++ b/rust/vendor/x509-parser/src/extensions/keyusage.rs
@@ -0,0 +1,150 @@
+use crate::error::{X509Error, X509Result};
+use asn1_rs::FromDer;
+use der_parser::der::*;
+use der_parser::error::BerError;
+use der_parser::{oid, oid::Oid};
+use nom::{Err, IResult};
+use std::fmt;
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct KeyUsage {
+ pub flags: u16,
+}
+
+impl KeyUsage {
+ pub fn digital_signature(&self) -> bool {
+ self.flags & 1 == 1
+ }
+ pub fn non_repudiation(&self) -> bool {
+ (self.flags >> 1) & 1u16 == 1
+ }
+ pub fn key_encipherment(&self) -> bool {
+ (self.flags >> 2) & 1u16 == 1
+ }
+ pub fn data_encipherment(&self) -> bool {
+ (self.flags >> 3) & 1u16 == 1
+ }
+ pub fn key_agreement(&self) -> bool {
+ (self.flags >> 4) & 1u16 == 1
+ }
+ pub fn key_cert_sign(&self) -> bool {
+ (self.flags >> 5) & 1u16 == 1
+ }
+ pub fn crl_sign(&self) -> bool {
+ (self.flags >> 6) & 1u16 == 1
+ }
+ pub fn encipher_only(&self) -> bool {
+ (self.flags >> 7) & 1u16 == 1
+ }
+ pub fn decipher_only(&self) -> bool {
+ (self.flags >> 8) & 1u16 == 1
+ }
+}
+
+// This list must have the same order as KeyUsage flags declaration (4.2.1.3)
+const KEY_USAGE_FLAGS: &[&str] = &[
+ "Digital Signature",
+ "Non Repudiation",
+ "Key Encipherment",
+ "Data Encipherment",
+ "Key Agreement",
+ "Key Cert Sign",
+ "CRL Sign",
+ "Encipher Only",
+ "Decipher Only",
+];
+
+impl fmt::Display for KeyUsage {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut s = KEY_USAGE_FLAGS
+ .iter()
+ .enumerate()
+ .fold(String::new(), |acc, (idx, s)| {
+ if self.flags >> idx & 1 != 0 {
+ acc + s + ", "
+ } else {
+ acc
+ }
+ });
+ s.pop();
+ s.pop();
+ f.write_str(&s)
+ }
+}
+
+impl<'a> FromDer<'a, X509Error> for KeyUsage {
+ fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
+ parse_keyusage(i).map_err(Err::convert)
+ }
+}
+
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct ExtendedKeyUsage<'a> {
+ pub any: bool,
+ pub server_auth: bool,
+ pub client_auth: bool,
+ pub code_signing: bool,
+ pub email_protection: bool,
+ pub time_stamping: bool,
+ pub ocsp_signing: bool,
+ pub other: Vec<Oid<'a>>,
+}
+
+impl<'a> FromDer<'a, X509Error> for ExtendedKeyUsage<'a> {
+ fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
+ parse_extendedkeyusage(i).map_err(Err::convert)
+ }
+}
+
+pub(crate) fn parse_keyusage(i: &[u8]) -> IResult<&[u8], KeyUsage, BerError> {
+ let (rest, obj) = parse_der_bitstring(i)?;
+ let bitstring = obj
+ .content
+ .as_bitstring()
+ .or(Err(Err::Error(BerError::BerTypeError)))?;
+ let flags = bitstring
+ .data
+ .iter()
+ .rev()
+ .fold(0, |acc, x| acc << 8 | (x.reverse_bits() as u16));
+ Ok((rest, KeyUsage { flags }))
+}
+
+pub(crate) fn parse_extendedkeyusage(i: &[u8]) -> IResult<&[u8], ExtendedKeyUsage, BerError> {
+ let (ret, seq) = <Vec<Oid>>::from_der(i)?;
+ let mut seen = std::collections::HashSet::new();
+ let mut eku = ExtendedKeyUsage {
+ any: false,
+ server_auth: false,
+ client_auth: false,
+ code_signing: false,
+ email_protection: false,
+ time_stamping: false,
+ ocsp_signing: false,
+ other: Vec::new(),
+ };
+ for oid in &seq {
+ if !seen.insert(oid.clone()) {
+ continue;
+ }
+ let asn1 = oid.as_bytes();
+ if asn1 == oid!(raw 2.5.29.37.0) {
+ eku.any = true;
+ } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.1) {
+ eku.server_auth = true;
+ } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.2) {
+ eku.client_auth = true;
+ } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.3) {
+ eku.code_signing = true;
+ } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.4) {
+ eku.email_protection = true;
+ } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.8) {
+ eku.time_stamping = true;
+ } else if asn1 == oid!(raw 1.3.6.1.5.5.7.3.9) {
+ eku.ocsp_signing = true;
+ } else {
+ eku.other.push(oid.clone());
+ }
+ }
+ Ok((ret, eku))
+}