apple_codesign/
apple_certificates.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5//! Apple X.509 certificates.
6//!
7//! This module defines well-known Apple X.509 certificates.
8//!
9//! The canonical source of this data is <https://www.apple.com/certificateauthority/>.
10//!
11//! Note that some certificates are commented out and not available
12//! because the official DER-encoded certificates provided by Apple
13//! do not conform to the encoding standards in RFC 5280.
14
15use {once_cell::sync::Lazy, std::ops::Deref, x509_certificate::CapturedX509Certificate};
16
17/// Apple Inc. Root Certificate
18static APPLE_INC_ROOT_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
19    CapturedX509Certificate::from_der(
20        include_bytes!("apple-certs/AppleIncRootCertificate.cer").to_vec(),
21    )
22    .unwrap()
23});
24
25/// Apple Computer, Inc. Root Certificate.
26static APPLE_COMPUTER_INC_ROOT_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
27    CapturedX509Certificate::from_der(
28        include_bytes!("apple-certs/AppleComputerRootCertificate.cer").to_vec(),
29    )
30    .unwrap()
31});
32
33/// Apple Root CA - G2 Root Certificate
34static APPLE_ROOT_CA_G2_ROOT_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
35    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleRootCA-G2.cer").to_vec())
36        .unwrap()
37});
38
39/// Apple Root CA - G3 Root Certificate
40static APPLE_ROOT_CA_G3_ROOT_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
41    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleRootCA-G3.cer").to_vec())
42        .unwrap()
43});
44
45/// Apple IST CA 2 - G1 Certificate
46static APPLE_IST_CA_2_G1_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
47    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleISTCA2G1.cer").to_vec())
48        .unwrap()
49});
50
51/// Apple IST CA 8 - G1 Certificate
52static APPLE_IST_CA_8_G1_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
53    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleISTCA8G1.cer").to_vec())
54        .unwrap()
55});
56
57/// Application Integration Certificate
58static APPLICATION_INTEGRATION_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
59    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleAAICA.cer").to_vec())
60        .unwrap()
61});
62
63/// Application Integration 2 Certificate
64static APPLICATION_INTEGRATION_2_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
65    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleAAI2CA.cer").to_vec())
66        .unwrap()
67});
68
69/// Application Integration - G3 Certificate
70static APPLICATION_INTEGRATION_G3_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
71    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleAAICAG3.cer").to_vec())
72        .unwrap()
73});
74
75/// Apple Application Integration CA 5 - G1 Certificate
76static APPLE_APPLICATION_INTEGRATION_CA_5_G1_CERTIFICATE: Lazy<CapturedX509Certificate> =
77    Lazy::new(|| {
78        CapturedX509Certificate::from_der(
79            include_bytes!("apple-certs/AppleApplicationIntegrationCA5G1.cer").to_vec(),
80        )
81        .unwrap()
82    });
83
84/// Apple Application Integration CA 7 - G1 Certificate
85static APPLE_APPLICATION_INTEGRATION_CA_7_G1_CERTIFICATE: Lazy<CapturedX509Certificate> =
86    Lazy::new(|| {
87        CapturedX509Certificate::from_der(
88            include_bytes!("apple-certs/AppleApplicationIntegrationCA7G1.cer").to_vec(),
89        )
90        .unwrap()
91    });
92
93/// Developer Authentication Certificate
94static DEVELOPER_AUTHENTICATION_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
95    CapturedX509Certificate::from_der(include_bytes!("apple-certs/DevAuthCA.cer").to_vec()).unwrap()
96});
97
98/// Developer ID - G1 (Expiring 02/01/2027 22:12:15 UTC) Certificate
99static DEVELOPER_ID_G1_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
100    CapturedX509Certificate::from_der(include_bytes!("apple-certs/DeveloperIDCA.cer").to_vec())
101        .unwrap()
102});
103
104/// Developer ID - G2 (Expiring 09/17/2031 00:00:00 UTC) Certificate
105static DEVELOPER_ID_G2_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
106    CapturedX509Certificate::from_der(include_bytes!("apple-certs/DeveloperIDG2CA.cer").to_vec())
107        .unwrap()
108});
109
110/// Software Update Certificate
111static SOFTWARE_UPDATE_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
112    CapturedX509Certificate::from_der(
113        include_bytes!("apple-certs/AppleSoftwareUpdateCertificationAuthority.cer").to_vec(),
114    )
115    .unwrap()
116});
117
118/// Timestamp Certificate
119static TIMESTAMP_CERTIFICATE: Lazy<CapturedX509Certificate> = Lazy::new(|| {
120    CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleTimestampCA.cer").to_vec())
121        .unwrap()
122});
123
124/// Worldwide Developer Relations - G1 (Expiring 02/07/2023 21:48:47 UTC) Certificate
125static WORLD_WIDE_DEVELOPER_RELATIONS_G1_CERTIFICATE: Lazy<CapturedX509Certificate> =
126    Lazy::new(|| {
127        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCA.cer").to_vec())
128            .unwrap()
129    });
130
131/// Worldwide Developer Relations - G2 (Expiring 05/06/2029 23:43:24 UTC) Certificate
132static WORLD_WIDE_DEVELOPER_RELATIONS_G2_CERTIFICATE: Lazy<CapturedX509Certificate> =
133    Lazy::new(|| {
134        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCAG2.cer").to_vec())
135            .unwrap()
136    });
137
138/// Worldwide Developer Relations - G3 (Expiring 02/20/2030 00:00:00 UTC) Certificate
139static WORLD_WIDE_DEVELOPER_RELATIONS_G3_CERTIFICATE: Lazy<CapturedX509Certificate> =
140    Lazy::new(|| {
141        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCAG3.cer").to_vec())
142            .unwrap()
143    });
144
145/// Worldwide Developer Relations - G4 (Expiring 12/10/2030 00:00:00 UTC) Certificate
146static WORLD_WIDE_DEVELOPER_RELATIONS_G4_CERTIFICATE: Lazy<CapturedX509Certificate> =
147    Lazy::new(|| {
148        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCAG4.cer").to_vec())
149            .unwrap()
150    });
151
152/// Worldwide Developer Relations - G5 (Expiring 12/10/2030 00:00:00 UTC) Certificate
153static WORLD_WIDE_DEVELOPER_RELATIONS_G5_CERTIFICATE: Lazy<CapturedX509Certificate> =
154    Lazy::new(|| {
155        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCAG5.cer").to_vec())
156            .unwrap()
157    });
158
159/// Worldwide Developer Relations - G6 (Expiring 03/19/2036 00:00:00 UTC) Certificate
160static WORLD_WIDE_DEVELOPER_RELATIONS_G6_CERTIFICATE: Lazy<CapturedX509Certificate> =
161    Lazy::new(|| {
162        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCAG6.cer").to_vec())
163            .unwrap()
164    });
165
166/// Worldwide Developer Relations - G7 (Expiring 11/17/2023 20:40:52 UTC) Certificate
167static WORLD_WIDE_DEVELOPER_RELATIONS_G7_CERTIFICATE: Lazy<CapturedX509Certificate> =
168    Lazy::new(|| {
169        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCAG7.cer").to_vec())
170            .unwrap()
171    });
172
173/// Worldwide Developer Relations - G8 (Expiring 01/24/2025 00:00:00 UTC) Certificate
174static WORLD_WIDE_DEVELOPER_RELATIONS_G8_CERTIFICATE: Lazy<CapturedX509Certificate> =
175    Lazy::new(|| {
176        CapturedX509Certificate::from_der(include_bytes!("apple-certs/AppleWWDRCAG8.cer").to_vec())
177            .unwrap()
178    });
179
180/// All known Apple certificates.
181static KNOWN_CERTIFICATES: Lazy<Vec<&CapturedX509Certificate>> = Lazy::new(|| {
182    vec![
183        // We put the 4 roots first, newest to oldest.
184        APPLE_ROOT_CA_G3_ROOT_CERTIFICATE.deref(),
185        APPLE_ROOT_CA_G2_ROOT_CERTIFICATE.deref(),
186        APPLE_INC_ROOT_CERTIFICATE.deref(),
187        APPLE_COMPUTER_INC_ROOT_CERTIFICATE.deref(),
188        APPLE_IST_CA_2_G1_CERTIFICATE.deref(),
189        APPLE_IST_CA_8_G1_CERTIFICATE.deref(),
190        APPLICATION_INTEGRATION_CERTIFICATE.deref(),
191        APPLICATION_INTEGRATION_2_CERTIFICATE.deref(),
192        APPLICATION_INTEGRATION_G3_CERTIFICATE.deref(),
193        APPLE_APPLICATION_INTEGRATION_CA_5_G1_CERTIFICATE.deref(),
194        APPLE_APPLICATION_INTEGRATION_CA_7_G1_CERTIFICATE.deref(),
195        DEVELOPER_AUTHENTICATION_CERTIFICATE.deref(),
196        DEVELOPER_ID_G1_CERTIFICATE.deref(),
197        DEVELOPER_ID_G2_CERTIFICATE.deref(),
198        SOFTWARE_UPDATE_CERTIFICATE.deref(),
199        TIMESTAMP_CERTIFICATE.deref(),
200        WORLD_WIDE_DEVELOPER_RELATIONS_G1_CERTIFICATE.deref(),
201        WORLD_WIDE_DEVELOPER_RELATIONS_G2_CERTIFICATE.deref(),
202        WORLD_WIDE_DEVELOPER_RELATIONS_G3_CERTIFICATE.deref(),
203        WORLD_WIDE_DEVELOPER_RELATIONS_G4_CERTIFICATE.deref(),
204        WORLD_WIDE_DEVELOPER_RELATIONS_G5_CERTIFICATE.deref(),
205        WORLD_WIDE_DEVELOPER_RELATIONS_G6_CERTIFICATE.deref(),
206        WORLD_WIDE_DEVELOPER_RELATIONS_G7_CERTIFICATE.deref(),
207        WORLD_WIDE_DEVELOPER_RELATIONS_G8_CERTIFICATE.deref(),
208    ]
209});
210
211static KNOWN_ROOTS: Lazy<Vec<&CapturedX509Certificate>> = Lazy::new(|| {
212    vec![
213        APPLE_ROOT_CA_G3_ROOT_CERTIFICATE.deref(),
214        APPLE_ROOT_CA_G2_ROOT_CERTIFICATE.deref(),
215        APPLE_INC_ROOT_CERTIFICATE.deref(),
216        APPLE_COMPUTER_INC_ROOT_CERTIFICATE.deref(),
217    ]
218});
219
220/// Defines all known Apple certificates.
221///
222/// This crate embeds the raw certificate data for the various known
223/// Apple certificate authorities, as advertised at
224/// <https://www.apple.com/certificateauthority/>.
225///
226/// This enumeration defines all the ones we know about. Instances can
227/// be dereferenced into concrete [CapturedX509Certificate] to get at the underlying
228/// certificate and access its metadata.
229#[derive(Clone, Copy, Debug, Eq, PartialEq)]
230pub enum KnownCertificate {
231    /// Apple Computer, Inc. Root Certificate.
232    ///
233    /// C = US, O = "Apple Computer, Inc.", OU = Apple Computer Certificate Authority, CN = Apple Root Certificate Authority
234    AppleComputerIncRoot,
235
236    /// Apple Inc. Root Certificate
237    ///
238    /// C = US, O = Apple Inc., OU = Apple Certification Authority, CN = Apple Root CA
239    AppleRootCa,
240
241    /// Apple Root CA - G2 Root Certificate
242    ///
243    /// CN = Apple Root CA - G2, OU = Apple Certification Authority, O = Apple Inc., C = US
244    AppleRootCaG2Root,
245
246    /// Apple Root CA - G3 Root Certificate
247    ///
248    /// CN = Apple Root CA - G3, OU = Apple Certification Authority, O = Apple Inc., C = US
249    AppleRootCaG3Root,
250
251    /// Apple IST CA 2 - G1 Certificate
252    ///
253    /// CN = Apple IST CA 2 - G1, OU = Certification Authority, O = Apple Inc., C = US
254    AppleIstCa2G1,
255
256    /// Apple IST CA 8 - G1 Certificate
257    ///
258    /// CN = Apple IST CA 8 - G1, OU = Certification Authority, O = Apple Inc., C = US
259    AppleIstCa8G1,
260
261    /// Application Integration Certificate
262    ///
263    /// C = US, O = Apple Inc., OU = Apple Certification Authority, CN = Apple Application Integration Certification Authority
264    ApplicationIntegration,
265
266    /// Application Integration 2 Certificate
267    ///
268    /// CN = Apple Application Integration 2 Certification Authority, OU = Apple Certification Authority, O = Apple Inc., C = US
269    ApplicationIntegration2,
270
271    /// Application Integration - G3 Certificate
272    ///
273    /// CN = Apple Application Integration CA - G3, OU = Apple Certification Authority, O = Apple Inc., C = US
274    ApplicationIntegrationG3,
275
276    /// Apple Application Integration CA 5 - G1 Certificate
277    ///
278    /// CN = Apple Application Integration CA 5 - G1, OU = Apple Certification Authority, O = Apple Inc., C = US
279    AppleApplicationIntegrationCa5G1,
280
281    /// Apple Application Integration CA 7 - G1 Certificate
282    ///
283    /// CN=Apple Application Integration CA 7 - G1, OU=Apple Certification Authority, O=Apple Inc., C=US
284    AppleApplicationIntegrationCa7G1,
285
286    /// Developer Authentication Certificate
287    ///
288    /// CN = Developer Authentication Certification Authority, OU = Apple Worldwide Developer Relations, O = Apple Inc., C = US
289    DeveloperAuthentication,
290
291    /// Developer ID - G1  Certificate
292    ///
293    /// CN = Developer ID Certification Authority, OU = Apple Certification Authority, O = Apple Inc., C = US
294    DeveloperIdG1,
295
296    /// Developer ID - G2 Certificate.
297    ///
298    /// CN = Developer ID Certification Authority, OU = G2, O = Apple Inc., C = US
299    DeveloperIdG2,
300
301    /// Software Update Certificate
302    ///
303    /// CN = Apple Software Update Certification Authority, OU = Certification Authority, O = Apple Inc., C = US
304    SoftwareUpdate,
305
306    /// Timestamp Certificate
307    ///
308    /// CN = Apple Timestamp Certification Authority, OU = Apple Certification Authority, O = Apple Inc., C = US
309    Timestamp,
310
311    /// Worldwide Developer Relations - G1 (Expiring 02/07/2023 21:48:47 UTC) Certificate
312    ///
313    /// C = US, O = Apple Inc., OU = Apple Worldwide Developer Relations, CN = Apple Worldwide Developer Relations Certification Authority
314    WwdrG1,
315
316    /// Worldwide Developer Relations - G2 (Expiring 05/06/2029 23:43:24 UTC) Certificate
317    ///
318    /// CN = Apple Worldwide Developer Relations CA - G2, OU = Apple Certification Authority, O = Apple Inc., C = US
319    WwdrG2,
320
321    /// Worldwide Developer Relations - G3 (Expiring 02/20/2030 00:00:00 UTC) Certificate
322    ///
323    /// CN = Apple Worldwide Developer Relations Certification Authority, OU = G3, O = Apple Inc., C = US
324    WwdrG3,
325
326    /// Worldwide Developer Relations - G4 (Expiring 12/10/2030 00:00:00 UTC) Certificate
327    ///
328    /// CN = Apple Worldwide Developer Relations Certification Authority, OU = G4, O = Apple Inc., C = US
329    WwdrG4,
330
331    /// Worldwide Developer Relations - G5 (Expiring 12/10/2030 00:00:00 UTC) Certificate
332    ///
333    /// CN = Apple Worldwide Developer Relations Certification Authority, OU = G5, O = Apple Inc., C = US
334    WwdrG5,
335
336    /// Worldwide Developer Relations - G6 (Expiring 03/19/2036 00:00:00 UTC) Certificate
337    ///
338    /// CN = Apple Worldwide Developer Relations Certification Authority, OU = G6, O = Apple Inc., C = US
339    WwdrG6,
340
341    /// Worldwide Developer Relations - G7 (Expiring 11/17/2023 20:40:52 UTC)
342    ///
343    /// C=US, O=Apple Inc., OU=G7, CN=Apple Worldwide Developer Relations Certification Authority
344    WwdrG7,
345
346    /// Worldwide Developer Relations - G8 (Expiring 01/24/2025 00:00:00 UTC)
347    ///
348    /// C=US, O=Apple Inc., OU=G8, CN=Apple Worldwide Developer Relations Certification Authority
349    WwdrG8,
350}
351
352impl Deref for KnownCertificate {
353    type Target = CapturedX509Certificate;
354
355    fn deref(&self) -> &Self::Target {
356        match self {
357            Self::AppleComputerIncRoot => APPLE_COMPUTER_INC_ROOT_CERTIFICATE.deref(),
358            Self::AppleRootCa => APPLE_INC_ROOT_CERTIFICATE.deref(),
359            Self::AppleRootCaG2Root => APPLE_ROOT_CA_G2_ROOT_CERTIFICATE.deref(),
360            Self::AppleRootCaG3Root => APPLE_ROOT_CA_G3_ROOT_CERTIFICATE.deref(),
361            Self::AppleIstCa2G1 => APPLE_IST_CA_2_G1_CERTIFICATE.deref(),
362            Self::AppleIstCa8G1 => APPLE_IST_CA_8_G1_CERTIFICATE.deref(),
363            Self::ApplicationIntegration => APPLICATION_INTEGRATION_CERTIFICATE.deref(),
364            Self::ApplicationIntegration2 => APPLICATION_INTEGRATION_2_CERTIFICATE.deref(),
365            Self::ApplicationIntegrationG3 => APPLICATION_INTEGRATION_G3_CERTIFICATE.deref(),
366            Self::AppleApplicationIntegrationCa5G1 => {
367                APPLE_APPLICATION_INTEGRATION_CA_5_G1_CERTIFICATE.deref()
368            }
369            Self::AppleApplicationIntegrationCa7G1 => {
370                APPLE_APPLICATION_INTEGRATION_CA_7_G1_CERTIFICATE.deref()
371            }
372            Self::DeveloperAuthentication => DEVELOPER_AUTHENTICATION_CERTIFICATE.deref(),
373            Self::DeveloperIdG1 => DEVELOPER_ID_G1_CERTIFICATE.deref(),
374            Self::DeveloperIdG2 => DEVELOPER_ID_G2_CERTIFICATE.deref(),
375            Self::SoftwareUpdate => SOFTWARE_UPDATE_CERTIFICATE.deref(),
376            Self::Timestamp => TIMESTAMP_CERTIFICATE.deref(),
377            Self::WwdrG1 => WORLD_WIDE_DEVELOPER_RELATIONS_G1_CERTIFICATE.deref(),
378            Self::WwdrG2 => WORLD_WIDE_DEVELOPER_RELATIONS_G2_CERTIFICATE.deref(),
379            Self::WwdrG3 => WORLD_WIDE_DEVELOPER_RELATIONS_G3_CERTIFICATE.deref(),
380            Self::WwdrG4 => WORLD_WIDE_DEVELOPER_RELATIONS_G4_CERTIFICATE.deref(),
381            Self::WwdrG5 => WORLD_WIDE_DEVELOPER_RELATIONS_G5_CERTIFICATE.deref(),
382            Self::WwdrG6 => WORLD_WIDE_DEVELOPER_RELATIONS_G6_CERTIFICATE.deref(),
383            Self::WwdrG7 => WORLD_WIDE_DEVELOPER_RELATIONS_G7_CERTIFICATE.deref(),
384            Self::WwdrG8 => WORLD_WIDE_DEVELOPER_RELATIONS_G8_CERTIFICATE.deref(),
385        }
386    }
387}
388
389impl AsRef<CapturedX509Certificate> for KnownCertificate {
390    fn as_ref(&self) -> &CapturedX509Certificate {
391        self.deref()
392    }
393}
394
395impl TryFrom<&CapturedX509Certificate> for KnownCertificate {
396    type Error = &'static str;
397
398    fn try_from(cert: &CapturedX509Certificate) -> Result<Self, Self::Error> {
399        let want = cert.constructed_data();
400
401        match cert.constructed_data() {
402            _ if APPLE_ROOT_CA_G3_ROOT_CERTIFICATE.constructed_data() == want => {
403                Ok(Self::AppleRootCaG3Root)
404            }
405            _ if APPLE_ROOT_CA_G2_ROOT_CERTIFICATE.constructed_data() == want => {
406                Ok(Self::AppleRootCaG2Root)
407            }
408            _ if APPLE_INC_ROOT_CERTIFICATE.constructed_data() == want => Ok(Self::AppleRootCa),
409            _ if APPLE_COMPUTER_INC_ROOT_CERTIFICATE.constructed_data() == want => {
410                Ok(Self::AppleComputerIncRoot)
411            }
412            _ if APPLE_IST_CA_2_G1_CERTIFICATE.constructed_data() == want => {
413                Ok(Self::AppleIstCa2G1)
414            }
415            _ if APPLE_IST_CA_8_G1_CERTIFICATE.constructed_data() == want => {
416                Ok(Self::AppleIstCa8G1)
417            }
418            _ if APPLICATION_INTEGRATION_CERTIFICATE.constructed_data() == want => {
419                Ok(Self::ApplicationIntegration)
420            }
421            _ if APPLICATION_INTEGRATION_2_CERTIFICATE.constructed_data() == want => {
422                Ok(Self::ApplicationIntegration2)
423            }
424            _ if APPLICATION_INTEGRATION_G3_CERTIFICATE.constructed_data() == want => {
425                Ok(Self::ApplicationIntegrationG3)
426            }
427            _ if APPLE_APPLICATION_INTEGRATION_CA_5_G1_CERTIFICATE.constructed_data() == want => {
428                Ok(Self::AppleApplicationIntegrationCa5G1)
429            }
430            _ if APPLE_APPLICATION_INTEGRATION_CA_7_G1_CERTIFICATE.constructed_data() == want => {
431                Ok(Self::AppleApplicationIntegrationCa7G1)
432            }
433            _ if DEVELOPER_AUTHENTICATION_CERTIFICATE.constructed_data() == want => {
434                Ok(Self::DeveloperAuthentication)
435            }
436            _ if DEVELOPER_ID_G1_CERTIFICATE.constructed_data() == want => Ok(Self::DeveloperIdG1),
437            _ if DEVELOPER_ID_G2_CERTIFICATE.constructed_data() == want => Ok(Self::DeveloperIdG2),
438            _ if SOFTWARE_UPDATE_CERTIFICATE.constructed_data() == want => Ok(Self::SoftwareUpdate),
439            _ if TIMESTAMP_CERTIFICATE.constructed_data() == want => Ok(Self::Timestamp),
440            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G1_CERTIFICATE.constructed_data() == want => {
441                Ok(Self::WwdrG1)
442            }
443            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G2_CERTIFICATE.constructed_data() == want => {
444                Ok(Self::WwdrG2)
445            }
446            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G3_CERTIFICATE.constructed_data() == want => {
447                Ok(Self::WwdrG3)
448            }
449            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G4_CERTIFICATE.constructed_data() == want => {
450                Ok(Self::WwdrG4)
451            }
452            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G5_CERTIFICATE.constructed_data() == want => {
453                Ok(Self::WwdrG5)
454            }
455            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G6_CERTIFICATE.constructed_data() == want => {
456                Ok(Self::WwdrG6)
457            }
458            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G7_CERTIFICATE.constructed_data() == want => {
459                Ok(Self::WwdrG7)
460            }
461            _ if WORLD_WIDE_DEVELOPER_RELATIONS_G8_CERTIFICATE.constructed_data() == want => {
462                Ok(Self::WwdrG8)
463            }
464            _ => Err("certificate not found"),
465        }
466    }
467}
468
469impl KnownCertificate {
470    /// Obtain a slice of all known [KnownCertificate].
471    ///
472    /// If you want to iterate over all certificates and find one, you can use
473    /// this.
474    pub fn all() -> &'static [&'static CapturedX509Certificate] {
475        KNOWN_CERTIFICATES.deref().as_ref()
476    }
477
478    /// All of Apple's known root certificate authority certificates.
479    pub fn all_roots() -> &'static [&'static CapturedX509Certificate] {
480        KNOWN_ROOTS.deref()
481    }
482}
483
484#[cfg(test)]
485mod test {
486    use {
487        super::*,
488        crate::certificate::{AppleCertificate, CertificateAuthorityExtension},
489    };
490
491    #[test]
492    fn all() {
493        for cert in KnownCertificate::all() {
494            assert!(cert.subject_common_name().is_some());
495            assert!(KnownCertificate::try_from(*cert).is_ok());
496        }
497    }
498
499    #[test]
500    fn apple_root_ca() {
501        assert!(APPLE_INC_ROOT_CERTIFICATE.is_apple_root_ca());
502        assert!(!APPLE_INC_ROOT_CERTIFICATE.is_apple_intermediate_ca());
503        assert!(APPLE_COMPUTER_INC_ROOT_CERTIFICATE.is_apple_root_ca());
504        assert!(!APPLE_COMPUTER_INC_ROOT_CERTIFICATE.is_apple_intermediate_ca());
505        assert!(APPLE_ROOT_CA_G2_ROOT_CERTIFICATE.is_apple_root_ca());
506        assert!(!APPLE_ROOT_CA_G2_ROOT_CERTIFICATE.is_apple_intermediate_ca());
507        assert!(APPLE_ROOT_CA_G3_ROOT_CERTIFICATE.is_apple_root_ca());
508        assert!(!APPLE_ROOT_CA_G3_ROOT_CERTIFICATE.is_apple_intermediate_ca());
509
510        assert!(!WORLD_WIDE_DEVELOPER_RELATIONS_G3_CERTIFICATE.is_apple_root_ca());
511        assert!(WORLD_WIDE_DEVELOPER_RELATIONS_G3_CERTIFICATE.is_apple_intermediate_ca());
512
513        let wanted = [APPLE_INC_ROOT_CERTIFICATE.deref(),
514            APPLE_COMPUTER_INC_ROOT_CERTIFICATE.deref(),
515            APPLE_ROOT_CA_G2_ROOT_CERTIFICATE.deref(),
516            APPLE_ROOT_CA_G3_ROOT_CERTIFICATE.deref()];
517
518        for cert in KnownCertificate::all() {
519            if wanted.contains(cert) {
520                continue;
521            }
522
523            assert!(!cert.is_apple_root_ca());
524            assert!(cert.is_apple_intermediate_ca());
525        }
526    }
527
528    #[test]
529    fn intermediate_have_apple_ca_extension() {
530        // All intermediate certs should have OIDs identifying them as such.
531        for cert in KnownCertificate::all()
532            .iter()
533            .filter(|cert| !cert.is_apple_root_ca())
534            // There are some intermediate certificates signed by GeoTrust. Filter them out
535            // as well.
536            .filter(|cert| {
537                cert.issuer_name()
538                    .iter_common_name()
539                    .all(|atv| !atv.to_string().unwrap().contains("GeoTrust"))
540            })
541        {
542            assert!(!cert.apple_ca_extensions().is_empty());
543        }
544
545        // Let's spot check a few.
546        assert_eq!(
547            KnownCertificate::DeveloperIdG1
548                .apple_ca_extensions()
549                .first(),
550            Some(&CertificateAuthorityExtension::DeveloperId)
551        );
552        assert_eq!(
553            KnownCertificate::DeveloperIdG2
554                .apple_ca_extensions()
555                .first(),
556            Some(&CertificateAuthorityExtension::DeveloperId)
557        );
558        assert_eq!(
559            KnownCertificate::WwdrG1.apple_ca_extensions().first(),
560            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelations)
561        );
562        assert_eq!(
563            KnownCertificate::WwdrG2.apple_ca_extensions().first(),
564            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelationsG2)
565        );
566        assert_eq!(
567            KnownCertificate::WwdrG3.apple_ca_extensions().first(),
568            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelations)
569        );
570        assert_eq!(
571            KnownCertificate::WwdrG4.apple_ca_extensions().first(),
572            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelations)
573        );
574        assert_eq!(
575            KnownCertificate::WwdrG5.apple_ca_extensions().first(),
576            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelations)
577        );
578        assert_eq!(
579            KnownCertificate::WwdrG6.apple_ca_extensions().first(),
580            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelations)
581        );
582        assert_eq!(
583            KnownCertificate::WwdrG7.apple_ca_extensions().first(),
584            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelations)
585        );
586        assert_eq!(
587            KnownCertificate::WwdrG8.apple_ca_extensions().first(),
588            Some(&CertificateAuthorityExtension::AppleWorldwideDeveloperRelations)
589        );
590    }
591
592    #[test]
593    fn chaining() {
594        let relevant = KnownCertificate::all()
595            .iter()
596            .filter(|cert| {
597                cert.issuer_name()
598                    .iter_common_name()
599                    .all(|atv| !atv.to_string().unwrap().contains("GeoTrust"))
600            })
601            .filter(|cert| {
602                cert.constructed_data() != APPLICATION_INTEGRATION_G3_CERTIFICATE.constructed_data()
603                    && cert.constructed_data()
604                        != APPLE_APPLICATION_INTEGRATION_CA_5_G1_CERTIFICATE.constructed_data()
605            });
606
607        for cert in relevant {
608            let chain = cert.resolve_signing_chain(KnownCertificate::all().iter().copied());
609            let apple_chain = cert.apple_issuing_chain();
610            assert_eq!(chain.len(), apple_chain.len());
611        }
612    }
613}