From 0bc75eccb4ce0945b4bee65f5b9a9f216cc726ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Fri, 4 Nov 2022 11:49:20 +0100 Subject: [PATCH] Use macros to have one source of KeyReferences --- src/commands.rs | 167 +++++------------------------------------- src/container.rs | 184 ++++++++++++++++++++++++++++++++++++++--------- src/lib.rs | 2 +- src/piv_types.rs | 6 +- 4 files changed, 172 insertions(+), 187 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 2910ec4..a8a7976 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -9,7 +9,13 @@ use core::convert::{TryFrom, TryInto}; use iso7816::{Instruction, Status}; use crate::state::TouchPolicy; -pub use crate::{container as containers, piv_types, Pin, Puk}; +pub use crate::{ + container::{ + self as containers, AuthenticateKeyReference, ChangeReferenceKeyReference, + GenerateAsymmetricKeyReference, VerifyKeyReference, + }, + piv_types, Pin, Puk, +}; // https://developers.yubico.com/PIV/Introduction/Yubico_extensions.html #[derive(Copy, Clone, Debug, Eq, PartialEq)] @@ -111,32 +117,6 @@ impl TryFrom<&[u8]> for GetData { } } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[repr(u8)] -pub enum VerifyKeyReference { - GlobalPin = 0x00, - PivPin = 0x80, - PrimaryFingerOcc = 0x96, - SecondaryFingerOcc = 0x97, - PairingCode = 0x98, -} - -impl TryFrom for VerifyKeyReference { - type Error = Status; - fn try_from(p2: u8) -> Result { - // If the PIV Card Application does not contain the Discovery Object as described in Part 1, - // then no other key reference shall be able to be verified by the PIV Card Application VERIFY command. - match p2 { - 0x00 => Ok(Self::GlobalPin), - 0x80 => Ok(Self::PivPin), - 0x96 => Ok(Self::PrimaryFingerOcc), - 0x97 => Ok(Self::SecondaryFingerOcc), - 0x98 => Ok(Self::PairingCode), - _ => Err(Status::KeyReferenceNotFound), - } - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct VerifyLogout(bool); @@ -179,7 +159,7 @@ impl TryFrom> for Verify { logout, data, } = arguments; - if key_reference != VerifyKeyReference::PivPin { + if key_reference != VerifyKeyReference::ApplicationPin { return Err(Status::FunctionNotSupported); } Ok(match (logout.0, data.len()) { @@ -195,26 +175,6 @@ impl TryFrom> for Verify { } } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[repr(u8)] -pub enum ChangeReferenceKeyReference { - GlobalPin = 0x00, - PivPin = 0x80, - Puk = 0x81, -} - -impl TryFrom for ChangeReferenceKeyReference { - type Error = Status; - fn try_from(p2: u8) -> Result { - match p2 { - 0x00 => Ok(Self::GlobalPin), - 0x80 => Ok(Self::PivPin), - 0x81 => Ok(Self::Puk), - _ => Err(Status::KeyReferenceNotFound), - } - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct ChangeReferenceArguments<'l> { pub key_reference: ChangeReferenceKeyReference, @@ -238,21 +198,18 @@ impl TryFrom> for ChangeReference { use ChangeReferenceKeyReference::*; Ok(match (key_reference, data) { (GlobalPin, _) => return Err(Status::FunctionNotSupported), - (PivPin, data) => ChangeReference::ChangePin { + (ApplicationPin, 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)?), - } - } + (PinUnblockingKey, data) => ChangeReference::ChangePuk { + old_puk: Puk(data[..8] + .try_into() + .map_err(|_| Status::IncorrectDataParameter)?), + new_puk: Puk(data[8..] + .try_into() + .map_err(|_| Status::IncorrectDataParameter)?), + }, }) } } @@ -276,72 +233,6 @@ impl TryFrom<&[u8]> for ResetPinRetries { } } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[repr(u8)] -pub enum AuthenticateKeyReference { - SecureMessaging = 0x04, - Authentication = 0x9a, - Administration = 0x9b, - Signature = 0x9c, - Management = 0x9d, - CardAuthentication = 0x9e, - Retired01 = 0x82, - Retired02 = 0x83, - Retired03 = 0x84, - Retired04 = 0x85, - Retired05 = 0x86, - Retired06 = 0x87, - Retired07 = 0x88, - Retired08 = 0x89, - Retired09 = 0x8A, - Retired10 = 0x8B, - Retired11 = 0x8C, - Retired12 = 0x8D, - Retired13 = 0x8E, - Retired14 = 0x8F, - Retired15 = 0x90, - Retired16 = 0x91, - Retired17 = 0x92, - Retired18 = 0x93, - Retired19 = 0x94, - Retired20 = 0x95, -} - -impl TryFrom for AuthenticateKeyReference { - type Error = Status; - fn try_from(p2: u8) -> Result { - match p2 { - 0x04 => Ok(Self::SecureMessaging), - 0x9a => Ok(Self::Authentication), - 0x9b => Ok(Self::Administration), - 0x9c => Ok(Self::Signature), - 0x9d => Ok(Self::Management), - 0x9e => Ok(Self::CardAuthentication), - 0x82 => Ok(Self::Retired01), - 0x83 => Ok(Self::Retired02), - 0x84 => Ok(Self::Retired03), - 0x85 => Ok(Self::Retired04), - 0x86 => Ok(Self::Retired05), - 0x87 => Ok(Self::Retired06), - 0x88 => Ok(Self::Retired07), - 0x89 => Ok(Self::Retired08), - 0x8A => Ok(Self::Retired09), - 0x8B => Ok(Self::Retired10), - 0x8C => Ok(Self::Retired11), - 0x8D => Ok(Self::Retired12), - 0x8E => Ok(Self::Retired13), - 0x8F => Ok(Self::Retired14), - 0x90 => Ok(Self::Retired15), - 0x91 => Ok(Self::Retired16), - 0x92 => Ok(Self::Retired17), - 0x93 => Ok(Self::Retired18), - 0x94 => Ok(Self::Retired19), - 0x95 => Ok(Self::Retired20), - _ => Err(Status::KeyReferenceNotFound), - } - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct AuthenticateArguments<'l> { /// To allow the authenticator to have additional algorithms beyond NIST SP 800-78-4, @@ -361,30 +252,6 @@ impl TryFrom<&[u8]> for PutData { } } -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[repr(u8)] -pub enum GenerateAsymmetricKeyReference { - SecureMessaging = 0x04, - Authentication = 0x9a, - Signature = 0x9c, - Management = 0x9d, - CardAuthentication = 0x9e, -} - -impl TryFrom for GenerateAsymmetricKeyReference { - type Error = Status; - fn try_from(p2: u8) -> Result { - match p2 { - 0x04 => Err(Status::FunctionNotSupported), - 0x9a => Ok(Self::Authentication), - 0x9c => Ok(Self::Signature), - 0x9d => Ok(Self::Management), - 0x9e => Ok(Self::CardAuthentication), - _ => Err(Status::KeyReferenceNotFound), - } - } -} - #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct GenerateAsymmetricArguments<'l> { pub key_reference: GenerateAsymmetricKeyReference, diff --git a/src/container.rs b/src/container.rs index 62359aa..cf98266 100644 --- a/src/container.rs +++ b/src/container.rs @@ -2,6 +2,61 @@ use core::convert::TryFrom; use hex_literal::hex; +macro_rules! enum_subset { + ( + $(#[$outer:meta])* + $vis:vis enum $name:ident: $sup:ident { + $($var:ident),+ + $(,)* + } + ) => { + $(#[$outer])* + #[repr(u8)] + $vis enum $name { + $( + $var, + )* + } + + impl TryFrom<$sup> for $name + { + type Error = ::iso7816::Status; + fn try_from(val: $sup) -> ::core::result::Result { + match val { + $( + $sup::$var => Ok($name::$var), + )* + _ => Err(::iso7816::Status::KeyReferenceNotFound) + } + } + } + + impl From<$name> for $sup + { + fn from(v: $name) -> $sup { + match v { + $( + $name::$var => $sup::$var, + )* + } + } + } + + impl TryFrom for $name { + type Error = ::iso7816::Status; + fn try_from(tag: u8) -> ::core::result::Result { + let v: $sup = tag.try_into()?; + match v { + $( + $sup::$var => Ok($name::$var), + )* + _ => Err(::iso7816::Status::KeyReferenceNotFound) + } + } + } + } +} + pub struct Tag<'a>(&'a [u8]); impl<'a> Tag<'a> { pub fn new(slice: &'a [u8]) -> Self { @@ -12,45 +67,108 @@ impl<'a> Tag<'a> { #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RetiredIndex(u8); -// #[repr(u8)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum KeyReference { - GlobalPin, - ApplicationPin, - PinUnblockingKey, - PrimaryFinger, - SecondaryFinger, - PairingCode, +crate::enum_u8! { + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub enum KeyReference { + GlobalPin = 0x00, + SecureMessaging = 0x04, + ApplicationPin = 0x80, + PinUnblockingKey = 0x81, + PrimaryFinger = 0x96, + SecondaryFinger = 0x97, + PairingCode = 0x98, - PivAuthentication, - PivCardApplicationAdministration, - DigitalSignature, - KeyManagement, - CardAuthentication, + PivAuthentication = 0x9A, + PivCardApplicationAdministration = 0x9B, + DigitalSignature = 0x9C, + KeyManagement = 0x9D, + CardAuthentication = 0x9E, - // 20x - RetiredKeyManagement(RetiredIndex), + Retired01 = 0x82, + Retired02 = 0x83, + Retired03 = 0x84, + Retired04 = 0x85, + Retired05 = 0x86, + Retired06 = 0x87, + Retired07 = 0x88, + Retired08 = 0x89, + Retired09 = 0x8A, + Retired10 = 0x8B, + Retired11 = 0x8C, + Retired12 = 0x8D, + Retired13 = 0x8E, + Retired14 = 0x8F, + Retired15 = 0x90, + Retired16 = 0x91, + Retired17 = 0x92, + Retired18 = 0x93, + Retired19 = 0x94, + Retired20 = 0x95, + } } -impl From for u8 { - fn from(reference: KeyReference) -> Self { - use KeyReference::*; - match reference { - GlobalPin => 0x00, - ApplicationPin => 0x80, - PinUnblockingKey => 0x81, - PrimaryFinger => 0x96, - SecondaryFinger => 0x97, - PairingCode => 0x98, +enum_subset! { + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub enum GenerateAsymmetricKeyReference: KeyReference { + SecureMessaging, + PivAuthentication, + DigitalSignature, + KeyManagement, + CardAuthentication, + } +} - PivAuthentication => 0x9A, - PivCardApplicationAdministration => 0x9B, - DigitalSignature => 0x9C, - KeyManagement => 0x9D, - CardAuthentication => 0x9E, +enum_subset! { + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub enum ChangeReferenceKeyReference: KeyReference { + GlobalPin, + ApplicationPin, + PinUnblockingKey, + } +} - RetiredKeyManagement(RetiredIndex(i)) => (0x82 - 1) + i, - } +enum_subset! { + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub enum VerifyKeyReference: KeyReference { + GlobalPin, + ApplicationPin, + PrimaryFinger, + SecondaryFinger, + PairingCode, + + } +} + +enum_subset! { + + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub enum AuthenticateKeyReference: KeyReference { + SecureMessaging, + PivAuthentication, + PivCardApplicationAdministration, + DigitalSignature, + KeyManagement, + CardAuthentication, + Retired01, + Retired02, + Retired03, + Retired04, + Retired05, + Retired06, + Retired07, + Retired08, + Retired09, + Retired10, + Retired11, + Retired12, + Retired13, + Retired14, + Retired15, + Retired16, + Retired17, + Retired18, + Retired19, + Retired20, } } diff --git a/src/lib.rs b/src/lib.rs index fcef2d1..0087cb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -148,7 +148,7 @@ where } Verify::Status(key_reference) => { - if key_reference != commands::VerifyKeyReference::PivPin { + if key_reference != commands::VerifyKeyReference::ApplicationPin { return Err(Status::FunctionNotSupported); } if self.state.runtime.app_security_status.pin_verified { diff --git a/src/piv_types.rs b/src/piv_types.rs index f57b90b..47e222a 100644 --- a/src/piv_types.rs +++ b/src/piv_types.rs @@ -2,9 +2,9 @@ use core::convert::{TryFrom, TryInto}; use flexiber::Encodable; use hex_literal::hex; -use iso7816::Status; use serde::{Deserialize, Serialize}; +#[macro_export] macro_rules! enum_u8 { ( $(#[$outer:meta])* @@ -22,13 +22,13 @@ macro_rules! enum_u8 { } impl TryFrom for $name { - type Error = Status; + type Error = ::iso7816::Status; fn try_from(val: u8) -> Result { match val { $( $num => Ok($name::$var), )* - _ => Err(Status::KeyReferenceNotFound) + _ => Err(::iso7816::Status::KeyReferenceNotFound) } } }