1use core::fmt::{self, Write};
19
20use num::FromPrimitive;
21use num_derive::FromPrimitive;
22
23use crate::crypto::{Crypto, PublicKey};
24use crate::dm::clusters::time_sync::UtcTime;
25use crate::error::{Error, ErrorCode};
26use crate::tlv::{FromTLV, Octets, TLVArray, TLVElement, TLVList, ToTLV};
27use crate::utils::epoch::MATTER_CERT_DOESNT_EXPIRE;
28use crate::utils::iter::TryFindIterator;
29
30use self::printer::CertPrinter;
31
32pub use self::asn1_writer::ASN1Writer;
33
34mod asn1_writer;
35pub mod der_utils;
36pub mod gen;
37mod printer;
38pub mod x509;
39
40pub const MAX_CERT_TLV_LEN: usize = 400;
42pub const MAX_CERT_ASN1_LEN: usize = 600;
45pub const MAX_CERT_TLV_AND_ASN1_LEN: usize = MAX_CERT_TLV_LEN + MAX_CERT_ASN1_LEN;
48
49const OID_PUB_KEY_ECPUBKEY: [u8; 7] = [0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01];
52const OID_EC_TYPE_PRIME256V1: [u8; 8] = [0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07];
53const OID_ECDSA_WITH_SHA256: [u8; 8] = [0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02];
54
55const MAX_DEPTH: usize = 10;
56
57#[derive(FromPrimitive)]
58pub enum CertTag {
59 SerialNum = 1,
60 SignAlgo = 2,
61 Issuer = 3,
62 NotBefore = 4,
63 NotAfter = 5,
64 Subject = 6,
65 PubKeyAlgo = 7,
66 EcCurveId = 8,
67 EcPubKey = 9,
68 Extensions = 10,
69 Signature = 11,
70}
71
72#[derive(FromPrimitive, Debug)]
73#[cfg_attr(feature = "defmt", derive(defmt::Format))]
74pub enum EcCurveIdValue {
75 Prime256V1 = 1,
76}
77
78pub fn get_ec_curve_id(algo: u8) -> Option<EcCurveIdValue> {
79 num::FromPrimitive::from_u8(algo)
80}
81
82#[derive(FromPrimitive, Debug)]
83#[cfg_attr(feature = "defmt", derive(defmt::Format))]
84pub enum PubKeyAlgoValue {
85 EcPubKey = 1,
86}
87
88pub fn get_pubkey_algo(algo: u8) -> Option<PubKeyAlgoValue> {
89 num::FromPrimitive::from_u8(algo)
90}
91
92#[derive(FromPrimitive, Debug)]
93#[cfg_attr(feature = "defmt", derive(defmt::Format))]
94pub enum SignAlgoValue {
95 ECDSAWithSHA256 = 1,
96}
97
98pub fn get_sign_algo(algo: u8) -> Option<SignAlgoValue> {
99 num::FromPrimitive::from_u8(algo)
100}
101
102#[derive(Default, Debug, Clone, FromTLV, ToTLV, PartialEq, Eq, Hash)]
103#[cfg_attr(feature = "defmt", derive(defmt::Format))]
104#[tlvargs(start = 1)]
105struct BasicConstraints {
106 is_ca: bool,
107 path: Option<u8>,
108}
109
110impl BasicConstraints {
111 pub fn encode(&self, w: &mut dyn CertConsumer) -> Result<(), Error> {
112 w.start_seq("")?;
113 if self.is_ca {
114 w.bool("CA:", true)?;
116 }
117 if let Some(len) = self.path {
118 w.integer("Path Len Constraint", &[len])?;
119 }
120 w.end_seq()
121 }
122}
123
124#[derive(Debug, Clone, FromTLV, ToTLV, PartialEq, Eq, Hash)]
137#[cfg_attr(feature = "defmt", derive(defmt::Format))]
138#[tlvargs(start = 1, lifetime = "'a", datatype = "naked")]
139enum Extension<'a> {
140 BasicConstraints(BasicConstraints),
141 KeyUsage(u16),
142 ExtKeyUsage(TLVArray<'a, u8>),
143 SubjectKeyId(Octets<'a>),
144 AuthorityKeyId(Octets<'a>),
145 FutureExtensions(Octets<'a>),
146}
147
148impl<'a> Extension<'a> {
149 fn encode_all(
150 iter: impl Iterator<Item = Result<Self, Error>> + 'a,
151 w: &mut dyn CertConsumer,
152 ) -> Result<(), Error> {
153 w.start_ctx("X509v3 extensions:", 3)?;
154 w.start_seq("")?;
155
156 for extension in iter {
157 extension?.encode(w)?;
158 }
159
160 w.end_seq()?;
161 w.end_ctx()?;
162
163 Ok(())
164 }
165
166 fn encode(&self, w: &mut dyn CertConsumer) -> Result<(), Error> {
167 const OID_BASIC_CONSTRAINTS: [u8; 3] = [0x55, 0x1D, 0x13];
168 const OID_KEY_USAGE: [u8; 3] = [0x55, 0x1D, 0x0F];
169 const OID_EXT_KEY_USAGE: [u8; 3] = [0x55, 0x1D, 0x25];
170 const OID_SUBJ_KEY_IDENTIFIER: [u8; 3] = [0x55, 0x1D, 0x0E];
171 const OID_AUTH_KEY_ID: [u8; 3] = [0x55, 0x1D, 0x23];
172
173 match self {
174 Extension::BasicConstraints(t) => {
175 Self::encode_extension_start(
176 "X509v3 Basic Constraints",
177 true,
178 &OID_BASIC_CONSTRAINTS,
179 w,
180 )?;
181 t.encode(w)?;
182 Self::encode_extension_end(w)?;
183 }
184 Extension::KeyUsage(t) => {
185 Self::encode_extension_start("X509v3 Key Usage", true, &OID_KEY_USAGE, w)?;
186 Self::encode_key_usage(*t, w)?;
187 Self::encode_extension_end(w)?;
188 }
189 Extension::ExtKeyUsage(t) => {
190 Self::encode_extension_start(
191 "X509v3 Extended Key Usage",
192 true,
193 &OID_EXT_KEY_USAGE,
194 w,
195 )?;
196 Self::encode_extended_key_usage(t.iter(), w)?;
197 Self::encode_extension_end(w)?;
198 }
199 Extension::SubjectKeyId(t) => {
200 Self::encode_extension_start("Subject Key ID", false, &OID_SUBJ_KEY_IDENTIFIER, w)?;
201 w.ostr("", t.0)?;
202 Self::encode_extension_end(w)?;
203 }
204 Extension::AuthorityKeyId(t) => {
205 Self::encode_extension_start("Auth Key ID", false, &OID_AUTH_KEY_ID, w)?;
206 w.start_seq("")?;
207 w.ctx("", 0, t.0)?;
208 w.end_seq()?;
209 Self::encode_extension_end(w)?;
210 }
211 Extension::FutureExtensions(t) => {
212 w.raw("Future Extensions", t.0)?;
219 }
220 }
221
222 Ok(())
223 }
224
225 fn encode_extension_start(
226 tag: &str,
227 critical: bool,
228 oid: &[u8],
229 w: &mut dyn CertConsumer,
230 ) -> Result<(), Error> {
231 w.start_seq(tag)?;
232 w.oid("", oid)?;
233 if critical {
234 w.bool("critical:", true)?;
235 }
236 w.start_compound_ostr("value:")
237 }
238
239 fn encode_extension_end(w: &mut dyn CertConsumer) -> Result<(), Error> {
240 w.end_compound_ostr()?;
241 w.end_seq()
242 }
243
244 #[allow(unused_assignments)]
245 fn encode_key_usage(key_usage: u16, w: &mut dyn CertConsumer) -> Result<(), Error> {
246 let mut key_usage_str = [0u8; 2];
247 Self::int_to_bitstring(key_usage, &mut key_usage_str);
248 w.bitstr(&Self::get_print_str(key_usage), true, &key_usage_str)?;
249 Ok(())
250 }
251
252 fn encode_extended_key_usage(
253 list: impl Iterator<Item = Result<u8, Error>>,
254 w: &mut dyn CertConsumer,
255 ) -> Result<(), Error> {
256 const OID_SERVER_AUTH: [u8; 8] = [0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01];
257 const OID_CLIENT_AUTH: [u8; 8] = [0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02];
258 const OID_CODE_SIGN: [u8; 8] = [0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03];
259 const OID_EMAIL_PROT: [u8; 8] = [0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x04];
260 const OID_TIMESTAMP: [u8; 8] = [0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08];
261 const OID_OCSP_SIGN: [u8; 8] = [0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x09];
262 let encoding = [
263 ("", &[0; 8]),
264 ("ServerAuth", &OID_SERVER_AUTH),
265 ("ClientAuth", &OID_CLIENT_AUTH),
266 ("CodeSign", &OID_CODE_SIGN),
267 ("EmailProtection", &OID_EMAIL_PROT),
268 ("Timestamp", &OID_TIMESTAMP),
269 ("OCSPSign", &OID_OCSP_SIGN),
270 ];
271
272 w.start_seq("")?;
273 for t in list {
274 let t = t? as usize;
275 if t > 0 && t <= encoding.len() {
276 w.oid(encoding[t].0, encoding[t].1)?;
277 } else {
278 error!("Skipping encoding key usage out of bounds");
279 }
280 }
281 w.end_seq()
282 }
283
284 fn get_print_str(key_usage: u16) -> heapless::String<256> {
285 const KEY_USAGE_DIGITAL_SIGN: u16 = 0x0001;
286 const KEY_USAGE_NON_REPUDIATION: u16 = 0x0002;
287 const KEY_USAGE_KEY_ENCIPHERMENT: u16 = 0x0004;
288 const KEY_USAGE_DATA_ENCIPHERMENT: u16 = 0x0008;
289 const KEY_USAGE_KEY_AGREEMENT: u16 = 0x0010;
290 const KEY_USAGE_KEY_CERT_SIGN: u16 = 0x0020;
291 const KEY_USAGE_CRL_SIGN: u16 = 0x0040;
292 const KEY_USAGE_ENCIPHER_ONLY: u16 = 0x0080;
293 const KEY_USAGE_DECIPHER_ONLY: u16 = 0x0100;
294
295 macro_rules! add_if {
296 ($key:ident, $bit:ident,$str:literal) => {
297 if ($key & $bit) != 0 {
298 $str
299 } else {
300 ""
301 }
302 };
303 }
304
305 let mut string = heapless::String::new();
306 write_unwrap!(
307 &mut string,
308 "{}{}{}{}{}{}{}{}{}",
309 add_if!(key_usage, KEY_USAGE_DIGITAL_SIGN, "digitalSignature "),
310 add_if!(key_usage, KEY_USAGE_NON_REPUDIATION, "nonRepudiation "),
311 add_if!(key_usage, KEY_USAGE_KEY_ENCIPHERMENT, "keyEncipherment "),
312 add_if!(key_usage, KEY_USAGE_DATA_ENCIPHERMENT, "dataEncipherment "),
313 add_if!(key_usage, KEY_USAGE_KEY_AGREEMENT, "keyAgreement "),
314 add_if!(key_usage, KEY_USAGE_KEY_CERT_SIGN, "keyCertSign "),
315 add_if!(key_usage, KEY_USAGE_CRL_SIGN, "CRLSign "),
316 add_if!(key_usage, KEY_USAGE_ENCIPHER_ONLY, "encipherOnly "),
317 add_if!(key_usage, KEY_USAGE_DECIPHER_ONLY, "decipherOnly "),
318 );
319
320 string
321 }
322
323 fn int_to_bitstring(mut a: u16, buf: &mut [u8]) {
324 if buf.len() >= 2 {
325 buf[0] = Self::reverse_byte((a & 0xff) as u8);
326 a >>= 8;
327 buf[1] = Self::reverse_byte((a & 0xff) as u8);
328 }
329 }
330
331 fn reverse_byte(byte: u8) -> u8 {
332 const LOOKUP: [u8; 16] = [
333 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e, 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b,
334 0x07, 0x0f,
335 ];
336 (LOOKUP[(byte & 0x0f) as usize] << 4) | LOOKUP[(byte >> 4) as usize]
337 }
338}
339
340#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, FromPrimitive)]
341#[cfg_attr(feature = "defmt", derive(defmt::Format))]
342#[repr(u8)]
343enum DNTag {
344 CommonName = 1,
345 Surname = 2,
346 SerialNum = 3,
347 CountryName = 4,
348 LocalityName = 5,
349 StateName = 6,
350 OrgName = 7,
351 OrgUnitName = 8,
352 Title = 9,
353 Name = 10,
354 GivenName = 11,
355 Intials = 12,
356 GenQalifier = 13,
357 DnQualifier = 14,
358 Pseudonym = 15,
359 DomainComponent = 16,
360 NodeId = 17,
361 FirmwareSignId = 18,
362 IcaId = 19,
363 RootCaId = 20,
364 FabricId = 21,
365 NocCat = 22,
366}
367
368#[derive(Debug, Clone, PartialEq, Eq, Hash)]
369#[cfg_attr(feature = "defmt", derive(defmt::Format))]
370enum DNValue<'a> {
371 Uint(u64),
372 Utf8(&'a str),
373 PrintableStr(&'a str),
374}
375
376#[derive(FromTLV, ToTLV, Debug, Clone, PartialEq, Eq, Hash)]
377#[cfg_attr(feature = "defmt", derive(defmt::Format))]
378#[tlvargs(lifetime = "'a")]
379struct DN<'a>(TLVElement<'a>);
380
381impl<'a> DN<'a> {
382 pub fn tag(&self) -> Result<DNTag, Error> {
383 let ctx = self.0.try_ctx()?.ok_or(ErrorCode::Invalid)? & 0x7f;
384
385 Ok(DNTag::from_u8(ctx).ok_or(ErrorCode::Invalid)?)
386 }
387
388 pub fn is_printable(&self) -> Result<bool, Error> {
389 let ctx = self.0.try_ctx()?.ok_or(ErrorCode::Invalid)?;
390
391 Ok(ctx >= 0x80)
392 }
393
394 fn uint(&self) -> Result<u64, Error> {
395 self.0.u64()
396 }
397
398 fn value(&self) -> Result<DNValue<'a>, Error> {
399 if let Ok(value) = self.0.utf8() {
400 if self.is_printable()? {
401 Ok(DNValue::PrintableStr(value))
402 } else {
403 Ok(DNValue::Utf8(value))
404 }
405 } else {
406 self.0.u64().map(DNValue::Uint)
407 }
408 }
409
410 fn encode_all(
411 values: impl Iterator<Item = Result<Self, Error>> + 'a,
412 tag: &str,
413 w: &mut dyn CertConsumer,
414 ) -> Result<(), Error> {
415 const OID_COMMON_NAME: [u8; 3] = [0x55_u8, 0x04, 0x03];
416 const OID_SURNAME: [u8; 3] = [0x55_u8, 0x04, 0x04];
417 const OID_SERIAL_NUMBER: [u8; 3] = [0x55_u8, 0x04, 0x05];
418 const OID_COUNTRY_NAME: [u8; 3] = [0x55_u8, 0x04, 0x06];
419 const OID_LOCALITY_NAME: [u8; 3] = [0x55_u8, 0x04, 0x07];
420 const OID_STATE_NAME: [u8; 3] = [0x55_u8, 0x04, 0x08];
421 const OID_ORGANIZATION_NAME: [u8; 3] = [0x55_u8, 0x04, 0x0A];
422 const OID_ORGANIZATIONAL_UNIT_NAME: [u8; 3] = [0x55_u8, 0x04, 0x0B];
423 const OID_TITLE: [u8; 3] = [0x55_u8, 0x04, 0x0C];
424 const OID_NAME: [u8; 3] = [0x55_u8, 0x04, 0x29];
425 const OID_GIVEN_NAME: [u8; 3] = [0x55_u8, 0x04, 0x2A];
426 const OID_INITIALS: [u8; 3] = [0x55_u8, 0x04, 0x2B];
427 const OID_GENERATION_QUALIFIER: [u8; 3] = [0x55_u8, 0x04, 0x2C];
428 const OID_DN_QUALIFIER: [u8; 3] = [0x55_u8, 0x04, 0x2E];
429 const OID_PSEUDONYM: [u8; 3] = [0x55_u8, 0x04, 0x41];
430 const OID_DOMAIN_COMPONENT: [u8; 10] = [
431 0x09_u8, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19,
432 ];
433 const OID_MATTER_NODE_ID: [u8; 10] = [
434 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x01,
435 ];
436 const OID_MATTER_FW_SIGNING_ID: [u8; 10] = [
437 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x02,
438 ];
439 const OID_MATTER_ICAC_ID: [u8; 10] = [
440 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x03,
441 ];
442 const OID_MATTER_RCAC_ID: [u8; 10] = [
443 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x04,
444 ];
445 const OID_MATTER_FABRIC_ID: [u8; 10] = [
446 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x05,
447 ];
448 const OID_MATTER_CASE_AUTH_TAG: [u8; 10] = [
449 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x06,
450 ];
451
452 const DN_ENCODING: [(&str, &[u8], Option<IntToStringLen>); 22] = [
453 ("Common Name:", &OID_COMMON_NAME, None),
454 ("Surname:", &OID_SURNAME, None),
455 ("Serial Number", &OID_SERIAL_NUMBER, None),
456 ("Country Name", &OID_COUNTRY_NAME, None),
457 ("Locality name", &OID_LOCALITY_NAME, None),
458 ("State Name", &OID_STATE_NAME, None),
459 ("Org Name", &OID_ORGANIZATION_NAME, None),
460 ("OU Name", &OID_ORGANIZATIONAL_UNIT_NAME, None),
461 ("Title", &OID_TITLE, None),
462 ("Name", &OID_NAME, None),
463 ("Given Name", &OID_GIVEN_NAME, None),
464 ("Initials", &OID_INITIALS, None),
465 ("Gen Qualifier", &OID_GENERATION_QUALIFIER, None),
466 ("DN Qualifier", &OID_DN_QUALIFIER, None),
467 ("Pseudonym", &OID_PSEUDONYM, None),
468 ("Domain Component", &OID_DOMAIN_COMPONENT, None),
469 (
470 "Chip Node Id:",
471 &OID_MATTER_NODE_ID,
472 Some(IntToStringLen::Len16),
473 ),
474 (
475 "Chip Firmware Signing Id:",
476 &OID_MATTER_FW_SIGNING_ID,
477 Some(IntToStringLen::Len16),
478 ),
479 (
480 "Chip ICA Id:",
481 &OID_MATTER_ICAC_ID,
482 Some(IntToStringLen::Len16),
483 ),
484 (
485 "Chip Root CA Id:",
486 &OID_MATTER_RCAC_ID,
487 Some(IntToStringLen::Len16),
488 ),
489 (
490 "Chip Fabric Id:",
491 &OID_MATTER_FABRIC_ID,
492 Some(IntToStringLen::Len16),
493 ),
494 (
495 "Chip NOC CAT Id:",
496 &OID_MATTER_CASE_AUTH_TAG,
497 Some(IntToStringLen::Len8),
498 ),
499 ];
500
501 w.start_seq(tag)?;
502 for dn in values {
503 let dn = dn?;
504 let tag = dn.tag();
505
506 if let Ok(tag) = &tag {
507 let index = *tag as usize - 1;
508 if index <= DN_ENCODING.len() {
509 let this = &DN_ENCODING[index];
510 dn.encode(this.0, this.1, w, this.2)?;
511 } else {
512 error!("Invalid DN, too high {:?}", tag);
514 }
515 } else {
516 error!("Non Matter DNs are not yet supported {:?}", tag);
518 }
519 }
520 w.end_seq()?;
521 Ok(())
522 }
523
524 fn encode(
525 &self,
526 name: &str,
527 oid: &[u8],
528 w: &mut dyn CertConsumer,
529 expected_len: Option<IntToStringLen>,
531 ) -> Result<(), Error> {
532 w.start_set("")?;
533 w.start_seq("")?;
534 w.oid(name, oid)?;
535 match self.value()? {
536 DNValue::Uint(v) => match expected_len {
537 Some(IntToStringLen::Len16) => {
538 let mut string = heapless::String::<32>::new();
539 write_unwrap!(&mut string, "{:016X}", v);
540 w.utf8str("", &string)?
541 }
542 Some(IntToStringLen::Len8) => {
543 let mut string = heapless::String::<32>::new();
544 write_unwrap!(&mut string, "{:08X}", v);
545 w.utf8str("", &string)?
546 }
547 _ => {
548 error!("Invalid encoding");
549 Err(ErrorCode::Invalid)?
550 }
551 },
552 DNValue::Utf8(v) => {
553 w.utf8str("", v)?;
554 }
555 DNValue::PrintableStr(v) => {
556 w.printstr("", v)?;
557 }
558 }
559 w.end_seq()?;
560 w.end_set()
561 }
562}
563
564#[derive(Copy, Clone)]
565enum IntToStringLen {
567 Len16,
568 Len8,
569}
570
571#[derive(FromTLV, ToTLV, Debug, Clone, PartialEq, Eq, Hash)]
572#[cfg_attr(feature = "defmt", derive(defmt::Format))]
573#[tlvargs(lifetime = "'a")]
574pub struct CertRef<'a>(TLVElement<'a>);
575
576impl<'a> CertRef<'a> {
577 pub const fn new(tlv: TLVElement<'a>) -> Self {
578 Self(tlv)
579 }
580
581 fn serial_no(&self) -> Result<&[u8], Error> {
582 self.0.structure()?.find_ctx(1)?.str()
583 }
584
585 fn sign_algo(&self) -> Result<u8, Error> {
586 self.0.structure()?.find_ctx(2)?.u8()
587 }
588
589 fn issuer(&self) -> Result<TLVList<'a, DN<'a>>, Error> {
590 TLVList::new(self.0.structure()?.find_ctx(3)?)
591 }
592
593 fn not_before(&self) -> Result<u32, Error> {
594 self.0.structure()?.find_ctx(4)?.u32()
595 }
596
597 fn not_after(&self) -> Result<u32, Error> {
598 self.0.structure()?.find_ctx(5)?.u32()
599 }
600
601 fn subject(&self) -> Result<TLVList<'a, DN<'a>>, Error> {
602 TLVList::new(self.0.structure()?.find_ctx(6)?)
603 }
604
605 fn pubkey_algo(&self) -> Result<u8, Error> {
606 self.0.structure()?.find_ctx(7)?.u8()
607 }
608
609 fn ec_curve_id(&self) -> Result<u8, Error> {
610 self.0.structure()?.find_ctx(8)?.u8()
611 }
612
613 pub fn pubkey(&self) -> Result<&[u8], Error> {
614 self.0.structure()?.find_ctx(9)?.str()
615 }
616
617 fn extensions(&self) -> Result<TLVList<'a, Extension<'a>>, Error> {
618 TLVList::new(self.0.structure()?.find_ctx(10)?)
619 }
620
621 fn signature(&self) -> Result<&[u8], Error> {
622 self.0.structure()?.find_ctx(11)?.str()
623 }
624
625 pub fn get_node_id(&self) -> Result<u64, Error> {
626 let dn = self
627 .subject()?
628 .iter()
629 .do_try_find(|dn| Ok(dn.tag()? == DNTag::NodeId))?
630 .ok_or(ErrorCode::NoNodeId)?;
631
632 dn.uint()
633 }
634
635 pub fn get_cat_ids(&self, output: &mut [u32]) -> Result<(), Error> {
636 let mut offset = 0;
637
638 self.subject()?.iter().try_for_each(|dn| {
639 let dn = dn?;
640
641 if dn.tag()? == DNTag::NocCat {
642 if offset == output.len() {
643 Err(ErrorCode::InvalidData)?;
644 }
645
646 output[offset] = dn.uint()? as u32;
647 offset += 1;
648 }
649
650 Ok(())
651 })
652 }
653
654 pub fn get_fabric_id(&self) -> Result<u64, Error> {
655 let dn = self
656 .subject()?
657 .iter()
658 .do_try_find(|dn| Ok(dn.tag()? == DNTag::FabricId))?
659 .ok_or(ErrorCode::NoFabricId)?;
660
661 dn.uint()
662 }
663
664 pub fn get_ca_id(&self) -> Result<u64, Error> {
670 let dn = self
671 .subject()?
672 .iter()
673 .do_try_find(|dn| {
674 let tag = dn.tag()?;
675 Ok(tag == DNTag::RootCaId || tag == DNTag::IcaId)
676 })?
677 .ok_or(ErrorCode::InvalidData)?;
678
679 dn.uint()
680 }
681
682 fn get_subject_key_id(&self) -> Result<&[u8], Error> {
683 let extension = self
684 .extensions()?
685 .iter()
686 .do_try_find(|extension| Ok(matches!(extension, Extension::SubjectKeyId(_))))?
687 .ok_or(Error::new(ErrorCode::Invalid))?;
688
689 let Extension::SubjectKeyId(id) = extension else {
690 unreachable!();
691 };
692
693 Ok(id.0)
694 }
695
696 fn basic_constraints(&self) -> Result<Option<(bool, Option<u8>)>, Error> {
702 let ext = self
703 .extensions()?
704 .iter()
705 .do_try_find(|e| Ok(matches!(e, Extension::BasicConstraints(_))))?;
706
707 Ok(match ext {
708 Some(Extension::BasicConstraints(bc)) => Some((bc.is_ca, bc.path)),
709 _ => None,
710 })
711 }
712
713 pub fn basic_constraints_path_len(&self) -> Result<Option<u8>, Error> {
720 Ok(self.basic_constraints()?.and_then(|(_, p)| p))
721 }
722
723 fn has_critical_future_extension(&self) -> Result<bool, Error> {
732 for ext in self.extensions()?.iter() {
733 if let Extension::FutureExtensions(bytes) = ext? {
734 if der_blob_has_critical_extension(bytes.0)? {
735 return Ok(true);
736 }
737 }
738 }
739 Ok(false)
740 }
741
742 fn key_usage(&self) -> Result<Option<u16>, Error> {
745 let ext = self
746 .extensions()?
747 .iter()
748 .do_try_find(|e| Ok(matches!(e, Extension::KeyUsage(_))))?;
749
750 Ok(match ext {
751 Some(Extension::KeyUsage(bits)) => Some(bits),
752 _ => None,
753 })
754 }
755
756 fn ext_key_usage_has_all(&self, required: &[u8]) -> Result<bool, Error> {
763 let ext = self
764 .extensions()?
765 .iter()
766 .do_try_find(|e| Ok(matches!(e, Extension::ExtKeyUsage(_))))?;
767
768 let Some(Extension::ExtKeyUsage(list)) = ext else {
769 return Ok(false);
770 };
771
772 for need in required {
773 let mut found = false;
774 for v in list.iter() {
775 if v? == *need {
776 found = true;
777 break;
778 }
779 }
780
781 if !found {
782 return Ok(false);
783 }
784 }
785
786 Ok(true)
787 }
788
789 fn cert_type(&self) -> Result<MatterCertType, Error> {
796 for dn in self.subject()?.iter() {
797 match dn?.tag()? {
798 DNTag::NodeId => return Ok(MatterCertType::Noc),
799 DNTag::IcaId => return Ok(MatterCertType::Icac),
800 DNTag::RootCaId => return Ok(MatterCertType::Rcac),
801 _ => {}
802 }
803 }
804
805 Err(ErrorCode::InvalidData.into())
806 }
807
808 fn is_authority(&self, their: &CertRef) -> Result<bool, Error> {
809 let their_subject = their.get_subject_key_id()?;
810
811 let authority = self.extensions()?.iter().do_try_find(|extension| {
812 Ok(if let Extension::AuthorityKeyId(id) = extension {
813 id.0 == their_subject
814 } else {
815 false
816 })
817 })?;
818
819 Ok(authority.is_some())
820 }
821
822 pub fn is_self_signed(&self) -> Result<bool, Error> {
826 self.is_authority(self)
827 }
828
829 pub fn as_asn1(&self, buf: &mut [u8]) -> Result<usize, Error> {
830 let mut w = ASN1Writer::new(buf);
831 self.encode(&mut w)?;
832 Ok(w.as_slice().len())
833 }
834
835 pub fn verify_chain_start<C: Crypto>(
846 &'a self,
847 crypto: C,
848 utc_time: UtcTime,
849 ) -> CertVerifier<'a, C> {
850 CertVerifier::new(self, crypto, utc_time)
851 }
852
853 fn encode(&self, w: &mut dyn CertConsumer) -> Result<(), Error> {
854 w.start_seq("")?;
855
856 w.start_ctx("Version:", 0)?;
857 w.integer("", &[2])?;
858 w.end_ctx()?;
859
860 w.integer("Serial Num:", self.serial_no()?)?;
861
862 w.start_seq("Signature Algorithm:")?;
863 let (str, oid) = match get_sign_algo(self.sign_algo()?).ok_or(ErrorCode::Invalid)? {
864 SignAlgoValue::ECDSAWithSHA256 => ("ECDSA with SHA256", OID_ECDSA_WITH_SHA256),
865 };
866 w.oid(str, &oid)?;
867 w.end_seq()?;
868
869 DN::encode_all(self.issuer()?.iter(), "Issuer:", w)?;
870
871 w.start_seq("Validity:")?;
872 w.utctime("Not Before:", self.not_before()?.into())?;
873 if self.not_after()? == 0 {
874 w.utctime("Not After:", MATTER_CERT_DOESNT_EXPIRE)?;
877 } else {
878 w.utctime("Not After:", self.not_after()?.into())?;
879 }
880 w.end_seq()?;
881
882 DN::encode_all(self.subject()?.iter(), "Subject:", w)?;
883
884 w.start_seq("")?;
885 w.start_seq("Public Key Algorithm")?;
886 let (str, pub_key) = match get_pubkey_algo(self.pubkey_algo()?).ok_or(ErrorCode::Invalid)? {
887 PubKeyAlgoValue::EcPubKey => ("ECPubKey", OID_PUB_KEY_ECPUBKEY),
888 };
889 w.oid(str, &pub_key)?;
890 let (str, curve_id) =
891 match get_ec_curve_id(self.ec_curve_id()?).ok_or(ErrorCode::Invalid)? {
892 EcCurveIdValue::Prime256V1 => ("Prime256v1", OID_EC_TYPE_PRIME256V1),
893 };
894 w.oid(str, &curve_id)?;
895 w.end_seq()?;
896
897 w.bitstr("Public-Key:", false, self.pubkey()?)?;
898 w.end_seq()?;
899
900 Extension::encode_all(self.extensions()?.iter(), w)?;
901
902 w.end_seq()
905 }
906}
907
908impl fmt::Display for CertRef<'_> {
909 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
910 let mut printer = CertPrinter::new(f);
911
912 self.encode(&mut printer).map_err(|_| fmt::Error)?;
913
914 writeln!(
916 f,
917 "Signature: {:x?}",
918 self.signature().map_err(|_| fmt::Error)?
919 )
920 }
921}
922
923#[derive(Debug, Clone, Copy, PartialEq, Eq)]
925#[cfg_attr(feature = "defmt", derive(defmt::Format))]
926enum MatterCertType {
927 Rcac,
929 Icac,
931 Noc,
933}
934
935fn der_blob_has_critical_extension(bytes: &[u8]) -> Result<bool, Error> {
941 use der::asn1::{AnyRef, ObjectIdentifier, OctetStringRef};
942 use der::{Decode, Reader, SliceReader, Tag};
943
944 let mut reader = SliceReader::new(bytes).map_err(|_| ErrorCode::InvalidData)?;
945 while !reader.is_finished() {
946 let any = AnyRef::decode(&mut reader).map_err(|_| ErrorCode::InvalidData)?;
947 let mut inner = SliceReader::new(any.value()).map_err(|_| ErrorCode::InvalidData)?;
948
949 ObjectIdentifier::decode(&mut inner).map_err(|_| ErrorCode::InvalidData)?;
951
952 if !inner.is_finished()
955 && inner.peek_tag().map_err(|_| ErrorCode::InvalidData)? == Tag::Boolean
956 && bool::decode(&mut inner).map_err(|_| ErrorCode::InvalidData)?
957 {
958 return Ok(true);
959 }
960 let _ = OctetStringRef::decode(&mut inner).map_err(|_| ErrorCode::InvalidData)?;
963 }
964 Ok(false)
965}
966
967pub struct CertVerifier<'a, C> {
968 cert: &'a CertRef<'a>,
969 crypto: C,
970 utc_time: UtcTime,
971 depth: u8,
974}
975
976impl<'a, C: Crypto> CertVerifier<'a, C> {
977 pub const fn new(cert: &'a CertRef<'a>, crypto: C, utc_time: UtcTime) -> Self {
978 Self {
979 cert,
980 crypto,
981 utc_time,
982 depth: 0,
983 }
984 }
985
986 fn verify_usage(&self) -> Result<(), Error> {
1004 use self::x509::key_usage_tlv;
1005
1006 if self.cert.has_critical_future_extension()? {
1011 Err(ErrorCode::InvalidData)?;
1012 }
1013
1014 let cert_type = self.cert.cert_type()?;
1015 let key_usage = self
1016 .cert
1017 .key_usage()?
1018 .ok_or_else(|| Error::new(ErrorCode::InvalidData))?;
1019
1020 match cert_type {
1021 MatterCertType::Noc => {
1022 if self.depth != 0 {
1024 Err(ErrorCode::InvalidData)?;
1025 }
1026
1027 let (is_ca, _) = self
1031 .cert
1032 .basic_constraints()?
1033 .ok_or_else(|| Error::new(ErrorCode::InvalidData))?;
1034 if is_ca {
1035 Err(ErrorCode::InvalidData)?;
1036 }
1037
1038 if (key_usage & key_usage_tlv::DIGITAL_SIGNATURE) == 0 {
1040 Err(ErrorCode::InvalidData)?;
1041 }
1042
1043 const SERVER_AUTH: u8 = 1;
1046 const CLIENT_AUTH: u8 = 2;
1047 if !self
1048 .cert
1049 .ext_key_usage_has_all(&[SERVER_AUTH, CLIENT_AUTH])?
1050 {
1051 Err(ErrorCode::InvalidData)?;
1052 }
1053 }
1054 MatterCertType::Icac | MatterCertType::Rcac => {
1055 let (is_ca, path_len) = self
1056 .cert
1057 .basic_constraints()?
1058 .ok_or_else(|| Error::new(ErrorCode::InvalidData))?;
1059 if !is_ca {
1060 Err(ErrorCode::InvalidData)?;
1061 }
1062
1063 if (key_usage & key_usage_tlv::KEY_CERT_SIGN) == 0 {
1065 Err(ErrorCode::InvalidData)?;
1066 }
1067
1068 if let (Some(max_intermediates), depth) = (path_len, self.depth) {
1076 if depth > 0 && depth - 1 > max_intermediates {
1077 Err(ErrorCode::InvalidData)?;
1078 }
1079 }
1080 }
1081 }
1082
1083 Ok(())
1084 }
1085
1086 pub fn add_cert<'p>(
1087 self,
1088 parent: &'p CertRef<'p>,
1089 buf: &mut [u8],
1090 ) -> Result<CertVerifier<'p, C>, Error>
1091 where
1092 'a: 'p,
1093 {
1094 if !self.cert.is_authority(parent)? {
1095 Err(ErrorCode::InvalidAuthKey)?;
1096 }
1097
1098 {
1099 let len = self.cert.as_asn1(buf)?;
1100 let asn1 = &buf[..len];
1101
1102 let result = self
1103 .crypto
1104 .pub_key(parent.pubkey()?.try_into()?)?
1105 .verify(asn1, self.cert.signature()?.try_into()?)?;
1106
1107 if !result {
1108 Err(ErrorCode::InvalidSignature)?;
1109 }
1110 }
1111
1112 let not_before = self.cert.not_before()? as u64;
1116 let not_after = self.cert.not_after()?;
1117
1118 if not_after > 0 && self.utc_time.any_secs() > not_after as u64 {
1119 Err(ErrorCode::InvalidTime)?;
1120 }
1121
1122 if let Some(secs) = self.utc_time.reliable_secs() {
1123 if secs < not_before {
1129 Err(ErrorCode::InvalidTime)?;
1130 }
1131 }
1132
1133 self.verify_usage()?;
1136
1137 Ok(CertVerifier {
1138 cert: parent,
1139 crypto: self.crypto,
1140 utc_time: self.utc_time,
1141 depth: self.depth.saturating_add(1),
1142 })
1143 }
1144
1145 pub fn finalise(self, buf: &mut [u8]) -> Result<(), Error> {
1146 let cert = self.cert;
1147 self.add_cert(cert, buf)?;
1148
1149 Ok(())
1150 }
1151}
1152
1153pub trait CertConsumer {
1154 fn start_seq(&mut self, tag: &str) -> Result<(), Error>;
1155 fn end_seq(&mut self) -> Result<(), Error>;
1156 fn integer(&mut self, tag: &str, i: &[u8]) -> Result<(), Error>;
1157 fn printstr(&mut self, tag: &str, s: &str) -> Result<(), Error>;
1158 fn utf8str(&mut self, tag: &str, s: &str) -> Result<(), Error>;
1159 fn bitstr(&mut self, tag: &str, truncate: bool, s: &[u8]) -> Result<(), Error>;
1160 fn ostr(&mut self, tag: &str, s: &[u8]) -> Result<(), Error>;
1161 fn start_compound_ostr(&mut self, tag: &str) -> Result<(), Error>;
1162 fn end_compound_ostr(&mut self) -> Result<(), Error>;
1163 fn bool(&mut self, tag: &str, b: bool) -> Result<(), Error>;
1164 fn start_set(&mut self, tag: &str) -> Result<(), Error>;
1165 fn end_set(&mut self) -> Result<(), Error>;
1166 fn ctx(&mut self, tag: &str, id: u8, val: &[u8]) -> Result<(), Error>;
1167 fn start_ctx(&mut self, tag: &str, id: u8) -> Result<(), Error>;
1168 fn end_ctx(&mut self) -> Result<(), Error>;
1169 fn oid(&mut self, tag: &str, oid: &[u8]) -> Result<(), Error>;
1170 fn utctime(&mut self, tag: &str, epoch: u64) -> Result<(), Error>;
1171 fn raw(&mut self, tag: &str, data: &[u8]) -> Result<(), Error>;
1178}
1179
1180#[cfg(test)]
1181mod tests {
1182 use crate::crypto::test_only_crypto;
1183 use crate::dm::clusters::time_sync::UtcTime;
1184 use crate::error::ErrorCode;
1185 use crate::tlv::{FromTLV, TLVElement, TagType, ToTLV};
1186 use crate::utils::storage::WriteBuf;
1187
1188 use super::CertRef;
1189
1190 #[test]
1191 fn test_asn1_encode_success() {
1192 {
1193 let mut asn1_buf = [0u8; 1000];
1194 let c = CertRef::new(TLVElement::new(CHIP_CERT_INPUT1));
1195 let len = unwrap!(c.as_asn1(&mut asn1_buf));
1196 assert_eq!(ASN1_OUTPUT1, &asn1_buf[..len]);
1197 }
1198
1199 {
1200 let mut asn1_buf = [0u8; 1000];
1201 let c = CertRef::new(TLVElement::new(CHIP_CERT_INPUT2));
1202 let len = unwrap!(c.as_asn1(&mut asn1_buf));
1203 assert_eq!(ASN1_OUTPUT2, &asn1_buf[..len]);
1204 }
1205
1206 {
1207 let mut asn1_buf = [0u8; 1000];
1208 let c = CertRef::new(TLVElement::new(CHIP_CERT_TXT_IN_DN));
1209 let len = unwrap!(c.as_asn1(&mut asn1_buf));
1210 assert_eq!(ASN1_OUTPUT_TXT_IN_DN, &asn1_buf[..len]);
1211 }
1212 }
1213
1214 #[test]
1215 fn test_verify_chain_success() {
1216 let mut buf = [0; 1000];
1217 let noc = CertRef::new(TLVElement::new(NOC1_SUCCESS));
1218 let icac = CertRef::new(TLVElement::new(ICAC1_SUCCESS));
1219 let rca = CertRef::new(TLVElement::new(RCA1_SUCCESS));
1220 let time = UtcTime::Reliable(unwrap!(noc.not_before()) as u64 * 1_000_000);
1221 let a = noc.verify_chain_start(test_only_crypto(), time);
1222 unwrap!(
1223 unwrap!(unwrap!(a.add_cert(&icac, &mut buf)).add_cert(&rca, &mut buf))
1224 .finalise(&mut buf)
1225 );
1226 }
1227
1228 #[test]
1229 fn test_verify_chain_incomplete() {
1230 let mut buf = [0; 1000];
1233 let noc = CertRef::new(TLVElement::new(NOC1_SUCCESS));
1234 let icac = CertRef::new(TLVElement::new(ICAC1_SUCCESS));
1235 let time = UtcTime::Reliable(unwrap!(noc.not_before()) as u64 * 1_000_000);
1236 let a = noc.verify_chain_start(test_only_crypto(), time);
1237 assert_eq!(
1238 Err(ErrorCode::InvalidAuthKey),
1239 unwrap!(a.add_cert(&icac, &mut buf))
1240 .finalise(&mut buf)
1241 .map_err(|e| e.code())
1242 );
1243 }
1244
1245 #[test]
1246 fn test_auth_key_chain_incorrect() {
1247 let mut buf = [0; 1000];
1248 let noc = CertRef::new(TLVElement::new(NOC1_AUTH_KEY_FAIL));
1249 let icac = CertRef::new(TLVElement::new(ICAC1_SUCCESS));
1250 let a = noc.verify_chain_start(test_only_crypto(), UtcTime::Reliable(0));
1251 assert_eq!(
1252 Err(ErrorCode::InvalidAuthKey),
1253 a.add_cert(&icac, &mut buf)
1254 .map(|_| ())
1255 .map_err(|e| e.code())
1256 );
1257 }
1258
1259 #[test]
1260 fn test_zero_value_of_not_after_field() {
1261 let mut buf = [0; 1000];
1262 let noc = CertRef::new(TLVElement::new(NOC_NOT_AFTER_ZERO));
1263 let rca = CertRef::new(TLVElement::new(RCA_FOR_NOC_NOT_AFTER_ZERO));
1264
1265 let time = UtcTime::Reliable(unwrap!(noc.not_before()) as u64 * 1_000_000);
1266 let v = noc.verify_chain_start(test_only_crypto(), time);
1267 let v = unwrap!(v.add_cert(&rca, &mut buf));
1268 unwrap!(v.finalise(&mut buf));
1269 }
1270
1271 #[test]
1272 fn test_cert_corrupted() {
1273 let mut buf = [0; 1000];
1274 let noc = CertRef::new(TLVElement::new(NOC1_CORRUPT_CERT));
1275 let icac = CertRef::new(TLVElement::new(ICAC1_SUCCESS));
1276 let a = noc.verify_chain_start(test_only_crypto(), UtcTime::Reliable(0));
1277 assert_eq!(
1278 Err(ErrorCode::InvalidSignature),
1279 a.add_cert(&icac, &mut buf)
1280 .map(|_| ())
1281 .map_err(|e| e.code())
1282 );
1283 }
1284
1285 #[test]
1286 fn test_tlv_conversions() {
1287 const TEST_INPUT: &[&[u8]; 4] = &[NOC1_SUCCESS, ICAC1_SUCCESS, ICAC2_SUCCESS, RCA1_SUCCESS];
1288
1289 for input in TEST_INPUT.iter() {
1290 info!("Testing next input...");
1291 let root = TLVElement::new(input);
1292 let cert = unwrap!(CertRef::from_tlv(&root));
1293 let mut buf = [0u8; 1024];
1294 let mut wb = WriteBuf::new(&mut buf);
1295 unwrap!(cert.to_tlv(&TagType::Anonymous, &mut wb));
1296
1297 let root2 = TLVElement::new(wb.as_slice());
1298 let cert2 = unwrap!(CertRef::from_tlv(&root2));
1299 assert_eq!(cert, cert2);
1300 }
1301 }
1302
1303 #[test]
1304 fn test_unordered_extensions() {
1305 let mut buf = [0; 1000];
1306
1307 let cert = CertRef::new(TLVElement::new(UNORDERED_EXTENSIONS_CHIP));
1308
1309 let asn1_len = unwrap!(cert.as_asn1(&mut buf));
1310 assert_eq!(&buf[..asn1_len], UNORDERED_EXTENSIONS_DER);
1311 }
1312
1313 #[test]
1319 fn test_der_blob_has_critical_extension() {
1320 use super::der_blob_has_critical_extension;
1321
1322 const NON_CRITICAL: &[u8] = &[
1329 0x30, 0x0A, 0x06, 0x03, 0x55, 0x1D, 0x63, 0x01, 0x01, 0x00, 0x04, 0x00,
1330 ];
1331 const CRITICAL: &[u8] = &[
1332 0x30, 0x0A, 0x06, 0x03, 0x55, 0x1D, 0x63, 0x01, 0x01, 0xFF, 0x04, 0x00,
1333 ];
1334 const DEFAULTED: &[u8] = &[
1335 0x30, 0x07, 0x06, 0x03, 0x55, 0x1D, 0x63, 0x04, 0x00,
1337 ];
1338
1339 assert!(!unwrap!(der_blob_has_critical_extension(&[])));
1341
1342 assert!(!unwrap!(der_blob_has_critical_extension(NON_CRITICAL)));
1344 assert!(!unwrap!(der_blob_has_critical_extension(DEFAULTED)));
1345 assert!(unwrap!(der_blob_has_critical_extension(CRITICAL)));
1346
1347 let mut two_noncritical = heapless::Vec::<u8, 64>::new();
1349 unwrap!(two_noncritical.extend_from_slice(NON_CRITICAL));
1350 unwrap!(two_noncritical.extend_from_slice(DEFAULTED));
1351 assert!(!unwrap!(der_blob_has_critical_extension(&two_noncritical)));
1352
1353 let mut second_is_critical = heapless::Vec::<u8, 64>::new();
1354 unwrap!(second_is_critical.extend_from_slice(NON_CRITICAL));
1355 unwrap!(second_is_critical.extend_from_slice(CRITICAL));
1356 assert!(unwrap!(der_blob_has_critical_extension(
1357 &second_is_critical
1358 )));
1359 }
1360
1361 #[test]
1366 fn test_extension_accessors_on_known_chain() {
1367 use super::x509::key_usage_tlv;
1368 use super::MatterCertType;
1369
1370 let noc = CertRef::new(TLVElement::new(NOC1_SUCCESS));
1371 let icac = CertRef::new(TLVElement::new(ICAC1_SUCCESS));
1372 let rca = CertRef::new(TLVElement::new(RCA1_SUCCESS));
1373
1374 assert_eq!(unwrap!(noc.cert_type()), MatterCertType::Noc);
1376
1377 let (noc_ca, noc_path) = unwrap!(unwrap!(noc.basic_constraints()));
1378 assert!(!noc_ca, "NOC must have cA = FALSE");
1379 assert_eq!(noc_path, None, "NOC must not carry pathLenConstraint");
1380
1381 let noc_ku = unwrap!(unwrap!(noc.key_usage()));
1382 assert_ne!(
1383 noc_ku & key_usage_tlv::DIGITAL_SIGNATURE,
1384 0,
1385 "NOC KeyUsage must include digitalSignature"
1386 );
1387
1388 assert!(
1389 unwrap!(noc.ext_key_usage_has_all(&[1, 2])),
1390 "NOC ExtKeyUsage must include both serverAuth (1) and clientAuth (2)"
1391 );
1392
1393 assert!(
1394 !unwrap!(noc.has_critical_future_extension()),
1395 "test NOC carries no future-extensions"
1396 );
1397
1398 assert_eq!(unwrap!(icac.cert_type()), MatterCertType::Icac);
1400
1401 let (icac_ca, icac_path) = unwrap!(unwrap!(icac.basic_constraints()));
1402 assert!(icac_ca, "ICAC must have cA = TRUE");
1403 assert!(
1408 matches!(icac_path, None | Some(0)),
1409 "unexpected pathLenConstraint on ICAC: {icac_path:?}"
1410 );
1411
1412 let icac_ku = unwrap!(unwrap!(icac.key_usage()));
1413 assert_ne!(
1414 icac_ku & key_usage_tlv::KEY_CERT_SIGN,
1415 0,
1416 "ICAC KeyUsage must include keyCertSign"
1417 );
1418
1419 assert!(
1420 !unwrap!(icac.ext_key_usage_has_all(&[1, 2])),
1421 "ICAC has no ExtendedKeyUsage extension"
1422 );
1423
1424 assert_eq!(unwrap!(rca.cert_type()), MatterCertType::Rcac);
1426
1427 let (rca_ca, rca_path) = unwrap!(unwrap!(rca.basic_constraints()));
1428 assert!(rca_ca, "RCAC must have cA = TRUE");
1429 assert_eq!(rca_path, None, "RCAC must not carry pathLenConstraint");
1430 assert_eq!(unwrap!(rca.basic_constraints_path_len()), None);
1432
1433 let rca_ku = unwrap!(unwrap!(rca.key_usage()));
1434 assert_ne!(
1435 rca_ku & key_usage_tlv::KEY_CERT_SIGN,
1436 0,
1437 "RCAC KeyUsage must include keyCertSign"
1438 );
1439 }
1440
1441 const NOC1_SUCCESS: &[u8] = &[
1443 0x15, 0x30, 0x1, 0x1, 0x1, 0x24, 0x2, 0x1, 0x37, 0x3, 0x24, 0x13, 0x1, 0x24, 0x15, 0x1,
1444 0x18, 0x26, 0x4, 0x80, 0x22, 0x81, 0x27, 0x26, 0x5, 0x80, 0x25, 0x4d, 0x3a, 0x37, 0x6,
1445 0x26, 0x11, 0x2, 0x5c, 0xbc, 0x0, 0x24, 0x15, 0x1, 0x18, 0x24, 0x7, 0x1, 0x24, 0x8, 0x1,
1446 0x30, 0x9, 0x41, 0x4, 0xba, 0x22, 0x56, 0x43, 0x4f, 0x59, 0x98, 0x32, 0x8d, 0xb8, 0xcb,
1447 0x3f, 0x24, 0x90, 0x9a, 0x96, 0x94, 0x43, 0x46, 0x67, 0xc2, 0x11, 0xe3, 0x80, 0x26, 0x65,
1448 0xfc, 0x65, 0x37, 0x77, 0x3, 0x25, 0x18, 0xd8, 0xdc, 0x85, 0xfa, 0xe6, 0x42, 0xe7, 0x55,
1449 0xc9, 0x37, 0xcc, 0xb, 0x78, 0x84, 0x3d, 0x2f, 0xac, 0x81, 0x88, 0x2e, 0x69, 0x0, 0xa5,
1450 0xfc, 0xcd, 0xe0, 0xad, 0xb2, 0x69, 0xca, 0x73, 0x37, 0xa, 0x35, 0x1, 0x28, 0x1, 0x18,
1451 0x24, 0x2, 0x1, 0x36, 0x3, 0x4, 0x2, 0x4, 0x1, 0x18, 0x30, 0x4, 0x14, 0x39, 0x68, 0x16,
1452 0x1e, 0xb5, 0x56, 0x6d, 0xd3, 0xf8, 0x61, 0xf2, 0x95, 0xf3, 0x55, 0xa0, 0xfb, 0xd2, 0x82,
1453 0xc2, 0x29, 0x30, 0x5, 0x14, 0xce, 0x60, 0xb4, 0x28, 0x96, 0x72, 0x27, 0x64, 0x81, 0xbc,
1454 0x4f, 0x0, 0x78, 0xa3, 0x30, 0x48, 0xfe, 0x6e, 0x65, 0x86, 0x18, 0x30, 0xb, 0x40, 0x2,
1455 0x88, 0x42, 0x0, 0x6f, 0xcc, 0xe0, 0xf0, 0x6c, 0xd9, 0xf9, 0x5e, 0xe4, 0xc2, 0xaa, 0x1f,
1456 0x57, 0x71, 0x62, 0xdb, 0x6b, 0x4e, 0xe7, 0x55, 0x3f, 0xc6, 0xc7, 0x9f, 0xf8, 0x30, 0xeb,
1457 0x16, 0x6e, 0x6d, 0xc6, 0x9c, 0xb, 0xb7, 0xe2, 0xb8, 0xe3, 0xe7, 0x57, 0x88, 0x7b, 0xda,
1458 0xe5, 0x79, 0x39, 0x6d, 0x2c, 0x37, 0xb2, 0x7f, 0xc3, 0x63, 0x2f, 0x7e, 0x70, 0xab, 0x5a,
1459 0x2c, 0xf7, 0x5b, 0x18,
1460 ];
1461
1462 const ICAC1_SUCCESS: &[u8] = &[
1463 21, 48, 1, 1, 0, 36, 2, 1, 55, 3, 36, 20, 0, 36, 21, 1, 24, 38, 4, 128, 34, 129, 39, 38, 5,
1464 128, 37, 77, 58, 55, 6, 36, 19, 1, 36, 21, 1, 24, 36, 7, 1, 36, 8, 1, 48, 9, 65, 4, 86, 25,
1465 119, 24, 63, 212, 255, 43, 88, 61, 233, 121, 52, 102, 223, 233, 0, 251, 109, 161, 239, 224,
1466 204, 220, 119, 48, 192, 111, 182, 45, 255, 190, 84, 160, 149, 117, 11, 139, 7, 188, 85,
1467 219, 156, 182, 85, 19, 8, 184, 223, 2, 227, 64, 107, 174, 52, 245, 12, 186, 201, 242, 191,
1468 241, 231, 80, 55, 10, 53, 1, 41, 1, 24, 36, 2, 96, 48, 4, 20, 206, 96, 180, 40, 150, 114,
1469 39, 100, 129, 188, 79, 0, 120, 163, 48, 72, 254, 110, 101, 134, 48, 5, 20, 212, 86, 147,
1470 190, 112, 121, 244, 156, 112, 107, 7, 111, 17, 28, 109, 229, 100, 164, 68, 116, 24, 48, 11,
1471 64, 243, 8, 190, 128, 155, 254, 245, 21, 205, 241, 217, 246, 204, 182, 247, 41, 81, 91, 33,
1472 155, 230, 223, 212, 116, 33, 162, 208, 148, 100, 89, 175, 253, 78, 212, 7, 69, 207, 140,
1473 45, 129, 249, 64, 104, 70, 68, 43, 164, 19, 126, 114, 138, 79, 104, 238, 20, 226, 88, 118,
1474 105, 56, 12, 92, 31, 171, 24,
1475 ];
1476
1477 const ICAC2_SUCCESS: &[u8] = &[
1479 21, 48, 1, 16, 67, 38, 73, 198, 26, 31, 20, 101, 57, 46, 16, 143, 77, 160, 128, 161, 36, 2,
1480 1, 55, 3, 39, 20, 255, 90, 200, 17, 145, 105, 71, 215, 24, 38, 4, 123, 59, 211, 42, 38, 5,
1481 35, 11, 27, 52, 55, 6, 39, 19, 254, 111, 27, 53, 189, 134, 103, 200, 24, 36, 7, 1, 36, 8,
1482 1, 48, 9, 65, 4, 88, 188, 13, 87, 50, 3, 213, 248, 182, 12, 240, 164, 220, 127, 150, 65,
1483 81, 244, 125, 24, 48, 203, 83, 111, 133, 175, 182, 10, 40, 80, 147, 28, 39, 121, 183, 61,
1484 159, 178, 231, 133, 75, 189, 143, 136, 191, 254, 115, 228, 186, 129, 56, 137, 213, 177, 13,
1485 46, 97, 202, 95, 41, 5, 16, 24, 228, 55, 10, 53, 1, 41, 1, 36, 2, 0, 24, 48, 5, 20, 243,
1486 119, 107, 152, 3, 212, 205, 76, 85, 38, 158, 240, 27, 213, 11, 235, 33, 21, 38, 5, 48, 4,
1487 20, 88, 240, 172, 159, 2, 82, 193, 71, 83, 67, 184, 97, 99, 61, 125, 67, 232, 202, 171,
1488 107, 36, 2, 96, 24, 48, 11, 64, 70, 43, 150, 195, 194, 170, 43, 125, 91, 213, 210, 221,
1489 175, 131, 131, 85, 22, 247, 213, 18, 101, 189, 30, 134, 20, 226, 217, 145, 41, 225, 181,
1490 150, 28, 200, 52, 237, 218, 195, 144, 209, 205, 73, 88, 114, 139, 216, 85, 170, 63, 238,
1491 164, 69, 35, 69, 39, 87, 211, 234, 57, 98, 19, 43, 13, 0, 24,
1492 ];
1493
1494 const NOC1_AUTH_KEY_FAIL: &[u8] = &[
1496 0x15, 0x30, 0x1, 0x1, 0x1, 0x24, 0x2, 0x1, 0x37, 0x3, 0x24, 0x13, 0x1, 0x24, 0x15, 0x1,
1497 0x18, 0x26, 0x4, 0x80, 0x22, 0x81, 0x27, 0x26, 0x5, 0x80, 0x25, 0x4d, 0x3a, 0x37, 0x6,
1498 0x26, 0x11, 0x2, 0x5c, 0xbc, 0x0, 0x24, 0x15, 0x1, 0x18, 0x24, 0x7, 0x1, 0x24, 0x8, 0x1,
1499 0x30, 0x9, 0x41, 0x4, 0xba, 0x22, 0x56, 0x43, 0x4f, 0x59, 0x98, 0x32, 0x8d, 0xb8, 0xcb,
1500 0x3f, 0x24, 0x90, 0x9a, 0x96, 0x94, 0x43, 0x46, 0x67, 0xc2, 0x11, 0xe3, 0x80, 0x26, 0x65,
1501 0xfc, 0x65, 0x37, 0x77, 0x3, 0x25, 0x18, 0xd8, 0xdc, 0x85, 0xfa, 0xe6, 0x42, 0xe7, 0x55,
1502 0xc9, 0x37, 0xcc, 0xb, 0x78, 0x84, 0x3d, 0x2f, 0xac, 0x81, 0x88, 0x2e, 0x69, 0x0, 0xa5,
1503 0xfc, 0xcd, 0xe0, 0xad, 0xb2, 0x69, 0xca, 0x73, 0x37, 0xa, 0x35, 0x1, 0x28, 0x1, 0x18,
1504 0x24, 0x2, 0x1, 0x36, 0x3, 0x4, 0x2, 0x4, 0x1, 0x18, 0x30, 0x4, 0x14, 0x39, 0x68, 0x16,
1505 0x1e, 0xb5, 0x56, 0x6d, 0xd3, 0xf8, 0x61, 0xf2, 0x95, 0xf3, 0x55, 0xa0, 0xfb, 0xd2, 0x82,
1506 0xc2, 0x29, 0x30, 0x5, 0x14, 0xce, 0x61, 0xb4, 0x28, 0x96, 0x72, 0x27, 0x64, 0x81, 0xbc,
1507 0x4f, 0x0, 0x78, 0xa3, 0x30, 0x48, 0xfe, 0x6e, 0x65, 0x86, 0x18, 0x30, 0xb, 0x40, 0x2,
1508 0x88, 0x42, 0x0, 0x6f, 0xcc, 0xe0, 0xf0, 0x6c, 0xd9, 0xf9, 0x5e, 0xe4, 0xc2, 0xaa, 0x1f,
1509 0x57, 0x71, 0x62, 0xdb, 0x6b, 0x4e, 0xe7, 0x55, 0x3f, 0xc6, 0xc7, 0x9f, 0xf8, 0x30, 0xeb,
1510 0x16, 0x6e, 0x6d, 0xc6, 0x9c, 0xb, 0xb7, 0xe2, 0xb8, 0xe3, 0xe7, 0x57, 0x88, 0x7b, 0xda,
1511 0xe5, 0x79, 0x39, 0x6d, 0x2c, 0x37, 0xb2, 0x7f, 0xc3, 0x63, 0x2f, 0x7e, 0x70, 0xab, 0x5a,
1512 0x2c, 0xf7, 0x5b, 0x18,
1513 ];
1514
1515 const NOC1_CORRUPT_CERT: &[u8] = &[
1517 0x15, 0x30, 0x1, 0x1, 0x1, 0x24, 0x2, 0x1, 0x37, 0x3, 0x24, 0x13, 0x1, 0x24, 0x15, 0x1,
1518 0x18, 0x26, 0x4, 0x80, 0x22, 0x81, 0x27, 0x26, 0x5, 0x80, 0x25, 0x4d, 0x3a, 0x37, 0x6,
1519 0x26, 0x11, 0x2, 0x5c, 0xbc, 0x0, 0x24, 0x15, 0x1, 0x18, 0x24, 0x7, 0x1, 0x24, 0x8, 0x1,
1520 0x30, 0x9, 0x41, 0x4, 0xba, 0x23, 0x56, 0x43, 0x4f, 0x59, 0x98, 0x32, 0x8d, 0xb8, 0xcb,
1521 0x3f, 0x24, 0x90, 0x9a, 0x96, 0x94, 0x43, 0x46, 0x67, 0xc2, 0x11, 0xe3, 0x80, 0x26, 0x65,
1522 0xfc, 0x65, 0x37, 0x77, 0x3, 0x25, 0x18, 0xd8, 0xdc, 0x85, 0xfa, 0xe6, 0x42, 0xe7, 0x55,
1523 0xc9, 0x37, 0xcc, 0xb, 0x78, 0x84, 0x3d, 0x2f, 0xac, 0x81, 0x88, 0x2e, 0x69, 0x0, 0xa5,
1524 0xfc, 0xcd, 0xe0, 0xad, 0xb2, 0x69, 0xca, 0x73, 0x37, 0xa, 0x35, 0x1, 0x28, 0x1, 0x18,
1525 0x24, 0x2, 0x1, 0x36, 0x3, 0x4, 0x2, 0x4, 0x1, 0x18, 0x30, 0x4, 0x14, 0x39, 0x68, 0x16,
1526 0x1e, 0xb5, 0x56, 0x6d, 0xd3, 0xf8, 0x61, 0xf2, 0x95, 0xf3, 0x55, 0xa0, 0xfb, 0xd2, 0x82,
1527 0xc2, 0x29, 0x30, 0x5, 0x14, 0xce, 0x60, 0xb4, 0x28, 0x96, 0x72, 0x27, 0x64, 0x81, 0xbc,
1528 0x4f, 0x0, 0x78, 0xa3, 0x30, 0x48, 0xfe, 0x6e, 0x65, 0x86, 0x18, 0x30, 0xb, 0x40, 0x2,
1529 0x88, 0x42, 0x0, 0x6f, 0xcc, 0xe0, 0xf0, 0x6c, 0xd9, 0xf9, 0x5e, 0xe4, 0xc2, 0xaa, 0x1f,
1530 0x57, 0x71, 0x62, 0xdb, 0x6b, 0x4e, 0xe7, 0x55, 0x3f, 0xc6, 0xc7, 0x9f, 0xf8, 0x30, 0xeb,
1531 0x16, 0x6e, 0x6d, 0xc6, 0x9c, 0xb, 0xb7, 0xe2, 0xb8, 0xe3, 0xe7, 0x57, 0x88, 0x7b, 0xda,
1532 0xe5, 0x79, 0x39, 0x6d, 0x2c, 0x37, 0xb2, 0x7f, 0xc3, 0x63, 0x2f, 0x7e, 0x70, 0xab, 0x5a,
1533 0x2c, 0xf7, 0x5b, 0x18,
1534 ];
1535
1536 const RCA1_SUCCESS: &[u8] = &[
1537 0x15, 0x30, 0x1, 0x1, 0x0, 0x24, 0x2, 0x1, 0x37, 0x3, 0x24, 0x14, 0x0, 0x24, 0x15, 0x1,
1538 0x18, 0x26, 0x4, 0x80, 0x22, 0x81, 0x27, 0x26, 0x5, 0x80, 0x25, 0x4d, 0x3a, 0x37, 0x6,
1539 0x24, 0x14, 0x0, 0x24, 0x15, 0x1, 0x18, 0x24, 0x7, 0x1, 0x24, 0x8, 0x1, 0x30, 0x9, 0x41,
1540 0x4, 0x6d, 0x70, 0x7e, 0x4b, 0x98, 0xf6, 0x2b, 0xab, 0x44, 0xd6, 0xfe, 0xa3, 0x2e, 0x39,
1541 0xd8, 0xc3, 0x0, 0xa0, 0xe, 0xa8, 0x6c, 0x83, 0xff, 0x69, 0xd, 0xe8, 0x42, 0x1, 0xeb, 0xd,
1542 0xaa, 0x68, 0x5d, 0xcb, 0x97, 0x2, 0x80, 0x1d, 0xa8, 0x50, 0x2, 0x2e, 0x5a, 0xa2, 0x5a,
1543 0x2e, 0x51, 0x26, 0x4, 0xd2, 0x39, 0x62, 0xcd, 0x82, 0x38, 0x63, 0x28, 0xbf, 0x15, 0x1c,
1544 0xa6, 0x27, 0xe0, 0xd7, 0x37, 0xa, 0x35, 0x1, 0x29, 0x1, 0x18, 0x24, 0x2, 0x60, 0x30, 0x4,
1545 0x14, 0xd4, 0x56, 0x93, 0xbe, 0x70, 0x79, 0xf4, 0x9c, 0x70, 0x6b, 0x7, 0x6f, 0x11, 0x1c,
1546 0x6d, 0xe5, 0x64, 0xa4, 0x44, 0x74, 0x30, 0x5, 0x14, 0xd4, 0x56, 0x93, 0xbe, 0x70, 0x79,
1547 0xf4, 0x9c, 0x70, 0x6b, 0x7, 0x6f, 0x11, 0x1c, 0x6d, 0xe5, 0x64, 0xa4, 0x44, 0x74, 0x18,
1548 0x30, 0xb, 0x40, 0x3, 0xd, 0x77, 0xe1, 0x9e, 0xea, 0x9c, 0x5, 0x5c, 0xcc, 0x47, 0xe8, 0xb3,
1549 0x18, 0x1a, 0xd1, 0x74, 0xee, 0xc6, 0x2e, 0xa1, 0x20, 0x16, 0xbd, 0x20, 0xb4, 0x3d, 0xac,
1550 0x24, 0xbe, 0x17, 0xf9, 0xe, 0xb7, 0x9a, 0x98, 0xc8, 0xbc, 0x6a, 0xce, 0x99, 0x2a, 0x2e,
1551 0x63, 0x4c, 0x76, 0x6, 0x45, 0x93, 0xd3, 0x7c, 0x4, 0x0, 0xe4, 0xc7, 0x78, 0xe9, 0x83,
1552 0x5b, 0xc, 0x33, 0x61, 0x5c, 0x2e, 0x18,
1553 ];
1554
1555 const CHIP_CERT_INPUT1: &[u8] = &[
1556 0x15, 0x30, 0x01, 0x01, 0x00, 0x24, 0x02, 0x01, 0x37, 0x03, 0x24, 0x14, 0x00, 0x24, 0x15,
1557 0x03, 0x18, 0x26, 0x04, 0x80, 0x22, 0x81, 0x27, 0x26, 0x05, 0x80, 0x25, 0x4d, 0x3a, 0x37,
1558 0x06, 0x24, 0x13, 0x01, 0x24, 0x15, 0x03, 0x18, 0x24, 0x07, 0x01, 0x24, 0x08, 0x01, 0x30,
1559 0x09, 0x41, 0x04, 0x69, 0xda, 0xe9, 0x42, 0x88, 0xcf, 0x64, 0x94, 0x2d, 0xd5, 0x0a, 0x74,
1560 0x2d, 0x50, 0xe8, 0x5e, 0xbe, 0x15, 0x53, 0x24, 0xe5, 0xc5, 0x6b, 0xe5, 0x7f, 0xc1, 0x41,
1561 0x11, 0x21, 0xdd, 0x46, 0xa3, 0x0d, 0x63, 0xc3, 0xe3, 0x90, 0x7a, 0x69, 0x64, 0xdd, 0x66,
1562 0x78, 0x10, 0xa6, 0xc8, 0x0f, 0xfd, 0xb6, 0xf2, 0x9b, 0x88, 0x50, 0x93, 0x77, 0x9e, 0xf7,
1563 0xb4, 0xda, 0x94, 0x11, 0x33, 0x1e, 0xfe, 0x37, 0x0a, 0x35, 0x01, 0x29, 0x01, 0x18, 0x24,
1564 0x02, 0x60, 0x30, 0x04, 0x14, 0xdf, 0xfb, 0x79, 0xf1, 0x2b, 0xbf, 0x68, 0x18, 0x59, 0x7f,
1565 0xf7, 0xe8, 0xaf, 0x88, 0x91, 0x1c, 0x72, 0x32, 0xf7, 0x52, 0x30, 0x05, 0x14, 0xed, 0x31,
1566 0x5e, 0x1a, 0xb7, 0xb9, 0x7a, 0xca, 0x04, 0x79, 0x5d, 0x82, 0x57, 0x7a, 0xd7, 0x0a, 0x75,
1567 0xd0, 0xdb, 0x7a, 0x18, 0x30, 0x0b, 0x40, 0xe5, 0xd4, 0xe6, 0x0e, 0x98, 0x62, 0x2f, 0xaa,
1568 0x59, 0xe0, 0x28, 0x59, 0xc2, 0xd4, 0xcd, 0x34, 0x85, 0x7f, 0x93, 0xbe, 0x14, 0x35, 0xa3,
1569 0x76, 0x8a, 0xc9, 0x2f, 0x59, 0x39, 0xa0, 0xb0, 0x75, 0xe8, 0x8e, 0x11, 0xa9, 0xc1, 0x9e,
1570 0xaa, 0xab, 0xa0, 0xdb, 0xb4, 0x79, 0x63, 0xfc, 0x02, 0x03, 0x27, 0x25, 0xac, 0x21, 0x6f,
1571 0xef, 0x27, 0xab, 0x0f, 0x90, 0x09, 0x99, 0x05, 0xa8, 0x60, 0xd8, 0x18,
1572 ];
1573
1574 const CHIP_CERT_INPUT2: &[u8] = &[
1575 0x15, 0x30, 0x01, 0x01, 0x01, 0x24, 0x02, 0x01, 0x37, 0x03, 0x24, 0x13, 0x01, 0x24, 0x15,
1576 0x03, 0x18, 0x26, 0x04, 0x80, 0x22, 0x81, 0x27, 0x26, 0x05, 0x80, 0x25, 0x4d, 0x3a, 0x37,
1577 0x06, 0x26, 0x11, 0x69, 0xb6, 0x01, 0x00, 0x24, 0x15, 0x03, 0x18, 0x24, 0x07, 0x01, 0x24,
1578 0x08, 0x01, 0x30, 0x09, 0x41, 0x04, 0x93, 0x04, 0xc6, 0xc4, 0xe1, 0xbc, 0x9a, 0xc8, 0xf5,
1579 0xb3, 0x7f, 0x83, 0xd6, 0x7f, 0x79, 0xc5, 0x35, 0xdc, 0x7f, 0xac, 0x87, 0xca, 0xcd, 0x08,
1580 0x80, 0x4a, 0x55, 0x60, 0x80, 0x09, 0xd3, 0x9b, 0x4a, 0xc8, 0xe7, 0x7b, 0x4d, 0x5c, 0x82,
1581 0x88, 0x24, 0xdf, 0x1c, 0xfd, 0xef, 0xb4, 0xbc, 0xb7, 0x2f, 0x36, 0xf7, 0x2b, 0xb2, 0xcc,
1582 0x14, 0x69, 0x63, 0xcc, 0x89, 0xd2, 0x74, 0x3f, 0xd1, 0x98, 0x37, 0x0a, 0x35, 0x01, 0x28,
1583 0x01, 0x18, 0x24, 0x02, 0x01, 0x36, 0x03, 0x04, 0x02, 0x04, 0x01, 0x18, 0x30, 0x04, 0x14,
1584 0x9c, 0xe7, 0xd9, 0xa8, 0x6b, 0xf8, 0x71, 0xfa, 0x08, 0x10, 0xa3, 0xf2, 0x3a, 0x95, 0x30,
1585 0xb1, 0x9e, 0xae, 0xc4, 0x2c, 0x30, 0x05, 0x14, 0xdf, 0xfb, 0x79, 0xf1, 0x2b, 0xbf, 0x68,
1586 0x18, 0x59, 0x7f, 0xf7, 0xe8, 0xaf, 0x88, 0x91, 0x1c, 0x72, 0x32, 0xf7, 0x52, 0x18, 0x30,
1587 0x0b, 0x40, 0xcf, 0x01, 0x37, 0x65, 0xd6, 0x8a, 0xca, 0xd8, 0x33, 0x9f, 0x0f, 0x4f, 0xd5,
1588 0xed, 0x48, 0x42, 0x91, 0xca, 0xab, 0xf7, 0xae, 0xe1, 0x3b, 0x2b, 0xef, 0x9f, 0x43, 0x5a,
1589 0x96, 0xe0, 0xa5, 0x38, 0x8e, 0x39, 0xd0, 0x20, 0x8a, 0x0c, 0x92, 0x2b, 0x21, 0x7d, 0xf5,
1590 0x6c, 0x1d, 0x65, 0x6c, 0x0f, 0xd1, 0xe8, 0x55, 0x14, 0x5e, 0x27, 0xfd, 0xa4, 0xac, 0xf9,
1591 0x93, 0xdb, 0x29, 0x49, 0xaa, 0x71, 0x18,
1592 ];
1593
1594 const CHIP_CERT_TXT_IN_DN: &[u8] = &[
1595 0x15, 0x30, 0x1, 0x1, 0x1, 0x24, 0x2, 0x1, 0x37, 0x3, 0x2c, 0x84, 0x2, 0x55, 0x53, 0x2c,
1596 0x7, 0x6, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2c, 0x1, 0xb, 0x4d, 0x61, 0x74, 0x74, 0x65,
1597 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x27, 0x14, 0x1, 0x0, 0x0, 0x0, 0xfe, 0xff, 0xff, 0xff,
1598 0x18, 0x26, 0x4, 0x7f, 0xd2, 0x43, 0x29, 0x26, 0x5, 0x7f, 0x94, 0x5b, 0xe5, 0x37, 0x6,
1599 0x2c, 0x84, 0x2, 0x55, 0x53, 0x2c, 0x7, 0x6, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2c, 0x1,
1600 0xb, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x27, 0x14, 0x1,
1601 0x0, 0x0, 0x0, 0xfe, 0xff, 0xff, 0xff, 0x18, 0x24, 0x7, 0x1, 0x24, 0x8, 0x1, 0x30, 0x9,
1602 0x41, 0x4, 0x5b, 0x37, 0xdf, 0x65, 0x49, 0xc2, 0xd, 0xc8, 0xd7, 0x22, 0xa6, 0xb8, 0xac,
1603 0xb6, 0x60, 0xa8, 0xa7, 0x64, 0xce, 0x7b, 0xaf, 0x6c, 0x6c, 0x22, 0x4f, 0x7e, 0xe8, 0x43,
1604 0x49, 0x68, 0x4a, 0xd7, 0xd8, 0x9, 0xff, 0x65, 0x0, 0x33, 0xd1, 0x52, 0x7d, 0xcf, 0x1f,
1605 0xba, 0xac, 0x6a, 0x9c, 0x3a, 0xd8, 0xb4, 0x1e, 0xda, 0xc9, 0x9, 0xf7, 0xb5, 0xc7, 0x60,
1606 0xfd, 0x54, 0x2c, 0x89, 0x23, 0x75, 0x37, 0xa, 0x35, 0x1, 0x29, 0x1, 0x24, 0x2, 0x1, 0x18,
1607 0x24, 0x2, 0x60, 0x30, 0x4, 0x14, 0x72, 0xc2, 0x1, 0xf7, 0x57, 0x19, 0x13, 0xb3, 0x48,
1608 0xca, 0x0, 0xca, 0x7b, 0x45, 0xf4, 0x77, 0x46, 0x68, 0xc9, 0x7e, 0x30, 0x5, 0x14, 0x72,
1609 0xc2, 0x1, 0xf7, 0x57, 0x19, 0x13, 0xb3, 0x48, 0xca, 0x0, 0xca, 0x7b, 0x45, 0xf4, 0x77,
1610 0x46, 0x68, 0xc9, 0x7e, 0x18, 0x30, 0xb, 0x40, 0x65, 0x16, 0x4b, 0x16, 0x6a, 0xdf, 0xf1,
1611 0x8c, 0x15, 0x61, 0xa, 0x8c, 0xe9, 0x1b, 0xd7, 0x3, 0xe9, 0xc1, 0xf6, 0x77, 0xb7, 0x11,
1612 0xce, 0x13, 0x35, 0x5, 0x15, 0x2d, 0xf0, 0xda, 0x15, 0x11, 0x16, 0x75, 0xac, 0x55, 0x91,
1613 0xce, 0xe7, 0x86, 0x85, 0x1c, 0xdd, 0x9e, 0xfd, 0xad, 0x29, 0x66, 0x74, 0xbe, 0xbc, 0xb2,
1614 0xa3, 0xa3, 0x20, 0x9b, 0xcd, 0xe7, 0xb3, 0x9, 0xdb, 0x55, 0x2c, 0x6f, 0x18,
1615 ];
1616
1617 const ASN1_OUTPUT1: &[u8] = &[
1618 0x30, 0x82, 0x01, 0x80, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0a, 0x06,
1619 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e,
1620 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x04, 0x0c, 0x10, 0x30,
1621 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1622 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01,
1623 0x05, 0x0c, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1624 0x30, 0x30, 0x30, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
1625 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30,
1626 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b,
1627 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x03, 0x0c, 0x10, 0x30, 0x30, 0x30, 0x30,
1628 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x20, 0x30,
1629 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x05, 0x0c, 0x10,
1630 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1631 0x33, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
1632 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x69, 0xda,
1633 0xe9, 0x42, 0x88, 0xcf, 0x64, 0x94, 0x2d, 0xd5, 0x0a, 0x74, 0x2d, 0x50, 0xe8, 0x5e, 0xbe,
1634 0x15, 0x53, 0x24, 0xe5, 0xc5, 0x6b, 0xe5, 0x7f, 0xc1, 0x41, 0x11, 0x21, 0xdd, 0x46, 0xa3,
1635 0x0d, 0x63, 0xc3, 0xe3, 0x90, 0x7a, 0x69, 0x64, 0xdd, 0x66, 0x78, 0x10, 0xa6, 0xc8, 0x0f,
1636 0xfd, 0xb6, 0xf2, 0x9b, 0x88, 0x50, 0x93, 0x77, 0x9e, 0xf7, 0xb4, 0xda, 0x94, 0x11, 0x33,
1637 0x1e, 0xfe, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01,
1638 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f,
1639 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d,
1640 0x0e, 0x04, 0x16, 0x04, 0x14, 0xdf, 0xfb, 0x79, 0xf1, 0x2b, 0xbf, 0x68, 0x18, 0x59, 0x7f,
1641 0xf7, 0xe8, 0xaf, 0x88, 0x91, 0x1c, 0x72, 0x32, 0xf7, 0x52, 0x30, 0x1f, 0x06, 0x03, 0x55,
1642 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xed, 0x31, 0x5e, 0x1a, 0xb7, 0xb9, 0x7a,
1643 0xca, 0x04, 0x79, 0x5d, 0x82, 0x57, 0x7a, 0xd7, 0x0a, 0x75, 0xd0, 0xdb, 0x7a,
1644 ];
1645
1646 const ASN1_OUTPUT2: &[u8] = &[
1647 0x30, 0x82, 0x01, 0xa1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06,
1648 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e,
1649 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x03, 0x0c, 0x10, 0x30,
1650 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31,
1651 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01,
1652 0x05, 0x0c, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1653 0x30, 0x30, 0x30, 0x33, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
1654 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x30, 0x31, 0x32, 0x33, 0x30, 0x30,
1655 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x44, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b,
1656 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x01, 0x0c, 0x10, 0x30, 0x30, 0x30, 0x30,
1657 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x42, 0x36, 0x36, 0x39, 0x31, 0x20, 0x30,
1658 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x05, 0x0c, 0x10,
1659 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1660 0x33, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06,
1661 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x93, 0x04,
1662 0xc6, 0xc4, 0xe1, 0xbc, 0x9a, 0xc8, 0xf5, 0xb3, 0x7f, 0x83, 0xd6, 0x7f, 0x79, 0xc5, 0x35,
1663 0xdc, 0x7f, 0xac, 0x87, 0xca, 0xcd, 0x08, 0x80, 0x4a, 0x55, 0x60, 0x80, 0x09, 0xd3, 0x9b,
1664 0x4a, 0xc8, 0xe7, 0x7b, 0x4d, 0x5c, 0x82, 0x88, 0x24, 0xdf, 0x1c, 0xfd, 0xef, 0xb4, 0xbc,
1665 0xb7, 0x2f, 0x36, 0xf7, 0x2b, 0xb2, 0xcc, 0x14, 0x69, 0x63, 0xcc, 0x89, 0xd2, 0x74, 0x3f,
1666 0xd1, 0x98, 0xa3, 0x81, 0x83, 0x30, 0x81, 0x80, 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13,
1667 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01,
1668 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x07, 0x80, 0x30, 0x20, 0x06, 0x03, 0x55, 0x1d, 0x25,
1669 0x01, 0x01, 0xff, 0x04, 0x16, 0x30, 0x14, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07,
1670 0x03, 0x02, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x1d, 0x06,
1671 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9c, 0xe7, 0xd9, 0xa8, 0x6b, 0xf8, 0x71,
1672 0xfa, 0x08, 0x10, 0xa3, 0xf2, 0x3a, 0x95, 0x30, 0xb1, 0x9e, 0xae, 0xc4, 0x2c, 0x30, 0x1f,
1673 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xdf, 0xfb, 0x79, 0xf1,
1674 0x2b, 0xbf, 0x68, 0x18, 0x59, 0x7f, 0xf7, 0xe8, 0xaf, 0x88, 0x91, 0x1c, 0x72, 0x32, 0xf7,
1675 0x52,
1676 ];
1677
1678 const ASN1_OUTPUT_TXT_IN_DN: &[u8] = &[
1679 0x30, 0x82, 0x01, 0xa9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, 0x06,
1680 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x56, 0x31, 0x0b, 0x30, 0x09,
1681 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03,
1682 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x14, 0x30, 0x12,
1683 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x52,
1684 0x6f, 0x6f, 0x74, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82,
1685 0xa2, 0x7c, 0x01, 0x04, 0x0c, 0x10, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x45, 0x30,
1686 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x20, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32,
1687 0x30, 0x38, 0x32, 0x30, 0x33, 0x30, 0x35, 0x35, 0x5a, 0x18, 0x0f, 0x32, 0x31, 0x32, 0x31,
1688 0x31, 0x32, 0x30, 0x38, 0x32, 0x30, 0x33, 0x30, 0x35, 0x35, 0x5a, 0x30, 0x56, 0x31, 0x0b,
1689 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d,
1690 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x14,
1691 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72,
1692 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
1693 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x04, 0x0c, 0x10, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46,
1694 0x45, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07,
1695 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03,
1696 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x5b, 0x37, 0xdf, 0x65, 0x49, 0xc2, 0x0d, 0xc8, 0xd7,
1697 0x22, 0xa6, 0xb8, 0xac, 0xb6, 0x60, 0xa8, 0xa7, 0x64, 0xce, 0x7b, 0xaf, 0x6c, 0x6c, 0x22,
1698 0x4f, 0x7e, 0xe8, 0x43, 0x49, 0x68, 0x4a, 0xd7, 0xd8, 0x09, 0xff, 0x65, 0x00, 0x33, 0xd1,
1699 0x52, 0x7d, 0xcf, 0x1f, 0xba, 0xac, 0x6a, 0x9c, 0x3a, 0xd8, 0xb4, 0x1e, 0xda, 0xc9, 0x09,
1700 0xf7, 0xb5, 0xc7, 0x60, 0xfd, 0x54, 0x2c, 0x89, 0x23, 0x75, 0xa3, 0x66, 0x30, 0x64, 0x30,
1701 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01,
1702 0xff, 0x02, 0x01, 0x01, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04,
1703 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04,
1704 0x14, 0x72, 0xc2, 0x01, 0xf7, 0x57, 0x19, 0x13, 0xb3, 0x48, 0xca, 0x00, 0xca, 0x7b, 0x45,
1705 0xf4, 0x77, 0x46, 0x68, 0xc9, 0x7e, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18,
1706 0x30, 0x16, 0x80, 0x14, 0x72, 0xc2, 0x01, 0xf7, 0x57, 0x19, 0x13, 0xb3, 0x48, 0xca, 0x00,
1707 0xca, 0x7b, 0x45, 0xf4, 0x77, 0x46, 0x68, 0xc9, 0x7e,
1708 ];
1709
1710 const NOC_NOT_AFTER_ZERO: &[u8] = &[
1712 0x15, 0x30, 0x1, 0x1, 0x1, 0x24, 0x2, 0x1, 0x37, 0x3, 0x27, 0x14, 0xfc, 0x8d, 0xcf, 0x45,
1713 0x19, 0xff, 0x9a, 0x9a, 0x24, 0x15, 0x1, 0x18, 0x26, 0x4, 0x21, 0x39, 0x5a, 0x2c, 0x24,
1714 0x5, 0x0, 0x37, 0x6, 0x24, 0x15, 0x1, 0x26, 0x11, 0x6c, 0x4a, 0x95, 0xd2, 0x18, 0x24, 0x7,
1715 0x1, 0x24, 0x8, 0x1, 0x30, 0x9, 0x41, 0x4, 0x41, 0x7f, 0xb1, 0x61, 0xb0, 0xbe, 0x19, 0x41,
1716 0x81, 0xb9, 0x9f, 0xe8, 0x7b, 0xdd, 0xdf, 0xc4, 0x46, 0xe0, 0x74, 0xba, 0x83, 0x21, 0xda,
1717 0x3d, 0xf7, 0x88, 0x68, 0x14, 0xa6, 0x9d, 0xa9, 0x14, 0x88, 0x94, 0x1e, 0xd3, 0x86, 0x62,
1718 0xc7, 0x6f, 0xb4, 0x79, 0xd2, 0xaf, 0x34, 0xe7, 0xd6, 0x4d, 0x87, 0x29, 0x67, 0x10, 0x73,
1719 0xb9, 0x81, 0xe0, 0x9, 0xe1, 0x13, 0xbb, 0x6a, 0xd2, 0x21, 0xaa, 0x37, 0xa, 0x35, 0x1,
1720 0x28, 0x1, 0x18, 0x24, 0x2, 0x1, 0x36, 0x3, 0x4, 0x2, 0x4, 0x1, 0x18, 0x30, 0x4, 0x14,
1721 0x98, 0xaf, 0xa1, 0x3d, 0x41, 0x67, 0x7a, 0x34, 0x8c, 0x67, 0x6c, 0xcc, 0x17, 0x6e, 0xd5,
1722 0x58, 0xd8, 0x2b, 0x86, 0x8, 0x30, 0x5, 0x14, 0xf8, 0xcf, 0xd0, 0x45, 0x6b, 0xe, 0xd1,
1723 0x6f, 0xc5, 0x67, 0xdf, 0x81, 0xd7, 0xe9, 0xb7, 0xeb, 0x39, 0x78, 0xec, 0x40, 0x18, 0x30,
1724 0xb, 0x40, 0xf9, 0x80, 0x94, 0xbf, 0xcf, 0x72, 0xa5, 0x54, 0x87, 0x12, 0x35, 0xc, 0x38,
1725 0x79, 0xa8, 0xb, 0x21, 0x94, 0xb5, 0x71, 0x2, 0xcb, 0xb, 0xda, 0xf9, 0x6c, 0x54, 0xcb,
1726 0x50, 0x4b, 0x2, 0x5, 0xea, 0xff, 0xfd, 0xb2, 0x1b, 0x24, 0x30, 0x79, 0xb1, 0x69, 0x87,
1727 0xa5, 0x7, 0xc6, 0x76, 0x15, 0x70, 0xc0, 0xec, 0x14, 0xd3, 0x9f, 0x1a, 0xa7, 0xe1, 0xca,
1728 0x25, 0x2e, 0x44, 0xfc, 0x96, 0x4d, 0x18,
1729 ];
1730
1731 const RCA_FOR_NOC_NOT_AFTER_ZERO: &[u8] = &[
1732 0x15, 0x30, 0x1, 0x1, 0x0, 0x24, 0x2, 0x1, 0x37, 0x3, 0x27, 0x14, 0xfc, 0x8d, 0xcf, 0x45,
1733 0x19, 0xff, 0x9a, 0x9a, 0x24, 0x15, 0x1, 0x18, 0x26, 0x4, 0xb1, 0x2a, 0x38, 0x2c, 0x26,
1734 0x5, 0x31, 0x5e, 0x19, 0x2e, 0x37, 0x6, 0x27, 0x14, 0xfc, 0x8d, 0xcf, 0x45, 0x19, 0xff,
1735 0x9a, 0x9a, 0x24, 0x15, 0x1, 0x18, 0x24, 0x7, 0x1, 0x24, 0x8, 0x1, 0x30, 0x9, 0x41, 0x4,
1736 0x15, 0x69, 0x1e, 0x7b, 0x6a, 0xea, 0x5, 0xdb, 0xf8, 0x4b, 0xfd, 0xdc, 0x6c, 0x75, 0x46,
1737 0x74, 0xb0, 0x60, 0xdb, 0x4, 0x71, 0xb6, 0xd0, 0x52, 0xf2, 0xf8, 0xe6, 0xbb, 0xd, 0xe5,
1738 0x60, 0x1f, 0x84, 0x66, 0x4f, 0x3c, 0x90, 0x89, 0xa6, 0xc6, 0x99, 0x61, 0xfb, 0x89, 0xf7,
1739 0xa, 0xa6, 0xe4, 0xa2, 0x21, 0xd3, 0x37, 0x30, 0x1b, 0xd2, 0x11, 0xc5, 0xcc, 0x0, 0xf4,
1740 0x7a, 0x14, 0xfc, 0x3c, 0x37, 0xa, 0x35, 0x1, 0x29, 0x1, 0x18, 0x24, 0x2, 0x60, 0x30, 0x4,
1741 0x14, 0xf8, 0xcf, 0xd0, 0x45, 0x6b, 0xe, 0xd1, 0x6f, 0xc5, 0x67, 0xdf, 0x81, 0xd7, 0xe9,
1742 0xb7, 0xeb, 0x39, 0x78, 0xec, 0x40, 0x30, 0x5, 0x14, 0xf8, 0xcf, 0xd0, 0x45, 0x6b, 0xe,
1743 0xd1, 0x6f, 0xc5, 0x67, 0xdf, 0x81, 0xd7, 0xe9, 0xb7, 0xeb, 0x39, 0x78, 0xec, 0x40, 0x18,
1744 0x30, 0xb, 0x40, 0x4c, 0xae, 0xac, 0xc1, 0x26, 0xdd, 0x56, 0xc, 0x85, 0x86, 0xbc, 0xeb,
1745 0xa2, 0xb5, 0xb7, 0xdf, 0x49, 0x92, 0x62, 0xcd, 0x2a, 0xb6, 0x4e, 0xc5, 0x31, 0x7c, 0xd9,
1746 0xb, 0x1c, 0xe9, 0x6e, 0xe5, 0x82, 0xc7, 0xb8, 0xda, 0x22, 0x31, 0x7b, 0x23, 0x5a, 0x2a,
1747 0xe6, 0x76, 0x28, 0xb6, 0xd4, 0xc7, 0x7b, 0x1c, 0x9c, 0x85, 0x71, 0x5f, 0xe6, 0xf6, 0x21,
1748 0x50, 0x5c, 0xa7, 0x7c, 0xc7, 0x1d, 0x9a, 0x18,
1749 ];
1750
1751 const UNORDERED_EXTENSIONS_CHIP: &[u8] = &[
1752 0x15, 0x30, 0x01, 0x10, 0x44, 0x9d, 0xeb, 0xca, 0x2e, 0x2e, 0x98, 0x42, 0xe0, 0x87, 0x6f,
1753 0x8b, 0xfa, 0x23, 0xe4, 0x54, 0x24, 0x02, 0x01, 0x37, 0x03, 0x27, 0x14, 0xf6, 0x56, 0xb7,
1754 0x85, 0xf4, 0xbf, 0x30, 0x00, 0x18, 0x26, 0x04, 0xe2, 0xdc, 0xbc, 0x2a, 0x26, 0x05, 0x72,
1755 0xdb, 0xc2, 0x59, 0x37, 0x06, 0x27, 0x14, 0xf6, 0x56, 0xb7, 0x85, 0xf4, 0xbf, 0x30, 0x00,
1756 0x18, 0x24, 0x07, 0x01, 0x24, 0x08, 0x01, 0x30, 0x09, 0x41, 0x04, 0xac, 0x73, 0x46, 0xeb,
1757 0x93, 0xc3, 0x42, 0x58, 0xf1, 0x69, 0x63, 0x65, 0xa6, 0x9f, 0xbe, 0xcb, 0x33, 0xd4, 0x82,
1758 0xd9, 0xdf, 0xc7, 0x3e, 0x94, 0x61, 0x58, 0x83, 0xba, 0x2e, 0x3a, 0xb2, 0xdd, 0x19, 0xcb,
1759 0x8c, 0x12, 0x2e, 0x19, 0x0e, 0x90, 0x2c, 0xb8, 0xec, 0xb9, 0xaa, 0xea, 0x10, 0x00, 0xbb,
1760 0x60, 0xeb, 0xe3, 0x92, 0xb9, 0x2c, 0x78, 0xbb, 0x41, 0xfd, 0x5c, 0xdc, 0xc3, 0x0f, 0x46,
1761 0x37, 0x0a, 0x35, 0x01, 0x29, 0x01, 0x18, 0x30, 0x04, 0x14, 0x2b, 0x33, 0x55, 0x73, 0xc7,
1762 0xc9, 0x12, 0x46, 0x59, 0xe8, 0xe5, 0xfc, 0x50, 0xc5, 0x68, 0x76, 0xfc, 0x93, 0xdc, 0x0b,
1763 0x24, 0x02, 0x61, 0x30, 0x05, 0x14, 0x2b, 0x33, 0x55, 0x73, 0xc7, 0xc9, 0x12, 0x46, 0x59,
1764 0xe8, 0xe5, 0xfc, 0x50, 0xc5, 0x68, 0x76, 0xfc, 0x93, 0xdc, 0x0b, 0x18, 0x30, 0x0b, 0x40,
1765 0x48, 0x8a, 0x6d, 0xf0, 0xa5, 0x9c, 0x3d, 0xb5, 0x5a, 0x29, 0xeb, 0xf6, 0x9a, 0xba, 0x7a,
1766 0xd2, 0x49, 0xb8, 0xcc, 0xe7, 0x33, 0xe3, 0xaa, 0x45, 0x99, 0x6e, 0x34, 0x3a, 0xe3, 0x23,
1767 0x1d, 0x30, 0x94, 0x36, 0x77, 0x33, 0x50, 0x9a, 0x28, 0x9b, 0x25, 0x42, 0xba, 0xaf, 0x13,
1768 0x50, 0xda, 0xe8, 0x43, 0xb4, 0xe1, 0x49, 0x8c, 0x61, 0x0d, 0xab, 0x24, 0xcd, 0xe2, 0x1c,
1769 0xb2, 0x5a, 0x36, 0xd5, 0x18,
1770 ];
1771
1772 const UNORDERED_EXTENSIONS_DER: &[u8] = &[
1773 0x30, 0x82, 0x01, 0x4b, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x44, 0x9d, 0xeb, 0xca,
1774 0x2e, 0x2e, 0x98, 0x42, 0xe0, 0x87, 0x6f, 0x8b, 0xfa, 0x23, 0xe4, 0x54, 0x30, 0x0a, 0x06,
1775 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1e,
1776 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x04, 0x0c, 0x10, 0x30,
1777 0x30, 0x33, 0x30, 0x42, 0x46, 0x46, 0x34, 0x38, 0x35, 0x42, 0x37, 0x35, 0x36, 0x46, 0x36,
1778 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x39, 0x32, 0x30, 0x32, 0x30, 0x31, 0x39, 0x34,
1779 0x36, 0x5a, 0x17, 0x0d, 0x34, 0x37, 0x30, 0x39, 0x32, 0x30, 0x32, 0x31, 0x31, 0x39, 0x34,
1780 0x36, 0x5a, 0x30, 0x22, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01,
1781 0x82, 0xa2, 0x7c, 0x01, 0x04, 0x0c, 0x10, 0x30, 0x30, 0x33, 0x30, 0x42, 0x46, 0x46, 0x34,
1782 0x38, 0x35, 0x42, 0x37, 0x35, 0x36, 0x46, 0x36, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a,
1783 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01,
1784 0x07, 0x03, 0x42, 0x00, 0x04, 0xac, 0x73, 0x46, 0xeb, 0x93, 0xc3, 0x42, 0x58, 0xf1, 0x69,
1785 0x63, 0x65, 0xa6, 0x9f, 0xbe, 0xcb, 0x33, 0xd4, 0x82, 0xd9, 0xdf, 0xc7, 0x3e, 0x94, 0x61,
1786 0x58, 0x83, 0xba, 0x2e, 0x3a, 0xb2, 0xdd, 0x19, 0xcb, 0x8c, 0x12, 0x2e, 0x19, 0x0e, 0x90,
1787 0x2c, 0xb8, 0xec, 0xb9, 0xaa, 0xea, 0x10, 0x00, 0xbb, 0x60, 0xeb, 0xe3, 0x92, 0xb9, 0x2c,
1788 0x78, 0xbb, 0x41, 0xfd, 0x5c, 0xdc, 0xc3, 0x0f, 0x46, 0xa3, 0x63, 0x30, 0x61, 0x30, 0x0f,
1789 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff,
1790 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x2b, 0x33, 0x55, 0x73,
1791 0xc7, 0xc9, 0x12, 0x46, 0x59, 0xe8, 0xe5, 0xfc, 0x50, 0xc5, 0x68, 0x76, 0xfc, 0x93, 0xdc,
1792 0x0b, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02,
1793 0x01, 0x86, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14,
1794 0x2b, 0x33, 0x55, 0x73, 0xc7, 0xc9, 0x12, 0x46, 0x59, 0xe8, 0xe5, 0xfc, 0x50, 0xc5, 0x68,
1795 0x76, 0xfc, 0x93, 0xdc, 0x0b,
1796 ];
1797}