Skip to main content

pkix/
pkcs10.rs

1/* Copyright (c) Fortanix, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7use yasna::{ASN1Error, ASN1ErrorKind, ASN1Result, BERReader, DERWriter, BERDecodable, Tag};
8use {DerWrite, FromDer};
9use types::*;
10use bit_vec::BitVec;
11use oid;
12
13// RFC2986, 4.1
14
15pub type DerCertificationRequest =
16    CertificationRequest<CertificationRequestInfo<'static, DerSequence<'static>>,
17                         DerSequence<'static>,
18                         BitVec>;
19
20#[derive(Clone, Debug, Eq, PartialEq, Hash)]
21pub struct CertificationRequest<I = CertificationRequestInfo<'static, DerSequence<'static>>,
22                                A: SignatureAlgorithm = DerSequence<'static>,
23                                S = BitVec> {
24    pub reqinfo: I,
25    pub sigalg: A,
26    pub sig: S,
27}
28
29impl<I: DerWrite, A: SignatureAlgorithm + DerWrite, S: DerWrite> DerWrite for CertificationRequest<I, A, S> {
30    fn write(&self, writer: DERWriter) {
31        writer.write_sequence(|writer| {
32            self.reqinfo.write(writer.next());
33            self.sigalg.write(writer.next());
34            self.sig.write(writer.next());
35        });
36    }
37}
38
39impl<I: BERDecodable, A: SignatureAlgorithm + BERDecodable, S: BERDecodable> BERDecodable for CertificationRequest<I, A, S> {
40    fn decode_ber<'a, 'b>(reader: BERReader<'a, 'b>) -> ASN1Result<Self> {
41        reader.read_sequence(|r| {
42            let reqinfo = I::decode_ber(r.next())?;
43            let sigalg = A::decode_ber(r.next())?;
44            let sig = S::decode_ber(r.next())?;
45
46            Ok(CertificationRequest { reqinfo, sigalg, sig })
47        })
48    }
49}
50
51impl<'a, K, A: SignatureAlgorithm, S> CertificationRequest<CertificationRequestInfo<'a, K>, A, S> {
52    pub fn has_attribute(&self, oid: &ObjectIdentifier) -> bool {
53        self.reqinfo.attributes.iter().any(|a| a.oid == *oid)
54    }
55
56    pub fn get_attribute<T: FromDer + HasOid>(&self) -> Option<Vec<T>> {
57        let oid = T::oid();
58
59        let mut iter = self.reqinfo.attributes.iter().filter(|a| a.oid == *oid);
60
61        // We reject CSRs where the same attribute (same OID) appears multiple times. Note that
62        // this is different from the case where the attribute (OID) appears once and has
63        // multiple values, that is handled by the second level of iteration below.
64        match (iter.next(), iter.next()) {
65            (Some(attr), None) => {
66                attr.value
67                    .iter()
68                    .map(|v| T::from_der(v))
69                    .collect::<ASN1Result<Vec<T>>>()
70                    .ok()
71            }
72            _ => None,
73        }
74    }
75
76    pub fn get_singular_attribute<T: FromDer + HasOid>(&self) -> Option<T> {
77        match self.get_attribute() {
78            None => None,
79            Some(mut values) => {
80                if values.len() != 1 {
81                    // warn!("Unexpected number of attribute values in CSR");
82                    return None;
83                } else {
84                    Some(values.pop().unwrap())
85                }
86            }
87        }
88    }
89}
90
91#[derive(Clone, Debug, Eq, PartialEq, Hash)]
92pub struct CertificationRequestInfo<'e, K> {
93    // version: v1
94    pub subject: Name,
95    pub spki: K,
96    pub attributes: Vec<Attribute<'e>>,
97}
98
99const CERTIFICATION_REQUEST_INFO_V1: u8 = 0;
100
101impl<'e, K: DerWrite> DerWrite for CertificationRequestInfo<'e, K> {
102    fn write(&self, writer: DERWriter) {
103        writer.write_sequence(|writer| {
104            CERTIFICATION_REQUEST_INFO_V1.write(writer.next());
105            self.subject.write(writer.next());
106            self.spki.write(writer.next());
107            writer.next().write_tagged_implicit(Tag::context(0), |w| {
108                w.write_set(|w| for attr in &self.attributes {
109                    attr.write(w.next());
110                })
111            });
112        });
113    }
114}
115
116impl<'a, K: BERDecodable> BERDecodable for CertificationRequestInfo<'a, K> {
117    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
118        reader.read_sequence(|r| {
119            let version = r.next().read_u8()?;
120            if version != CERTIFICATION_REQUEST_INFO_V1 {
121                return Err(ASN1Error::new(ASN1ErrorKind::Invalid));
122            }
123            let subject = Name::decode_ber(r.next())?;
124            let spki = K::decode_ber(r.next())?;
125            let attributes = r.next().read_tagged_implicit(Tag::context(0), |r| {
126                let mut attributes = Vec::<Attribute<'static>>::new();
127                r.read_set_of(|r| {
128                    attributes.push(Attribute::decode_ber(r)?);
129                    Ok(())
130                })?;
131                Ok(attributes)
132            })?;
133
134            Ok(CertificationRequestInfo { subject, spki, attributes })
135        })
136    }
137}
138
139#[derive(Clone, Debug, Eq, PartialEq, Hash)]
140pub struct ExtensionRequest {
141    pub extensions: Extensions,
142}
143
144impl HasOid for ExtensionRequest {
145    fn oid() -> &'static ObjectIdentifier {
146        &oid::extensionRequest
147    }
148}
149
150impl DerWrite for ExtensionRequest {
151    fn write(&self, writer: DERWriter) {
152        self.extensions.write(writer)
153    }
154}
155
156impl BERDecodable for ExtensionRequest {
157    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
158        Ok(ExtensionRequest { extensions: Extensions::decode_ber(reader)? })
159    }
160}
161
162impl ExtensionRequest {
163    pub fn get_requested_extension<T: FromDer + HasOid>(&self) -> Option<T> {
164        self.extensions.get_extension::<T>()
165    }
166}
167
168#[cfg(test)]
169mod tests {
170    use super::*;
171    use crate::test::test_encode_decode;
172
173    #[test]
174    fn extension_request() {
175        let extension_request = ExtensionRequest {
176            extensions: Extensions(vec![
177                Extension {
178                    oid: oid::basicConstraints.clone(),
179                    critical: true,
180                    value: vec![0x30, 0x00],
181                },
182                Extension {
183                    oid: oid::keyUsage.clone(),
184                    critical: true,
185                    value: vec![0x03, 0x03, 0x07, 0x80, 0x00],
186                },
187            ])
188        };
189
190        let der = &[
191            0x30, 0x1f, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d,
192            0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00,
193            0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
194            0x01, 0xff, 0x04, 0x05, 0x03, 0x03, 0x07, 0x80,
195            0x00];
196
197        test_encode_decode(&extension_request, der);
198    }
199}