Use macros to have one source of KeyReferences

This commit is contained in:
Sosthène Guédon
2022-11-04 11:49:20 +01:00
parent 42c1e73a79
commit 0bc75eccb4
4 changed files with 172 additions and 187 deletions
+17 -150
View File
@@ -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<u8> for VerifyKeyReference {
type Error = Status;
fn try_from(p2: u8) -> Result<Self, Self::Error> {
// 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<VerifyArguments<'_>> 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<VerifyArguments<'_>> for Verify {
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(u8)]
pub enum ChangeReferenceKeyReference {
GlobalPin = 0x00,
PivPin = 0x80,
Puk = 0x81,
}
impl TryFrom<u8> for ChangeReferenceKeyReference {
type Error = Status;
fn try_from(p2: u8) -> Result<Self, Self::Error> {
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<ChangeReferenceArguments<'_>> 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<u8> for AuthenticateKeyReference {
type Error = Status;
fn try_from(p2: u8) -> Result<Self, Self::Error> {
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<u8> for GenerateAsymmetricKeyReference {
type Error = Status;
fn try_from(p2: u8) -> Result<Self, Self::Error> {
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,
+151 -33
View File
@@ -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<Self, Self::Error> {
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<u8> for $name {
type Error = ::iso7816::Status;
fn try_from(tag: u8) -> ::core::result::Result<Self, Self::Error> {
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<KeyReference> 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,
}
}
+1 -1
View File
@@ -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 {
+3 -3
View File
@@ -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<u8> for $name {
type Error = Status;
type Error = ::iso7816::Status;
fn try_from(val: u8) -> Result<Self, Self::Error> {
match val {
$(
$num => Ok($name::$var),
)*
_ => Err(Status::KeyReferenceNotFound)
_ => Err(::iso7816::Status::KeyReferenceNotFound)
}
}
}