1 use crate::{oids, GeneralName, GeneralNames};
2 use core::slice::{Iter, IterMut};
3 use picky_asn1::bit_string::BitString;
4 use picky_asn1::wrapper::{
5     ApplicationTag1, Asn1SequenceOf, BitStringAsn1, ContextTag0, ContextTag2, Implicit, IntegerAsn1,
6     ObjectIdentifierAsn1, OctetStringAsn1, OctetStringAsn1Container,
7 };
8 use serde::{de, ser, Deserialize, Serialize};
9 use std::fmt;
10 
11 /// [RFC 5280 #4.1.2.9](https://tools.ietf.org/html/rfc5280#section-4.1.2.9)
12 #[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
13 pub struct Extensions(pub Vec<Extension>);
14 
15 /// [RFC 5280 #4.1.2.9](https://tools.ietf.org/html/rfc5280#section-4.1.2.9)
16 #[derive(Debug, PartialEq, Clone)]
17 pub struct Extension {
18     extn_id: ObjectIdentifierAsn1,
19     critical: Implicit<bool>,
20     extn_value: ExtensionValue,
21 }
22 
23 impl Extension {
extn_id(&self) -> &ObjectIdentifierAsn124     pub fn extn_id(&self) -> &ObjectIdentifierAsn1 {
25         &self.extn_id
26     }
27 
critical(&self) -> bool28     pub fn critical(&self) -> bool {
29         self.critical.0
30     }
31 
extn_value(&self) -> ExtensionView<'_>32     pub fn extn_value(&self) -> ExtensionView<'_> {
33         ExtensionView::from(&self.extn_value)
34     }
35 
into_critical(mut self) -> Self36     pub fn into_critical(mut self) -> Self {
37         self.critical = true.into();
38         self
39     }
40 
into_non_critical(mut self) -> Self41     pub fn into_non_critical(mut self) -> Self {
42         self.critical = false.into();
43         self
44     }
45 
set_critical(&mut self, critical: bool)46     pub fn set_critical(&mut self, critical: bool) {
47         self.critical = critical.into();
48     }
49 
50     /// When present, conforming CAs SHOULD mark this extension as critical
51     ///
52     /// Default is critical.
new_key_usage(key_usage: KeyUsage) -> Self53     pub fn new_key_usage(key_usage: KeyUsage) -> Self {
54         Self {
55             extn_id: oids::key_usage().into(),
56             critical: true.into(),
57             extn_value: ExtensionValue::KeyUsage(key_usage.into()),
58         }
59     }
60 
61     /// Conforming CAs MUST mark this extension as non-critical
62     ///
63     /// Default is non-critical.
new_subject_key_identifier<V: Into<Vec<u8>>>(ski: V) -> Self64     pub fn new_subject_key_identifier<V: Into<Vec<u8>>>(ski: V) -> Self {
65         Self {
66             extn_id: oids::subject_key_identifier().into(),
67             critical: false.into(),
68             extn_value: ExtensionValue::SubjectKeyIdentifier(OctetStringAsn1(ski.into()).into()),
69         }
70     }
71 
72     /// Conforming CAs MUST mark this extension as non-critical
73     ///
74     /// Default is critical.
new_authority_key_identifier<KI, I, SN>( key_identifier: KI, authority_cert_issuer: I, authority_cert_serial_number: SN, ) -> Self where KI: Into<Option<KeyIdentifier>>, I: Into<Option<GeneralName>>, SN: Into<Option<IntegerAsn1>>,75     pub fn new_authority_key_identifier<KI, I, SN>(
76         key_identifier: KI,
77         authority_cert_issuer: I,
78         authority_cert_serial_number: SN,
79     ) -> Self
80     where
81         KI: Into<Option<KeyIdentifier>>,
82         I: Into<Option<GeneralName>>,
83         SN: Into<Option<IntegerAsn1>>,
84     {
85         Self {
86             extn_id: oids::authority_key_identifier().into(),
87             critical: false.into(),
88             extn_value: ExtensionValue::AuthorityKeyIdentifier(
89                 AuthorityKeyIdentifier {
90                     key_identifier: key_identifier.into().map(ContextTag0),
91                     authority_cert_issuer: authority_cert_issuer.into().map(ApplicationTag1),
92                     authority_cert_serial_number: authority_cert_serial_number.into().map(ContextTag2),
93                 }
94                 .into(),
95             ),
96         }
97     }
98 
99     /// Marking this extension as critical is always acceptable.
100     /// Check details here: https://tools.ietf.org/html/rfc5280#section-4.2.1.9
101     /// You may change this value using `into_non_critical` or `set_critical` methods.
102     ///
103     /// Default is critical.
new_basic_constraints<CA: Into<Option<bool>>, PLC: Into<Option<u8>>>( ca: CA, path_len_constraints: PLC, ) -> Self104     pub fn new_basic_constraints<CA: Into<Option<bool>>, PLC: Into<Option<u8>>>(
105         ca: CA,
106         path_len_constraints: PLC,
107     ) -> Self {
108         Self {
109             extn_id: oids::basic_constraints().into(),
110             critical: true.into(),
111             extn_value: ExtensionValue::BasicConstraints(
112                 BasicConstraints {
113                     ca: Implicit(ca.into()),
114                     path_len_constraint: Implicit(path_len_constraints.into()),
115                 }
116                 .into(),
117             ),
118         }
119     }
120 
121     /// This extension MAY, at the option of the certificate issuer, be either critical or non-critical.
122     /// Conforming CAs SHOULD NOT mark this extension as critical if the anyExtendedKeyUsage
123     /// KeyPurposeId is present.
124     ///
125     /// Default is non-critical if anyExtendedKeyUsage is present, critical otherwise.
new_extended_key_usage<EKU>(extended_key_usage: EKU) -> Self where EKU: Into<ExtendedKeyUsage>,126     pub fn new_extended_key_usage<EKU>(extended_key_usage: EKU) -> Self
127     where
128         EKU: Into<ExtendedKeyUsage>,
129     {
130         let eku = extended_key_usage.into();
131         Self {
132             extn_id: oids::extended_key_usage().into(),
133             critical: Implicit(!eku.contains(oids::kp_any_extended_key_usage())),
134             extn_value: ExtensionValue::ExtendedKeyUsage(eku.into()),
135         }
136     }
137 
138     /// If the subject field contains an empty sequence, then the issuing CA MUST include a
139     /// subjectAltName extension that is marked as critical. When including
140     /// the subjectAltName extension in a certificate that has a non-empty
141     /// subject distinguished name, conforming CAs SHOULD mark the
142     /// subjectAltName extension as non-critical.
143     ///
144     /// Default is critical.
new_subject_alt_name<N: Into<SubjectAltName>>(name: N) -> Self145     pub fn new_subject_alt_name<N: Into<SubjectAltName>>(name: N) -> Self {
146         let name = name.into();
147         Self {
148             extn_id: oids::subject_alternative_name().into(),
149             critical: true.into(),
150             extn_value: ExtensionValue::SubjectAltName(name.into()),
151         }
152     }
153 
154     /// Where present, conforming CAs SHOULD mark this extension as non-critical.
155     ///
156     /// Default is non-critical.
new_issuer_alt_name<N: Into<IssuerAltName>>(name: N) -> Self157     pub fn new_issuer_alt_name<N: Into<IssuerAltName>>(name: N) -> Self {
158         let name = name.into();
159         Self {
160             extn_id: oids::issuer_alternative_name().into(),
161             critical: false.into(),
162             extn_value: ExtensionValue::IssuerAltName(name.into()),
163         }
164     }
165 }
166 
167 impl ser::Serialize for Extension {
serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error> where S: ser::Serializer,168     fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
169     where
170         S: ser::Serializer,
171     {
172         use ser::SerializeSeq;
173         let mut seq = serializer.serialize_seq(Some(3))?;
174         seq.serialize_element(&self.extn_id)?;
175 
176         if self.critical.0 != bool::default() {
177             seq.serialize_element(&self.critical)?;
178         }
179 
180         seq.serialize_element(&self.extn_value)?;
181 
182         seq.end()
183     }
184 }
185 
186 impl<'de> de::Deserialize<'de> for Extension {
deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error> where D: de::Deserializer<'de>,187     fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
188     where
189         D: de::Deserializer<'de>,
190     {
191         struct Visitor;
192 
193         impl<'de> de::Visitor<'de> for Visitor {
194             type Value = Extension;
195 
196             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
197                 formatter.write_str("a valid DER-encoded algorithm identifier")
198             }
199 
200             fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
201             where
202                 A: de::SeqAccess<'de>,
203             {
204                 let id: ObjectIdentifierAsn1 = seq_next_element!(seq, Extension, "id");
205                 let critical: Implicit<bool> = seq_next_element!(seq, Extension, "critical");
206                 let value = match Into::<String>::into(&id.0).as_str() {
207                     oids::AUTHORITY_KEY_IDENTIFIER => ExtensionValue::AuthorityKeyIdentifier(seq_next_element!(
208                         seq,
209                         Extension,
210                         "AuthorityKeyIdentifier"
211                     )),
212                     oids::SUBJECT_KEY_IDENTIFIER => {
213                         ExtensionValue::SubjectKeyIdentifier(seq_next_element!(seq, Extension, "SubjectKeyIdentifier"))
214                     }
215                     oids::KEY_USAGE => ExtensionValue::KeyUsage(seq_next_element!(seq, Extension, "KeyUsage")),
216                     oids::SUBJECT_ALTERNATIVE_NAME => {
217                         ExtensionValue::SubjectAltName(seq_next_element!(seq, Extension, "SubjectAltName"))
218                     }
219                     oids::ISSUER_ALTERNATIVE_NAME => {
220                         ExtensionValue::IssuerAltName(seq_next_element!(seq, Extension, "IssuerAltName"))
221                     }
222                     oids::BASIC_CONSTRAINTS => {
223                         ExtensionValue::BasicConstraints(seq_next_element!(seq, Extension, "BasicConstraints"))
224                     }
225                     oids::EXTENDED_KEY_USAGE => {
226                         ExtensionValue::ExtendedKeyUsage(seq_next_element!(seq, Extension, "ExtendedKeyUsage"))
227                     }
228                     _ => ExtensionValue::Generic(seq_next_element!(seq, Extension, "Generic")),
229                 };
230 
231                 Ok(Extension {
232                     extn_id: id,
233                     critical,
234                     extn_value: value,
235                 })
236             }
237         }
238 
239         deserializer.deserialize_seq(Visitor)
240     }
241 }
242 
243 /// A view on an Extension's value designed to be easier to match on
244 #[derive(Debug, PartialEq, Clone)]
245 pub enum ExtensionView<'a> {
246     AuthorityKeyIdentifier(&'a AuthorityKeyIdentifier),
247     SubjectKeyIdentifier(&'a SubjectKeyIdentifier),
248     KeyUsage(&'a KeyUsage),
249     SubjectAltName(super::name::GeneralNames),
250     IssuerAltName(super::name::GeneralNames),
251     BasicConstraints(&'a BasicConstraints),
252     ExtendedKeyUsage(&'a ExtendedKeyUsage),
253     Generic(&'a OctetStringAsn1),
254 }
255 
256 impl<'a> From<&'a ExtensionValue> for ExtensionView<'a> {
from(value: &'a ExtensionValue) -> Self257     fn from(value: &'a ExtensionValue) -> Self {
258         match value {
259             ExtensionValue::AuthorityKeyIdentifier(OctetStringAsn1Container(val)) => Self::AuthorityKeyIdentifier(val),
260             ExtensionValue::SubjectKeyIdentifier(OctetStringAsn1Container(val)) => Self::SubjectKeyIdentifier(val),
261             ExtensionValue::KeyUsage(OctetStringAsn1Container(val)) => Self::KeyUsage(val),
262             ExtensionValue::SubjectAltName(OctetStringAsn1Container(val)) => Self::SubjectAltName(val.clone()),
263             ExtensionValue::IssuerAltName(OctetStringAsn1Container(val)) => Self::IssuerAltName(val.clone()),
264             ExtensionValue::BasicConstraints(OctetStringAsn1Container(val)) => Self::BasicConstraints(val),
265             ExtensionValue::ExtendedKeyUsage(OctetStringAsn1Container(val)) => Self::ExtendedKeyUsage(val),
266             ExtensionValue::Generic(val) => Self::Generic(val),
267         }
268     }
269 }
270 
271 #[derive(Debug, PartialEq, Clone)]
272 enum ExtensionValue {
273     AuthorityKeyIdentifier(OctetStringAsn1Container<AuthorityKeyIdentifier>),
274     SubjectKeyIdentifier(OctetStringAsn1Container<SubjectKeyIdentifier>),
275     KeyUsage(OctetStringAsn1Container<KeyUsage>),
276     //CertificatePolicies(OctetStringAsn1Container<Asn1SequenceOf<PolicyInformation>>),
277     //PolicyMappings(OctetStringAsn1Container<Asn1SequenceOfPolicyMapping>>),
278     SubjectAltName(OctetStringAsn1Container<SubjectAltName>),
279     IssuerAltName(OctetStringAsn1Container<IssuerAltName>),
280     //SubjectDirectoryAttributes(OctetStringAsn1Container<Asn1SequenceOf<Attribute>>),
281     BasicConstraints(OctetStringAsn1Container<BasicConstraints>),
282     //NameConstraints(…),
283     //PolicyConstraints(…),
284     ExtendedKeyUsage(OctetStringAsn1Container<ExtendedKeyUsage>),
285     //CRLDistributionPoints(…),
286     //InhibitAnyPolicy(…),
287     //FreshestCRL(…),
288     Generic(OctetStringAsn1),
289 }
290 
291 impl ser::Serialize for ExtensionValue {
serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error> where S: ser::Serializer,292     fn serialize<S>(&self, serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
293     where
294         S: ser::Serializer,
295     {
296         match self {
297             ExtensionValue::AuthorityKeyIdentifier(aki) => aki.serialize(serializer),
298             ExtensionValue::SubjectKeyIdentifier(ski) => ski.serialize(serializer),
299             ExtensionValue::KeyUsage(key_usage) => key_usage.serialize(serializer),
300             ExtensionValue::SubjectAltName(san) => san.serialize(serializer),
301             ExtensionValue::IssuerAltName(ian) => ian.serialize(serializer),
302             ExtensionValue::BasicConstraints(basic_constraints) => basic_constraints.serialize(serializer),
303             ExtensionValue::ExtendedKeyUsage(eku) => eku.serialize(serializer),
304             ExtensionValue::Generic(octet_string) => octet_string.serialize(serializer),
305         }
306     }
307 }
308 
309 /// [RFC 5280 #4.2.1.1](https://tools.ietf.org/html/rfc5280#section-4.2.1.1)
310 ///
311 /// ```not_rust
312 /// AuthorityKeyIdentifier ::= SEQUENCE {
313 ///     keyIdentifier             [0] KeyIdentifier           OPTIONAL,
314 ///     authorityCertIssuer       [1] GeneralNames            OPTIONAL,
315 ///     authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL  }
316 /// ```
317 #[derive(Serialize, Debug, PartialEq, Clone)]
318 pub struct AuthorityKeyIdentifier {
319     key_identifier: Option<ContextTag0<KeyIdentifier>>,
320     authority_cert_issuer: Option<ApplicationTag1<GeneralName>>,
321     authority_cert_serial_number: Option<ContextTag2<IntegerAsn1>>,
322 }
323 
324 impl AuthorityKeyIdentifier {
key_identifier(&self) -> Option<&[u8]>325     pub fn key_identifier(&self) -> Option<&[u8]> {
326         self.key_identifier.as_ref().map(|ki| (ki.0).0.as_slice())
327     }
328 
authority_cert_issuer(&self) -> Option<super::name::GeneralName>329     pub fn authority_cert_issuer(&self) -> Option<super::name::GeneralName> {
330         self.authority_cert_issuer.as_ref().map(|aci| aci.clone().0)
331     }
332 
authority_cert_serial_number(&self) -> Option<&IntegerAsn1>333     pub fn authority_cert_serial_number(&self) -> Option<&IntegerAsn1> {
334         self.authority_cert_serial_number.as_ref().map(|acsn| &acsn.0)
335     }
336 }
337 
338 pub type KeyIdentifier = OctetStringAsn1;
339 
340 impl<'de> de::Deserialize<'de> for AuthorityKeyIdentifier {
deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error> where D: de::Deserializer<'de>,341     fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
342     where
343         D: de::Deserializer<'de>,
344     {
345         struct Visitor;
346 
347         impl<'de> de::Visitor<'de> for Visitor {
348             type Value = AuthorityKeyIdentifier;
349 
350             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
351                 formatter.write_str("a valid DER-encoded algorithm identifier")
352             }
353 
354             fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
355             where
356                 A: de::SeqAccess<'de>,
357             {
358                 Ok(AuthorityKeyIdentifier {
359                     key_identifier: seq.next_element().unwrap_or(Some(None)).unwrap_or(None),
360                     authority_cert_issuer: seq.next_element().unwrap_or(Some(None)).unwrap_or(None),
361                     authority_cert_serial_number: seq.next_element().unwrap_or(Some(None)).unwrap_or(None),
362                 })
363             }
364         }
365 
366         deserializer.deserialize_seq(Visitor)
367     }
368 }
369 
370 /// [RFC 5280 #4.2.1.2](https://tools.ietf.org/html/rfc5280#section-4.2.1.2)
371 pub type SubjectKeyIdentifier = OctetStringAsn1;
372 
373 /// [RFC 5280 #4.2.1.3](https://tools.ietf.org/html/rfc5280#section-4.2.1.3)
374 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
375 pub struct KeyUsage(BitStringAsn1);
376 
377 impl Default for KeyUsage {
default() -> Self378     fn default() -> Self {
379         Self::new(9)
380     }
381 }
382 
383 macro_rules! bit_string_get_set {
384     ($getter:ident , $setter:ident , $idx:literal) => {
385         pub fn $getter(&self) -> bool {
386             self.0.is_set($idx)
387         }
388 
389         pub fn $setter(&mut self, val: bool) {
390             if self.0.get_num_bits() <= $idx {
391                 self.0.set_num_bits($idx + 1)
392             }
393             self.0.set($idx, val);
394         }
395     };
396     ( $( $getter:ident , $setter:ident , $idx:literal ; )+ ) => {
397         $( bit_string_get_set! { $getter, $setter, $idx } )+
398     };
399 }
400 
401 impl KeyUsage {
new(num_bits: usize) -> Self402     pub fn new(num_bits: usize) -> Self {
403         Self(BitString::with_len(num_bits).into())
404     }
405 
as_bytes(&self) -> &[u8]406     pub fn as_bytes(&self) -> &[u8] {
407         self.0.payload_view()
408     }
409 
410     bit_string_get_set! {
411         digital_signature, set_digital_signature, 0;
412         content_commitment, set_content_commitment, 1;
413         key_encipherment, set_key_encipherment, 2;
414         data_encipherment, set_data_encipherment, 3;
415         key_agreement, set_key_agreement, 4;
416         key_cert_sign, set_key_cert_sign, 5;
417         crl_sign, set_crl_sign, 6;
418         encipher_only, set_encipher_only, 7;
419         decipher_only, set_decipher_only, 8;
420     }
421 }
422 
423 /// [RFC 5280 #4.2.1.6](https://tools.ietf.org/html/rfc5280#section-4.2.1.6)
424 type SubjectAltName = GeneralNames;
425 
426 /// [RFC 5280 #4.2.1.7](https://tools.ietf.org/html/rfc5280#section-4.2.1.7)
427 type IssuerAltName = GeneralNames;
428 
429 /// [RFC 5280 #4.2.1.9](https://tools.ietf.org/html/rfc5280#section-4.2.1.9)
430 ///
431 /// ```not_rust
432 /// BasicConstraints ::= SEQUENCE {
433 ///      cA                      BOOLEAN DEFAULT FALSE,
434 ///      pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
435 /// ```
436 #[derive(Serialize, Debug, PartialEq, Clone)]
437 pub struct BasicConstraints {
438     ca: Implicit<Option<bool>>, // default is false
439     path_len_constraint: Implicit<Option<u8>>,
440 }
441 
442 impl BasicConstraints {
ca(&self) -> Option<bool>443     pub fn ca(&self) -> Option<bool> {
444         self.ca.0
445     }
446 
pathlen(&self) -> Option<u8>447     pub fn pathlen(&self) -> Option<u8> {
448         self.path_len_constraint.0
449     }
450 }
451 
452 impl<'de> de::Deserialize<'de> for BasicConstraints {
deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error> where D: de::Deserializer<'de>,453     fn deserialize<D>(deserializer: D) -> Result<Self, <D as de::Deserializer<'de>>::Error>
454     where
455         D: de::Deserializer<'de>,
456     {
457         struct Visitor;
458 
459         impl<'de> de::Visitor<'de> for Visitor {
460             type Value = BasicConstraints;
461 
462             fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
463                 formatter.write_str("a valid DER-encoded basic constraints extension")
464             }
465 
466             fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
467             where
468                 A: de::SeqAccess<'de>,
469             {
470                 Ok(BasicConstraints {
471                     ca: Implicit(seq.next_element().unwrap_or(Some(None)).unwrap_or(None)),
472                     path_len_constraint: Implicit(seq.next_element().unwrap_or(Some(None)).unwrap_or(None)),
473                 })
474             }
475         }
476 
477         deserializer.deserialize_seq(Visitor)
478     }
479 }
480 
481 /// [RFC 5280 #4.2.1.12](https://tools.ietf.org/html/rfc5280#section-4.2.1.12)
482 #[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
483 pub struct ExtendedKeyUsage(Asn1SequenceOf<ObjectIdentifierAsn1>);
484 
485 impl<OID: Into<ObjectIdentifierAsn1>> From<Vec<OID>> for ExtendedKeyUsage {
from(purpose_oids: Vec<OID>) -> Self486     fn from(purpose_oids: Vec<OID>) -> Self {
487         ExtendedKeyUsage::new(purpose_oids)
488     }
489 }
490 
491 impl ExtendedKeyUsage {
new<OID: Into<ObjectIdentifierAsn1>>(purpose_oids: Vec<OID>) -> Self492     pub fn new<OID: Into<ObjectIdentifierAsn1>>(purpose_oids: Vec<OID>) -> Self {
493         Self(
494             purpose_oids
495                 .into_iter()
496                 .map(|oid| oid.into())
497                 .collect::<Vec<_>>()
498                 .into(),
499         )
500     }
501 
iter(&self) -> Iter<ObjectIdentifierAsn1>502     pub fn iter(&self) -> Iter<ObjectIdentifierAsn1> {
503         (self.0).0.iter()
504     }
505 
iter_mut(&mut self) -> IterMut<ObjectIdentifierAsn1>506     pub fn iter_mut(&mut self) -> IterMut<ObjectIdentifierAsn1> {
507         (self.0).0.iter_mut()
508     }
509 
contains<C: PartialEq<oid::ObjectIdentifier>>(&self, item: C) -> bool510     pub fn contains<C: PartialEq<oid::ObjectIdentifier>>(&self, item: C) -> bool {
511         (self.0).0.iter().any(|id| item.eq(&id.0))
512     }
513 }
514 
515 #[cfg(test)]
516 mod tests {
517     use super::*;
518     use crate::GeneralName;
519     use picky_asn1::restricted_string::IA5String;
520 
521     #[test]
key_usage()522     fn key_usage() {
523         let encoded: [u8; 4] = [0x03, 0x02, 0x01, 0xA0];
524         let mut key_usage = KeyUsage::new(7);
525         key_usage.set_digital_signature(true);
526         key_usage.set_key_encipherment(true);
527         assert_eq!(key_usage.as_bytes(), &[0xA0]);
528         check_serde!(key_usage: KeyUsage in encoded);
529     }
530 
531     #[test]
eku_ku_bc_san_extensions()532     fn eku_ku_bc_san_extensions() {
533         let cert_der = base64::decode(
534             "MIIDIjCCAgoCAQAwIDELMAkGA1UEBhMCRlIxETAPBgNVBAMMCERyYXBlYXUhMIIB\
535                            IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5GqDEM7AfctJizsFEqtAvXd5\
536                            Fl1GtyXDAnx68MUTuSL22t8aBZoCCi3/9AlS75uUqKggHnRuY2MRYPQaUzpE1F1a\
537                            aZJNr6tXQy39FtdXrDq2zfwZdDmLW6sPmhvJrBO4yWjuG3wh1paPHy+rBHOjYt+9\
538                            Pbl/FmDDjIzF8B2LZDuLdnS94Fs/JhogJL/XF4b6RLW60gEnYFjL+ebYdV/f3JYi\
539                            ccQxY4imvbB2URlIO3t+aG9WMmhHZbbOi/HBdFG1fB7Hsa9Ek2FXshULzEDCJcMz\
540                            n8HD96XbVBmlaz9nYIcZ83eCOhra67FfFy4pIE1M9saxYJg/OJrMHG12r89yUQID\
541                            AQABoIG8MIG5BgkqhkiG9w0BCQ4xgaswgagwCQYDVR0TBAIwADALBgNVHQ8EBAMC\
542                            BeAwJwYDVR0lBCAwHgYIKwYBBQUHAwIGCCsGAQUFBwMBBggrBgEFBQcDAzBlBgNV\
543                            HREEXjBcghFkZXZlbC5leGFtcGxlLmNvbYIQaXB2Ni5leGFtcGxlLmNvbYIQaXB2\
544                            NC5leGFtcGxlLmNvbYIQdGVzdC5leGFtcGxlLmNvbYIRcGFydHkuZXhhbXBsZS5j\
545                            b20wDQYJKoZIhvcNAQELBQADggEBANaSDnpQUGcGypAaafJKAGME2Od8F4pvKjKF\
546                            lREoWC7JFGIGE/pUrnvrE7qIFmCM3mnFWXEHvResFsdPmEWar+1jMdFinxBg0+J+\
547                            Op0fxOwfHpxs++8hPsQgnDdL9pIjYFwmIAm64jnyq6wsYIl5CpkvBjGVRVddXkTb\
548                            VDWhWaGncSdDur6++dp2OAGYTAv4XIHc0nhtcBoxeL4VhjcuksOdGg3JF02gW6Rc\
549                            B1gipqD0jun8kPgWcQY22zhmP2HuPp0y58t9cu9FsnUcAFa//5pQA1LuaSFp65D4\
550                            92uaByS3lH18xzrkygzn1BeHRpo0fk4I9Rk8uy2QygCk43Pv6SU=",
551         )
552         .expect("cert der");
553 
554         let encoded = &cert_der[359..359 + 3 + 168];
555 
556         let mut key_usage = KeyUsage::new(3);
557         key_usage.set_digital_signature(true);
558         key_usage.set_content_commitment(true);
559         key_usage.set_key_encipherment(true);
560 
561         let extensions = Extensions(vec![
562             Extension::new_basic_constraints(None, None).into_non_critical(),
563             Extension::new_key_usage(key_usage).into_non_critical(),
564             Extension::new_extended_key_usage(vec![
565                 oids::kp_client_auth(),
566                 oids::kp_server_auth(),
567                 oids::kp_code_signing(),
568             ])
569             .into_non_critical(),
570             Extension::new_subject_alt_name(vec![
571                 GeneralName::DNSName(IA5String::from_string("devel.example.com".into()).unwrap().into()),
572                 GeneralName::DNSName(IA5String::from_string("ipv6.example.com".into()).unwrap().into()),
573                 GeneralName::DNSName(IA5String::from_string("ipv4.example.com".into()).unwrap().into()),
574                 GeneralName::DNSName(IA5String::from_string("test.example.com".into()).unwrap().into()),
575                 GeneralName::DNSName(IA5String::from_string("party.example.com".into()).unwrap().into()),
576             ])
577             .into_non_critical(),
578         ]);
579 
580         check_serde!(extensions: Extensions in encoded);
581     }
582 }
583