mbedtls/x509/
certificate.rs

1/* Copyright (c) Fortanix, Inc.
2 *
3 * Licensed under the GNU General Public License, version 2 <LICENSE-GPL or
4 * https://www.gnu.org/licenses/gpl-2.0.html> or the Apache License, Version
5 * 2.0 <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>, at your
6 * option. This file may not be copied, modified, or distributed except
7 * according to those terms. */
8
9use 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    // ensure casts don't underflow
71    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    /// Input must be NULL-terminated
94    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            // Use from_pem_multiple for parsing multiple certificates in a pem.
100            return Err(codes::X509BadInputData.into());
101        }
102
103        Ok(cert)
104    }
105
106    /// Input must be NULL-terminated
107    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        // Asserts cn is still alive here. Prevents bugs (e.g., forgetting to insert `.as_ref()` when using cn)
250        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    /// Like `verify`. In case of errors, returns `VerifyError` as well.
277    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    /// Like `verify`, optionally accepts an `expected_common_name` arg.
287    ///
288    /// * `expected_common_name`
289    /// (From mbedtls documentation) The expected Common Name. This will be checked to be present in the certificate’s
290    /// subjectAltNames extension or, if this extension is absent, as a CN component in its Subject name. DNS names
291    /// and IP addresses are fully supported, while the URI subtype is partially supported: only exact matching,
292    /// without any normalization procedures described in 7.4 of RFC5280, will result in a positive URI verification.
293    /// This may be `None` if the CN need not be verified.
294    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    /// Like `verify_with_expected_common_name`. In case of errors, returns `VerifyError` as well.
313    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    /// Like `verify_with_callback`. In case of errors, returns `VerifyError` as well.
344    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    /// Like `verify_with_callback`, optionally accepts an `expected_common_name` arg.
358    ///
359    /// * `expected_common_name`
360    /// (From mbedtls documentation) The expected Common Name. This will be checked to be present in the certificate’s
361    /// subjectAltNames extension or, if this extension is absent, as a CN component in its Subject name. DNS names
362    /// and IP addresses are fully supported, while the URI subtype is partially supported: only exact matching,
363    /// without any normalization procedures described in 7.4 of RFC5280, will result in a positive URI verification.
364    /// This may be `None` if the CN need not be verified.
365    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    /// Like `verify_with_callback_expected_common_name`. In case of errors, returns `VerifyError` as well.
380    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
395// TODO
396//
397// x509_crt_verify_with_profile
398// x509_crt_is_revoked
399//
400// x509_crt_parse_file
401// x509_crt_parse_path
402//
403
404impl 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
560// TODO
561// x509write_crt_set_version
562// x509write_crt_set_ns_cert_type
563// x509write_crt_set_authority_key_identifier
564// x509write_crt_set_subject_key_identifier
565//
566
567impl 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            // If alignment is wrong it means someone pushed their own allocator to mbedtls
573            // and that is not functioning correctly.
574            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                // We have a certificate that was never initialized.
602                //
603                // This is not possible from 'mbedtls' side as all certificates are first init
604                // then they parse a der/pem. This is also not possible from
605                // rust side as all init() calls are followed by parsing.
606                unreachable!("Trying to clone an uninitialized certificate.");
607            } else {
608                // We have a certificate that was already created once, failing the re-parse is
609                // a possible memory corruption or bad usage of mbedtls internals.
610                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        // This leaks a *mut Certificate that we can cast to x509_crt as it's
637        // transparent and has no extra fields.
638        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        // no iterations in for loop: head equals tail
663        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
771// Follows same pattern as IntoIter from rust-lang's linked_list.rs
772// - line 108: https://github.com/rust-lang/rust/blob/master/library/alloc/src/collections/linked_list.rs
773pub 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    /// Consumes the list into an iterator yielding elements by value.
791    #[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        // Certificate C_INT2 is missing at the beginning so the verification should
1104        // fail at first
1105        let mut chain = MbedtlsList::<Certificate>::new();
1106        chain.push(c_leaf.clone());
1107        chain.push(c_int1.clone());
1108
1109        // The certificates used for this test are expired so we remove the CERT_EXPIRED
1110        // flag with the callback
1111        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        // try again after fixing the chain
1123        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        // Using debug strings so failing unit tests can identify any issue with
1174        // contents.
1175        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        // Using debug strings so failing unit tests can identify any issue with
1256        // contents.
1257        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        // Using debug strings so failing unit tests can identify any issue with
1338        // contents.
1339        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        // Using debug strings so failing unit tests can identify any issue with
1378        // contents.
1379        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        // Using debug strings so failing unit tests can identify any issue with
1443        // contents.
1444        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        // First item reference within a list of 3 elements still has next set.
1453        assert_ne!((**cert).inner.next, ::core::ptr::null_mut());
1454        assert_eq!(c1_info, format!("{:?}", cert));
1455
1456        let cert = cert.clone();
1457
1458        // Cloning it strips it away from the list and forces the next to be null
1459        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        // Using into_iter and extracting a certificate must have its next set to null
1465        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        // Using debug strings so failing unit tests can identify any issue with
1484        // contents.
1485        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}