use super::{Command, Response};
use securechannel::{Challenge, CommandMessage, Cryptogram, ResponseMessage};
use serialization::deserialize;
use session::{SessionError, SessionErrorKind::*};
use {Adapter, CommandType, ObjectId, SessionId};
pub(crate) fn create_session<A: Adapter>(
adapter: &A,
auth_key_id: ObjectId,
host_challenge: Challenge,
) -> Result<(SessionId, CreateSessionResponse), SessionError> {
let command_message: CommandMessage = CreateSessionCommand {
auth_key_id,
host_challenge,
}.into();
let uuid = command_message.uuid;
let response_body = adapter.send_message(uuid, command_message.into())?;
let response_message = ResponseMessage::parse(response_body)?;
if response_message.is_err() {
fail!(ResponseError, "HSM error: {:?}", response_message.code);
}
if response_message.command().unwrap() != CommandType::CreateSession {
fail!(
ProtocolError,
"command type mismatch: expected {:?}, got {:?}",
CommandType::CreateSession,
response_message.command().unwrap()
);
}
let session_id = response_message
.session_id
.ok_or_else(|| err!(CreateFailed, "no session ID in response"))?;
let session_response = deserialize(response_message.data.as_ref())?;
Ok((session_id, session_response))
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct CreateSessionCommand {
pub auth_key_id: ObjectId,
pub host_challenge: Challenge,
}
impl Command for CreateSessionCommand {
type ResponseType = CreateSessionResponse;
}
#[derive(Serialize, Deserialize, Debug)]
pub(crate) struct CreateSessionResponse {
pub card_challenge: Challenge,
pub card_cryptogram: Cryptogram,
}
impl Response for CreateSessionResponse {
const COMMAND_TYPE: CommandType = CommandType::CreateSession;
}