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