1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
// Copyright 2021 Contributors to the Parsec project.
// SPDX-License-Identifier: Apache-2.0
//! Session management functions
use crate::context::Function;
use crate::error::{Error, Result, Rv, RvError};
use crate::session::{CloseOnDrop, Session, SessionInfo, UserType};
use crate::types::{AuthPin, RawAuthPin};
#[cfg(doc)]
use cryptoki_sys::CKF_PROTECTED_AUTHENTICATION_PATH;
use cryptoki_sys::CK_SESSION_INFO;
use log::error;
use secrecy::ExposeSecret;
use std::convert::{TryFrom, TryInto};
impl Drop for Session {
fn drop(&mut self) {
if self.close_on_drop == CloseOnDrop::DoNotClose || self.closed.get() {
return;
}
match self.close_inner() {
Err(Error::Pkcs11(RvError::SessionClosed, Function::CloseSession)) => (), // the session has already been closed: ignore.
Ok(()) => (),
Err(err) => {
error!("Failed to close session: {err}");
}
}
}
}
impl Session {
/// Log a session in.
///
/// # Arguments
///
/// * `user_type` - The type of user to log in as
/// * `pin` - The PIN to use, or `None` if you wish to use the protected authentication path
///
/// _NOTE: By passing `None` into `login`, you must ensure that the
/// [CKF_PROTECTED_AUTHENTICATION_PATH] flag is set in the `TokenFlags`._
pub fn login(&self, user_type: UserType, pin: Option<&AuthPin>) -> Result<()> {
let (pin, pin_len) = match pin {
Some(pin) => (
pin.expose_secret().as_ptr() as *mut u8,
pin.expose_secret().len(),
),
None => (std::ptr::null_mut(), 0),
};
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Login)(
self.handle(),
user_type.into(),
pin,
pin_len.try_into()?,
))
.into_result(Function::Login)
}
}
/// Logs a session in using a slice of raw bytes as a PIN. Some dongle drivers allow
/// non UTF-8 characters in the PIN and, as a result, we aren't guaranteed that we can
/// pass in a UTF-8 string to `login`. Therefore, it's useful to be able to pass in raw bytes
/// rather than convert a UTF-8 string to bytes.
///
/// # Arguments
///
/// * `user_type` - The type of user to log in as
/// * `pin` - The PIN to use
///
/// _NOTE: By passing `None` into `login`, you must ensure that the
/// [CKF_PROTECTED_AUTHENTICATION_PATH] flag is set in the `TokenFlags`._
pub fn login_with_raw(&self, user_type: UserType, pin: &RawAuthPin) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Login)(
self.handle(),
user_type.into(),
pin.expose_secret().as_ptr() as *mut u8,
pin.expose_secret().len().try_into()?,
))
.into_result(Function::Login)
}
}
/// Log a session out
pub fn logout(&self) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_Logout)(self.handle()))
.into_result(Function::Logout)
}
}
/// Returns the information about a session
pub fn get_session_info(&self) -> Result<SessionInfo> {
let mut session_info = CK_SESSION_INFO::default();
unsafe {
Rv::from(get_pkcs11!(self.client(), C_GetSessionInfo)(
self.handle(),
&mut session_info,
))
.into_result(Function::GetSessionInfo)?;
SessionInfo::try_from(session_info)
}
}
// Helper function to be able to close a session only taking a reference.
// This is used in the Drop trait function which only takes a reference as input.
pub(super) fn close_inner(&self) -> Result<()> {
unsafe {
Rv::from(get_pkcs11!(self.client(), C_CloseSession)(self.handle()))
.into_result(Function::CloseSession)?;
}
self.closed.set(true);
Ok(())
}
}