1use core::fmt;
10use core::iter::FromIterator;
11use core::ptr::NonNull;
12
13use mbedtls_sys::types::raw_types::{c_char, c_void};
14use mbedtls_sys::*;
15
16use crate::alloc::{mbedtls_calloc, Box as MbedtlsBox, CString, List as MbedtlsList};
17#[cfg(not(feature = "std"))]
18use crate::alloc_prelude::*;
19use crate::error::{codes, Error, IntoResult, Result};
20use crate::hash::Type as MdType;
21use crate::pk::Pk;
22use crate::private::UnsafeFrom;
23use crate::rng::Random;
24use crate::x509::{self, Crl, Time, VerifyCallback};
25
26#[cfg(feature = "std")]
27use yasna::{models::ObjectIdentifier, ASN1Error, ASN1ErrorKind, ASN1Result, BERDecodable, BERReader};
28
29use super::VerifyError;
30
31#[derive(Debug, Copy, Clone, Eq, PartialEq)]
32pub enum CertificateVersion {
33 V1,
34 V2,
35 V3,
36}
37
38#[cfg(feature = "std")]
39#[derive(Debug, Clone, Eq, PartialEq)]
40pub struct Extension {
41 pub oid: ObjectIdentifier,
42 pub critical: bool,
43 pub value: Vec<u8>,
44}
45
46#[cfg(feature = "std")]
47impl BERDecodable for Extension {
48 fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
49 reader.read_sequence(|reader| {
50 let oid = reader.next().read_oid()?;
51 let critical = reader.read_optional(|r| r.read_bool())?.unwrap_or(false);
52 let value = reader.next().read_bytes()?;
53 Ok(Extension { oid, critical, value })
54 })
55 }
56}
57
58define!(
59 #[c_ty(x509_crt)]
60 #[repr(transparent)]
61 struct Certificate;
62 const drop: fn(&mut Self) = x509_crt_free;
63 impl<'a> Into<ptr> {}
64 impl<'a> UnsafeFrom<ptr> {}
65);
66
67unsafe impl Sync for Certificate {}
68
69fn x509_time_to_time(tm: &x509_time) -> Result<Time> {
70 if tm.year < 0 || tm.mon < 0 || tm.day < 0 || tm.hour < 0 || tm.min < 0 || tm.sec < 0 {
72 return Err(codes::X509InvalidDate.into());
73 }
74
75 Time::new(
76 tm.year as u16,
77 tm.mon as u8,
78 tm.day as u8,
79 tm.hour as u8,
80 tm.min as u8,
81 tm.sec as u8,
82 )
83 .ok_or(codes::X509InvalidDate.into())
84}
85
86impl Certificate {
87 pub fn from_der(der: &[u8]) -> Result<MbedtlsBox<Certificate>> {
88 let mut cert = MbedtlsBox::<Certificate>::init()?;
89 unsafe { x509_crt_parse_der((&mut (*cert)).into(), der.as_ptr(), der.len()) }.into_result()?;
90 Ok(cert)
91 }
92
93 pub fn from_pem(pem: &[u8]) -> Result<MbedtlsBox<Certificate>> {
95 let mut cert = MbedtlsBox::<Certificate>::init()?;
96 unsafe { x509_crt_parse((&mut (*cert)).into(), pem.as_ptr(), pem.len()) }.into_result()?;
97
98 if !(*cert).inner.next.is_null() {
99 return Err(codes::X509BadInputData.into());
101 }
102
103 Ok(cert)
104 }
105
106 pub fn from_pem_multiple(pem: &[u8]) -> Result<MbedtlsList<Certificate>> {
108 let mut cert = MbedtlsBox::<Certificate>::init()?;
109 unsafe { x509_crt_parse((&mut (*cert)).into(), pem.as_ptr(), pem.len()) }.into_result()?;
110
111 let mut list = MbedtlsList::<Certificate>::new();
112 list.push(cert);
113 Ok(list)
114 }
115
116 pub fn check_key_usage(&self, usage: super::KeyUsage) -> bool {
117 unsafe { x509_crt_check_key_usage(&self.inner, usage.bits()) }
118 .into_result()
119 .is_ok()
120 }
121
122 pub fn check_extended_key_usage(&self, usage_oid: &[c_char]) -> bool {
123 unsafe { x509_crt_check_extended_key_usage(&self.inner, usage_oid.as_ptr(), usage_oid.len()) }
124 .into_result()
125 .is_ok()
126 }
127
128 pub fn issuer(&self) -> Result<String> {
129 crate::private::alloc_string_repeat(|buf, size| unsafe { x509_dn_gets(buf, size, &self.inner.issuer) })
130 }
131
132 pub fn issuer_raw(&self) -> Result<Vec<u8>> {
133 Ok(super::x509_buf_to_vec(&self.inner.issuer_raw))
134 }
135
136 pub fn subject(&self) -> Result<String> {
137 crate::private::alloc_string_repeat(|buf, size| unsafe { x509_dn_gets(buf, size, &self.inner.subject) })
138 }
139
140 pub fn subject_raw(&self) -> Result<Vec<u8>> {
141 Ok(super::x509_buf_to_vec(&self.inner.subject_raw))
142 }
143
144 pub fn serial(&self) -> Result<String> {
145 crate::private::alloc_string_repeat(|buf, size| unsafe { x509_serial_gets(buf, size, &self.inner.serial) })
146 }
147
148 pub fn serial_raw(&self) -> Result<Vec<u8>> {
149 Ok(super::x509_buf_to_vec(&self.inner.serial))
150 }
151
152 pub fn public_key(&self) -> &Pk {
153 unsafe { &*(&self.inner.pk as *const _ as *const _) }
154 }
155
156 pub fn public_key_mut(&mut self) -> &mut Pk {
157 unsafe { &mut *(&mut self.inner.pk as *mut _ as *mut _) }
158 }
159
160 pub fn as_der(&self) -> &[u8] {
161 unsafe { ::core::slice::from_raw_parts(self.inner.raw.p, self.inner.raw.len) }
162 }
163
164 pub fn version(&self) -> Result<CertificateVersion> {
165 match self.inner.version {
166 1 => Ok(CertificateVersion::V1),
167 2 => Ok(CertificateVersion::V2),
168 3 => Ok(CertificateVersion::V3),
169 _ => Err(codes::X509InvalidVersion.into()),
170 }
171 }
172
173 pub fn not_before(&self) -> Result<super::Time> {
174 x509_time_to_time(&self.inner.valid_from)
175 }
176
177 pub fn not_after(&self) -> Result<super::Time> {
178 x509_time_to_time(&self.inner.valid_to)
179 }
180
181 pub fn extensions_raw(&self) -> Result<Vec<u8>> {
182 Ok(super::x509_buf_to_vec(&self.inner.v3_ext))
183 }
184
185 #[cfg(feature = "std")]
186 pub fn extensions(&self) -> Result<Vec<Extension>> {
187 let mut ext = Vec::new();
188
189 yasna::parse_der(&self.extensions_raw()?, |r| {
190 r.read_sequence_of(|r| {
191 if let Ok(data) = r.read_der() {
192 let e: Extension = yasna::decode_der(&data)?;
193 ext.push(e);
194 return Ok(());
195 } else {
196 return Err(ASN1Error::new(ASN1ErrorKind::Eof));
197 }
198 })?;
199 return Ok(());
200 })
201 .map_err(|_| Error::from(codes::X509InvalidExtensions))?;
202
203 Ok(ext)
204 }
205
206 pub fn signature(&self) -> Result<Vec<u8>> {
207 Ok(super::x509_buf_to_vec(&self.inner.sig))
208 }
209
210 pub fn digest_type(&self) -> MdType {
211 MdType::from(self.inner.sig_md)
212 }
213
214 fn verify_ex<F>(
215 chain: &MbedtlsList<Certificate>,
216 trust_ca: &MbedtlsList<Certificate>,
217 ca_crl: Option<&mut Crl>,
218 err_info: Option<&mut String>,
219 cb: Option<F>,
220 expected_common_name: Option<&str>,
221 ) -> core::result::Result<(), (Error, VerifyError)>
222 where
223 F: VerifyCallback + 'static,
224 {
225 if chain.is_empty() {
226 return Err((codes::X509BadInputData.into(), VerifyError::CERT_MISSING));
227 }
228 let (f_vrfy, p_vrfy): (Option<unsafe extern "C" fn(_, _, _, _) -> _>, _) = if let Some(cb) = cb.as_ref() {
229 (Some(x509::verify_callback::<F>), cb as *const _ as *mut c_void)
230 } else {
231 (None, ::core::ptr::null_mut())
232 };
233
234 let cn = expected_common_name.map(|cn| CString::new(cn));
235 let mut flags = 0;
236 let result = unsafe {
237 x509_crt_verify(
238 chain.inner_ffi_mut(),
239 trust_ca.inner_ffi_mut(),
240 ca_crl.map_or(::core::ptr::null_mut(), |crl| crl.handle_mut()),
241 cn.as_ref().map_or(::core::ptr::null(), |cn| cn.as_ptr()),
242 &mut flags,
243 f_vrfy,
244 p_vrfy,
245 )
246 }
247 .into_result();
248
249 drop(cn);
251
252 if result.is_err() {
253 if let Some(err_info) = err_info {
254 let verify_info = crate::private::alloc_string_repeat(|buf, size| unsafe {
255 let prefix = "\0";
256 x509_crt_verify_info(buf, size, prefix.as_ptr() as *const _, flags)
257 });
258 if let Ok(error_str) = verify_info {
259 *err_info = error_str;
260 }
261 }
262 }
263 let verify_err = VerifyError::from_bits_truncate(flags);
264 result.map_err(|e| (e, verify_err)).map(|_| ())
265 }
266
267 pub fn verify(
268 chain: &MbedtlsList<Certificate>,
269 trust_ca: &MbedtlsList<Certificate>,
270 ca_crl: Option<&mut Crl>,
271 err_info: Option<&mut String>,
272 ) -> Result<()> {
273 Self::verify_ex(chain, trust_ca, ca_crl, err_info, None::<&dyn VerifyCallback>, None).map_err(|(e, _ve)| e)
274 }
275
276 pub fn verify_return_verify_err(
278 chain: &MbedtlsList<Certificate>,
279 trust_ca: &MbedtlsList<Certificate>,
280 ca_crl: Option<&mut Crl>,
281 err_info: Option<&mut String>,
282 ) -> core::result::Result<(), (Error, VerifyError)> {
283 Self::verify_ex(chain, trust_ca, ca_crl, err_info, None::<&dyn VerifyCallback>, None)
284 }
285
286 pub fn verify_with_expected_common_name(
295 chain: &MbedtlsList<Certificate>,
296 trust_ca: &MbedtlsList<Certificate>,
297 ca_crl: Option<&mut Crl>,
298 err_info: Option<&mut String>,
299 expected_common_name: Option<&str>,
300 ) -> Result<()> {
301 Self::verify_ex(
302 chain,
303 trust_ca,
304 ca_crl,
305 err_info,
306 None::<&dyn VerifyCallback>,
307 expected_common_name,
308 )
309 .map_err(|(e, _ve)| e)
310 }
311
312 pub fn verify_with_expected_common_name_return_verify_err(
314 chain: &MbedtlsList<Certificate>,
315 trust_ca: &MbedtlsList<Certificate>,
316 ca_crl: Option<&mut Crl>,
317 err_info: Option<&mut String>,
318 expected_common_name: Option<&str>,
319 ) -> core::result::Result<(), (Error, VerifyError)> {
320 Self::verify_ex(
321 chain,
322 trust_ca,
323 ca_crl,
324 err_info,
325 None::<&dyn VerifyCallback>,
326 expected_common_name,
327 )
328 }
329
330 pub fn verify_with_callback<F>(
331 chain: &MbedtlsList<Certificate>,
332 trust_ca: &MbedtlsList<Certificate>,
333 ca_crl: Option<&mut Crl>,
334 err_info: Option<&mut String>,
335 cb: F,
336 ) -> Result<()>
337 where
338 F: VerifyCallback + 'static,
339 {
340 Self::verify_ex(chain, trust_ca, ca_crl, err_info, Some(cb), None).map_err(|(e, _ve)| e)
341 }
342
343 pub fn verify_with_callback_return_verify_err<F>(
345 chain: &MbedtlsList<Certificate>,
346 trust_ca: &MbedtlsList<Certificate>,
347 ca_crl: Option<&mut Crl>,
348 err_info: Option<&mut String>,
349 cb: F,
350 ) -> core::result::Result<(), (Error, VerifyError)>
351 where
352 F: VerifyCallback + 'static,
353 {
354 Self::verify_ex(chain, trust_ca, ca_crl, err_info, Some(cb), None)
355 }
356
357 pub fn verify_with_callback_expected_common_name<F>(
366 chain: &MbedtlsList<Certificate>,
367 trust_ca: &MbedtlsList<Certificate>,
368 ca_crl: Option<&mut Crl>,
369 err_info: Option<&mut String>,
370 cb: F,
371 expected_common_name: Option<&str>,
372 ) -> Result<()>
373 where
374 F: VerifyCallback + 'static,
375 {
376 Self::verify_ex(chain, trust_ca, ca_crl, err_info, Some(cb), expected_common_name).map_err(|(e, _ve)| e)
377 }
378
379 pub fn verify_with_callback_expected_common_name_return_verify_err<F>(
381 chain: &MbedtlsList<Certificate>,
382 trust_ca: &MbedtlsList<Certificate>,
383 ca_crl: Option<&mut Crl>,
384 err_info: Option<&mut String>,
385 cb: F,
386 expected_common_name: Option<&str>,
387 ) -> core::result::Result<(), (Error, VerifyError)>
388 where
389 F: VerifyCallback + 'static,
390 {
391 Self::verify_ex(chain, trust_ca, ca_crl, err_info, Some(cb), expected_common_name)
392 }
393}
394
395impl fmt::Debug for Certificate {
405 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
406 match crate::private::alloc_string_repeat(|buf, size| unsafe {
407 x509_crt_info(buf, size, b"\0".as_ptr() as *const _, &self.inner)
408 }) {
409 Err(_) => Err(fmt::Error),
410 Ok(s) => f.write_str(&s),
411 }
412 }
413}
414
415define!(
416 #[c_ty(x509write_cert)]
417 struct Builder<'a>;
418 pub const new: fn() -> Self = x509write_crt_init;
419 const drop: fn(&mut Self) = x509write_crt_free;
420);
421
422impl<'a> Builder<'a> {
423 unsafe fn subject_with_nul_unchecked(&mut self, subject: &[u8]) -> Result<&mut Self> {
424 x509write_crt_set_subject_name(&mut self.inner, subject.as_ptr() as *const _).into_result()?;
425 Ok(self)
426 }
427
428 #[cfg(feature = "std")]
429 pub fn subject(&mut self, subject: &str) -> Result<&mut Self> {
430 match ::std::ffi::CString::new(subject) {
431 Err(_) => Err(codes::X509InvalidName.into()),
432 Ok(s) => unsafe { self.subject_with_nul_unchecked(s.as_bytes_with_nul()) },
433 }
434 }
435
436 pub fn subject_with_nul(&mut self, subject: &str) -> Result<&mut Self> {
437 if subject.as_bytes().iter().any(|&c| c == 0) {
438 unsafe { self.subject_with_nul_unchecked(subject.as_bytes()) }
439 } else {
440 Err(codes::X509InvalidName.into())
441 }
442 }
443
444 unsafe fn issuer_with_nul_unchecked(&mut self, issuer: &[u8]) -> Result<&mut Self> {
445 x509write_crt_set_issuer_name(&mut self.inner, issuer.as_ptr() as *const _).into_result()?;
446 Ok(self)
447 }
448
449 #[cfg(feature = "std")]
450 pub fn issuer(&mut self, issuer: &str) -> Result<&mut Self> {
451 match ::std::ffi::CString::new(issuer) {
452 Err(_) => Err(codes::X509InvalidName.into()),
453 Ok(s) => unsafe { self.issuer_with_nul_unchecked(s.as_bytes_with_nul()) },
454 }
455 }
456
457 pub fn issuer_with_nul(&mut self, issuer: &str) -> Result<&mut Self> {
458 if issuer.as_bytes().iter().any(|&c| c == 0) {
459 unsafe { self.issuer_with_nul_unchecked(issuer.as_bytes()) }
460 } else {
461 Err(codes::X509InvalidName.into())
462 }
463 }
464
465 pub fn subject_key(&mut self, key: &'a mut Pk) -> &mut Self {
466 unsafe { x509write_crt_set_subject_key(&mut self.inner, key.into()) };
467 self
468 }
469
470 pub fn issuer_key(&mut self, key: &'a mut Pk) -> &mut Self {
471 unsafe { x509write_crt_set_issuer_key(&mut self.inner, key.into()) };
472 self
473 }
474
475 pub fn signature_hash(&mut self, md: MdType) -> &mut Self {
476 unsafe { x509write_crt_set_md_alg(&mut self.inner, md.into()) };
477 self
478 }
479
480 pub fn key_usage(&mut self, usage: crate::x509::KeyUsage) -> Result<&mut Self> {
481 unsafe { x509write_crt_set_key_usage(&mut self.inner, usage.bits()) }.into_result()?;
482 Ok(self)
483 }
484
485 pub fn extension(&mut self, oid: &[u8], val: &[u8], critical: bool) -> Result<&mut Self> {
486 unsafe {
487 x509write_crt_set_extension(
488 &mut self.inner,
489 oid.as_ptr() as *const _,
490 oid.len(),
491 critical as _,
492 val.as_ptr(),
493 val.len(),
494 )
495 }
496 .into_result()?;
497 Ok(self)
498 }
499
500 pub fn basic_constraints(&mut self, ca: bool, pathlen: Option<u32>) -> Result<&mut Self> {
501 unsafe { x509write_crt_set_basic_constraints(&mut self.inner, ca as _, pathlen.unwrap_or(0) as _) }.into_result()?;
502 Ok(self)
503 }
504
505 pub fn validity(&mut self, not_before: super::Time, not_after: super::Time) -> Result<&mut Self> {
506 unsafe {
507 x509write_crt_set_validity(
508 &mut self.inner,
509 not_before.to_x509_time().as_ptr() as _,
510 not_after.to_x509_time().as_ptr() as _,
511 )
512 }
513 .into_result()?;
514 Ok(self)
515 }
516
517 pub fn serial(&mut self, serial: &[u8]) -> Result<&mut Self> {
518 let serial = crate::bignum::Mpi::from_binary(serial)?;
519 unsafe { x509write_crt_set_serial(&mut self.inner, (&serial).into()) }.into_result()?;
520 Ok(self)
521 }
522
523 pub fn write_der<'buf, F: Random>(&mut self, buf: &'buf mut [u8], rng: &mut F) -> Result<Option<&'buf [u8]>> {
524 match unsafe {
525 x509write_crt_der(&mut self.inner, buf.as_mut_ptr(), buf.len(), Some(F::call), rng.data_ptr()).into_result()
526 } {
527 Err(e) if e.low_level() == Some(codes::Asn1BufTooSmall) => Ok(None),
528 Err(e) => Err(e),
529 Ok(n) => Ok(Some(&buf[buf.len() - (n as usize)..])),
530 }
531 }
532
533 pub fn write_der_vec<F: Random>(&mut self, rng: &mut F) -> Result<Vec<u8>> {
534 crate::private::alloc_vec_repeat(
535 |buf, size| unsafe { x509write_crt_der(&mut self.inner, buf, size, Some(F::call), rng.data_ptr()) },
536 true,
537 )
538 }
539
540 pub fn write_pem<'buf, F: Random>(&mut self, buf: &'buf mut [u8], rng: &mut F) -> Result<Option<&'buf [u8]>> {
541 match unsafe {
542 x509write_crt_der(&mut self.inner, buf.as_mut_ptr(), buf.len(), Some(F::call), rng.data_ptr()).into_result()
543 } {
544 Err(e) if e.low_level() == Some(codes::Base64BufferTooSmall) => Ok(None),
545 Err(e) => Err(e),
546 Ok(n) => Ok(Some(&buf[buf.len() - (n as usize)..])),
547 }
548 }
549
550 pub fn write_pem_string<F: Random>(&mut self, rng: &mut F) -> Result<String> {
551 crate::private::alloc_string_repeat(|buf, size| unsafe {
552 match x509write_crt_pem(&mut self.inner, buf as _, size, Some(F::call), rng.data_ptr()) {
553 0 => crate::private::cstr_to_slice(buf as _).len() as _,
554 r => r,
555 }
556 })
557 }
558}
559
560impl MbedtlsBox<Certificate> {
568 fn init() -> Result<Self> {
569 unsafe {
570 let inner = mbedtls_calloc(1, core::mem::size_of::<x509_crt>()) as *mut x509_crt;
571
572 assert_eq!(inner.align_offset(core::mem::align_of::<x509_crt>()), 0);
575
576 let inner = NonNull::new(inner).ok_or(Error::from(codes::X509AllocFailed))?;
577 x509_crt_init(inner.as_ptr());
578
579 Ok(MbedtlsBox { inner: inner.cast() })
580 }
581 }
582
583 fn list_next(&self) -> Option<&MbedtlsBox<Certificate>> {
584 unsafe {
585 <&Option<MbedtlsBox<_>> as UnsafeFrom<_>>::from(&(**self).inner.next)
586 .unwrap()
587 .as_ref()
588 }
589 }
590
591 fn list_next_mut(&mut self) -> &mut Option<MbedtlsBox<Certificate>> {
592 unsafe { <&mut Option<MbedtlsBox<_>> as UnsafeFrom<_>>::from(&mut (**self).inner.next).unwrap() }
593 }
594}
595
596impl Clone for MbedtlsBox<Certificate> {
597 fn clone(&self) -> MbedtlsBox<Certificate> {
598 unsafe {
599 let len = (**self).inner.raw.len;
600 if len == 0 {
601 unreachable!("Trying to clone an uninitialized certificate.");
607 } else {
608 Certificate::from_der(core::slice::from_raw_parts((**self).inner.raw.p, len))
611 .expect("Failed re-parsing existing DER")
612 }
613 }
614 }
615}
616
617impl<'a> UnsafeFrom<*const *mut x509_crt> for &'a Option<MbedtlsBox<Certificate>> {
618 unsafe fn from(ptr: *const *mut x509_crt) -> Option<&'a Option<MbedtlsBox<Certificate>>> {
619 (ptr as *const Option<MbedtlsBox<Certificate>>).as_ref()
620 }
621}
622
623impl<'a> UnsafeFrom<*mut *mut x509_crt> for &'a mut Option<MbedtlsBox<Certificate>> {
624 unsafe fn from(ptr: *mut *mut x509_crt) -> Option<&'a mut Option<MbedtlsBox<Certificate>>> {
625 (ptr as *mut Option<MbedtlsBox<Certificate>>).as_mut()
626 }
627}
628
629impl MbedtlsList<Certificate> {
630 pub fn new() -> Self {
631 Self { inner: None }
632 }
633
634 #[allow(dead_code)]
635 pub(crate) fn into_raw(mut self) -> *mut x509_crt {
636 self.inner.take().map(|x| x.into_raw()).unwrap_or(core::ptr::null_mut()) as *mut x509_crt
639 }
640
641 pub fn is_empty(&self) -> bool {
642 self.inner.is_none()
643 }
644
645 pub fn push(&mut self, certificate: MbedtlsBox<Certificate>) -> () {
646 self.append(MbedtlsList::<Certificate> {
647 inner: Some(certificate),
648 });
649 }
650
651 pub fn pop_back(&mut self) -> Option<MbedtlsBox<Certificate>> {
652 let mut iter = self.iter_mut();
653
654 let mut prev = iter.next()?;
655 for cur in &mut iter {
656 if cur.list_next().is_none() {
657 return prev.list_next_mut().take();
658 }
659 prev = cur;
660 }
661
662 self.inner.take()
664 }
665
666 pub fn pop_front(&mut self) -> Option<MbedtlsBox<Certificate>> {
667 let mut ret = self.inner.take()?;
668 self.inner = ret.list_next_mut().take();
669 Some(ret)
670 }
671
672 pub fn append(&mut self, list: MbedtlsList<Certificate>) {
673 let tail = match self.iter_mut().last() {
674 None => &mut self.inner,
675 Some(last) => last.list_next_mut(),
676 };
677 *tail = list.inner;
678 }
679
680 pub fn iter(&self) -> Iter<'_> {
681 Iter {
682 next: self.inner.as_ref(),
683 }
684 }
685
686 pub fn iter_mut(&mut self) -> IterMut<'_> {
687 IterMut {
688 next: self.inner.as_mut(),
689 }
690 }
691
692 pub(crate) unsafe fn inner_ffi_mut(&self) -> *mut x509_crt {
693 self.inner
694 .as_ref()
695 .map_or(::core::ptr::null_mut(), |c| c.inner.as_ptr() as *mut x509_crt)
696 }
697}
698
699impl Clone for MbedtlsList<Certificate> {
700 fn clone(&self) -> MbedtlsList<Certificate> {
701 self.iter().cloned().collect()
702 }
703}
704
705impl Into<*const x509_crt> for &MbedtlsList<Certificate> {
706 fn into(self) -> *const x509_crt {
707 self.inner
708 .as_ref()
709 .map_or(::core::ptr::null_mut(), |c| c.inner.as_ptr() as *const x509_crt)
710 }
711}
712
713impl Into<*mut x509_crt> for &mut MbedtlsList<Certificate> {
714 fn into(self) -> *mut x509_crt {
715 self.inner
716 .as_ref()
717 .map_or(::core::ptr::null_mut(), |c| c.inner.as_ptr() as *mut x509_crt)
718 }
719}
720
721impl<'a> UnsafeFrom<*const *const x509_crt> for &'a MbedtlsList<Certificate> {
722 unsafe fn from(ptr: *const *const x509_crt) -> Option<&'a MbedtlsList<Certificate>> {
723 if ptr.is_null() || (*ptr).is_null() {
724 return None;
725 }
726
727 (ptr as *const MbedtlsList<Certificate>).as_ref()
728 }
729}
730
731impl<'a> UnsafeFrom<*mut *mut x509_crt> for &'a mut MbedtlsList<Certificate> {
732 unsafe fn from(ptr: *mut *mut x509_crt) -> Option<&'a mut MbedtlsList<Certificate>> {
733 if ptr.is_null() || (*ptr).is_null() {
734 return None;
735 }
736
737 (ptr as *mut MbedtlsList<Certificate>).as_mut()
738 }
739}
740
741pub struct Iter<'a> {
742 next: Option<&'a MbedtlsBox<Certificate>>,
743}
744
745impl<'a> Iterator for Iter<'a> {
746 type Item = &'a MbedtlsBox<Certificate>;
747
748 fn next(&mut self) -> Option<&'a MbedtlsBox<Certificate>> {
749 let ret = self.next.take()?;
750 self.next = ret.list_next();
751 Some(ret)
752 }
753}
754
755pub struct IterMut<'a> {
756 next: Option<&'a mut MbedtlsBox<Certificate>>,
757}
758
759impl<'a> Iterator for IterMut<'a> {
760 type Item = &'a mut MbedtlsBox<Certificate>;
761
762 fn next(&mut self) -> Option<&'a mut MbedtlsBox<Certificate>> {
763 let ret = self.next.take()?;
764 unsafe {
765 self.next = <&mut Option<MbedtlsBox<_>> as UnsafeFrom<_>>::from(&mut (**ret).inner.next).and_then(|v| v.as_mut());
766 }
767 Some(ret)
768 }
769}
770
771pub struct IntoIter {
774 list: MbedtlsList<Certificate>,
775}
776
777impl Iterator for IntoIter {
778 type Item = MbedtlsBox<Certificate>;
779
780 #[inline]
781 fn next(&mut self) -> Option<MbedtlsBox<Certificate>> {
782 self.list.pop_front()
783 }
784}
785
786impl IntoIterator for MbedtlsList<Certificate> {
787 type Item = MbedtlsBox<Certificate>;
788 type IntoIter = IntoIter;
789
790 #[inline]
792 fn into_iter(self) -> IntoIter {
793 IntoIter { list: self }
794 }
795}
796
797impl<'a> IntoIterator for &'a MbedtlsList<Certificate> {
798 type Item = &'a MbedtlsBox<Certificate>;
799 type IntoIter = Iter<'a>;
800
801 fn into_iter(self) -> Iter<'a> {
802 self.iter()
803 }
804}
805
806impl<'a> IntoIterator for &'a mut MbedtlsList<Certificate> {
807 type Item = &'a mut MbedtlsBox<Certificate>;
808 type IntoIter = IterMut<'a>;
809
810 fn into_iter(self) -> IterMut<'a> {
811 self.iter_mut()
812 }
813}
814
815impl FromIterator<MbedtlsBox<Certificate>> for MbedtlsList<Certificate> {
816 fn from_iter<I: IntoIterator<Item = MbedtlsBox<Certificate>>>(iter: I) -> Self {
817 let mut list = Self::new();
818 list.extend(iter);
819 list
820 }
821}
822
823impl Extend<MbedtlsBox<Certificate>> for MbedtlsList<Certificate> {
824 fn extend<I: IntoIterator<Item = MbedtlsBox<Certificate>>>(&mut self, iter: I) {
825 iter.into_iter().for_each(move |elt| self.push(elt));
826 }
827}
828
829#[cfg(test)]
830mod tests {
831 use super::*;
832
833 struct Test {
834 key1: Pk,
835 key2: Pk,
836 }
837
838 impl Test {
839 fn new() -> Self {
840 Test {
841 key1: Pk::from_private_key(crate::test_support::keys::PEM_SELF_SIGNED_KEY, None).unwrap(),
842 key2: Pk::from_private_key(crate::test_support::keys::PEM_SELF_SIGNED_KEY, None).unwrap(),
843 }
844 }
845
846 fn builder<'a>(&'a mut self) -> Builder<'a> {
847 let mut b = Builder::new();
848 b.subject_key(&mut self.key1)
849 .subject_with_nul("CN=mbedtls.example\0")
850 .unwrap()
851 .issuer_key(&mut self.key2)
852 .issuer_with_nul("CN=mbedtls.example\0")
853 .unwrap()
854 .validity(
855 Time::new(2000, 1, 1, 0, 0, 0).unwrap(),
856 Time::new(2009, 12, 31, 23, 59, 59).unwrap(),
857 )
858 .unwrap();
859 b
860 }
861 }
862
863 const TEST_PEM: &'static str = r"-----BEGIN CERTIFICATE-----
864MIICsTCCAZmgAwIBAgIBBTANBgkqhkiG9w0BAQsFADAaMRgwFgYDVQQDDA9tYmVk
865dGxzLmV4YW1wbGUwHhcNMDAwMTAxMDAwMDAwWhcNMDkxMjMxMjM1OTU5WjAaMRgw
866FgYDVQQDDA9tYmVkdGxzLmV4YW1wbGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
867ggEKAoIBAQDFjAgmCJUmKAQ/OAg0MBh3E2+l5asSHdBNmTm0gr3vmnmFcUqlIpUG
8683BGd85o0c9X5qnxBKJafTJLu2xRqjx1TMlBdtVpP0CXy5qPYwvO8UWIGyrsniy8G
869fpDjXGkUFbm91Cw1c/lCD7R16lLHK+7Npq9oxpk3KfMHivQorFd31byo0VxZv/sF
870YViCbDtOYmMifQX/qkqsbvkxSuPklzpxAxF824mtKMRimwGQbZ4tbLlAFNugO02e
871V0Hq8xHxfbmNrblSqIy68/Udjg4Y9feFi8NVfYg/rsFjuL+Fv/3dLBBhaMffyV9J
8720eULXgVw5ZXNaQgKb6sSBQqiU3LftHDTAgMBAAGjAjAAMA0GCSqGSIb3DQEBCwUA
873A4IBAQAEfQ3N4I9+tWOltiVumy3JaJNyw4LhtOwM4TSjvHFq/sNqCQMuA3ixXgS0
874pPjcURyEnH46tEBR9dLonAVGguusVcUjsHyfpgzda7VlAg6OI8l5XnujiLhf8b/D
875m1X5f8kDP5ob0hbWo4YIssLH1FN0AMF9FtUyeoYjTtE56fG2uLIVYnIApTRvhrFa
876wtfutqbhaHaSyMNuh2Apt7lozJfbfZ/2SJv69s+dFLMyZNNAh2DI8s+9XTEIs787
877JeRsNCbrxuEPG6p06ofrO68zdn1ZOksOlUoPy4X3DVKEipnBtyUfqbIr6uWvDsko
878JS7pkcufTIoN0Yj0SxAWLW711FgB
879-----END CERTIFICATE-----
880";
881
882 const TEST_DER: &'static [u8] = &[
883 0x30, 0x82, 0x02, 0xb1, 0x30, 0x82, 0x01, 0x99, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x05, 0x30, 0x0d, 0x06, 0x09,
884 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
885 0x04, 0x03, 0x0c, 0x0f, 0x6d, 0x62, 0x65, 0x64, 0x74, 0x6c, 0x73, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x30,
886 0x1e, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x39,
887 0x31, 0x32, 0x33, 0x31, 0x32, 0x33, 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
888 0x04, 0x03, 0x0c, 0x0f, 0x6d, 0x62, 0x65, 0x64, 0x74, 0x6c, 0x73, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x30,
889 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82,
890 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00, 0xc5, 0x8c, 0x08, 0x26, 0x08, 0x95, 0x26, 0x28,
891 0x04, 0x3f, 0x38, 0x08, 0x34, 0x30, 0x18, 0x77, 0x13, 0x6f, 0xa5, 0xe5, 0xab, 0x12, 0x1d, 0xd0, 0x4d, 0x99, 0x39, 0xb4,
892 0x82, 0xbd, 0xef, 0x9a, 0x79, 0x85, 0x71, 0x4a, 0xa5, 0x22, 0x95, 0x06, 0xdc, 0x11, 0x9d, 0xf3, 0x9a, 0x34, 0x73, 0xd5,
893 0xf9, 0xaa, 0x7c, 0x41, 0x28, 0x96, 0x9f, 0x4c, 0x92, 0xee, 0xdb, 0x14, 0x6a, 0x8f, 0x1d, 0x53, 0x32, 0x50, 0x5d, 0xb5,
894 0x5a, 0x4f, 0xd0, 0x25, 0xf2, 0xe6, 0xa3, 0xd8, 0xc2, 0xf3, 0xbc, 0x51, 0x62, 0x06, 0xca, 0xbb, 0x27, 0x8b, 0x2f, 0x06,
895 0x7e, 0x90, 0xe3, 0x5c, 0x69, 0x14, 0x15, 0xb9, 0xbd, 0xd4, 0x2c, 0x35, 0x73, 0xf9, 0x42, 0x0f, 0xb4, 0x75, 0xea, 0x52,
896 0xc7, 0x2b, 0xee, 0xcd, 0xa6, 0xaf, 0x68, 0xc6, 0x99, 0x37, 0x29, 0xf3, 0x07, 0x8a, 0xf4, 0x28, 0xac, 0x57, 0x77, 0xd5,
897 0xbc, 0xa8, 0xd1, 0x5c, 0x59, 0xbf, 0xfb, 0x05, 0x61, 0x58, 0x82, 0x6c, 0x3b, 0x4e, 0x62, 0x63, 0x22, 0x7d, 0x05, 0xff,
898 0xaa, 0x4a, 0xac, 0x6e, 0xf9, 0x31, 0x4a, 0xe3, 0xe4, 0x97, 0x3a, 0x71, 0x03, 0x11, 0x7c, 0xdb, 0x89, 0xad, 0x28, 0xc4,
899 0x62, 0x9b, 0x01, 0x90, 0x6d, 0x9e, 0x2d, 0x6c, 0xb9, 0x40, 0x14, 0xdb, 0xa0, 0x3b, 0x4d, 0x9e, 0x57, 0x41, 0xea, 0xf3,
900 0x11, 0xf1, 0x7d, 0xb9, 0x8d, 0xad, 0xb9, 0x52, 0xa8, 0x8c, 0xba, 0xf3, 0xf5, 0x1d, 0x8e, 0x0e, 0x18, 0xf5, 0xf7, 0x85,
901 0x8b, 0xc3, 0x55, 0x7d, 0x88, 0x3f, 0xae, 0xc1, 0x63, 0xb8, 0xbf, 0x85, 0xbf, 0xfd, 0xdd, 0x2c, 0x10, 0x61, 0x68, 0xc7,
902 0xdf, 0xc9, 0x5f, 0x49, 0xd1, 0xe5, 0x0b, 0x5e, 0x05, 0x70, 0xe5, 0x95, 0xcd, 0x69, 0x08, 0x0a, 0x6f, 0xab, 0x12, 0x05,
903 0x0a, 0xa2, 0x53, 0x72, 0xdf, 0xb4, 0x70, 0xd3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x02, 0x30, 0x00, 0x30, 0x0d, 0x06,
904 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0x04, 0x7d, 0x0d,
905 0xcd, 0xe0, 0x8f, 0x7e, 0xb5, 0x63, 0xa5, 0xb6, 0x25, 0x6e, 0x9b, 0x2d, 0xc9, 0x68, 0x93, 0x72, 0xc3, 0x82, 0xe1, 0xb4,
906 0xec, 0x0c, 0xe1, 0x34, 0xa3, 0xbc, 0x71, 0x6a, 0xfe, 0xc3, 0x6a, 0x09, 0x03, 0x2e, 0x03, 0x78, 0xb1, 0x5e, 0x04, 0xb4,
907 0xa4, 0xf8, 0xdc, 0x51, 0x1c, 0x84, 0x9c, 0x7e, 0x3a, 0xb4, 0x40, 0x51, 0xf5, 0xd2, 0xe8, 0x9c, 0x05, 0x46, 0x82, 0xeb,
908 0xac, 0x55, 0xc5, 0x23, 0xb0, 0x7c, 0x9f, 0xa6, 0x0c, 0xdd, 0x6b, 0xb5, 0x65, 0x02, 0x0e, 0x8e, 0x23, 0xc9, 0x79, 0x5e,
909 0x7b, 0xa3, 0x88, 0xb8, 0x5f, 0xf1, 0xbf, 0xc3, 0x9b, 0x55, 0xf9, 0x7f, 0xc9, 0x03, 0x3f, 0x9a, 0x1b, 0xd2, 0x16, 0xd6,
910 0xa3, 0x86, 0x08, 0xb2, 0xc2, 0xc7, 0xd4, 0x53, 0x74, 0x00, 0xc1, 0x7d, 0x16, 0xd5, 0x32, 0x7a, 0x86, 0x23, 0x4e, 0xd1,
911 0x39, 0xe9, 0xf1, 0xb6, 0xb8, 0xb2, 0x15, 0x62, 0x72, 0x00, 0xa5, 0x34, 0x6f, 0x86, 0xb1, 0x5a, 0xc2, 0xd7, 0xee, 0xb6,
912 0xa6, 0xe1, 0x68, 0x76, 0x92, 0xc8, 0xc3, 0x6e, 0x87, 0x60, 0x29, 0xb7, 0xb9, 0x68, 0xcc, 0x97, 0xdb, 0x7d, 0x9f, 0xf6,
913 0x48, 0x9b, 0xfa, 0xf6, 0xcf, 0x9d, 0x14, 0xb3, 0x32, 0x64, 0xd3, 0x40, 0x87, 0x60, 0xc8, 0xf2, 0xcf, 0xbd, 0x5d, 0x31,
914 0x08, 0xb3, 0xbf, 0x3b, 0x25, 0xe4, 0x6c, 0x34, 0x26, 0xeb, 0xc6, 0xe1, 0x0f, 0x1b, 0xaa, 0x74, 0xea, 0x87, 0xeb, 0x3b,
915 0xaf, 0x33, 0x76, 0x7d, 0x59, 0x3a, 0x4b, 0x0e, 0x95, 0x4a, 0x0f, 0xcb, 0x85, 0xf7, 0x0d, 0x52, 0x84, 0x8a, 0x99, 0xc1,
916 0xb7, 0x25, 0x1f, 0xa9, 0xb2, 0x2b, 0xea, 0xe5, 0xaf, 0x0e, 0xc9, 0x28, 0x25, 0x2e, 0xe9, 0x91, 0xcb, 0x9f, 0x4c, 0x8a,
917 0x0d, 0xd1, 0x88, 0xf4, 0x4b, 0x10, 0x16, 0x2d, 0x6e, 0xf5, 0xd4, 0x58, 0x01,
918 ];
919
920 #[test]
921 fn write_der() {
922 let mut t = Test::new();
923 let output = t
924 .builder()
925 .serial(&[5])
926 .unwrap()
927 .signature_hash(MdType::Sha256)
928 .write_der_vec(&mut crate::test_support::rand::test_rng())
929 .unwrap();
930 assert!(output == TEST_DER);
931 }
932
933 #[test]
934 fn write_pem() {
935 let mut t = Test::new();
936 let output = t
937 .builder()
938 .serial(&[5])
939 .unwrap()
940 .signature_hash(MdType::Sha256)
941 .write_pem_string(&mut crate::test_support::rand::test_rng())
942 .unwrap();
943 assert_eq!(output, TEST_PEM);
944 }
945
946 const TEST_CERT_PEM: &'static str = "-----BEGIN CERTIFICATE-----
947MIIDLDCCAhSgAwIBAgIRALY0SS5pY9Yb/aIHvSAvmOswDQYJKoZIhvcNAQELBQAw
948HzEQMA4GA1UEAxMHVGVzdCBDQTELMAkGA1UEBhMCVVMwHhcNMTkwMTA4MDAxODM1
949WhcNMjkwMTA1MDAxODM1WjAjMRIwEAYDVQQDEwlUZXN0IENlcnQxDTALBgNVBAoT
950BFRlc3Qwgd8wDQYJKoZIhvcNAQEBBQADgc0AMIHJAoHBAKYINzSAKG1/Kn/5dWXq
951cfJgfQkzVn1HPzdb4NNZL+H7woGuzDGrcQ7EPi7r4EuAEE2fCjhSfiYlacoBOxd/
952k9Fp4Iv2ygCY1nj8RY0tFCZcZDVYj5F7uqyJMf7+QSOpnZ4cb3zdj1HkBmq7ac0C
9537tXkubvM6gBS3H3XlhfszcEjvhavaxVVoitdqW8RJ2DHvqGwFUxPgFCuuQudeCI/
954UzBiPMRqu3Pr9Xhcc0ruG5SkCg5isbWWnKNj7X1gTre6WwIDAQABo4GiMIGfMCEG
955A1UdDgQaBBhoOfrVfmVEEhzGvEIZU8yWIGVcV8+sBgIwMgYDVR0RBCswKYERdGVz
956dEBmb3J0YW5peC5jb22CFGV4YW1wbGUuZm9ydGFuaXguY29tMAwGA1UdEwEB/wQC
957MAAwIwYDVR0jBBwwGoAYeQdrzI2gB35BFvhLjkycXGr37E+gANmHMBMGA1UdJQQM
958MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBKSyY45jagwBIbAzTgSzQq
959wXsXixowANXchMBhKUFRnjrJnacoI4CeZD+dHA/3yic0xjl0IVh59ihlMtQ7DaYI
960b7ISqWyPVz3kIwyas64J1iFxnS41s+kZY9XnY6Jz8OJda7xfzQzXrOaIgh3xck+z
961lWyWBGzVgSbzripmaAzMyKrsvmgPpfx5aE7zP2QVOzGXE/QuoXqj/bmblNlUZu11
9625XJ4nSxziKSdNaZZBCn+m2lZiW6GWK7idvNHT/MVBR5mM74jbSrPVSFk6mk2Ei+d
963cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
964-----END CERTIFICATE-----\0";
965
966 #[test]
967 fn cert_field_access() {
968 let cert = Certificate::from_pem(TEST_CERT_PEM.as_bytes()).unwrap();
969
970 assert_eq!(cert.version().unwrap(), CertificateVersion::V3);
971 assert_eq!(cert.issuer().unwrap(), "CN=Test CA, C=US");
972 assert_eq!(cert.subject().unwrap(), "CN=Test Cert, O=Test");
973 assert_eq!(cert.serial().unwrap(), "B6:34:49:2E:69:63:D6:1B:FD:A2:07:BD:20:2F:98:EB");
974 assert_eq!(cert.digest_type(), MdType::Sha256);
975
976 assert_eq!(hex::encode(cert.serial_raw().unwrap()), "00b634492e6963d61bfda207bd202f98eb");
977 assert_eq!(
978 hex::encode(cert.issuer_raw().unwrap()),
979 "301f3110300e0603550403130754657374204341310b3009060355040613025553"
980 );
981 assert_eq!(
982 hex::encode(cert.subject_raw().unwrap()),
983 "30233112301006035504031309546573742043657274310d300b060355040a130454657374"
984 );
985 assert_eq!(hex::encode(cert.signature().unwrap()), "4a4b2638e636a0c0121b0334e04b342ac17b178b1a3000d5dc84c0612941519e3ac99da72823809e643f9d1c0ff7ca2734c63974215879f6286532d43b0da6086fb212a96c8f573de4230c9ab3ae09d621719d2e35b3e91963d5e763a273f0e25d6bbc5fcd0cd7ace688821df1724fb3956c96046cd58126f3ae2a66680cccc8aaecbe680fa5fc79684ef33f64153b319713f42ea17aa3fdb99b94d95466ed75e572789d2c7388a49d35a6590429fe9b6959896e8658aee276f3474ff315051e6633be236d2acf552164ea6936122f9d718a746c7fd170f4c2d19f996aa49632d7f146b93adcc25017d117a4309dbd045c4cc0fd0fce4326b30a9fc6ae9aad0c");
986 assert_eq!(hex::encode(cert.extensions_raw().unwrap()), "30819f30210603551d0e041a04186839fad57e6544121cc6bc421953cc9620655c57cfac060230320603551d11042b302981117465737440666f7274616e69782e636f6d82146578616d706c652e666f7274616e69782e636f6d300c0603551d130101ff0402300030230603551d23041c301a801879076bcc8da0077e4116f84b8e4c9c5c6af7ec4fa000d98730130603551d25040c300a06082b06010505070302");
987
988 assert_eq!(cert.not_before().unwrap(), Time::new(2019, 1, 8, 0, 18, 35).unwrap());
989 assert_eq!(cert.not_after().unwrap(), Time::new(2029, 1, 5, 0, 18, 35).unwrap());
990
991 #[cfg(feature = "std")]
992 {
993 let ext = cert.extensions().unwrap();
994 assert_eq!(ext.len(), 5);
995
996 assert_eq!(
997 ext[0],
998 Extension {
999 oid: ObjectIdentifier::from_slice(&[2, 5, 29, 14]),
1000 critical: false,
1001 value: hex::decode("04186839FAD57E6544121CC6BC421953CC9620655C57CFAC0602").unwrap(),
1002 }
1003 );
1004 assert_eq!(
1005 ext[1],
1006 Extension {
1007 oid: ObjectIdentifier::from_slice(&[2, 5, 29, 17]),
1008 critical: false,
1009 value: hex::decode(
1010 "302981117465737440666f7274616e69782e636f6d82146578616d706c652e666f7274616e69782e636f6d"
1011 )
1012 .unwrap()
1013 }
1014 );
1015 assert_eq!(
1016 ext[2],
1017 Extension {
1018 oid: ObjectIdentifier::from_slice(&[2, 5, 29, 19]),
1019 critical: true,
1020 value: hex::decode("3000").unwrap()
1021 }
1022 );
1023 assert_eq!(
1024 ext[3],
1025 Extension {
1026 oid: ObjectIdentifier::from_slice(&[2, 5, 29, 35]),
1027 critical: false,
1028 value: hex::decode("301a801879076BCC8DA0077E4116F84B8E4C9C5C6AF7EC4FA000D987").unwrap()
1029 }
1030 );
1031 assert_eq!(
1032 ext[4],
1033 Extension {
1034 oid: ObjectIdentifier::from_slice(&[2, 5, 29, 37]),
1035 critical: false,
1036 value: hex::decode("300a06082b06010505070302").unwrap(),
1037 }
1038 );
1039 }
1040 }
1041
1042 #[test]
1043 fn channel_binding_hash() {
1044 const TEST_CERT_PEM: &'static str = "-----BEGIN CERTIFICATE-----
1045MIIDLDCCAhSgAwIBAgIRALY0SS5pY9Yb/aIHvSAvmOswDQYJKoZIhvcNAQELBQAw
1046HzEQMA4GA1UEAxMHVGVzdCBDQTELMAkGA1UEBhMCVVMwHhcNMTkwMTA4MDAxODM1
1047WhcNMjkwMTA1MDAxODM1WjAjMRIwEAYDVQQDEwlUZXN0IENlcnQxDTALBgNVBAoT
1048BFRlc3Qwgd8wDQYJKoZIhvcNAQEBBQADgc0AMIHJAoHBAKYINzSAKG1/Kn/5dWXq
1049cfJgfQkzVn1HPzdb4NNZL+H7woGuzDGrcQ7EPi7r4EuAEE2fCjhSfiYlacoBOxd/
1050k9Fp4Iv2ygCY1nj8RY0tFCZcZDVYj5F7uqyJMf7+QSOpnZ4cb3zdj1HkBmq7ac0C
10517tXkubvM6gBS3H3XlhfszcEjvhavaxVVoitdqW8RJ2DHvqGwFUxPgFCuuQudeCI/
1052UzBiPMRqu3Pr9Xhcc0ruG5SkCg5isbWWnKNj7X1gTre6WwIDAQABo4GiMIGfMCEG
1053A1UdDgQaBBhoOfrVfmVEEhzGvEIZU8yWIGVcV8+sBgIwMgYDVR0RBCswKYERdGVz
1054dEBmb3J0YW5peC5jb22CFGV4YW1wbGUuZm9ydGFuaXguY29tMAwGA1UdEwEB/wQC
1055MAAwIwYDVR0jBBwwGoAYeQdrzI2gB35BFvhLjkycXGr37E+gANmHMBMGA1UdJQQM
1056MAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBKSyY45jagwBIbAzTgSzQq
1057wXsXixowANXchMBhKUFRnjrJnacoI4CeZD+dHA/3yic0xjl0IVh59ihlMtQ7DaYI
1058b7ISqWyPVz3kIwyas64J1iFxnS41s+kZY9XnY6Jz8OJda7xfzQzXrOaIgh3xck+z
1059lWyWBGzVgSbzripmaAzMyKrsvmgPpfx5aE7zP2QVOzGXE/QuoXqj/bmblNlUZu11
10605XJ4nSxziKSdNaZZBCn+m2lZiW6GWK7idvNHT/MVBR5mM74jbSrPVSFk6mk2Ei+d
1061cYp0bH/RcPTC0Z+ZaqSWMtfxRrk63MJQF9EXpDCdvQRcTMD9D85DJrMKn8aumq0M
1062-----END CERTIFICATE-----\0";
1063
1064 let list = Certificate::from_pem_multiple(&TEST_CERT_PEM.as_bytes()).unwrap();
1065
1066 let mut iter = list.iter();
1067 let cert = iter.next().unwrap();
1068
1069 let pk = cert.public_key();
1070
1071 assert_eq!(pk.pk_type(), crate::pk::Type::Rsa);
1072 assert_eq!(pk.rsa_public_exponent().unwrap(), 0x10001);
1073
1074 let channel_binding_hash = match cert.digest_type() {
1075 MdType::Md5 | MdType::Sha1 => MdType::Sha256,
1076 digest => digest,
1077 };
1078
1079 let mut digest = [0u8; 64];
1080 let digest_len = crate::hash::Md::hash(channel_binding_hash, cert.as_der(), &mut digest).unwrap();
1081
1082 assert_eq!(
1083 digest[0..digest_len],
1084 [
1085 0xcc, 0x61, 0xd9, 0x07, 0xc2, 0xcb, 0x49, 0x58, 0x73, 0xbf, 0xd7, 0x43, 0x21, 0xb2, 0xd4, 0x30, 0xc6, 0xfe,
1086 0xa6, 0x6c, 0x28, 0x96, 0x23, 0xc6, 0x28, 0x4c, 0xdd, 0x14, 0xda, 0x1d, 0xc4, 0x17
1087 ]
1088 );
1089 }
1090
1091 #[test]
1092 fn verify_chain() {
1093 const C_LEAF: &'static str = concat!(include_str!("../../tests/data/chain-leaf.crt"), "\0");
1094 const C_INT1: &'static str = concat!(include_str!("../../tests/data/chain-int1.crt"), "\0");
1095 const C_INT2: &'static str = concat!(include_str!("../../tests/data/chain-int2.crt"), "\0");
1096 const C_ROOT: &'static str = concat!(include_str!("../../tests/data/chain-root.crt"), "\0");
1097
1098 let c_leaf = Certificate::from_pem(C_LEAF.as_bytes()).unwrap();
1099 let c_int1 = Certificate::from_pem(C_INT1.as_bytes()).unwrap();
1100 let c_int2 = Certificate::from_pem(C_INT2.as_bytes()).unwrap();
1101 let mut c_root = Certificate::from_pem_multiple(C_ROOT.as_bytes()).unwrap();
1102
1103 let mut chain = MbedtlsList::<Certificate>::new();
1106 chain.push(c_leaf.clone());
1107 chain.push(c_int1.clone());
1108
1109 let verify_callback = |_crt: &Certificate, _depth: i32, verify_flags: &mut VerifyError| {
1112 verify_flags.remove(VerifyError::CERT_EXPIRED);
1113 Ok(())
1114 };
1115
1116 let res = Certificate::verify_with_callback(&chain, &mut c_root, None, None, verify_callback);
1117 match res {
1118 Ok(_) => panic!("Certificate chain verification should have failed, but it succeeded"),
1119 Err(err) => assert_eq!(err, codes::X509CertVerifyFailed.into()),
1120 }
1121
1122 chain.push(c_int2.clone());
1124
1125 let mut err_str = String::new();
1126
1127 let res = Certificate::verify_with_callback(&chain, &mut c_root, None, Some(&mut err_str), verify_callback);
1128
1129 match res {
1130 Ok(()) => (),
1131 Err(e) => panic!("Failed to verify, error: {}, err_str: {}", e, err_str),
1132 };
1133 }
1134
1135 #[test]
1136 fn clone_test() {
1137 let cert_chain = Certificate::from_pem(TEST_CERT_PEM.as_bytes()).unwrap();
1138
1139 let mut chain = MbedtlsList::<Certificate>::new();
1140 chain.push(cert_chain.clone());
1141 chain.push(cert_chain.clone());
1142 chain.push(cert_chain);
1143
1144 let clone = chain.clone();
1145 let mut it = clone.iter();
1146
1147 assert!(it.next().is_some());
1148 assert!(it.next().is_some());
1149 assert!(it.next().is_some());
1150 assert!(it.next().is_none());
1151 assert!(it.next().is_none());
1152
1153 let mut it = chain.iter();
1154 assert!(it.next().is_some());
1155 assert!(it.next().is_some());
1156 assert!(it.next().is_some());
1157 assert!(it.next().is_none());
1158 assert!(it.next().is_none());
1159 }
1160
1161 #[test]
1162 fn list_pop_back_test() {
1163 const C_LEAF: &'static str = concat!(include_str!("../../tests/data/chain-leaf.crt"), "\0");
1164 const C_INT1: &'static str = concat!(include_str!("../../tests/data/chain-int1.crt"), "\0");
1165 const C_INT2: &'static str = concat!(include_str!("../../tests/data/chain-int2.crt"), "\0");
1166
1167 let mut chain = MbedtlsList::<Certificate>::new();
1168
1169 let c1 = Certificate::from_pem_multiple(C_LEAF.as_bytes()).unwrap();
1170 let c2 = Certificate::from_pem_multiple(C_INT1.as_bytes()).unwrap();
1171 let c3 = Certificate::from_pem_multiple(C_INT2.as_bytes()).unwrap();
1172
1173 let c1_info = format!("{:?}", c1.iter().next().unwrap());
1176 let c2_info = format!("{:?}", c2.iter().next().unwrap());
1177 let c3_info = format!("{:?}", c3.iter().next().unwrap());
1178
1179 chain.append(c1.clone());
1180 chain.append(c2.clone());
1181 chain.append(c3.clone());
1182
1183 {
1184 let mut it = chain.iter();
1185 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1186 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1187 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1188 assert!(it.next().is_none());
1189 }
1190
1191 assert_eq!(c3_info, format!("{:?}", chain.pop_back().unwrap()));
1192 {
1193 let mut it = chain.iter();
1194 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1195 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1196 assert!(it.next().is_none());
1197 }
1198
1199 chain.append(c3.clone());
1200 chain.append(c1.clone());
1201 {
1202 let mut it = chain.iter();
1203 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1204 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1205 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1206 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1207 assert!(it.next().is_none());
1208 }
1209
1210 assert_eq!(c1_info, format!("{:?}", chain.pop_back().unwrap()));
1211 assert_eq!(c3_info, format!("{:?}", chain.pop_back().unwrap()));
1212 assert_eq!(c2_info, format!("{:?}", chain.pop_back().unwrap()));
1213
1214 {
1215 let mut it = chain.iter();
1216 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1217 assert!(it.next().is_none());
1218 }
1219
1220 assert_eq!(c1_info, format!("{:?}", chain.pop_back().unwrap()));
1221
1222 {
1223 let mut it = chain.iter();
1224 assert!(it.next().is_none());
1225 }
1226
1227 assert!(chain.pop_back().is_none());
1228 {
1229 let mut it = chain.iter();
1230 assert!(it.next().is_none());
1231 }
1232
1233 chain.append(c3.clone());
1234 chain.append(c1.clone());
1235 {
1236 let mut it = chain.iter();
1237 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1238 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1239 assert!(it.next().is_none());
1240 }
1241 }
1242
1243 #[test]
1244 fn list_pop_front_test() {
1245 const C_LEAF: &'static str = concat!(include_str!("../../tests/data/chain-leaf.crt"), "\0");
1246 const C_INT1: &'static str = concat!(include_str!("../../tests/data/chain-int1.crt"), "\0");
1247 const C_INT2: &'static str = concat!(include_str!("../../tests/data/chain-int2.crt"), "\0");
1248
1249 let mut chain = MbedtlsList::<Certificate>::new();
1250
1251 let c1 = Certificate::from_pem(C_LEAF.as_bytes()).unwrap();
1252 let c2 = Certificate::from_pem(C_INT1.as_bytes()).unwrap();
1253 let c3 = Certificate::from_pem(C_INT2.as_bytes()).unwrap();
1254
1255 let c1_info = format!("{:?}", c1);
1258 let c2_info = format!("{:?}", c2);
1259 let c3_info = format!("{:?}", c3);
1260
1261 chain.push(c1.clone());
1262 chain.push(c2.clone());
1263 chain.push(c3.clone());
1264
1265 {
1266 let mut it = chain.iter();
1267 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1268 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1269 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1270 assert!(it.next().is_none());
1271 }
1272
1273 assert_eq!(c1_info, format!("{:?}", chain.pop_front().unwrap()));
1274 {
1275 let mut it = chain.iter();
1276 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1277 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1278 assert!(it.next().is_none());
1279 }
1280
1281 chain.push(c3.clone());
1282 chain.push(c1.clone());
1283 {
1284 let mut it = chain.iter();
1285 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1286 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1287 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1288 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1289 assert!(it.next().is_none());
1290 }
1291
1292 assert_eq!(c2_info, format!("{:?}", chain.pop_front().unwrap()));
1293 assert_eq!(c3_info, format!("{:?}", chain.pop_front().unwrap()));
1294 assert_eq!(c3_info, format!("{:?}", chain.pop_front().unwrap()));
1295
1296 {
1297 let mut it = chain.iter();
1298 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1299 assert!(it.next().is_none());
1300 }
1301
1302 assert_eq!(c1_info, format!("{:?}", chain.pop_front().unwrap()));
1303
1304 {
1305 let mut it = chain.iter();
1306 assert!(it.next().is_none());
1307 }
1308
1309 assert!(chain.pop_front().is_none());
1310 {
1311 let mut it = chain.iter();
1312 assert!(it.next().is_none());
1313 }
1314
1315 chain.push(c3.clone());
1316 chain.push(c1.clone());
1317 {
1318 let mut it = chain.iter();
1319 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1320 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1321 assert!(it.next().is_none());
1322 }
1323 }
1324
1325 #[test]
1326 fn list_clone_test1() {
1327 const C_LEAF: &'static str = concat!(include_str!("../../tests/data/chain-leaf.crt"), "\0");
1328 const C_INT1: &'static str = concat!(include_str!("../../tests/data/chain-int1.crt"), "\0");
1329 const C_INT2: &'static str = concat!(include_str!("../../tests/data/chain-int2.crt"), "\0");
1330
1331 let mut chain = MbedtlsList::<Certificate>::new();
1332
1333 let c1 = Certificate::from_pem_multiple(C_LEAF.as_bytes()).unwrap();
1334 let c2 = Certificate::from_pem_multiple(C_INT1.as_bytes()).unwrap();
1335 let c3 = Certificate::from_pem_multiple(C_INT2.as_bytes()).unwrap();
1336
1337 let c1_info = format!("{:?}", c1.iter().next().unwrap());
1340 let c2_info = format!("{:?}", c2.iter().next().unwrap());
1341 let c3_info = format!("{:?}", c3.iter().next().unwrap());
1342
1343 chain.append(c1.clone());
1344 chain.append(c2.clone());
1345 chain.append(c3.clone());
1346
1347 chain.append(chain.clone());
1348 {
1349 let it_clone = chain.clone();
1350 let mut it = it_clone.iter();
1351
1352 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1353 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1354 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1355 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1356 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1357 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1358
1359 assert!(it.next().is_none());
1360 assert!(it.next().is_none());
1361 assert!(it.next().is_none());
1362 }
1363 }
1364
1365 #[test]
1366 fn list_into_iter() {
1367 const C_LEAF: &'static str = concat!(include_str!("../../tests/data/chain-leaf.crt"), "\0");
1368 const C_INT1: &'static str = concat!(include_str!("../../tests/data/chain-int1.crt"), "\0");
1369 const C_INT2: &'static str = concat!(include_str!("../../tests/data/chain-int2.crt"), "\0");
1370
1371 let mut chain = MbedtlsList::<Certificate>::new();
1372
1373 let c1 = Certificate::from_pem_multiple(C_LEAF.as_bytes()).unwrap();
1374 let c2 = Certificate::from_pem_multiple(C_INT1.as_bytes()).unwrap();
1375 let c3 = Certificate::from_pem_multiple(C_INT2.as_bytes()).unwrap();
1376
1377 let c1_info = format!("{:?}", c1.iter().next().unwrap());
1380 let c2_info = format!("{:?}", c2.iter().next().unwrap());
1381 let c3_info = format!("{:?}", c3.iter().next().unwrap());
1382
1383 chain.append(c1.clone());
1384 chain.append(c2.clone());
1385 chain.append(c3.clone());
1386
1387 {
1388 let mut it = chain.clone().into_iter();
1389 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1390 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1391 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1392 assert!(it.next().is_none());
1393 }
1394
1395 let clone = chain.clone();
1396
1397 {
1398 let mut it = chain.into_iter();
1399 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1400 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1401 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1402 assert!(it.next().is_none());
1403 }
1404
1405 {
1406 let mut it = clone.into_iter();
1407 assert_eq!(c1_info, format!("{:?}", it.next().unwrap()));
1408 assert_eq!(c2_info, format!("{:?}", it.next().unwrap()));
1409 assert_eq!(c3_info, format!("{:?}", it.next().unwrap()));
1410 assert!(it.next().is_none());
1411 }
1412 }
1413
1414 #[test]
1415 fn unsafefrom_ptr_checks_test() {
1416 let mut ptr: *mut x509_crt = ::core::ptr::null_mut() as *mut x509_crt;
1417 let ptr_test: *mut *mut x509_crt = &mut ptr as *mut *mut x509_crt;
1418
1419 let option = unsafe { <&mut Option<MbedtlsBox<_>> as UnsafeFrom<_>>::from(ptr_test).unwrap() };
1420 assert!(option.is_none());
1421
1422 let cert_list: Option<&mut MbedtlsList<Certificate>> = unsafe { UnsafeFrom::from(ptr_test) };
1423 assert!(cert_list.is_none());
1424
1425 let ptr_test: *mut *mut x509_crt = ::core::ptr::null_mut() as *mut *mut x509_crt;
1426 let cert_list: Option<&mut MbedtlsList<Certificate>> = unsafe { UnsafeFrom::from(ptr_test) };
1427 assert!(cert_list.is_none());
1428 }
1429
1430 #[test]
1431 fn mbedtls_list_to_box_iter_clone() {
1432 const C_LEAF: &'static str = concat!(include_str!("../../tests/data/chain-leaf.crt"), "\0");
1433 const C_INT1: &'static str = concat!(include_str!("../../tests/data/chain-int1.crt"), "\0");
1434 const C_INT2: &'static str = concat!(include_str!("../../tests/data/chain-int2.crt"), "\0");
1435
1436 let mut chain = MbedtlsList::<Certificate>::new();
1437
1438 let c1 = Certificate::from_pem(C_LEAF.as_bytes()).unwrap();
1439 let c2 = Certificate::from_pem(C_INT1.as_bytes()).unwrap();
1440 let c3 = Certificate::from_pem(C_INT2.as_bytes()).unwrap();
1441
1442 let c1_info = format!("{:?}", c1);
1445
1446 chain.push(c1.clone());
1447 chain.push(c2.clone());
1448 chain.push(c3.clone());
1449
1450 let cert: &MbedtlsBox<Certificate> = chain.iter().next().unwrap();
1451
1452 assert_ne!((**cert).inner.next, ::core::ptr::null_mut());
1454 assert_eq!(c1_info, format!("{:?}", cert));
1455
1456 let cert = cert.clone();
1457
1458 assert_eq!((*cert).inner.next, ::core::ptr::null_mut());
1460 assert_eq!(c1_info, format!("{:?}", cert));
1461
1462 let cert = chain.clone().into_iter().next().unwrap();
1463
1464 assert_eq!((*cert).inner.next, ::core::ptr::null_mut());
1466 assert_eq!(c1_info, format!("{:?}", cert));
1467 }
1468
1469 #[test]
1470 fn mbedtls_list_into_test() {
1471 const C_LEAF: &'static str = concat!(include_str!("../../tests/data/chain-leaf.crt"), "\0");
1472
1473 let mut chain = MbedtlsList::<Certificate>::new();
1474
1475 let ptr: *const x509_crt = (&chain).into();
1476 assert_eq!(ptr, ::core::ptr::null());
1477
1478 let ptr: *mut x509_crt = (&mut chain).into();
1479 assert_eq!(ptr, ::core::ptr::null_mut());
1480
1481 let c1 = Certificate::from_pem(C_LEAF.as_bytes()).unwrap();
1482
1483 let c1_info = format!("{:?}", *c1);
1486 chain.push(c1.clone());
1487
1488 let ptr: *const x509_crt = (&chain).into();
1489 assert_ne!(ptr, ::core::ptr::null());
1490
1491 let cert: &Certificate = unsafe { UnsafeFrom::from(ptr).unwrap() };
1492 assert_eq!(c1_info, format!("{:?}", cert));
1493
1494 let ptr: *mut x509_crt = (&mut chain).into();
1495 assert_ne!(ptr, ::core::ptr::null_mut());
1496
1497 let cert: &mut Certificate = unsafe { UnsafeFrom::from(ptr).unwrap() };
1498 assert_eq!(c1_info, format!("{:?}", cert));
1499 }
1500
1501 #[test]
1502 fn cert_send_sync() {
1503 assert!(
1504 crate::tests::TestTrait::<dyn Send, Certificate>::new().impls_trait(),
1505 "Certificate should be Send"
1506 );
1507 assert!(
1508 crate::tests::TestTrait::<dyn Send, MbedtlsBox<Certificate>>::new().impls_trait(),
1509 "MbedtlsBox<Certificate> should be Send"
1510 );
1511 assert!(
1512 crate::tests::TestTrait::<dyn Send, MbedtlsList<Certificate>>::new().impls_trait(),
1513 "MbedtlsList<Certificate> should be Send"
1514 );
1515 assert!(
1516 crate::tests::TestTrait::<dyn Sync, Certificate>::new().impls_trait(),
1517 "Certificate should be Sync"
1518 );
1519 assert!(
1520 crate::tests::TestTrait::<dyn Sync, MbedtlsBox<Certificate>>::new().impls_trait(),
1521 "MbedtlsBox<Certificate> should be Sync"
1522 );
1523 assert!(
1524 crate::tests::TestTrait::<dyn Sync, MbedtlsList<Certificate>>::new().impls_trait(),
1525 "MbedtlsList<Certificate> should be Sync"
1526 );
1527 }
1528
1529 #[test]
1530 fn empty_cert_chain_test() {
1531 const C_CERT: &'static str = concat!(include_str!("../../tests/data/certificate.crt"), "\0");
1532 const C_ROOT: &'static str = concat!(include_str!("../../tests/data/root.crt"), "\0");
1533
1534 let mut certs = MbedtlsList::new();
1535 certs.push(Certificate::from_pem(&C_CERT.as_bytes()).unwrap());
1536 let mut roots = MbedtlsList::new();
1537 roots.push(Certificate::from_pem(&C_ROOT.as_bytes()).unwrap());
1538
1539 assert!(Certificate::verify(&certs, &roots, None, None).is_ok());
1540
1541 let empty_certs = MbedtlsList::new();
1542
1543 assert_eq!(
1544 Certificate::verify(&certs, &empty_certs, None, None).unwrap_err(),
1545 codes::X509CertVerifyFailed.into()
1546 );
1547 assert_eq!(
1548 Certificate::verify(&empty_certs, &empty_certs, None, None).unwrap_err(),
1549 codes::X509BadInputData.into()
1550 );
1551 assert_eq!(
1552 Certificate::verify(&empty_certs, &roots, None, None).unwrap_err(),
1553 codes::X509BadInputData.into()
1554 );
1555 }
1556
1557 #[test]
1558 fn empty_crl_test() {
1559 const C_CERT: &'static str = concat!(include_str!("../../tests/data/certificate.crt"), "\0");
1560 const C_ROOT: &'static str = concat!(include_str!("../../tests/data/root.crt"), "\0");
1561 const C_CRL: &'static [u8] = include_bytes!("../../tests/data/root.empty.crl");
1562
1563 let mut certs = MbedtlsList::new();
1564 certs.push(Certificate::from_pem(&C_CERT.as_bytes()).unwrap());
1565 let mut roots = MbedtlsList::new();
1566 roots.push(Certificate::from_pem(&C_ROOT.as_bytes()).unwrap());
1567
1568 assert!(Certificate::verify(&certs, &roots, None, None).is_ok());
1569
1570 let mut crl = Crl::new();
1571 crl.push_from_der(C_CRL).unwrap();
1572 assert!(Certificate::verify(&certs, &roots, Some(&mut crl), None).is_ok());
1573 }
1574
1575 #[test]
1576 fn revoked_cert_crl_test() {
1577 const C_CERT: &'static str = concat!(include_str!("../../tests/data/certificate.crt"), "\0");
1578 const C_ROOT: &'static str = concat!(include_str!("../../tests/data/root.crt"), "\0");
1579 const C_CRL: &'static [u8] = include_bytes!("../../tests/data/root.revoked.crl");
1580
1581 let mut certs = MbedtlsList::new();
1582 certs.push(Certificate::from_pem(&C_CERT.as_bytes()).unwrap());
1583 let mut roots = MbedtlsList::new();
1584 roots.push(Certificate::from_pem(&C_ROOT.as_bytes()).unwrap());
1585
1586 let mut crl = Crl::new();
1587 crl.push_from_der(C_CRL).unwrap();
1588
1589 let mut err = String::new();
1590 assert_eq!(
1591 Certificate::verify(&certs, &roots, Some(&mut crl), Some(&mut err)).unwrap_err(),
1592 codes::X509CertVerifyFailed.into()
1593 );
1594 assert_eq!(err, "The certificate has been revoked (is on a CRL)\n");
1595 }
1596
1597 #[test]
1598 fn expected_common_name_test() {
1599 const C_CERT: &'static str = concat!(include_str!("../../tests/data/certificate.crt"), "\0");
1600 const C_ROOT: &'static str = concat!(include_str!("../../tests/data/root.crt"), "\0");
1601
1602 let mut certs = MbedtlsList::new();
1603 certs.push(Certificate::from_pem(&C_CERT.as_bytes()).unwrap());
1604 let mut roots = MbedtlsList::new();
1605 roots.push(Certificate::from_pem(&C_ROOT.as_bytes()).unwrap());
1606
1607 let mut err = String::new();
1608 assert!(
1609 Certificate::verify_with_expected_common_name(&certs, &roots, None, Some(&mut err), Some("example.com")).is_ok(),
1610 );
1611 }
1612
1613 #[test]
1614 fn expected_common_name_wrong_name_test() {
1615 const C_CERT: &'static str = concat!(include_str!("../../tests/data/certificate.crt"), "\0");
1616 const C_ROOT: &'static str = concat!(include_str!("../../tests/data/root.crt"), "\0");
1617
1618 let mut certs = MbedtlsList::new();
1619 certs.push(Certificate::from_pem(&C_CERT.as_bytes()).unwrap());
1620 let mut roots = MbedtlsList::new();
1621 roots.push(Certificate::from_pem(&C_ROOT.as_bytes()).unwrap());
1622
1623 let mut err = String::new();
1624 assert!(
1625 Certificate::verify_with_expected_common_name(&certs, &roots, None, Some(&mut err), Some("notit.com")).is_err()
1626 );
1627 }
1628
1629 #[test]
1630 fn test_combined_error_from_mbedtls() {
1631 let err = super::x509::Certificate::from_der(&b"\x30\x02\x05\x00"[..]).unwrap_err();
1632 assert_eq!(
1633 err,
1634 crate::Error::HighAndLowLevel(codes::X509InvalidFormat, codes::Asn1UnexpectedTag)
1635 );
1636 }
1637}