no bug - Import translations from android-l10n r=release a=l10n CLOSED TREE
[gecko.git] / security / manager / ssl / ipcclientcerts / src / backend.rs
blob44048d31160b8bdfac36541bd3544000fbd0fead
1 /* -*- Mode: rust; rust-indent-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 use pkcs11_bindings::*;
7 use rsclientcerts::error::{Error, ErrorType};
8 use rsclientcerts::manager::{ClientCertsBackend, CryptokiObject, Sign, SlotType};
9 use rsclientcerts::util::*;
10 use sha2::{Digest, Sha256};
11 use std::ffi::c_void;
13 use crate::FindObjectsFunction;
14 use crate::SignFunction;
16 pub struct Cert {
17     class: Vec<u8>,
18     token: Vec<u8>,
19     id: Vec<u8>,
20     label: Vec<u8>,
21     value: Vec<u8>,
22     issuer: Vec<u8>,
23     serial_number: Vec<u8>,
24     subject: Vec<u8>,
25     slot_type: SlotType,
28 impl Cert {
29     fn new(der: &[u8], slot_type: SlotType) -> Result<Cert, Error> {
30         let (serial_number, issuer, subject) = read_encoded_certificate_identifiers(der)?;
31         let id = Sha256::digest(der).to_vec();
32         Ok(Cert {
33             class: serialize_uint(CKO_CERTIFICATE)?,
34             token: serialize_uint(CK_TRUE)?,
35             id,
36             label: b"IPC certificate".to_vec(),
37             value: der.to_vec(),
38             issuer,
39             serial_number,
40             subject,
41             slot_type,
42         })
43     }
45     fn class(&self) -> &[u8] {
46         &self.class
47     }
49     fn token(&self) -> &[u8] {
50         &self.token
51     }
53     fn id(&self) -> &[u8] {
54         &self.id
55     }
57     fn label(&self) -> &[u8] {
58         &self.label
59     }
61     fn value(&self) -> &[u8] {
62         &self.value
63     }
65     fn issuer(&self) -> &[u8] {
66         &self.issuer
67     }
69     fn serial_number(&self) -> &[u8] {
70         &self.serial_number
71     }
73     fn subject(&self) -> &[u8] {
74         &self.subject
75     }
78 impl CryptokiObject for Cert {
79     fn matches(&self, slot_type: SlotType, attrs: &[(CK_ATTRIBUTE_TYPE, Vec<u8>)]) -> bool {
80         if self.slot_type != slot_type {
81             return false;
82         }
83         for (attr_type, attr_value) in attrs {
84             let comparison = match *attr_type {
85                 CKA_CLASS => self.class(),
86                 CKA_TOKEN => self.token(),
87                 CKA_LABEL => self.label(),
88                 CKA_ID => self.id(),
89                 CKA_VALUE => self.value(),
90                 CKA_ISSUER => self.issuer(),
91                 CKA_SERIAL_NUMBER => self.serial_number(),
92                 CKA_SUBJECT => self.subject(),
93                 _ => return false,
94             };
95             if attr_value.as_slice() != comparison {
96                 return false;
97             }
98         }
99         true
100     }
102     fn get_attribute(&self, attribute: CK_ATTRIBUTE_TYPE) -> Option<&[u8]> {
103         let result = match attribute {
104             CKA_CLASS => self.class(),
105             CKA_TOKEN => self.token(),
106             CKA_LABEL => self.label(),
107             CKA_ID => self.id(),
108             CKA_VALUE => self.value(),
109             CKA_ISSUER => self.issuer(),
110             CKA_SERIAL_NUMBER => self.serial_number(),
111             CKA_SUBJECT => self.subject(),
112             _ => return None,
113         };
114         Some(result)
115     }
118 pub struct Key {
119     cert: Vec<u8>,
120     class: Vec<u8>,
121     token: Vec<u8>,
122     id: Vec<u8>,
123     private: Vec<u8>,
124     key_type: Vec<u8>,
125     modulus: Option<Vec<u8>>,
126     ec_params: Option<Vec<u8>>,
127     slot_type: SlotType,
128     sign: SignFunction,
131 impl Key {
132     fn new(
133         modulus: Option<&[u8]>,
134         ec_params: Option<&[u8]>,
135         cert: &[u8],
136         slot_type: SlotType,
137         sign: SignFunction,
138     ) -> Result<Key, Error> {
139         let id = Sha256::digest(cert).to_vec();
140         let key_type = if modulus.is_some() { CKK_RSA } else { CKK_EC };
141         Ok(Key {
142             cert: cert.to_vec(),
143             class: serialize_uint(CKO_PRIVATE_KEY)?,
144             token: serialize_uint(CK_TRUE)?,
145             id,
146             private: serialize_uint(CK_TRUE)?,
147             key_type: serialize_uint(key_type)?,
148             modulus: modulus.map(|b| b.to_vec()),
149             ec_params: ec_params.map(|b| b.to_vec()),
150             slot_type,
151             sign,
152         })
153     }
155     fn class(&self) -> &[u8] {
156         &self.class
157     }
159     fn token(&self) -> &[u8] {
160         &self.token
161     }
163     pub fn id(&self) -> &[u8] {
164         &self.id
165     }
167     fn private(&self) -> &[u8] {
168         &self.private
169     }
171     fn key_type(&self) -> &[u8] {
172         &self.key_type
173     }
175     fn modulus(&self) -> Option<&[u8]> {
176         match &self.modulus {
177             Some(modulus) => Some(modulus.as_slice()),
178             None => None,
179         }
180     }
182     fn ec_params(&self) -> Option<&[u8]> {
183         match &self.ec_params {
184             Some(ec_params) => Some(ec_params.as_slice()),
185             None => None,
186         }
187     }
190 impl CryptokiObject for Key {
191     fn matches(&self, slot_type: SlotType, attrs: &[(CK_ATTRIBUTE_TYPE, Vec<u8>)]) -> bool {
192         if self.slot_type != slot_type {
193             return false;
194         }
195         for (attr_type, attr_value) in attrs {
196             let comparison = match *attr_type {
197                 CKA_CLASS => self.class(),
198                 CKA_TOKEN => self.token(),
199                 CKA_ID => self.id(),
200                 CKA_PRIVATE => self.private(),
201                 CKA_KEY_TYPE => self.key_type(),
202                 CKA_MODULUS => {
203                     if let Some(modulus) = self.modulus() {
204                         modulus
205                     } else {
206                         return false;
207                     }
208                 }
209                 CKA_EC_PARAMS => {
210                     if let Some(ec_params) = self.ec_params() {
211                         ec_params
212                     } else {
213                         return false;
214                     }
215                 }
216                 _ => return false,
217             };
218             if attr_value.as_slice() != comparison {
219                 return false;
220             }
221         }
222         true
223     }
225     fn get_attribute(&self, attribute: CK_ATTRIBUTE_TYPE) -> Option<&[u8]> {
226         match attribute {
227             CKA_CLASS => Some(self.class()),
228             CKA_TOKEN => Some(self.token()),
229             CKA_ID => Some(self.id()),
230             CKA_PRIVATE => Some(self.private()),
231             CKA_KEY_TYPE => Some(self.key_type()),
232             CKA_MODULUS => self.modulus(),
233             CKA_EC_PARAMS => self.ec_params(),
234             _ => None,
235         }
236     }
239 impl Sign for Key {
240     fn get_signature_length(
241         &mut self,
242         data: &[u8],
243         params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
244     ) -> Result<usize, Error> {
245         // Unfortunately we don't have a way of getting the length of a signature without creating
246         // one.
247         let dummy_signature_bytes = self.sign(data, params)?;
248         Ok(dummy_signature_bytes.len())
249     }
251     fn sign(
252         &mut self,
253         data: &[u8],
254         params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
255     ) -> Result<Vec<u8>, Error> {
256         let mut signature = Vec::new();
257         let (params_len, params) = match params {
258             Some(params) => (
259                 std::mem::size_of::<CK_RSA_PKCS_PSS_PARAMS>(),
260                 params as *const _ as *const u8,
261             ),
262             None => (0, std::ptr::null()),
263         };
264         (self.sign)(
265             self.cert.len(),
266             self.cert.as_ptr(),
267             data.len(),
268             data.as_ptr(),
269             params_len,
270             params,
271             Some(sign_callback),
272             &mut signature as *mut _ as *mut c_void,
273         );
274         if signature.len() > 0 {
275             Ok(signature)
276         } else {
277             Err(error_here!(ErrorType::LibraryFailure))
278         }
279     }
282 unsafe extern "C" fn sign_callback(data_len: usize, data: *const u8, ctx: *mut c_void) {
283     let signature: &mut Vec<u8> = std::mem::transmute(ctx);
284     signature.clear();
285     if data_len != 0 {
286         signature.extend_from_slice(std::slice::from_raw_parts(data, data_len));
287     }
290 unsafe extern "C" fn find_objects_callback(
291     typ: u8,
292     data_len: usize,
293     data: *const u8,
294     extra_len: usize,
295     extra: *const u8,
296     slot_type: u32,
297     ctx: *mut c_void,
298 ) {
299     let data = if data_len == 0 {
300         &[]
301     } else {
302         std::slice::from_raw_parts(data, data_len)
303     };
304     let extra = if extra_len == 0 {
305         &[]
306     } else {
307         std::slice::from_raw_parts(extra, extra_len)
308     };
309     let slot_type = match slot_type {
310         1 => SlotType::Modern,
311         2 => SlotType::Legacy,
312         _ => return,
313     };
314     let find_objects_context: &mut FindObjectsContext = std::mem::transmute(ctx);
315     match typ {
316         1 => match Cert::new(data, slot_type) {
317             Ok(cert) => find_objects_context.certs.push(cert),
318             Err(_) => {}
319         },
320         2 => match Key::new(
321             Some(data),
322             None,
323             extra,
324             slot_type,
325             find_objects_context.sign,
326         ) {
327             Ok(key) => find_objects_context.keys.push(key),
328             Err(_) => {}
329         },
330         3 => match Key::new(
331             None,
332             Some(data),
333             extra,
334             slot_type,
335             find_objects_context.sign,
336         ) {
337             Ok(key) => find_objects_context.keys.push(key),
338             Err(_) => {}
339         },
340         _ => {}
341     }
344 struct FindObjectsContext {
345     certs: Vec<Cert>,
346     keys: Vec<Key>,
347     sign: SignFunction,
350 impl FindObjectsContext {
351     fn new(sign: SignFunction) -> FindObjectsContext {
352         FindObjectsContext {
353             certs: Vec::new(),
354             keys: Vec::new(),
355             sign,
356         }
357     }
360 pub struct Backend {
361     find_objects: FindObjectsFunction,
362     sign: SignFunction,
365 impl Backend {
366     pub fn new(find_objects: FindObjectsFunction, sign: SignFunction) -> Backend {
367         Backend { find_objects, sign }
368     }
371 impl ClientCertsBackend for Backend {
372     type Cert = Cert;
373     type Key = Key;
375     fn find_objects(&self) -> Result<(Vec<Cert>, Vec<Key>), Error> {
376         let mut find_objects_context = FindObjectsContext::new(self.sign);
377         (self.find_objects)(
378             Some(find_objects_callback),
379             &mut find_objects_context as *mut _ as *mut c_void,
380         );
381         Ok((find_objects_context.certs, find_objects_context.keys))
382     }