use crate::{
audit::AuditOption,
connector, object,
session::{
self,
securechannel::{Challenge, SecureChannel},
},
};
use std::collections::BTreeMap;
use super::{audit::CommandAuditOptions, object::Objects, session::HsmSession};
#[derive(Debug)]
pub(crate) struct State {
pub(super) command_audit_options: CommandAuditOptions,
pub(super) force_audit: AuditOption,
sessions: BTreeMap<session::Id, HsmSession>,
pub(super) objects: Objects,
}
impl State {
pub fn new() -> Self {
Self {
command_audit_options: CommandAuditOptions::default(),
force_audit: AuditOption::Off,
sessions: BTreeMap::new(),
objects: Objects::default(),
}
}
pub fn create_session(
&mut self,
authentication_key_id: object::Id,
host_challenge: Challenge,
) -> &HsmSession {
let card_challenge = Challenge::new();
let session_id = self
.sessions
.keys()
.max()
.map(|id| id.succ().expect("session count exceeded"))
.unwrap_or_else(|| session::Id::from_u8(0).unwrap());
let channel = {
let authentication_key_obj = self
.objects
.get(authentication_key_id, object::Type::AuthenticationKey)
.unwrap_or_else(|| {
panic!(
"MockHsm has no authentication::Key in slot {:?}",
authentication_key_id
)
});
SecureChannel::new(
session_id,
authentication_key_obj
.payload
.authentication_key()
.expect("auth key payload"),
host_challenge,
card_challenge,
)
};
let session = HsmSession::new(session_id, card_challenge, channel);
assert!(self.sessions.insert(session_id, session).is_none());
self.get_session(session_id).unwrap()
}
pub fn get_session(&mut self, id: session::Id) -> Result<&mut HsmSession, connector::Error> {
self.sessions.get_mut(&id).ok_or_else(|| {
connector::Error::new(
connector::ErrorKind::RequestError,
Some(format!("invalid session ID: {:?}", id)),
)
})
}
pub fn close_session(&mut self, id: session::Id) {
assert!(self.sessions.remove(&id).is_some());
}
pub fn reset(&mut self) {
self.command_audit_options = CommandAuditOptions::default();
self.sessions = BTreeMap::new();
self.objects = Objects::default();
}
}