mirror of
https://github.com/trussed-dev/piv-authenticator.git
synced 2026-06-20 04:16:15 -07:00
Implementing GetData; pivy-tool list works again
This commit is contained in:
committed by
Nicolas Stalder
parent
8f653cf8d4
commit
efd65019dc
+34
-25
@@ -9,16 +9,16 @@ use core::convert::{TryFrom, TryInto};
|
||||
use iso7816::{Instruction, Status};
|
||||
use apdu_dispatch::{Command as IsoCommand, command::Data};
|
||||
|
||||
pub use crate::{Pin, Puk};
|
||||
pub use crate::{container as containers, piv_types, Pin, Puk};
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Command<'l> {
|
||||
/// Select the application
|
||||
///
|
||||
/// Resets security indicators if we are implicitly deselected.
|
||||
Select(Select<'l>),
|
||||
/// Get a data object / container.
|
||||
GetData(GetData),
|
||||
GetData(containers::Container),
|
||||
/// Check PIN
|
||||
///
|
||||
/// This verifies that the sent PIN (global or PIV) is correct.
|
||||
@@ -49,7 +49,7 @@ impl<'l> Command<'l> {
|
||||
}
|
||||
|
||||
/// TODO: change into enum
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct Select<'l> {
|
||||
pub aid: &'l [u8],
|
||||
}
|
||||
@@ -67,18 +67,27 @@ impl<'l> TryFrom<&'l Data> for Select<'l> {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
pub enum GetData {
|
||||
}
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct GetData(containers::Container);
|
||||
|
||||
impl TryFrom<&Data> for GetData {
|
||||
type Error = Status;
|
||||
fn try_from(data: &Data) -> Result<Self, Self::Error> {
|
||||
todo!();
|
||||
let mut decoder = flexiber::Decoder::new(data);
|
||||
let tagged_slice: flexiber::TaggedSlice = decoder.decode().map_err(|_| Status::IncorrectDataParameter)?;
|
||||
if tagged_slice.tag() != flexiber::Tag::application(0x1C) {
|
||||
return Err(Status::IncorrectDataParameter);
|
||||
}
|
||||
let container: containers::Container = containers::Tag::new(tagged_slice.as_bytes())
|
||||
.try_into()
|
||||
.map_err(|_| Status::IncorrectDataParameter)?;
|
||||
|
||||
info_now!("request to GetData for container {:?}", container);
|
||||
Ok(Self(container))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum VerifyKeyReference {
|
||||
GlobalPin = 0x00,
|
||||
@@ -108,7 +117,7 @@ impl TryFrom<u8> for VerifyKeyReference {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct VerifyLogout(bool);
|
||||
|
||||
impl TryFrom<u8> for VerifyLogout {
|
||||
@@ -122,21 +131,21 @@ impl TryFrom<u8> for VerifyLogout {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct VerifyArguments<'l> {
|
||||
pub key_reference: VerifyKeyReference,
|
||||
pub logout: VerifyLogout,
|
||||
pub data: &'l Data
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[non_exhaustive]
|
||||
pub enum VerifyLogin {
|
||||
PivPin(Pin),
|
||||
GlobalPin([u8; 8]),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Verify {
|
||||
Login(VerifyLogin),
|
||||
Logout(VerifyKeyReference),
|
||||
@@ -160,7 +169,7 @@ impl TryFrom<VerifyArguments<'_>> for Verify {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum ChangeReferenceKeyReference {
|
||||
GlobalPin = 0x00,
|
||||
@@ -180,13 +189,13 @@ impl TryFrom<u8> for ChangeReferenceKeyReference {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct ChangeReferenceArguments<'l> {
|
||||
pub key_reference: ChangeReferenceKeyReference,
|
||||
pub data: &'l Data
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum ChangeReference {
|
||||
ChangePin { old_pin: Pin, new_pin: Pin },
|
||||
ChangePuk { old_puk: Puk, new_puk: Puk },
|
||||
@@ -217,7 +226,7 @@ impl TryFrom<ChangeReferenceArguments<'_>> for ChangeReference {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct ResetPinRetries {
|
||||
pub padded_pin: [u8; 8],
|
||||
pub puk: [u8; 8],
|
||||
@@ -236,7 +245,7 @@ impl TryFrom<&Data> for ResetPinRetries {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum AuthenticateKeyReference {
|
||||
SecureMessaging = 0x04,
|
||||
@@ -302,7 +311,7 @@ impl TryFrom<u8> for AuthenticateKeyReference {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct AuthenticateArguments<'l> {
|
||||
/// To allow the authenticator to have additional algorithms beyond NIST SP 800-78-4,
|
||||
/// this is passed through as-is.
|
||||
@@ -311,7 +320,7 @@ pub struct AuthenticateArguments<'l> {
|
||||
pub data: &'l Data
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Authenticate {
|
||||
}
|
||||
|
||||
@@ -322,7 +331,7 @@ impl TryFrom<AuthenticateArguments<'_>> for Authenticate {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct PutData {
|
||||
}
|
||||
|
||||
@@ -333,7 +342,7 @@ impl TryFrom<&Data> for PutData {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[repr(u8)]
|
||||
pub enum GenerateAsymmetricKeyReference {
|
||||
SecureMessaging = 0x04,
|
||||
@@ -357,13 +366,13 @@ impl TryFrom<u8> for GenerateAsymmetricKeyReference {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct GenerateAsymmetricArguments<'l> {
|
||||
pub key_reference: GenerateAsymmetricKeyReference,
|
||||
pub data: &'l Data
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum GenerateAsymmetric {
|
||||
}
|
||||
|
||||
@@ -403,7 +412,7 @@ impl<'l> TryFrom<&'l IsoCommand> for Command<'l> {
|
||||
}
|
||||
|
||||
(0x00, Instruction::GetData, 0x3F, 0xFF) => {
|
||||
Self::GetData(GetData::try_from(data)?)
|
||||
Self::GetData(GetData::try_from(data)?.0)
|
||||
}
|
||||
|
||||
(0x00, Instruction::Verify, p1, p2) => {
|
||||
|
||||
+2
-2
@@ -22,8 +22,8 @@ pub const PIV_AID: &[u8] = &hex!("A000000308 00001000 0100");
|
||||
|
||||
pub const DERIVED_PIV_AID: [u8; 11] = hex!("A000000308 00002000 0100");
|
||||
|
||||
pub const APPLICATION_LABEL: &[u8] = b"SoloKeys PIV v1.0.0-alpha1";
|
||||
pub const APPLICATION_URL: &[u8] = b"https://piv.codes/SoloKeys/PIV/1.0.0-alpha1";
|
||||
pub const APPLICATION_LABEL: &[u8] = b"SoloKeys PIV";
|
||||
pub const APPLICATION_URL: &[u8] = b"https://github.com/solokeys/piv-authenticator";
|
||||
// pub const APPLICATION_URL: &[u8] = b"https://piv.is/SoloKeys/PIV/1.0.0-alpha1";
|
||||
|
||||
|
||||
|
||||
+8
-2
@@ -2,12 +2,17 @@ use core::convert::TryFrom;
|
||||
use flexiber::{Decodable, Encodable};
|
||||
|
||||
pub struct Tag<'a>(&'a [u8]);
|
||||
impl<'a> Tag<'a> {
|
||||
pub fn new(slice: &'a [u8]) -> Self {
|
||||
Self(slice)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct RetiredIndex(u8);
|
||||
|
||||
// #[repr(u8)]
|
||||
#[derive(Clone, Copy, Eq, PartialEq)]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum KeyReference {
|
||||
GlobalPin,
|
||||
ApplicationPin,
|
||||
@@ -51,6 +56,7 @@ impl From<KeyReference> for u8 {
|
||||
|
||||
/// The 36 data objects defined by PIV (SP 800-37-4, Part 1).
|
||||
///
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum Container {
|
||||
CardCapabilityContainer,
|
||||
CardHolderUniqueIdentifier,
|
||||
|
||||
+48
-58
@@ -10,6 +10,7 @@ extern crate hex_literal;
|
||||
pub mod commands;
|
||||
pub use commands::Command;
|
||||
pub mod constants;
|
||||
pub mod container;
|
||||
pub mod state;
|
||||
pub mod derp;
|
||||
pub mod piv_types;
|
||||
@@ -60,6 +61,7 @@ where
|
||||
|
||||
pub fn select(&mut self, _apdu: &IsoCommand, reply: &mut response::Data) -> Result {
|
||||
use piv_types::Algorithms::*;
|
||||
info_now!("selecting PIV maybe");
|
||||
|
||||
let application_property_template = piv_types::ApplicationPropertyTemplate::default()
|
||||
.with_application_label(APPLICATION_LABEL)
|
||||
@@ -73,10 +75,12 @@ where
|
||||
application_property_template
|
||||
.encode_to_heapless_vec(reply)
|
||||
.unwrap();
|
||||
info_now!("returning: {}", hex_str!(reply));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn respond(&mut self, command: &IsoCommand, reply: &mut response::Data) -> Result {
|
||||
info_now!("PIV responding to {:?}", command);
|
||||
let last_or_only = command.class().chain().last_or_only();
|
||||
|
||||
// TODO: avoid owned copy?
|
||||
@@ -107,10 +111,12 @@ where
|
||||
|
||||
// parse Iso7816Command as PivCommand
|
||||
let command: Command = (&entire_command).try_into()?;
|
||||
info_now!("parsed: {:?}", &command);
|
||||
|
||||
match command {
|
||||
Command::Verify(verify) => self.verify(verify),
|
||||
Command::ChangeReference(change_reference) => self.change_reference(change_reference),
|
||||
Command::GetData(container) => self.get_data(container, reply),
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
@@ -863,90 +869,74 @@ where
|
||||
Err(Status::IncorrectDataParameter)
|
||||
}
|
||||
|
||||
fn get_data(&mut self, command: &IsoCommand, reply: &mut response::Data) -> Result {
|
||||
if command.p1 != 0x3f || command.p2 != 0xff {
|
||||
return Err(Status::IncorrectP1OrP2Parameter);
|
||||
}
|
||||
|
||||
// TODO: adapt `derp` and use a proper DER parser
|
||||
// match container {
|
||||
// containers::Container::CardHolderUniqueIdentifier =>
|
||||
// piv_types::CardHolderUniqueIdentifier::default()
|
||||
// .encode
|
||||
// _ => todo!(),
|
||||
// }
|
||||
// todo!();
|
||||
|
||||
let data = command.data();
|
||||
|
||||
if data.len() < 3 {
|
||||
return Err(Status::IncorrectDataParameter);
|
||||
}
|
||||
|
||||
let tag = data[0];
|
||||
if tag != 0x5c {
|
||||
return Err(Status::IncorrectDataParameter);
|
||||
}
|
||||
|
||||
let len = data[1] as usize;
|
||||
let data = &data[2..];
|
||||
if data.len() != len {
|
||||
return Err(Status::IncorrectDataParameter);
|
||||
}
|
||||
|
||||
if data.len() == 0 || data.len() > 3 {
|
||||
return Err(Status::IncorrectDataParameter);
|
||||
}
|
||||
|
||||
// lookup what is asked for
|
||||
info_now!("looking up {:?}", data);
|
||||
fn get_data(&mut self, container: container::Container, reply: &mut response::Data) -> Result {
|
||||
|
||||
// TODO: check security status, else return Status::SecurityStatusNotSatisfied
|
||||
|
||||
// Table 3, Part 1, SP 800-73-4
|
||||
// https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf#page=30
|
||||
match data {
|
||||
DataObjects::DiscoveryObject => {
|
||||
use crate::container::Container;
|
||||
match container {
|
||||
Container::DiscoveryObject => {
|
||||
// Err(Status::InstructionNotSupportedOrInvalid)
|
||||
let data = response::Data::try_from_slice(DISCOVERY_OBJECT).unwrap();
|
||||
reply.extend_from_slice(&data).ok();
|
||||
// todo!("discovery object"),
|
||||
}
|
||||
|
||||
DataObjects::BiometricInformationTemplate => {
|
||||
Container::BiometricInformationTemplatesGroupTemplate => {
|
||||
return Err(Status::InstructionNotSupportedOrInvalid)
|
||||
// todo!("biometric information template"),
|
||||
}
|
||||
|
||||
// '5FC1 02' (351B)
|
||||
DataObjects::CardHolderUniqueIdentifier => {
|
||||
Container::CardHolderUniqueIdentifier => {
|
||||
let guid = self.state.persistent(&mut self.trussed).guid();
|
||||
piv_types::CardHolderUniqueIdentifier::default()
|
||||
.with_guid(guid)
|
||||
.encode_to_heapless_vec(reply)
|
||||
.unwrap();
|
||||
info_now!("returning CHUID {}", hex_str!(reply));
|
||||
}
|
||||
|
||||
// '5FC1 05' (351B)
|
||||
DataObjects::X509CertificateForPivAuthentication => {
|
||||
// return Err(Status::NotFound);
|
||||
// // '5FC1 05' (351B)
|
||||
// Container::X509CertificateForPivAuthentication => {
|
||||
// // return Err(Status::NotFound);
|
||||
|
||||
// info_now!("loading 9a cert");
|
||||
// it seems like fetching this certificate is the way Filo's agent decides
|
||||
// whether the key is "already setup":
|
||||
// https://github.com/FiloSottile/yubikey-agent/blob/8781bc0082db5d35712a2244e3ab3086f415dd59/setup.go#L69-L70
|
||||
let data = try_syscall!(self.trussed.read_file(
|
||||
trussed::types::Location::Internal,
|
||||
trussed::types::PathBuf::from(b"authentication-key.x5c"),
|
||||
)).map_err(|_| {
|
||||
// info_now!("error loading: {:?}", &e);
|
||||
Status::NotFound
|
||||
} )?.data;
|
||||
// // info_now!("loading 9a cert");
|
||||
// // it seems like fetching this certificate is the way Filo's agent decides
|
||||
// // whether the key is "already setup":
|
||||
// // https://github.com/FiloSottile/yubikey-agent/blob/8781bc0082db5d35712a2244e3ab3086f415dd59/setup.go#L69-L70
|
||||
// let data = try_syscall!(self.trussed.read_file(
|
||||
// trussed::types::Location::Internal,
|
||||
// trussed::types::PathBuf::from(b"authentication-key.x5c"),
|
||||
// )).map_err(|_| {
|
||||
// // info_now!("error loading: {:?}", &e);
|
||||
// Status::NotFound
|
||||
// } )?.data;
|
||||
|
||||
// todo: cleanup
|
||||
let tag = flexiber::Tag::application(0x13); // 0x53
|
||||
flexiber::TaggedSlice::from(tag, &data)
|
||||
.unwrap()
|
||||
.encode_to_heapless_vec(reply)
|
||||
.unwrap();
|
||||
}
|
||||
// // todo: cleanup
|
||||
// let tag = flexiber::Tag::application(0x13); // 0x53
|
||||
// flexiber::TaggedSlice::from(tag, &data)
|
||||
// .unwrap()
|
||||
// .encode_to_heapless_vec(reply)
|
||||
// .unwrap();
|
||||
// }
|
||||
|
||||
// '5F FF01' (754B)
|
||||
YubicoObjects::AttestationCertificate => {
|
||||
let data = response::Data::try_from_slice(YUBICO_ATTESTATION_CERTIFICATE).unwrap();
|
||||
reply.extend_from_slice(&data).ok();
|
||||
}
|
||||
// // '5F FF01' (754B)
|
||||
// YubicoObjects::AttestationCertificate => {
|
||||
// let data = response::Data::try_from_slice(YUBICO_ATTESTATION_CERTIFICATE).unwrap();
|
||||
// reply.extend_from_slice(&data).ok();
|
||||
// }
|
||||
|
||||
_ => return Err(Status::NotFound),
|
||||
}
|
||||
|
||||
+23
-7
@@ -71,10 +71,12 @@ impl Encodable for CryptographicAlgorithmTemplate<'_> {
|
||||
}
|
||||
|
||||
fn encode(&self, encoder: &mut flexiber::Encoder<'_>) -> flexiber::Result<()> {
|
||||
let cryptographic_algorithm_identifier_tag = flexiber::Tag::application(0);
|
||||
// '80'
|
||||
let cryptographic_algorithm_identifier_tag = flexiber::Tag::context(0);
|
||||
for alg in self.algorithms.iter() {
|
||||
encoder.encode(&flexiber::TaggedSlice::from(cryptographic_algorithm_identifier_tag, &[*alg as _])?)?;
|
||||
}
|
||||
// '06'
|
||||
let object_identifier_tag = flexiber::Tag::universal(6);
|
||||
encoder.encode(&flexiber::TaggedSlice::from(object_identifier_tag, &[0x00])?)
|
||||
}
|
||||
@@ -223,15 +225,21 @@ pub struct CardHolderUniqueIdentifier<'l> {
|
||||
|
||||
#[tlv(simple = "0x34")]
|
||||
// 16B type 1,2,4 UUID
|
||||
guid: &'l [u8],
|
||||
guid: [u8; 16],
|
||||
|
||||
/// YYYYMMDD
|
||||
#[tlv(simple = "0x35")]
|
||||
expiration_date: [u8; 8],
|
||||
|
||||
#[tlv(simple = "0x36")]
|
||||
// 16B, like guid
|
||||
cardholder_uuid: Option<&'l [u8]>,
|
||||
// Having this with "None" serialized as '36 00', which throws e.g. pivy-tool off.
|
||||
// This is in fact incorrect:
|
||||
// -> should be '36 10 <...>' with a 16-byte valid UUID of version 1, 4 or 5
|
||||
//
|
||||
// Need to fix in `flexiber`.
|
||||
//
|
||||
// #[tlv(simple = "0x36")]
|
||||
// // 16B, like guid
|
||||
// cardholder_uuid: Option<&'l [u8]>,
|
||||
|
||||
#[tlv(simple = "0x3E")]
|
||||
issuer_asymmetric_signature: &'l [u8],
|
||||
@@ -249,12 +257,20 @@ impl Default for CardHolderUniqueIdentifier<'static> {
|
||||
Self {
|
||||
// 9999 = non-federal
|
||||
fasc_n: &[0x99, 0x99],
|
||||
guid: crate::constants::GUID,
|
||||
guid: hex!("00000000000040008000000000000000"),
|
||||
expiration_date: *b"99991231",
|
||||
cardholder_uuid: None,
|
||||
// cardholder_uuid: None,
|
||||
// at least pivy only checks for non-empty entry
|
||||
issuer_asymmetric_signature: b" ",
|
||||
error_detection_code: [0u8; 0],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CardHolderUniqueIdentifier<'_> {
|
||||
pub fn with_guid(self, guid: [u8; 16]) -> Self {
|
||||
let mut modified_self = self;
|
||||
modified_self.guid = guid;
|
||||
modified_self
|
||||
}
|
||||
}
|
||||
|
||||
+29
-14
@@ -1,9 +1,9 @@
|
||||
use core::convert::TryFrom;
|
||||
use core::convert::{TryFrom, TryInto};
|
||||
|
||||
use trussed::{
|
||||
block,
|
||||
Client as TrussedClient,
|
||||
syscall,
|
||||
syscall, try_syscall,
|
||||
types::{KeyId, PathBuf, Location},
|
||||
};
|
||||
|
||||
@@ -217,6 +217,8 @@ pub struct PersistentState {
|
||||
// pin_hash: Option<[u8; 16]>,
|
||||
// Ideally, we'd dogfood a "Monotonic Counter" from `trussed`.
|
||||
timestamp: u32,
|
||||
// must be a valid RFC 4122 UUID 1, 2 or 4
|
||||
guid: [u8; 16],
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq)]
|
||||
@@ -348,6 +350,10 @@ where
|
||||
const DEFAULT_PIN: &'static [u8] = b"123456\xff\xff";
|
||||
const DEFAULT_PUK: &'static [u8] = b"12345678";
|
||||
|
||||
pub fn guid(&self) -> [u8; 16] {
|
||||
self.state.guid
|
||||
}
|
||||
|
||||
pub fn remaining_pin_retries(&self) -> u8 {
|
||||
if self.state.consecutive_pin_mismatches >= Self::PIN_RETRIES_DEFAULT {
|
||||
0
|
||||
@@ -449,11 +455,21 @@ where
|
||||
}
|
||||
|
||||
pub fn initialize(trussed: &'t mut T) -> Self {
|
||||
info_now!("initializing PIV state");
|
||||
let management_key = syscall!(trussed.unsafe_inject_shared_key(
|
||||
YUBICO_DEFAULT_MANAGEMENT_KEY,
|
||||
trussed::types::Location::Internal,
|
||||
)).key;
|
||||
|
||||
let mut guid: [u8; 16] = syscall!(trussed.random_bytes(16))
|
||||
.bytes
|
||||
.as_ref()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
|
||||
guid[6] = (guid[6] & 0xf) | 0x40;
|
||||
guid[8] = (guid[8] & 0x3f) | 0x80;
|
||||
|
||||
let keys = Keys {
|
||||
authentication_key: None,
|
||||
management_key: management_key,
|
||||
@@ -463,7 +479,7 @@ where
|
||||
retired_keys: Default::default(),
|
||||
};
|
||||
|
||||
Self {
|
||||
let mut state = Self {
|
||||
trussed,
|
||||
state: PersistentState {
|
||||
keys,
|
||||
@@ -472,8 +488,11 @@ where
|
||||
pin: Pin::try_from(Self::DEFAULT_PIN).unwrap(),
|
||||
puk: Puk::try_from(Self::DEFAULT_PUK).unwrap(),
|
||||
timestamp: 0,
|
||||
guid,
|
||||
}
|
||||
}
|
||||
};
|
||||
state.save();
|
||||
state
|
||||
}
|
||||
|
||||
pub fn load(trussed: &'t mut T) -> Result<Self> {
|
||||
@@ -482,13 +501,13 @@ where
|
||||
PathBuf::from(Self::FILENAME),
|
||||
).unwrap()
|
||||
).map_err(|e| {
|
||||
// hprintln!("loading error: {:?}", &e).ok();
|
||||
info!("loading error: {:?}", &e);
|
||||
drop(e)
|
||||
})?.data;
|
||||
|
||||
let previous_state: PersistentState = trussed::cbor_deserialize(&data).map_err(|e| {
|
||||
// hprintln!("cbor deser error: {:?}", e);
|
||||
// hprintln!("data: {:X?}", &data).ok();
|
||||
info!("cbor deser error: {:?}", e);
|
||||
info!("data: {:X?}", &data);
|
||||
drop(e)
|
||||
})?;
|
||||
// horrible deser bug to forget Ok here :)
|
||||
@@ -497,15 +516,11 @@ where
|
||||
|
||||
pub fn load_or_initialize(trussed: &'t mut T) -> Self {
|
||||
// todo: can't seem to combine load + initialize without code repetition
|
||||
let data = block!(trussed.read_file(
|
||||
Location::Internal,
|
||||
PathBuf::from(Self::FILENAME),
|
||||
).unwrap()
|
||||
);
|
||||
let data = try_syscall!(trussed.read_file(Location::Internal, PathBuf::from(Self::FILENAME)));
|
||||
if let Ok(data) = data {
|
||||
let previous_state = trussed::cbor_deserialize(&data.data).map_err(|e| {
|
||||
// hprintln!("cbor deser error: {:?}", e);
|
||||
// hprintln!("data: {:X?}", &data).ok();
|
||||
info!("cbor deser error: {:?}", e);
|
||||
info!("data: {:X?}", &data);
|
||||
drop(e)
|
||||
});
|
||||
if let Ok(state) = previous_state {
|
||||
|
||||
Reference in New Issue
Block a user