Skip to main content

esteid_cryptoki/
filter.rs

1use std::path::PathBuf;
2
3use tokenkey::ModuleSpec;
4use x509_cert::der::asn1::{PrintableStringRef, Utf8StringRef};
5use x509_cert::der::oid::ObjectIdentifier;
6use x509_cert::der::Decode;
7
8const OID_COMMON_NAME: ObjectIdentifier = ObjectIdentifier::new_unwrap("2.5.4.3");
9
10/// Certificate issuer CN prefixes accepted as an ID-card CA.
11const ESTEID_ISSUER_CN_PREFIXES: &[&str] = &["ESTEID", "Test ESTEID"];
12
13/// OpenSC module candidates.
14pub fn modules() -> Vec<ModuleSpec> {
15    vec![ModuleSpec {
16        name: "opensc-pkcs11".into(),
17        paths: vec![
18            // macOS
19            PathBuf::from("/Library/OpenSC/lib/opensc-pkcs11.so"),
20            PathBuf::from("/opt/homebrew/lib/opensc-pkcs11.so"),
21            // Linux
22            PathBuf::from("/usr/lib/x86_64-linux-gnu/opensc-pkcs11.so"),
23            PathBuf::from("/usr/lib64/opensc-pkcs11.so"),
24            PathBuf::from("/usr/lib/opensc-pkcs11.so"),
25            // Windows
26            PathBuf::from(r"C:\Windows\System32\opensc-pkcs11.dll"),
27        ],
28    }]
29}
30
31/// Whether `cert_der`'s issuer common name starts with an accepted ESTEID CA prefix.
32pub(crate) fn is_esteid_issued(cert_der: &[u8]) -> bool {
33    let Ok(cert) = x509_cert::Certificate::from_der(cert_der) else {
34        return false;
35    };
36    let Some(cn) = issuer_common_name(&cert) else {
37        return false;
38    };
39    ESTEID_ISSUER_CN_PREFIXES
40        .iter()
41        .any(|prefix| cn.starts_with(prefix))
42}
43
44/// The issuer's `CN` attribute.
45fn issuer_common_name(cert: &x509_cert::Certificate) -> Option<String> {
46    cert.tbs_certificate.issuer.0.iter().find_map(|rdn| {
47        rdn.0.iter().find_map(|atv| {
48            if atv.oid != OID_COMMON_NAME {
49                return None;
50            }
51            atv.value
52                .decode_as::<Utf8StringRef>()
53                .map(|s| s.to_string())
54                .or_else(|_| {
55                    atv.value
56                        .decode_as::<PrintableStringRef>()
57                        .map(|s| s.to_string())
58                })
59                .ok()
60        })
61    })
62}