Bug 1940967 - Vendor glean_parser v16.2.0 r=TravisLong,mach-reviewers,ahal
[gecko.git] / security / manager / ssl / rsclientcerts / src / manager.rs
blob507bed3a830821ebdd6211dbe06749bfef59033f
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 std::collections::{BTreeMap, BTreeSet};
8 use std::sync::mpsc::{channel, Receiver, Sender};
9 use std::thread;
10 use std::thread::JoinHandle;
11 use std::time::{Duration, Instant};
13 use crate::error::{Error, ErrorType};
14 use crate::error_here;
15 use crate::util::*;
17 /// Helper enum to differentiate between sessions on the modern slot and sessions on the legacy
18 /// slot. The former is for EC keys and RSA keys that can be used with RSA-PSS whereas the latter is
19 /// for RSA keys that cannot be used with RSA-PSS.
20 #[derive(Clone, Copy, PartialEq)]
21 pub enum SlotType {
22     Modern,
23     Legacy,
26 pub trait CryptokiObject {
27     fn matches(&self, slot_type: SlotType, attrs: &[(CK_ATTRIBUTE_TYPE, Vec<u8>)]) -> bool;
28     fn get_attribute(&self, attribute: CK_ATTRIBUTE_TYPE) -> Option<&[u8]>;
31 pub trait Sign {
32     fn get_signature_length(
33         &mut self,
34         data: &[u8],
35         params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
36     ) -> Result<usize, Error>;
37     fn sign(
38         &mut self,
39         data: &[u8],
40         params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
41     ) -> Result<Vec<u8>, Error>;
44 pub trait ClientCertsBackend {
45     type Cert: CryptokiObject;
46     type Key: CryptokiObject + Sign;
48     #[allow(clippy::type_complexity)]
49     fn find_objects(&self) -> Result<(Vec<Self::Cert>, Vec<Self::Key>), Error>;
52 /// Helper type for sending `ManagerArguments` to the real `Manager`.
53 type ManagerArgumentsSender = Sender<ManagerArguments>;
54 /// Helper type for receiving `ManagerReturnValue`s from the real `Manager`.
55 type ManagerReturnValueReceiver = Receiver<ManagerReturnValue>;
57 /// Helper enum that encapsulates arguments to send from the `ManagerProxy` to the real `Manager`.
58 /// `ManagerArguments::Stop` is a special variant that stops the background thread and drops the
59 /// `Manager`.
60 enum ManagerArguments {
61     OpenSession(SlotType),
62     CloseSession(CK_SESSION_HANDLE),
63     CloseAllSessions(SlotType),
64     StartSearch(CK_SESSION_HANDLE, Vec<(CK_ATTRIBUTE_TYPE, Vec<u8>)>),
65     Search(CK_SESSION_HANDLE, usize),
66     ClearSearch(CK_SESSION_HANDLE),
67     GetAttributes(CK_OBJECT_HANDLE, Vec<CK_ATTRIBUTE_TYPE>),
68     StartSign(
69         CK_SESSION_HANDLE,
70         CK_OBJECT_HANDLE,
71         Option<CK_RSA_PKCS_PSS_PARAMS>,
72     ),
73     GetSignatureLength(CK_SESSION_HANDLE, Vec<u8>),
74     Sign(CK_SESSION_HANDLE, Vec<u8>),
75     Stop,
78 /// Helper enum that encapsulates return values from the real `Manager` that are sent back to the
79 /// `ManagerProxy`. `ManagerReturnValue::Stop` is a special variant that indicates that the
80 /// `Manager` will stop.
81 enum ManagerReturnValue {
82     OpenSession(Result<CK_SESSION_HANDLE, Error>),
83     CloseSession(Result<(), Error>),
84     CloseAllSessions(Result<(), Error>),
85     StartSearch(Result<(), Error>),
86     Search(Result<Vec<CK_OBJECT_HANDLE>, Error>),
87     ClearSearch(Result<(), Error>),
88     GetAttributes(Result<Vec<Option<Vec<u8>>>, Error>),
89     StartSign(Result<(), Error>),
90     GetSignatureLength(Result<usize, Error>),
91     Sign(Result<Vec<u8>, Error>),
92     Stop(Result<(), Error>),
95 /// Helper macro to implement the body of each public `ManagerProxy` function. Takes a
96 /// `ManagerProxy` instance (should always be `self`), a `ManagerArguments` representing the
97 /// `Manager` function to call and the arguments to use, and the qualified type of the expected
98 /// `ManagerReturnValue` that will be received from the `Manager` when it is done.
99 macro_rules! manager_proxy_fn_impl {
100     ($manager:ident, $argument_enum:expr, $return_type:path) => {
101         match $manager.proxy_call($argument_enum) {
102             Ok($return_type(result)) => result,
103             Ok(_) => Err(error_here!(ErrorType::LibraryFailure)),
104             Err(e) => Err(e),
105         }
106     };
109 /// `ManagerProxy` synchronously proxies calls from any thread to the `Manager` that runs on a
110 /// single thread. This is necessary because the underlying OS APIs in use are not guaranteed to be
111 /// thread-safe (e.g. they may use thread-local storage). Using it should be identical to using the
112 /// real `Manager`.
113 pub struct ManagerProxy {
114     sender: ManagerArgumentsSender,
115     receiver: ManagerReturnValueReceiver,
116     thread_handle: Option<JoinHandle<()>>,
119 impl ManagerProxy {
120     pub fn new<B: ClientCertsBackend + Send + 'static>(backend: B) -> Result<ManagerProxy, Error> {
121         let (proxy_sender, manager_receiver) = channel();
122         let (manager_sender, proxy_receiver) = channel();
123         let thread_handle = thread::Builder::new()
124             .name("osclientcert".into())
125             .spawn(move || {
126                 let mut real_manager = Manager::new(backend);
127                 while let Ok(arguments) = manager_receiver.recv() {
128                     let results = match arguments {
129                         ManagerArguments::OpenSession(slot_type) => {
130                             ManagerReturnValue::OpenSession(real_manager.open_session(slot_type))
131                         }
132                         ManagerArguments::CloseSession(session_handle) => {
133                             ManagerReturnValue::CloseSession(
134                                 real_manager.close_session(session_handle),
135                             )
136                         }
137                         ManagerArguments::CloseAllSessions(slot_type) => {
138                             ManagerReturnValue::CloseAllSessions(
139                                 real_manager.close_all_sessions(slot_type),
140                             )
141                         }
142                         ManagerArguments::StartSearch(session, attrs) => {
143                             ManagerReturnValue::StartSearch(
144                                 real_manager.start_search(session, attrs),
145                             )
146                         }
147                         ManagerArguments::Search(session, max_objects) => {
148                             ManagerReturnValue::Search(real_manager.search(session, max_objects))
149                         }
150                         ManagerArguments::ClearSearch(session) => {
151                             ManagerReturnValue::ClearSearch(real_manager.clear_search(session))
152                         }
153                         ManagerArguments::GetAttributes(object_handle, attr_types) => {
154                             ManagerReturnValue::GetAttributes(
155                                 real_manager.get_attributes(object_handle, attr_types),
156                             )
157                         }
158                         ManagerArguments::StartSign(session, key_handle, params) => {
159                             ManagerReturnValue::StartSign(
160                                 real_manager.start_sign(session, key_handle, params),
161                             )
162                         }
163                         ManagerArguments::GetSignatureLength(session, data) => {
164                             ManagerReturnValue::GetSignatureLength(
165                                 real_manager.get_signature_length(session, data),
166                             )
167                         }
168                         ManagerArguments::Sign(session, data) => {
169                             ManagerReturnValue::Sign(real_manager.sign(session, data))
170                         }
171                         ManagerArguments::Stop => ManagerReturnValue::Stop(Ok(())),
172                     };
173                     let stop_after_send = matches!(&results, &ManagerReturnValue::Stop(_));
174                     match manager_sender.send(results) {
175                         Ok(()) => {}
176                         Err(_) => {
177                             break;
178                         }
179                     }
180                     if stop_after_send {
181                         break;
182                     }
183                 }
184             });
185         match thread_handle {
186             Ok(thread_handle) => Ok(ManagerProxy {
187                 sender: proxy_sender,
188                 receiver: proxy_receiver,
189                 thread_handle: Some(thread_handle),
190             }),
191             Err(_) => Err(error_here!(ErrorType::LibraryFailure)),
192         }
193     }
195     fn proxy_call(&self, args: ManagerArguments) -> Result<ManagerReturnValue, Error> {
196         match self.sender.send(args) {
197             Ok(()) => {}
198             Err(_) => {
199                 return Err(error_here!(ErrorType::LibraryFailure));
200             }
201         };
202         let result = match self.receiver.recv() {
203             Ok(result) => result,
204             Err(_) => {
205                 return Err(error_here!(ErrorType::LibraryFailure));
206             }
207         };
208         Ok(result)
209     }
211     pub fn open_session(&mut self, slot_type: SlotType) -> Result<CK_SESSION_HANDLE, Error> {
212         manager_proxy_fn_impl!(
213             self,
214             ManagerArguments::OpenSession(slot_type),
215             ManagerReturnValue::OpenSession
216         )
217     }
219     pub fn close_session(&mut self, session: CK_SESSION_HANDLE) -> Result<(), Error> {
220         manager_proxy_fn_impl!(
221             self,
222             ManagerArguments::CloseSession(session),
223             ManagerReturnValue::CloseSession
224         )
225     }
227     pub fn close_all_sessions(&mut self, slot_type: SlotType) -> Result<(), Error> {
228         manager_proxy_fn_impl!(
229             self,
230             ManagerArguments::CloseAllSessions(slot_type),
231             ManagerReturnValue::CloseAllSessions
232         )
233     }
235     pub fn start_search(
236         &mut self,
237         session: CK_SESSION_HANDLE,
238         attrs: Vec<(CK_ATTRIBUTE_TYPE, Vec<u8>)>,
239     ) -> Result<(), Error> {
240         manager_proxy_fn_impl!(
241             self,
242             ManagerArguments::StartSearch(session, attrs),
243             ManagerReturnValue::StartSearch
244         )
245     }
247     pub fn search(
248         &mut self,
249         session: CK_SESSION_HANDLE,
250         max_objects: usize,
251     ) -> Result<Vec<CK_OBJECT_HANDLE>, Error> {
252         manager_proxy_fn_impl!(
253             self,
254             ManagerArguments::Search(session, max_objects),
255             ManagerReturnValue::Search
256         )
257     }
259     pub fn clear_search(&mut self, session: CK_SESSION_HANDLE) -> Result<(), Error> {
260         manager_proxy_fn_impl!(
261             self,
262             ManagerArguments::ClearSearch(session),
263             ManagerReturnValue::ClearSearch
264         )
265     }
267     pub fn get_attributes(
268         &self,
269         object_handle: CK_OBJECT_HANDLE,
270         attr_types: Vec<CK_ATTRIBUTE_TYPE>,
271     ) -> Result<Vec<Option<Vec<u8>>>, Error> {
272         manager_proxy_fn_impl!(
273             self,
274             ManagerArguments::GetAttributes(object_handle, attr_types,),
275             ManagerReturnValue::GetAttributes
276         )
277     }
279     pub fn start_sign(
280         &mut self,
281         session: CK_SESSION_HANDLE,
282         key_handle: CK_OBJECT_HANDLE,
283         params: Option<CK_RSA_PKCS_PSS_PARAMS>,
284     ) -> Result<(), Error> {
285         manager_proxy_fn_impl!(
286             self,
287             ManagerArguments::StartSign(session, key_handle, params),
288             ManagerReturnValue::StartSign
289         )
290     }
292     pub fn get_signature_length(
293         &self,
294         session: CK_SESSION_HANDLE,
295         data: Vec<u8>,
296     ) -> Result<usize, Error> {
297         manager_proxy_fn_impl!(
298             self,
299             ManagerArguments::GetSignatureLength(session, data),
300             ManagerReturnValue::GetSignatureLength
301         )
302     }
304     pub fn sign(&mut self, session: CK_SESSION_HANDLE, data: Vec<u8>) -> Result<Vec<u8>, Error> {
305         manager_proxy_fn_impl!(
306             self,
307             ManagerArguments::Sign(session, data),
308             ManagerReturnValue::Sign
309         )
310     }
312     pub fn stop(&mut self) -> Result<(), Error> {
313         manager_proxy_fn_impl!(self, ManagerArguments::Stop, ManagerReturnValue::Stop)?;
314         let thread_handle = match self.thread_handle.take() {
315             Some(thread_handle) => thread_handle,
316             None => return Err(error_here!(ErrorType::LibraryFailure)),
317         };
318         thread_handle
319             .join()
320             .map_err(|_| error_here!(ErrorType::LibraryFailure))
321     }
324 // Determines if the attributes of a given search correspond to NSS looking for all certificates or
325 // private keys. Returns true if so, and false otherwise.
326 // These searches are of the form:
327 //   { { type: CKA_TOKEN, value: [1] },
328 //     { type: CKA_CLASS, value: [CKO_CERTIFICATE or CKO_PRIVATE_KEY, as serialized bytes] } }
329 // (although not necessarily in that order - see nssToken_TraverseCertificates and
330 // nssToken_FindPrivateKeys)
331 fn search_is_for_all_certificates_or_keys(
332     attrs: &[(CK_ATTRIBUTE_TYPE, Vec<u8>)],
333 ) -> Result<bool, Error> {
334     if attrs.len() != 2 {
335         return Ok(false);
336     }
337     let token_bytes = vec![1_u8];
338     let mut found_token = false;
339     let cko_certificate_bytes = serialize_uint(CKO_CERTIFICATE)?;
340     let cko_private_key_bytes = serialize_uint(CKO_PRIVATE_KEY)?;
341     let mut found_certificate_or_private_key = false;
342     for (attr_type, attr_value) in attrs.iter() {
343         if attr_type == &CKA_TOKEN && attr_value == &token_bytes {
344             found_token = true;
345         }
346         if attr_type == &CKA_CLASS
347             && (attr_value == &cko_certificate_bytes || attr_value == &cko_private_key_bytes)
348         {
349             found_certificate_or_private_key = true;
350         }
351     }
352     Ok(found_token && found_certificate_or_private_key)
355 const SUPPORTED_ATTRIBUTES: &[CK_ATTRIBUTE_TYPE] = &[
356     CKA_CLASS,
357     CKA_TOKEN,
358     CKA_LABEL,
359     CKA_ID,
360     CKA_VALUE,
361     CKA_ISSUER,
362     CKA_SERIAL_NUMBER,
363     CKA_SUBJECT,
364     CKA_PRIVATE,
365     CKA_KEY_TYPE,
366     CKA_MODULUS,
367     CKA_EC_PARAMS,
370 enum Object<B: ClientCertsBackend> {
371     Cert(B::Cert),
372     Key(B::Key),
375 impl<B: ClientCertsBackend> Object<B> {
376     fn matches(&self, slot_type: SlotType, attrs: &[(CK_ATTRIBUTE_TYPE, Vec<u8>)]) -> bool {
377         match self {
378             Object::Cert(cert) => cert.matches(slot_type, attrs),
379             Object::Key(key) => key.matches(slot_type, attrs),
380         }
381     }
383     fn get_attribute(&self, attribute: CK_ATTRIBUTE_TYPE) -> Option<&[u8]> {
384         match self {
385             Object::Cert(cert) => cert.get_attribute(attribute),
386             Object::Key(key) => key.get_attribute(attribute),
387         }
388     }
390     fn id(&self) -> Result<&[u8], Error> {
391         self.get_attribute(CKA_ID)
392             .ok_or_else(|| error_here!(ErrorType::LibraryFailure))
393     }
395     fn get_signature_length(
396         &mut self,
397         data: Vec<u8>,
398         params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
399     ) -> Result<usize, Error> {
400         match self {
401             Object::Cert(_) => Err(error_here!(ErrorType::InvalidArgument)),
402             Object::Key(key) => key.get_signature_length(&data, params),
403         }
404     }
406     fn sign(
407         &mut self,
408         data: Vec<u8>,
409         params: &Option<CK_RSA_PKCS_PSS_PARAMS>,
410     ) -> Result<Vec<u8>, Error> {
411         match self {
412             Object::Cert(_) => Err(error_here!(ErrorType::InvalidArgument)),
413             Object::Key(key) => key.sign(&data, params),
414         }
415     }
418 /// The `Manager` keeps track of the state of this module with respect to the PKCS #11
419 /// specification. This includes what sessions are open, which search and sign operations are
420 /// ongoing, and what objects are known and by what handle.
421 pub struct Manager<B: ClientCertsBackend> {
422     /// A map of session to session type (modern or legacy). Sessions can be created (opened) and
423     /// later closed.
424     sessions: BTreeMap<CK_SESSION_HANDLE, SlotType>,
425     /// A map of searches to PKCS #11 object handles that match those searches.
426     searches: BTreeMap<CK_SESSION_HANDLE, Vec<CK_OBJECT_HANDLE>>,
427     /// A map of sign operations to a pair of the object handle and optionally some params being
428     /// used by each one.
429     signs: BTreeMap<CK_SESSION_HANDLE, (CK_OBJECT_HANDLE, Option<CK_RSA_PKCS_PSS_PARAMS>)>,
430     /// A map of object handles to the underlying objects.
431     objects: BTreeMap<CK_OBJECT_HANDLE, Object<B>>,
432     /// A set of certificate identifiers (not the same as handles).
433     cert_ids: BTreeSet<Vec<u8>>,
434     /// A set of key identifiers (not the same as handles). For each id in this set, there should be
435     /// a corresponding identical id in the `cert_ids` set.
436     key_ids: BTreeSet<Vec<u8>>,
437     /// The next session handle to hand out.
438     next_session: CK_SESSION_HANDLE,
439     /// The next object handle to hand out.
440     next_handle: CK_OBJECT_HANDLE,
441     /// The last time the implementation looked for new objects in the backend.
442     /// The implementation does this search no more than once every 3 seconds.
443     last_scan_time: Option<Instant>,
444     backend: B,
447 impl<B: ClientCertsBackend> Manager<B> {
448     pub fn new(backend: B) -> Manager<B> {
449         Manager {
450             sessions: BTreeMap::new(),
451             searches: BTreeMap::new(),
452             signs: BTreeMap::new(),
453             objects: BTreeMap::new(),
454             cert_ids: BTreeSet::new(),
455             key_ids: BTreeSet::new(),
456             next_session: 1,
457             next_handle: 1,
458             last_scan_time: None,
459             backend,
460         }
461     }
463     /// When a new search session is opened (provided at least 3 seconds have elapsed since the
464     /// last session was opened), this searches for certificates and keys to expose. We
465     /// de-duplicate previously-found certificates and keys by keeping track of their IDs.
466     fn maybe_find_new_objects(&mut self) -> Result<(), Error> {
467         let now = Instant::now();
468         match self.last_scan_time {
469             Some(last_scan_time) => {
470                 if now.duration_since(last_scan_time) < Duration::new(3, 0) {
471                     return Ok(());
472                 }
473             }
474             None => {}
475         }
476         self.last_scan_time = Some(now);
477         let (certs, keys) = self.backend.find_objects()?;
478         for cert in certs {
479             let object = Object::Cert(cert);
480             if self.cert_ids.contains(object.id()?) {
481                 continue;
482             }
483             self.cert_ids.insert(object.id()?.to_vec());
484             let handle = self.get_next_handle();
485             self.objects.insert(handle, object);
486         }
487         for key in keys {
488             let object = Object::Key(key);
489             if self.key_ids.contains(object.id()?) {
490                 continue;
491             }
492             self.key_ids.insert(object.id()?.to_vec());
493             let handle = self.get_next_handle();
494             self.objects.insert(handle, object);
495         }
496         Ok(())
497     }
499     pub fn open_session(&mut self, slot_type: SlotType) -> Result<CK_SESSION_HANDLE, Error> {
500         let next_session = self.next_session;
501         self.next_session += 1;
502         self.sessions.insert(next_session, slot_type);
503         Ok(next_session)
504     }
506     pub fn close_session(&mut self, session: CK_SESSION_HANDLE) -> Result<(), Error> {
507         self.sessions
508             .remove(&session)
509             .ok_or_else(|| error_here!(ErrorType::InvalidInput))
510             .map(|_| ())
511     }
513     pub fn close_all_sessions(&mut self, slot_type: SlotType) -> Result<(), Error> {
514         let mut to_remove = Vec::new();
515         for (session, open_slot_type) in self.sessions.iter() {
516             if slot_type == *open_slot_type {
517                 to_remove.push(*session);
518             }
519         }
520         for session in to_remove {
521             if self.sessions.remove(&session).is_none() {
522                 return Err(error_here!(ErrorType::LibraryFailure));
523             }
524         }
525         Ok(())
526     }
528     fn get_next_handle(&mut self) -> CK_OBJECT_HANDLE {
529         let next_handle = self.next_handle;
530         self.next_handle += 1;
531         next_handle
532     }
534     /// PKCS #11 specifies that search operations happen in three phases: setup, get any matches
535     /// (this part may be repeated if the caller uses a small buffer), and end. This implementation
536     /// does all of the work up front and gathers all matching objects during setup and retains them
537     /// until they are retrieved and consumed via `search`.
538     pub fn start_search(
539         &mut self,
540         session: CK_SESSION_HANDLE,
541         attrs: Vec<(CK_ATTRIBUTE_TYPE, Vec<u8>)>,
542     ) -> Result<(), Error> {
543         let slot_type = match self.sessions.get(&session) {
544             Some(slot_type) => *slot_type,
545             None => return Err(error_here!(ErrorType::InvalidArgument)),
546         };
547         // If the search is for an attribute we don't support, no objects will match. This check
548         // saves us having to look through all of our objects.
549         for (attr, _) in &attrs {
550             if !SUPPORTED_ATTRIBUTES.contains(attr) {
551                 self.searches.insert(session, Vec::new());
552                 return Ok(());
553             }
554         }
555         // When NSS wants to find all certificates or all private keys, it will perform a search
556         // with a particular set of attributes. This implementation uses these searches as an
557         // indication for the backend to re-scan for new objects from tokens that may have been
558         // inserted or certificates that may have been imported into the OS. Since these searches
559         // are relatively rare, this minimizes the impact of doing these re-scans.
560         if search_is_for_all_certificates_or_keys(&attrs)? {
561             self.maybe_find_new_objects()?;
562         }
563         let mut handles = Vec::new();
564         for (handle, object) in &self.objects {
565             if object.matches(slot_type, &attrs) {
566                 handles.push(*handle);
567             }
568         }
569         self.searches.insert(session, handles);
570         Ok(())
571     }
573     /// Given a session and a maximum number of object handles to return, attempts to retrieve up to
574     /// that many objects from the corresponding search. Updates the search so those objects are not
575     /// returned repeatedly. `max_objects` must be non-zero.
576     pub fn search(
577         &mut self,
578         session: CK_SESSION_HANDLE,
579         max_objects: usize,
580     ) -> Result<Vec<CK_OBJECT_HANDLE>, Error> {
581         if max_objects == 0 {
582             return Err(error_here!(ErrorType::InvalidArgument));
583         }
584         match self.searches.get_mut(&session) {
585             Some(search) => {
586                 let split_at = if max_objects >= search.len() {
587                     0
588                 } else {
589                     search.len() - max_objects
590                 };
591                 let to_return = search.split_off(split_at);
592                 if to_return.len() > max_objects {
593                     return Err(error_here!(ErrorType::LibraryFailure));
594                 }
595                 Ok(to_return)
596             }
597             None => Err(error_here!(ErrorType::InvalidArgument)),
598         }
599     }
601     pub fn clear_search(&mut self, session: CK_SESSION_HANDLE) -> Result<(), Error> {
602         self.searches.remove(&session);
603         Ok(())
604     }
606     pub fn get_attributes(
607         &self,
608         object_handle: CK_OBJECT_HANDLE,
609         attr_types: Vec<CK_ATTRIBUTE_TYPE>,
610     ) -> Result<Vec<Option<Vec<u8>>>, Error> {
611         let object = match self.objects.get(&object_handle) {
612             Some(object) => object,
613             None => return Err(error_here!(ErrorType::InvalidArgument)),
614         };
615         let mut results = Vec::with_capacity(attr_types.len());
616         for attr_type in attr_types {
617             let result = object
618                 .get_attribute(attr_type)
619                 .map(|value| value.to_owned());
620             results.push(result);
621         }
622         Ok(results)
623     }
625     /// The way NSS uses PKCS #11 to sign data happens in two phases: setup and sign. This
626     /// implementation makes a note of which key is to be used (if it exists) during setup. When the
627     /// caller finishes with the sign operation, this implementation retrieves the key handle and
628     /// performs the signature.
629     pub fn start_sign(
630         &mut self,
631         session: CK_SESSION_HANDLE,
632         key_handle: CK_OBJECT_HANDLE,
633         params: Option<CK_RSA_PKCS_PSS_PARAMS>,
634     ) -> Result<(), Error> {
635         if self.signs.contains_key(&session) {
636             return Err(error_here!(ErrorType::InvalidArgument));
637         }
638         self.signs.insert(session, (key_handle, params));
639         Ok(())
640     }
642     pub fn get_signature_length(
643         &mut self,
644         session: CK_SESSION_HANDLE,
645         data: Vec<u8>,
646     ) -> Result<usize, Error> {
647         let (key_handle, params) = match self.signs.get(&session) {
648             Some((key_handle, params)) => (key_handle, params),
649             None => return Err(error_here!(ErrorType::InvalidArgument)),
650         };
651         let key = match self.objects.get_mut(key_handle) {
652             Some(key) => key,
653             None => return Err(error_here!(ErrorType::InvalidArgument)),
654         };
655         key.get_signature_length(data, params)
656     }
658     pub fn sign(&mut self, session: CK_SESSION_HANDLE, data: Vec<u8>) -> Result<Vec<u8>, Error> {
659         // Performing the signature (via C_Sign, which is the only way we support) finishes the sign
660         // operation, so it needs to be removed here.
661         let (key_handle, params) = match self.signs.remove(&session) {
662             Some((key_handle, params)) => (key_handle, params),
663             None => return Err(error_here!(ErrorType::InvalidArgument)),
664         };
665         let key = match self.objects.get_mut(&key_handle) {
666             Some(key) => key,
667             None => return Err(error_here!(ErrorType::InvalidArgument)),
668         };
669         key.sign(data, &params)
670     }