native_pkcs11_traits/
lib.rs

1// Copyright 2022 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::{
16    any::Any,
17    hash::Hash,
18    sync::{Arc, LazyLock, RwLock},
19};
20
21use x509_cert::der::Decode;
22
23pub type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
24
25//  The Backend is first staged so it can be stored in a Box<dyn Backend>. This
26//  allows the Backend to be reference with `&'static`.
27static STAGED_BACKEND: RwLock<Option<Box<dyn Backend>>> = RwLock::new(None);
28static BACKEND: LazyLock<Box<dyn Backend>> =
29    LazyLock::new(|| STAGED_BACKEND.write().unwrap().take().unwrap());
30
31/// Stores a backend to later be returned by all calls `crate::backend()`.
32pub fn register_backend(backend: Box<dyn Backend>) {
33    *STAGED_BACKEND.write().unwrap() = Some(backend);
34}
35
36pub fn backend() -> &'static dyn Backend {
37    BACKEND.as_ref()
38}
39
40#[derive(Debug, PartialEq, Eq, Clone)]
41pub enum DigestType {
42    Sha1,
43    Sha224,
44    Sha256,
45    Sha384,
46    Sha512,
47}
48
49impl DigestType {
50    pub fn digest_len(&self) -> usize {
51        match self {
52            DigestType::Sha1 => 20,
53            DigestType::Sha224 => 28,
54            DigestType::Sha256 => 32,
55            DigestType::Sha384 => 48,
56            DigestType::Sha512 => 64,
57        }
58    }
59}
60
61#[derive(Debug, Clone)]
62pub enum SignatureAlgorithm {
63    Ecdsa,
64    RsaRaw,
65    RsaPkcs1v15Raw,
66    RsaPkcs1v15Sha1,
67    RsaPkcs1v15Sha384,
68    RsaPkcs1v15Sha256,
69    RsaPkcs1v15Sha512,
70    RsaPss { digest: DigestType, mask_generation_function: DigestType, salt_length: u64 },
71}
72
73pub trait PrivateKey: Send + Sync {
74    fn id(&self) -> Vec<u8>;
75    fn label(&self) -> String;
76    fn sign(&self, algorithm: &SignatureAlgorithm, data: &[u8]) -> Result<Vec<u8>>;
77    fn delete(&self);
78    fn algorithm(&self) -> KeyAlgorithm;
79    fn find_public_key(&self, backend: &dyn Backend) -> Result<Option<Box<dyn PublicKey>>> {
80        backend.find_public_key(KeySearchOptions::Id(self.id()))
81    }
82}
83
84impl std::fmt::Debug for dyn PrivateKey {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.debug_struct("PrivateKey").field("label", &self.label()).finish_non_exhaustive()
87    }
88}
89
90impl PartialEq for dyn PrivateKey {
91    fn eq(&self, other: &Self) -> bool {
92        self.id() == other.id() && self.label() == other.label()
93    }
94}
95
96impl Eq for dyn PrivateKey {}
97impl Hash for dyn PrivateKey {
98    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
99        self.type_id().hash(state);
100        self.id().hash(state);
101        self.label().hash(state);
102    }
103}
104
105pub trait PublicKey: Send + Sync + std::fmt::Debug {
106    fn id(&self) -> Vec<u8>;
107    fn label(&self) -> String;
108    fn to_der(&self) -> Vec<u8>;
109    fn verify(&self, algorithm: &SignatureAlgorithm, data: &[u8], signature: &[u8]) -> Result<()>;
110    fn delete(self: Box<Self>);
111    fn algorithm(&self) -> KeyAlgorithm;
112}
113
114impl PartialEq for dyn PublicKey {
115    fn eq(&self, other: &Self) -> bool {
116        self.id() == other.id() && self.label() == other.label()
117    }
118}
119
120impl Eq for dyn PublicKey {}
121impl Hash for dyn PublicKey {
122    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
123        self.type_id().hash(state);
124        self.id().hash(state);
125        self.label().hash(state);
126    }
127}
128
129pub trait Certificate: Send + Sync + std::fmt::Debug {
130    fn id(&self) -> Vec<u8>;
131    fn label(&self) -> String;
132    fn to_der(&self) -> Vec<u8>;
133    fn public_key(&self) -> &dyn PublicKey;
134    fn delete(self: Box<Self>);
135    fn algorithm(&self) -> KeyAlgorithm {
136        self.public_key().algorithm()
137    }
138}
139
140impl PartialEq for dyn Certificate {
141    fn eq(&self, other: &Self) -> bool {
142        self.to_der() == other.to_der() && self.label() == other.label()
143    }
144}
145impl Eq for dyn Certificate {}
146impl Hash for dyn Certificate {
147    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
148        self.type_id().hash(state);
149        self.to_der().hash(state);
150        self.label().hash(state);
151    }
152}
153
154pub trait CertificateExt: Certificate {
155    fn issuer(&self) -> Vec<u8> {
156        let der = self.to_der();
157        let c = x509_cert::Certificate::from_der(&der).unwrap();
158        x509_cert::der::Encode::to_der(&c.tbs_certificate.issuer).unwrap()
159    }
160
161    fn serial_number(&self) -> Vec<u8> {
162        let der = self.to_der();
163        let c = x509_cert::Certificate::from_der(&der).unwrap();
164        x509_cert::der::Encode::to_der(&c.tbs_certificate.serial_number).unwrap()
165    }
166
167    fn subject(&self) -> Vec<u8> {
168        let der = self.to_der();
169        let c = x509_cert::Certificate::from_der(&der).unwrap();
170        x509_cert::der::Encode::to_der(&c.tbs_certificate.subject).unwrap()
171    }
172}
173
174impl<T: Certificate + ?Sized> CertificateExt for T {}
175
176#[derive(Debug)]
177pub enum KeySearchOptions {
178    //  TODO(kcking): search keys by _both_ id and label as that is how they are
179    // de-duped and referenced.
180    Id(Vec<u8>),
181    Label(String),
182}
183
184#[derive(Debug, Clone, Copy, PartialEq, Eq)]
185pub enum KeyAlgorithm {
186    Rsa,
187    Ecc,
188}
189
190pub trait Backend: Send + Sync {
191    fn name(&self) -> String;
192    fn find_all_certificates(&self) -> Result<Vec<Box<dyn Certificate>>>;
193    fn find_private_key(&self, query: KeySearchOptions) -> Result<Option<Arc<dyn PrivateKey>>>;
194    fn find_public_key(&self, query: KeySearchOptions) -> Result<Option<Box<dyn PublicKey>>>;
195    fn find_all_private_keys(&self) -> Result<Vec<Arc<dyn PrivateKey>>>;
196    fn find_all_public_keys(&self) -> Result<Vec<Arc<dyn PublicKey>>>;
197    fn generate_key(
198        &self,
199        algorithm: KeyAlgorithm,
200        label: Option<&str>,
201    ) -> Result<Arc<dyn PrivateKey>>;
202}
203
204pub fn random_label() -> String {
205    use rand::{Rng, distr::Alphanumeric};
206    String::from("bumpkey ")
207        + &rand::rng().sample_iter(&Alphanumeric).take(32).map(char::from).collect::<String>()
208}