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