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