mirror of
https://github.com/trussed-dev/piv-authenticator.git
synced 2026-06-20 04:16:15 -07:00
Implement request for challenge
This commit is contained in:
@@ -5,6 +5,8 @@
|
||||
|
||||
use hex_literal::hex;
|
||||
|
||||
use crate::state::ManagementAlgorithm;
|
||||
|
||||
pub const RID_LENGTH: usize = 5;
|
||||
|
||||
// top nibble of first byte is "category", here "A" = International
|
||||
@@ -269,6 +271,8 @@ pub const YUBICO_DEFAULT_MANAGEMENT_KEY: &[u8; 24] = &hex!(
|
||||
"
|
||||
);
|
||||
|
||||
pub const YUBICO_DEFAULT_MANAGEMENT_KEY_ALG: ManagementAlgorithm = ManagementAlgorithm::Tdes;
|
||||
|
||||
// stolen from le yubico
|
||||
pub const DISCOVERY_OBJECT: &[u8; 20] =
|
||||
b"~\x12O\x0b\xa0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00_/\x02@\x00";
|
||||
|
||||
@@ -60,6 +60,8 @@ macro_rules! enum_subset {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) use enum_subset;
|
||||
|
||||
pub struct Tag<'a>(&'a [u8]);
|
||||
impl<'a> Tag<'a> {
|
||||
pub fn new(slice: &'a [u8]) -> Self {
|
||||
|
||||
+30
-5
@@ -30,6 +30,7 @@ pub mod vpicc;
|
||||
use core::convert::TryInto;
|
||||
|
||||
use flexiber::EncodableHeapless;
|
||||
use heapless_bytes::Bytes;
|
||||
use iso7816::{Data, Status};
|
||||
use trussed::client;
|
||||
use trussed::{syscall, try_syscall};
|
||||
@@ -37,7 +38,9 @@ use trussed::{syscall, try_syscall};
|
||||
use constants::*;
|
||||
|
||||
pub type Result = iso7816::Result<()>;
|
||||
use state::{LoadedState, State};
|
||||
use state::{CommandCache, LoadedState, State};
|
||||
|
||||
use crate::piv_types::DynamicAuthenticationTemplate;
|
||||
|
||||
/// PIV authenticator Trussed app.
|
||||
///
|
||||
@@ -496,11 +499,33 @@ impl<'a, T: trussed::Client + trussed::client::Ed255> LoadedAuthenticator<'a, T>
|
||||
pub fn request_for_challenge<const R: usize>(
|
||||
&mut self,
|
||||
_auth: GeneralAuthenticate,
|
||||
_data: derp::Input<'_>,
|
||||
_reply: &mut Data<R>,
|
||||
data: derp::Input<'_>,
|
||||
reply: &mut Data<R>,
|
||||
) -> Result {
|
||||
info!("Request for challenge");
|
||||
todo!()
|
||||
if data.len() != 0 {
|
||||
warn!("Request for challenge with non empty data");
|
||||
return Err(Status::IncorrectDataParameter);
|
||||
}
|
||||
info!("Request for challenge ");
|
||||
let challenge = syscall!(self.trussed.random_bytes(
|
||||
self.state
|
||||
.persistent
|
||||
.keys
|
||||
.management_key
|
||||
.alg
|
||||
.challenge_length()
|
||||
))
|
||||
.bytes;
|
||||
self.state.runtime.command_cache = Some(CommandCache::AuthenticateChallenge(
|
||||
Bytes::from_slice(&challenge).unwrap(),
|
||||
));
|
||||
let resp = DynamicAuthenticationTemplate::with_challenge(&challenge);
|
||||
resp.encode_to_heapless_vec(reply)
|
||||
.map_err(|_err| {
|
||||
error!("Failed to encode challenge: {_err:?}");
|
||||
Status::UnspecifiedNonpersistentExecutionError
|
||||
})
|
||||
.map(drop)
|
||||
}
|
||||
|
||||
pub fn request_for_witness<const R: usize>(
|
||||
|
||||
+36
-14
@@ -13,6 +13,7 @@ use trussed::{
|
||||
};
|
||||
|
||||
use crate::constants::*;
|
||||
use crate::piv_types::Algorithms;
|
||||
|
||||
use crate::{Pin, Puk};
|
||||
|
||||
@@ -133,13 +134,36 @@ impl SlotName {
|
||||
}
|
||||
}
|
||||
|
||||
crate::container::enum_subset! {
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
pub enum ManagementAlgorithm: Algorithms {
|
||||
Tdes,
|
||||
Aes256
|
||||
}
|
||||
}
|
||||
|
||||
impl ManagementAlgorithm {
|
||||
pub fn challenge_length(self) -> usize {
|
||||
match self {
|
||||
Self::Tdes => 8,
|
||||
Self::Aes256 => 16,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
pub struct ManagementKey {
|
||||
pub id: KeyId,
|
||||
pub alg: ManagementAlgorithm,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
pub struct Keys {
|
||||
// 9a "PIV Authentication Key" (YK: PIV Authentication)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub authentication_key: Option<KeyId>,
|
||||
// 9b "PIV Card Application Administration Key" (YK: PIV Management)
|
||||
pub management_key: KeyId,
|
||||
pub management_key: ManagementKey,
|
||||
// 9c "Digital Signature Key" (YK: Digital Signature)
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub signature_key: Option<KeyId>,
|
||||
@@ -295,17 +319,12 @@ pub struct AppSecurityStatus {
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum CommandCache {
|
||||
GetData(GetData),
|
||||
AuthenticateManagement(AuthenticateManagement),
|
||||
AuthenticateChallenge(Bytes<16>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct GetData {}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub struct AuthenticateManagement {
|
||||
pub challenge: [u8; 8],
|
||||
}
|
||||
|
||||
impl Persistent {
|
||||
pub const PIN_RETRIES_DEFAULT: u8 = 3;
|
||||
// hmm...!
|
||||
@@ -424,19 +443,22 @@ impl Persistent {
|
||||
syscall!(client
|
||||
.unsafe_inject_shared_key(management_key, trussed::types::Location::Internal,))
|
||||
.key;
|
||||
let old_management_key = self.keys.management_key;
|
||||
self.keys.management_key = new_management_key;
|
||||
let old_management_key = self.keys.management_key.id;
|
||||
self.keys.management_key.id = new_management_key;
|
||||
self.save(client);
|
||||
syscall!(client.delete(old_management_key));
|
||||
}
|
||||
|
||||
pub fn initialize(client: &mut impl trussed::Client) -> Self {
|
||||
info!("initializing PIV state");
|
||||
let management_key = syscall!(client.unsafe_inject_shared_key(
|
||||
YUBICO_DEFAULT_MANAGEMENT_KEY,
|
||||
trussed::types::Location::Internal,
|
||||
))
|
||||
.key;
|
||||
let management_key = ManagementKey {
|
||||
id: syscall!(client.unsafe_inject_shared_key(
|
||||
YUBICO_DEFAULT_MANAGEMENT_KEY,
|
||||
trussed::types::Location::Internal,
|
||||
))
|
||||
.key,
|
||||
alg: YUBICO_DEFAULT_MANAGEMENT_KEY_ALG,
|
||||
};
|
||||
|
||||
let mut guid: [u8; 16] = syscall!(client.random_bytes(16))
|
||||
.bytes
|
||||
|
||||
Reference in New Issue
Block a user