• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::{
2     error::{X509Error, X509Result},
3     extensions::X509Extension,
4     traits::FromDer,
5 };
6 
7 use der_parser::der::{
8     der_read_element_header, parse_der_oid, parse_der_sequence_defined_g, DerTag,
9 };
10 use der_parser::error::BerError;
11 use der_parser::oid::Oid;
12 use nom::combinator::map_res;
13 use nom::Err;
14 use oid_registry::*;
15 use std::collections::HashMap;
16 
17 /// Attributes for Certification Request
18 #[derive(Clone, Debug, PartialEq)]
19 pub struct X509CriAttribute<'a> {
20     pub oid: Oid<'a>,
21     pub value: &'a [u8],
22     pub(crate) parsed_attribute: ParsedCriAttribute<'a>,
23 }
24 
25 impl<'a> FromDer<'a> for X509CriAttribute<'a> {
from_der(i: &'a [u8]) -> X509Result<X509CriAttribute>26     fn from_der(i: &'a [u8]) -> X509Result<X509CriAttribute> {
27         parse_der_sequence_defined_g(|i, _| {
28             let (i, oid) = map_res(parse_der_oid, |x| x.as_oid_val())(i)?;
29             let value_start = i;
30             let (i, hdr) = der_read_element_header(i)?;
31             if hdr.tag != DerTag::Set {
32                 return Err(Err::Error(BerError::BerTypeError));
33             };
34 
35             let (i, parsed_attribute) = crate::cri_attributes::parser::parse_attribute(i, &oid)?;
36             let ext = X509CriAttribute {
37                 oid,
38                 value: &value_start[..value_start.len() - i.len()],
39                 parsed_attribute,
40             };
41             Ok((i, ext))
42         })(i)
43         .map_err(|_| X509Error::InvalidAttributes.into())
44     }
45 }
46 
47 /// Section 3.1 of rfc 5272
48 #[derive(Clone, Debug, PartialEq)]
49 pub struct ExtensionRequest<'a> {
50     pub extensions: Vec<X509Extension<'a>>,
51 }
52 
53 impl<'a> FromDer<'a> for ExtensionRequest<'a> {
from_der(i: &'a [u8]) -> X509Result<'a, Self>54     fn from_der(i: &'a [u8]) -> X509Result<'a, Self> {
55         parser::parse_extension_request(i).map_err(Err::convert)
56     }
57 }
58 
59 /// Attributes for Certification Request
60 #[derive(Clone, Debug, PartialEq)]
61 pub enum ParsedCriAttribute<'a> {
62     ExtensionRequest(ExtensionRequest<'a>),
63     UnsupportedAttribute,
64 }
65 
66 pub(crate) mod parser {
67     use crate::cri_attributes::*;
68     use der_parser::error::BerError;
69     use der_parser::{oid::Oid, *};
70     use lazy_static::lazy_static;
71     use nom::combinator::map;
72     use nom::{Err, IResult};
73 
74     type AttrParser = fn(&[u8]) -> IResult<&[u8], ParsedCriAttribute, BerError>;
75 
76     lazy_static! {
77         static ref ATTRIBUTE_PARSERS: HashMap<Oid<'static>, AttrParser> = {
78             macro_rules! add {
79                 ($m:ident, $oid:ident, $p:ident) => {
80                     $m.insert($oid, $p as AttrParser);
81                 };
82             }
83 
84             let mut m = HashMap::new();
85             add!(m, OID_PKCS9_EXTENSION_REQUEST, parse_extension_request_ext);
86             m
87         };
88     }
89 
90     // look into the parser map if the extension is known, and parse it
91     // otherwise, leave it as UnsupportedExtension
parse_attribute<'a>( i: &'a [u8], oid: &Oid, ) -> IResult<&'a [u8], ParsedCriAttribute<'a>, BerError>92     pub(crate) fn parse_attribute<'a>(
93         i: &'a [u8],
94         oid: &Oid,
95     ) -> IResult<&'a [u8], ParsedCriAttribute<'a>, BerError> {
96         if let Some(parser) = ATTRIBUTE_PARSERS.get(oid) {
97             parser(i)
98         } else {
99             Ok((i, ParsedCriAttribute::UnsupportedAttribute))
100         }
101     }
102 
parse_extension_request(i: &[u8]) -> IResult<&[u8], ExtensionRequest, BerError>103     pub(super) fn parse_extension_request(i: &[u8]) -> IResult<&[u8], ExtensionRequest, BerError> {
104         crate::extensions::parse_extension_sequence(i)
105             .map(|(i, extensions)| (i, ExtensionRequest { extensions }))
106             .map_err(|_| Err::Error(BerError::BerTypeError))
107     }
108 
parse_extension_request_ext(i: &[u8]) -> IResult<&[u8], ParsedCriAttribute, BerError>109     fn parse_extension_request_ext(i: &[u8]) -> IResult<&[u8], ParsedCriAttribute, BerError> {
110         map(
111             parse_extension_request,
112             ParsedCriAttribute::ExtensionRequest,
113         )(i)
114     }
115 }
116 
parse_cri_attributes(i: &[u8]) -> X509Result<Vec<X509CriAttribute>>117 pub(crate) fn parse_cri_attributes(i: &[u8]) -> X509Result<Vec<X509CriAttribute>> {
118     let (i, hdr) = der_read_element_header(i).or(Err(Err::Error(X509Error::InvalidAttributes)))?;
119     if i.is_empty() {
120         return Ok((i, Vec::new()));
121     }
122     (0..hdr.structured)
123         .into_iter()
124         .try_fold((i, Vec::new()), |(i, mut attrs), _| {
125             let (rem, attr) = X509CriAttribute::from_der(i)?;
126             attrs.push(attr);
127             Ok((rem, attrs))
128         })
129 }
130