Run cargo fmt

This commit is contained in:
Sosthène Guédon
2024-03-01 14:29:40 +01:00
committed by Nicolas Stalder
parent 1922d6d97b
commit 508116066c
9 changed files with 432 additions and 292 deletions
+56 -26
View File
@@ -66,7 +66,6 @@ impl<'l> TryFrom<&'l [u8]> for Select<'l> {
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct GetData(containers::Container);
@@ -74,7 +73,9 @@ impl TryFrom<&[u8]> for GetData {
type Error = Status;
fn try_from(data: &[u8]) -> Result<Self, Self::Error> {
let mut decoder = flexiber::Decoder::new(data);
let tagged_slice: flexiber::TaggedSlice = decoder.decode().map_err(|_| Status::IncorrectDataParameter)?;
let tagged_slice: flexiber::TaggedSlice = decoder
.decode()
.map_err(|_| Status::IncorrectDataParameter)?;
if tagged_slice.tag() != flexiber::Tag::application(0x1C) {
return Err(Status::IncorrectDataParameter);
}
@@ -155,13 +156,20 @@ pub enum Verify {
impl TryFrom<VerifyArguments<'_>> for Verify {
type Error = Status;
fn try_from(arguments: VerifyArguments<'_>) -> Result<Self, Self::Error> {
let VerifyArguments { key_reference, logout, data } = arguments;
let VerifyArguments {
key_reference,
logout,
data,
} = arguments;
if key_reference != VerifyKeyReference::PivPin {
return Err(Status::FunctionNotSupported);
}
Ok(match (logout.0, data.len()) {
(false, 0) => Verify::Status(key_reference),
(false, 8) => Verify::Login(VerifyLogin::PivPin(data.try_into().map_err(|_| Status::IncorrectDataParameter)?)),
(false, 8) => Verify::Login(VerifyLogin::PivPin(
data.try_into()
.map_err(|_| Status::IncorrectDataParameter)?,
)),
(false, _) => return Err(Status::IncorrectDataParameter),
(true, 0) => Verify::Logout(key_reference),
(true, _) => return Err(Status::IncorrectDataParameter),
@@ -204,22 +212,27 @@ pub enum ChangeReference {
impl TryFrom<ChangeReferenceArguments<'_>> for ChangeReference {
type Error = Status;
fn try_from(arguments: ChangeReferenceArguments<'_>) -> Result<Self, Self::Error> {
let ChangeReferenceArguments { key_reference, data } = arguments;
let ChangeReferenceArguments {
key_reference,
data,
} = arguments;
use ChangeReferenceKeyReference::*;
Ok(match (key_reference, data) {
(GlobalPin, _) => return Err(Status::FunctionNotSupported),
(PivPin, data) => {
ChangeReference::ChangePin {
old_pin: Pin::try_from(&data[..8]).map_err(|_| Status::IncorrectDataParameter)?,
new_pin: Pin::try_from(&data[8..]).map_err(|_| Status::IncorrectDataParameter)?,
}
}
(PivPin, data) => ChangeReference::ChangePin {
old_pin: Pin::try_from(&data[..8]).map_err(|_| Status::IncorrectDataParameter)?,
new_pin: Pin::try_from(&data[8..]).map_err(|_| Status::IncorrectDataParameter)?,
},
(Puk, data) => {
use crate::commands::Puk;
ChangeReference::ChangePuk {
old_puk: Puk(data[..8].try_into().map_err(|_| Status::IncorrectDataParameter)?),
new_puk: Puk(data[8..].try_into().map_err(|_| Status::IncorrectDataParameter)?),
old_puk: Puk(data[..8]
.try_into()
.map_err(|_| Status::IncorrectDataParameter)?),
new_puk: Puk(data[8..]
.try_into()
.map_err(|_| Status::IncorrectDataParameter)?),
}
}
})
@@ -229,7 +242,7 @@ impl TryFrom<ChangeReferenceArguments<'_>> for ChangeReference {
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ResetPinRetries {
pub padded_pin: [u8; 8],
pub puk: [u8; 8],
pub puk: [u8; 8],
}
impl TryFrom<&[u8]> for ResetPinRetries {
@@ -321,8 +334,7 @@ pub struct AuthenticateArguments<'l> {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Authenticate {
}
pub enum Authenticate {}
impl TryFrom<AuthenticateArguments<'_>> for Authenticate {
type Error = Status;
@@ -332,8 +344,7 @@ impl TryFrom<AuthenticateArguments<'_>> for Authenticate {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct PutData {
}
pub struct PutData {}
impl TryFrom<&[u8]> for PutData {
type Error = Status;
@@ -373,8 +384,7 @@ pub struct GenerateAsymmetricArguments<'l> {
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum GenerateAsymmetric {
}
pub enum GenerateAsymmetric {}
impl TryFrom<GenerateAsymmetricArguments<'_>> for GenerateAsymmetric {
type Error = Status;
@@ -392,7 +402,12 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command<C>> for Command<'l> {
///
/// The individual piv::Command TryFroms then further interpret these validated parameters.
fn try_from(command: &'l iso7816::Command<C>) -> Result<Self, Self::Error> {
let (class, instruction, p1, p2) = (command.class(), command.instruction(), command.p1, command.p2);
let (class, instruction, p1, p2) = (
command.class(),
command.instruction(),
command.p1,
command.p2,
);
let data = command.data();
if !class.secure_messaging().none() {
@@ -406,7 +421,6 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command<C>> for Command<'l> {
// TODO: should we check `command.expected() == 0`, where specified?
Ok(match (class.into_inner(), instruction, p1, p2) {
(0x00, Instruction::Select, 0x04, 0x00) => {
Self::Select(Select::try_from(data.as_slice())?)
}
@@ -418,12 +432,19 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command<C>> for Command<'l> {
(0x00, Instruction::Verify, p1, p2) => {
let logout = VerifyLogout::try_from(p1)?;
let key_reference = VerifyKeyReference::try_from(p2)?;
Self::Verify(Verify::try_from(VerifyArguments { key_reference, logout, data })?)
Self::Verify(Verify::try_from(VerifyArguments {
key_reference,
logout,
data,
})?)
}
(0x00, Instruction::ChangeReferenceData, 0x00, p2) => {
let key_reference = ChangeReferenceKeyReference::try_from(p2)?;
Self::ChangeReference(ChangeReference::try_from(ChangeReferenceArguments { key_reference, data })?)
Self::ChangeReference(ChangeReference::try_from(ChangeReferenceArguments {
key_reference,
data,
})?)
}
(0x00, Instruction::ResetRetryCounter, 0x00, 0x80) => {
@@ -433,7 +454,11 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command<C>> for Command<'l> {
(0x00, Instruction::GeneralAuthenticate, p1, p2) => {
let unparsed_algorithm = p1;
let key_reference = AuthenticateKeyReference::try_from(p2)?;
Self::Authenticate(Authenticate::try_from(AuthenticateArguments { unparsed_algorithm, key_reference, data })?)
Self::Authenticate(Authenticate::try_from(AuthenticateArguments {
unparsed_algorithm,
key_reference,
data,
})?)
}
(0x00, Instruction::PutData, 0x3F, 0xFF) => {
@@ -442,7 +467,12 @@ impl<'l, const C: usize> TryFrom<&'l iso7816::Command<C>> for Command<'l> {
(0x00, Instruction::GenerateAsymmetricKeyPair, 0x00, p2) => {
let key_reference = GenerateAsymmetricKeyReference::try_from(p2)?;
Self::GenerateAsymmetric(GenerateAsymmetric::try_from(GenerateAsymmetricArguments { key_reference, data })?)
Self::GenerateAsymmetric(GenerateAsymmetric::try_from(
GenerateAsymmetricArguments {
key_reference,
data,
},
)?)
}
_ => return Err(Status::FunctionNotSupported),
+9 -11
View File
@@ -19,7 +19,8 @@ pub const DERIVED_PIV_PIX: [u8; 6] = hex!("0000 2000 0100");
pub const PIV_TRUNCATED_AID: [u8; 9] = hex!("A000000308 00001000");
// pub const PIV_AID: &[u8] = &hex!("A000000308 00001000 0100");
pub const PIV_AID: iso7816::Aid = iso7816::Aid::new_truncatable(&hex!("A000000308 00001000 0100"), 9);
pub const PIV_AID: iso7816::Aid =
iso7816::Aid::new_truncatable(&hex!("A000000308 00001000 0100"), 9);
pub const DERIVED_PIV_AID: [u8; 11] = hex!("A000000308 00002000 0100");
@@ -27,7 +28,6 @@ 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";
// https://git.io/JfWuD
pub const YUBICO_OTP_PIX: [u8; 3] = hex!("200101");
pub const YUBICO_OTP_AID: iso7816::Aid = iso7816::Aid::new(&hex!("A000000527 200101"));
@@ -84,7 +84,7 @@ pub const SELECT: (u8, u8, u8, u8) = (
// p2: i think this is dummy here
0x00, // b2, b1 zero means "file occurence": first/only occurence,
// b4, b3 zero means "file control information": return FCI template
// 256,
// 256,
);
//
@@ -101,12 +101,11 @@ pub const SELECT: (u8, u8, u8, u8) = (
pub const GET_DATA: (u8, u8, u8, u8) = (
0x00, // as before, would be 0x0C for secure messaging
0xCB, // GET DATA. There's also `CA`, setting bit 1 here
// means (7816-4, sec. 5.1.2): use BER-TLV, as opposed
// to "no indication provided".
// means (7816-4, sec. 5.1.2): use BER-TLV, as opposed
// to "no indication provided".
// P1, P2: 7816-4, sec. 7.4.1: bit 1 of INS set => P1,P2 identifies
// a file. And 0x3FFF identifies current DF
0x3F,
0xFF,
0x3F, 0xFF,
// 256,
);
@@ -233,7 +232,6 @@ pub const GET_DATA: (u8, u8, u8, u8) = (
// }
//}
// 6A, 80 incorrect parameter in command data field
// 6A, 81 function not supported
// 6A, 82 data object not found ( = NOT FOUND for files, e.g. certificate, e.g. after GET-DATA)
@@ -420,13 +418,13 @@ pub const YUBICO_ATTESTATION_CERTIFICATE_FOR_9A: &'static [u8; 584] = &[
];
// pub const YUBICO_DEFAULT_MANAGEMENT_KEY: &'static [u8; 24] = b"123456781234567812345678";
pub const YUBICO_DEFAULT_MANAGEMENT_KEY: &'static [u8; 24] = &[
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
];
// stolen from le yubico
pub const DISCOVERY_OBJECT: &'static [u8; 20] = b"~\x12O\x0b\xa0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00_/\x02@\x00";
pub const DISCOVERY_OBJECT: &'static [u8; 20] =
b"~\x12O\x0b\xa0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00_/\x02@\x00";
// import secrets; secrets.token_bytes(16)
pub const GUID: &'static [u8; 16] = b"\x0c\x92\xc9\x04\xd0\xdeL\xd9\xf6\xd1\xa2\x9fE3\xca\xeb";
+50 -52
View File
@@ -29,7 +29,6 @@ pub enum KeyReference {
// 20x
RetiredKeyManagement(RetiredIndex),
}
impl From<KeyReference> for u8 {
@@ -85,7 +84,7 @@ impl From<Container> for ContainerId {
use Container::*;
Self(match container {
CardCapabilityContainer => 0xDB00,
CardHolderUniqueIdentifier =>0x3000,
CardHolderUniqueIdentifier => 0x3000,
X509CertificateFor9A => 0x0101,
CardholderFingerprints => 0x6010,
SecurityObject => 0x9000,
@@ -194,64 +193,63 @@ impl TryFrom<Tag<'_>> for Container {
}
}
// #[derive(Clone, Copy, PartialEq)]
// pub struct CertInfo {
// compressed: bool,
// }
// #[derive(Clone, Copy, PartialEq)]
// pub struct CertInfo {
// compressed: bool,
// }
// impl From<CertInfo> for u8 {
// fn from(cert_info: CertInfo) -> Self {
// cert_info.compressed as u8
// }
// }
// impl From<CertInfo> for u8 {
// fn from(cert_info: CertInfo) -> Self {
// cert_info.compressed as u8
// }
// }
// impl Encodable for CertInfo {
// fn encoded_len(&self) -> der::Result<der::Length> {
// Length::from(1)
// }
// impl Encodable for CertInfo {
// fn encoded_len(&self) -> der::Result<der::Length> {
// Length::from(1)
// }
// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> {
// encoder.encode(der::Any::new(0x71, &[u8::from(self)]))
// }
// }
// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> {
// encoder.encode(der::Any::new(0x71, &[u8::from(self)]))
// }
// }
// pub struct Certificate<'a> {
// // max bytes: 1856
// certificate: &'a [u8], // tag: 0x70
// // 1B
// cert_info: CertInfo, // tag: 0x71
// // 38
// // mscuid: ?, // tag: 0x72
// error_detection_code: [u8; 0], // tag: 0xFE
// }
// pub struct Certificate<'a> {
// // max bytes: 1856
// certificate: &'a [u8], // tag: 0x70
// // 1B
// cert_info: CertInfo, // tag: 0x71
// // 38
// // mscuid: ?, // tag: 0x72
// error_detection_code: [u8; 0], // tag: 0xFE
// }
// impl Encodable for CertInfo {
// fn encoded_len(&self) -> der::Result<der::Length> {
// Length::from(1)
// }
// impl Encodable for CertInfo {
// fn encoded_len(&self) -> der::Result<der::Length> {
// Length::from(1)
// }
// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> {
// encoder.encode(der::Any::new(0x71, &[u8::from(self)]))
// }
// }
// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> {
// encoder.encode(der::Any::new(0x71, &[u8::from(self)]))
// }
// }
// #[derive(Encodable)]
// pub struct DiscoveryObject<'a> {
// #[tlv(tag = "0x4F")]
// piv_card_application_aid: &'a [u8; 11], // tag: 0x4F, max bytes = 12,
// #[tlv(tag = 0x5F2f)]
// pin_usage_policy: [u8; 2], // tag: 0x5F2F, max bytes = 2,
// }
// #[derive(Encodable)]
// pub struct DiscoveryObject<'a> {
// #[tlv(tag = "0x4F")]
// piv_card_application_aid: &'a [u8; 11], // tag: 0x4F, max bytes = 12,
// #[tlv(tag = 0x5F2f)]
// pin_usage_policy: [u8; 2], // tag: 0x5F2F, max bytes = 2,
// }
// impl Encodable for CertInfo {
// fn encoded_len(&self) -> der::Result<der::Length> {
// Length::from(1)
// }
// impl Encodable for CertInfo {
// fn encoded_len(&self) -> der::Result<der::Length> {
// Length::from(1)
// }
// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> {
// encoder.encode(der::Any::new(0x71, &[u8::from(self)]))
// }
// }
// fn encode(&self, encoder: &mut Encoder<'_>) -> der::Result<()> {
// encoder.encode(der::Any::new(0x71, &[u8::from(self)]))
// }
// }
// }
+12 -5
View File
@@ -1,20 +1,27 @@
use crate::{Authenticator, /*constants::PIV_AID,*/ Result};
use apdu_dispatch::{app::App, command, Command, response};
use apdu_dispatch::{app::App, command, response, Command};
use trussed::client;
#[cfg(feature = "apdu-dispatch")]
impl<T> App<{command::SIZE}, {response::SIZE}> for Authenticator<T, {command::SIZE}>
impl<T> App<{ command::SIZE }, { response::SIZE }> for Authenticator<T, { command::SIZE }>
where
T: client::Client + client::Ed255 + client::Tdes
T: client::Client + client::Ed255 + client::Tdes,
{
fn select(&mut self, apdu: &Command, reply: &mut response::Data) -> Result {
self.select(apdu, reply)
}
fn deselect(&mut self) { self.deselect() }
fn deselect(&mut self) {
self.deselect()
}
fn call(&mut self, _: iso7816::Interface, apdu: &Command, reply: &mut response::Data) -> Result {
fn call(
&mut self,
_: iso7816::Interface,
apdu: &Command,
reply: &mut response::Data,
) -> Result {
self.respond(apdu, reply)
}
}
+169 -117
View File
File diff suppressed because it is too large Load Diff
+49 -28
View File
@@ -34,7 +34,7 @@ impl TryFrom<&[u8]> for Pin {
Err(())
}
}
_ => Err(())
_ => Err(()),
}
}
}
@@ -103,45 +103,53 @@ impl Encodable for CryptographicAlgorithmTemplate<'_> {
// '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 _])?)?;
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])?)
encoder.encode(&flexiber::TaggedSlice::from(
object_identifier_tag,
&[0x00],
)?)
}
}
#[derive(Clone, Copy, Encodable, Eq, PartialEq)]
pub struct CoexistentTagAllocationAuthorityTemplate<'l> {
#[tlv(application, primitive, number = "0xF")] // = 0x4F
#[tlv(application, primitive, number = "0xF")] // = 0x4F
pub application_identifier: &'l [u8],
}
impl Default for CoexistentTagAllocationAuthorityTemplate<'static> {
fn default() -> Self {
Self { application_identifier: crate::constants::NIST_RID }
Self {
application_identifier: crate::constants::NIST_RID,
}
}
}
#[derive(Clone, Copy, Encodable, Eq, PartialEq)]
#[tlv(application, constructed, number = "0x1")] // = 0x61
#[tlv(application, constructed, number = "0x1")] // = 0x61
pub struct ApplicationPropertyTemplate<'l> {
/// Application identifier of application: PIX (without RID, with version)
#[tlv(application, primitive, number = "0xF")] // = 0x4F
aid: &'l[u8],
#[tlv(application, primitive, number = "0xF")] // = 0x4F
aid: &'l [u8],
/// Text describing the application; e.g., for use on a man-machine interface.
#[tlv(application, primitive, number = "0x10")] // = 0x50
#[tlv(application, primitive, number = "0x10")] // = 0x50
application_label: &'l [u8],
/// Reference to the specification describing the application.
#[tlv(application, primitive, number = "0x50")] // = 0x5F50
#[tlv(application, primitive, number = "0x50")] // = 0x5F50
application_url: &'l [u8],
#[tlv(context, constructed, number = "0xC")] // = 0xAC
#[tlv(context, constructed, number = "0xC")] // = 0xAC
supported_cryptographic_algorithms: CryptographicAlgorithmTemplate<'l>,
#[tlv(application, constructed, number = "0x19")] // = 0x79
#[tlv(application, constructed, number = "0x19")] // = 0x79
coexistent_tag_allocation_authority: CoexistentTagAllocationAuthorityTemplate<'l>,
}
@@ -158,7 +166,6 @@ impl Default for ApplicationPropertyTemplate<'static> {
}
impl<'a> ApplicationPropertyTemplate<'a> {
pub const fn with_application_label(self, application_label: &'a [u8]) -> Self {
Self {
aid: self.aid,
@@ -179,18 +186,22 @@ impl<'a> ApplicationPropertyTemplate<'a> {
}
}
pub const fn with_supported_cryptographic_algorithms(self, supported_cryptographic_algorithms: &'a [Algorithms]) -> Self {
pub const fn with_supported_cryptographic_algorithms(
self,
supported_cryptographic_algorithms: &'a [Algorithms],
) -> Self {
Self {
aid: self.aid,
application_label: self.application_label,
application_url: self.application_url,
supported_cryptographic_algorithms: CryptographicAlgorithmTemplate { algorithms: supported_cryptographic_algorithms},
supported_cryptographic_algorithms: CryptographicAlgorithmTemplate {
algorithms: supported_cryptographic_algorithms,
},
coexistent_tag_allocation_authority: self.coexistent_tag_allocation_authority,
}
}
}
/// TODO: This should be an enum of sorts, maybe.
///
/// The data objects that appear in the dynamic authentication template (tag '7C') in the data field
@@ -201,40 +212,52 @@ impl<'a> ApplicationPropertyTemplate<'a> {
/// - '80 00' Returns '80 TL <encrypted random>' (as per definition)
/// - '81 00' Returns '81 TL <random>' (as per external authenticate example)
#[derive(Clone, Copy, Default, Encodable, Eq, PartialEq)]
#[tlv(application, constructed, number = "0x1C")] // = 0x7C
#[tlv(application, constructed, number = "0x1C")] // = 0x7C
pub struct DynamicAuthenticationTemplate<'l> {
/// The Witness (tag '80') contains encrypted data (unrevealed fact).
/// This data is decrypted by the card.
#[tlv(simple = "0x80")]
witness: Option<&'l[u8]>,
witness: Option<&'l [u8]>,
/// The Challenge (tag '81') contains clear data (byte sequence),
/// which is encrypted by the card.
#[tlv(simple = "0x81")]
challenge: Option<&'l[u8]>,
challenge: Option<&'l [u8]>,
/// The Response (tag '82') contains either the decrypted data from tag '80'
/// or the encrypted data from tag '81'.
#[tlv(simple = "0x82")]
response: Option<&'l[u8]>,
response: Option<&'l [u8]>,
/// Not documented in SP-800-73-4
#[tlv(simple = "0x85")]
exponentiation: Option<&'l[u8]>,
exponentiation: Option<&'l [u8]>,
}
impl<'a> DynamicAuthenticationTemplate<'a> {
pub fn with_challenge(challenge: &'a [u8]) -> Self {
Self { challenge: Some(challenge), ..Default::default() }
Self {
challenge: Some(challenge),
..Default::default()
}
}
pub fn with_exponentiation(exponentiation: &'a [u8]) -> Self {
Self { exponentiation: Some(exponentiation), ..Default::default() }
Self {
exponentiation: Some(exponentiation),
..Default::default()
}
}
pub fn with_response(response: &'a [u8]) -> Self {
Self { response: Some(response), ..Default::default() }
Self {
response: Some(response),
..Default::default()
}
}
pub fn with_witness(witness: &'a [u8]) -> Self {
Self { witness: Some(witness), ..Default::default() }
Self {
witness: Some(witness),
..Default::default()
}
}
}
@@ -246,7 +269,7 @@ impl<'a> DynamicAuthenticationTemplate<'a> {
// pivy: https://git.io/JfzBo
// https://www.idmanagement.gov/wp-content/uploads/sites/1171/uploads/TIG_SCEPACS_v2.3.pdf
#[derive(Clone, Copy, Encodable, Eq, PartialEq)]
#[tlv(application, primitive, number = "0x13")] // = 0x53
#[tlv(application, primitive, number = "0x13")] // = 0x53
pub struct CardHolderUniqueIdentifier<'l> {
#[tlv(simple = "0x30")]
// pivy: 26B, TIG: 25B
@@ -269,7 +292,6 @@ pub struct CardHolderUniqueIdentifier<'l> {
// #[tlv(simple = "0x36")]
// // 16B, like guid
// cardholder_uuid: Option<&'l [u8]>,
#[tlv(simple = "0x3E")]
issuer_asymmetric_signature: &'l [u8],
@@ -384,4 +406,3 @@ pub struct DiscoveryObject {
#[tlv(slice, application, number = "0x2f")]
pin_usage_policy: [u8; 2], // tag: 0x5F2F, max bytes = 2,
}
+46 -39
View File
@@ -1,10 +1,9 @@
use core::convert::{TryFrom, TryInto};
use trussed::{
block,
block, syscall, try_syscall,
types::{KeyId, Location, PathBuf},
Client as TrussedClient,
syscall, try_syscall,
types::{KeyId, PathBuf, Location},
};
use crate::constants::*;
@@ -37,7 +36,10 @@ pub struct Slot {
impl Default for Slot {
fn default() -> Self {
Self { key: None, pin_policy: PinPolicy::Once, /*touch_policy: TouchPolicy::Never*/ }
Self {
key: None,
pin_policy: PinPolicy::Once, /*touch_policy: TouchPolicy::Never*/
}
}
}
@@ -46,10 +48,15 @@ impl Slot {
use SlotName::*;
match name {
// Management => Slot { pin_policy: PinPolicy::Never, ..Default::default() },
Signature => Slot { pin_policy: PinPolicy::Always, ..Default::default() },
Pinless => Slot { pin_policy: PinPolicy::Never, ..Default::default() },
Signature => Slot {
pin_policy: PinPolicy::Always,
..Default::default()
},
Pinless => Slot {
pin_policy: PinPolicy::Never,
..Default::default()
},
_ => Default::default(),
}
}
}
@@ -68,9 +75,9 @@ impl core::convert::TryFrom<u8> for RetiredSlotIndex {
}
pub enum SlotName {
Identity,
Management, // Personalization? Administration?
Management, // Personalization? Administration?
Signature,
Decryption, // Management after all?
Decryption, // Management after all?
Pinless,
Retired(RetiredSlotIndex),
Attestation,
@@ -78,8 +85,8 @@ pub enum SlotName {
impl SlotName {
pub fn default_pin_policy(&self) -> PinPolicy {
use SlotName::*;
use PinPolicy::*;
use SlotName::*;
match *self {
Signature => Always,
Pinless | Management | Attestation => Never,
@@ -88,7 +95,10 @@ impl SlotName {
}
pub fn default_slot(&self) -> Slot {
Slot { key: None, pin_policy: self.default_pin_policy() }
Slot {
key: None,
pin_policy: self.default_pin_policy(),
}
}
pub fn reference(&self) -> u8 {
@@ -137,7 +147,6 @@ pub struct Keys {
pub retired_keys: [Option<KeyId>; 20],
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct State<const C: usize> {
pub runtime: Runtime<C>,
@@ -156,8 +165,8 @@ impl<const C: usize> State<C> {
// TODO: it is really not good to overwrite user data on failure to decode old state.
// To fix this, need a flag to detect if we're "fresh", and/or initialize state in factory.
pub fn persistent<'t, T>(&mut self, trussed: &'t mut T) -> Persistent<'t, T>
where T: TrussedClient
+ trussed::client::Tdes
where
T: TrussedClient + trussed::client::Tdes,
{
Persistent::load_or_initialize(trussed)
}
@@ -237,7 +246,6 @@ impl<T> AsRef<PersistentState> for Persistent<'_, T> {
pub struct Runtime<const C: usize> {
// aid: Option<
// consecutive_pin_mismatches: u8,
pub global_security_status: GlobalSecurityStatus,
// pub currently_selected_application: SelectableAid,
pub app_security_status: AppSecurityStatus,
@@ -299,8 +307,7 @@ pub struct Runtime<const C: usize> {
// }
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct GlobalSecurityStatus {
}
pub struct GlobalSecurityStatus {}
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum SecurityStatus {
@@ -328,10 +335,8 @@ pub enum CommandCache {
AuthenticateManagement(AuthenticateManagement),
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct GetData {
}
pub struct GetData {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct AuthenticateManagement {
@@ -342,7 +347,6 @@ impl<'t, T> Persistent<'t, T>
where
T: TrussedClient + trussed::client::Tdes,
{
pub const PIN_RETRIES_DEFAULT: u8 = 3;
// hmm...!
pub const PUK_RETRIES_DEFAULT: u8 = 5;
@@ -444,10 +448,10 @@ where
pub fn set_management_key(&mut self, management_key: &[u8; 24]) {
// let new_management_key = syscall!(self.trussed.unsafe_inject_tdes_key(
let new_management_key = syscall!(self.trussed.unsafe_inject_shared_key(
management_key,
trussed::types::Location::Internal,
)).key;
let new_management_key = syscall!(self
.trussed
.unsafe_inject_shared_key(management_key, trussed::types::Location::Internal,))
.key;
let old_management_key = self.state.keys.management_key;
self.state.keys.management_key = new_management_key;
self.save();
@@ -459,7 +463,8 @@ where
let management_key = syscall!(trussed.unsafe_inject_shared_key(
YUBICO_DEFAULT_MANAGEMENT_KEY,
trussed::types::Location::Internal,
)).key;
))
.key;
let mut guid: [u8; 16] = syscall!(trussed.random_bytes(16))
.bytes
@@ -489,21 +494,21 @@ where
puk: Puk::try_from(Self::DEFAULT_PUK).unwrap(),
timestamp: 0,
guid,
}
},
};
state.save();
state
}
pub fn load(trussed: &'t mut T) -> Result<Self> {
let data = block!(trussed.read_file(
Location::Internal,
PathBuf::from(Self::FILENAME),
).unwrap()
).map_err(|e| {
let data = block!(trussed
.read_file(Location::Internal, PathBuf::from(Self::FILENAME),)
.unwrap())
.map_err(|e| {
info!("loading error: {:?}", &e);
drop(e)
})?.data;
})?
.data;
let previous_state: PersistentState = trussed::cbor_deserialize(&data).map_err(|e| {
info!("cbor deser error: {:?}", e);
@@ -511,12 +516,16 @@ where
drop(e)
})?;
// horrible deser bug to forget Ok here :)
Ok(Self { trussed, state: previous_state })
Ok(Self {
trussed,
state: previous_state,
})
}
pub fn load_or_initialize(trussed: &'t mut T) -> Self {
// todo: can't seem to combine load + initialize without code repetition
let data = try_syscall!(trussed.read_file(Location::Internal, PathBuf::from(Self::FILENAME)));
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| {
info!("cbor deser error: {:?}", e);
@@ -524,8 +533,8 @@ where
drop(e)
});
if let Ok(state) = previous_state {
// horrible deser bug to forget Ok here :)
return Self { trussed, state }
// horrible deser bug to forget Ok here :)
return Self { trussed, state };
}
}
@@ -548,6 +557,4 @@ where
self.save();
self.state.timestamp
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ fn get_data() {
// let cmd = cmd!("00 47 00 9A 0B AC 09 80 01 11 AA 01 02 AB 01 02");
// let cmd = cmd!("00 f8 00 00");
// // without PIN, no key generation
// // without PIN, no key generation
setup::piv(|piv| {
// ykGetSerial
+40 -13
View File
@@ -1,5 +1,6 @@
trussed::platform!(Platform,
R: rand_core::OsRng,//chacha20::ChaCha8Rng,
trussed::platform!(
Platform,
R: rand_core::OsRng, //chacha20::ChaCha8Rng,
S: store::Store,
UI: ui::UserInterface,
);
@@ -8,15 +9,21 @@ const COMMAND_SIZE: usize = 3072;
#[macro_export]
macro_rules! cmd {
($tt:tt) => { iso7816::Command::<3072>::try_from(&hex_literal::hex!($tt)).unwrap() }
($tt:tt) => {
iso7816::Command::<3072>::try_from(&hex_literal::hex!($tt)).unwrap()
};
}
pub type Piv<'service> = piv_authenticator::Authenticator<
trussed::ClientImplementation<&'service mut trussed::service::Service<Platform>>, COMMAND_SIZE>;
trussed::ClientImplementation<&'service mut trussed::service::Service<Platform>>,
COMMAND_SIZE,
>;
pub fn piv<R>(test: impl FnOnce(&mut Piv) -> R) -> R {
use trussed::Interchange as _;
unsafe { trussed::pipe::TrussedInterchange::reset_claims(); }
unsafe {
trussed::pipe::TrussedInterchange::reset_claims();
}
let trussed_platform = init_platform();
let mut trussed_service = trussed::service::Service::new(trussed_platform);
let client_id = "test";
@@ -31,7 +38,7 @@ pub fn init_platform() -> Platform {
store::InternalStorage::new(),
store::ExternalStorage::new(),
store::VolatileStorage::new(),
);
);
let ui = ui::UserInterface::new();
let platform = Platform::new(rng, store, ui);
@@ -41,28 +48,48 @@ pub fn init_platform() -> Platform {
pub mod ui {
use trussed::platform::{consent, reboot, ui};
pub struct UserInterface { start_time: std::time::Instant }
pub struct UserInterface {
start_time: std::time::Instant,
}
impl UserInterface { pub fn new() -> Self { Self { start_time: std::time::Instant::now() } } }
impl UserInterface {
pub fn new() -> Self {
Self {
start_time: std::time::Instant::now(),
}
}
}
impl trussed::platform::UserInterface for UserInterface {
fn check_user_presence(&mut self) -> consent::Level { consent::Level::Normal }
fn check_user_presence(&mut self) -> consent::Level {
consent::Level::Normal
}
fn set_status(&mut self, _status: ui::Status) {}
fn refresh(&mut self) {}
fn uptime(&mut self) -> core::time::Duration { self.start_time.elapsed() }
fn reboot(&mut self, _to: reboot::To) -> ! { loop { continue; } }
fn uptime(&mut self) -> core::time::Duration {
self.start_time.elapsed()
}
fn reboot(&mut self, _to: reboot::To) -> ! {
loop {
continue;
}
}
}
}
pub mod store {
use littlefs2::{const_ram_storage, consts, fs::{Allocation, Filesystem}};
use littlefs2::{
const_ram_storage, consts,
fs::{Allocation, Filesystem},
};
use trussed::types::{LfsResult, LfsStorage};
const_ram_storage!(InternalStorage, 8192);
const_ram_storage!(ExternalStorage, 8192);
const_ram_storage!(VolatileStorage, 8192);
trussed::store!(Store,
trussed::store!(
Store,
Internal: InternalStorage,
External: ExternalStorage,
Volatile: VolatileStorage