From 016d1c6ec2e00c834e8693ad43cae07b00f26415 Mon Sep 17 00:00:00 2001 From: Arthur Gautier Date: Tue, 15 Aug 2023 23:16:00 +0000 Subject: [PATCH] Adds support for FIPS option (#460) --- src/audit.rs | 9 +++++++-- src/audit/commands.rs | 1 + src/client.rs | 35 +++++++++++++++++++++++++++++++++++ src/mockhsm/command.rs | 5 +++++ src/mockhsm/state.rs | 4 ++++ 5 files changed, 52 insertions(+), 2 deletions(-) diff --git a/src/audit.rs b/src/audit.rs index 048ac0a4..7e1dd41b 100644 --- a/src/audit.rs +++ b/src/audit.rs @@ -3,7 +3,10 @@ pub(crate) mod commands; mod error; -pub use self::error::{Error, ErrorKind}; +pub use self::{ + commands::{LogDigest, LogEntries, LogEntry}, + error::{Error, ErrorKind}, +}; use crate::command; use serde::{de, ser, Deserialize, Serialize}; @@ -97,6 +100,7 @@ impl<'de> Deserialize<'de> for AuditOption { pub(crate) enum AuditTag { Force = 0x01, Command = 0x03, + Fips = 0x05, } impl AuditTag { @@ -105,6 +109,7 @@ impl AuditTag { Ok(match byte { 0x01 => AuditTag::Force, 0x03 => AuditTag::Command, + 0x05 => AuditTag::Fips, _ => fail!(ErrorKind::TagInvalid, "invalid audit tag value: {}", byte), }) } @@ -129,7 +134,7 @@ impl<'de> Deserialize<'de> for AuditTag { type Value = AuditTag; fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("an unsigned byte with values 0x01 or 0x03") + formatter.write_str("an unsigned byte with values 0x01, 0x03, or 0x05") } fn visit_u8(self, value: u8) -> Result { diff --git a/src/audit/commands.rs b/src/audit/commands.rs index a2a9c0be..3548fc93 100644 --- a/src/audit/commands.rs +++ b/src/audit/commands.rs @@ -5,4 +5,5 @@ mod get_option; mod set_log_index; mod set_option; +pub use self::get_log_entries::{LogDigest, LogEntries, LogEntry}; pub(crate) use self::{get_log_entries::*, get_option::*, set_log_index::*, set_option::*}; diff --git a/src/client.rs b/src/client.rs index 310f15f2..038e63fd 100644 --- a/src/client.rs +++ b/src/client.rs @@ -443,6 +443,25 @@ impl Client { .map_err(|e| format_err!(ErrorKind::ProtocolError, e).into()) } + /// Get the FIPS operation global option + /// + /// + pub fn get_fips_option(&self) -> Result { + let response = self.send_command(GetOptionCommand { + tag: AuditTag::Fips, + })?; + + ensure!( + response.0.len() == 1, + ErrorKind::ProtocolError, + "expected 1-byte response, got {}", + response.0.len() + ); + + AuditOption::from_u8(response.0[0]) + .map_err(|e| format_err!(ErrorKind::ProtocolError, e).into()) + } + /// Get some number of bytes of pseudo random data generated on the device. /// /// @@ -900,6 +919,22 @@ impl Client { Ok(()) } + /// Put the FIPS global option: when enabled, it disables algorithms that are + /// not allowed by FIPS 140. + /// + /// Options are `Off`, or `On` + /// + /// + pub fn set_fips_option(&self, option: AuditOption) -> Result<(), Error> { + self.send_command(SetOptionCommand { + tag: AuditTag::Fips, + length: 1, + value: vec![option.to_u8()], + })?; + + Ok(()) + } + /// Set the index of the last consumed index of the HSM audit log. /// /// diff --git a/src/mockhsm/command.rs b/src/mockhsm/command.rs index dfa68612..23088d0c 100644 --- a/src/mockhsm/command.rs +++ b/src/mockhsm/command.rs @@ -360,6 +360,7 @@ fn get_option(state: &State, cmd_data: &[u8]) -> response::Message { let results = match command.tag { AuditTag::Command => state.command_audit_options.serialize(), AuditTag::Force => vec![state.force_audit.to_u8()], + AuditTag::Fips => vec![state.fips.to_u8()], }; GetOptionResponse(results).serialize() @@ -572,6 +573,10 @@ fn put_option(state: &mut State, cmd_data: &[u8]) -> response::Message { .command_audit_options .put(audit_cmd.command_type(), audit_cmd.audit_option()); } + AuditTag::Fips => { + assert_eq!(length, 1); + state.fips = AuditOption::from_u8(value[0]).unwrap() + } } PutOptionResponse {}.serialize() diff --git a/src/mockhsm/state.rs b/src/mockhsm/state.rs index 7cc31a9e..b184bc40 100644 --- a/src/mockhsm/state.rs +++ b/src/mockhsm/state.rs @@ -22,6 +22,9 @@ pub(crate) struct State { /// via the `SetLogIndex` command. pub(super) force_audit: AuditOption, + /// Fips mode + pub(super) fips: AuditOption, + /// Active sessions with the MockHsm sessions: BTreeMap, @@ -35,6 +38,7 @@ impl State { Self { command_audit_options: CommandAuditOptions::default(), force_audit: AuditOption::Off, + fips: AuditOption::Off, sessions: BTreeMap::new(), objects: Objects::default(), }