Elaborate "PW status bytes", fix broken naming of members.
Implement set_pw_status_bytes(). Add test code to card-functionality.
This commit is contained in:
parent
c14664b9d5
commit
cb8f3c7cb1
6 changed files with 107 additions and 10 deletions
|
@ -36,9 +36,13 @@ fn main() -> Result<()> {
|
||||||
//
|
//
|
||||||
// panic!();
|
// panic!();
|
||||||
|
|
||||||
print!("Verify");
|
// print!("Verify");
|
||||||
let verify_out = run_test(&mut card, test_verify, &[])?;
|
// let verify_out = run_test(&mut card, test_verify, &[])?;
|
||||||
println!(" {:x?}", verify_out);
|
// println!(" {:x?}", verify_out);
|
||||||
|
|
||||||
|
print!("PW Status bytes");
|
||||||
|
let pw_out = run_test(&mut card, test_pw_status, &[])?;
|
||||||
|
println!(" {:x?}", pw_out);
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,6 +352,31 @@ pub fn test_set_user_data(
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn test_pw_status(
|
||||||
|
ca: &mut CardApp,
|
||||||
|
_param: &[&str],
|
||||||
|
) -> Result<TestOutput, TestError> {
|
||||||
|
let mut out = vec![];
|
||||||
|
|
||||||
|
let ard = ca.get_app_data()?;
|
||||||
|
let mut pws = ard.get_pw_status_bytes()?;
|
||||||
|
|
||||||
|
println!("pws {:?}", pws);
|
||||||
|
|
||||||
|
ca.verify_pw3("12345678")?;
|
||||||
|
|
||||||
|
pws.set_pw1_cds_multi(true);
|
||||||
|
pws.set_pw1_pin_block(true);
|
||||||
|
|
||||||
|
ca.set_pw_status_bytes(&pws, false)?;
|
||||||
|
|
||||||
|
let ard = ca.get_app_data()?;
|
||||||
|
let pws = ard.get_pw_status_bytes()?;
|
||||||
|
println!("pws {:?}", pws);
|
||||||
|
|
||||||
|
Ok(out)
|
||||||
|
}
|
||||||
|
|
||||||
/// Outputs:
|
/// Outputs:
|
||||||
/// - verify pw3 (check) -> Status
|
/// - verify pw3 (check) -> Status
|
||||||
/// - verify pw1 (check) -> Status
|
/// - verify pw1 (check) -> Status
|
||||||
|
|
|
@ -118,6 +118,11 @@ pub(crate) fn put_url(url: Vec<u8>) -> Command {
|
||||||
put_data(&[0x5f, 0x50], url)
|
put_data(&[0x5f, 0x50], url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PUT DO "PW status bytes"
|
||||||
|
pub(crate) fn put_pw_status(data: Vec<u8>) -> Command {
|
||||||
|
put_data(&[0xc4], data)
|
||||||
|
}
|
||||||
|
|
||||||
/// Change PW1 (user pin).
|
/// Change PW1 (user pin).
|
||||||
/// This can be used to reset the counter and set a pin.
|
/// This can be used to reset the counter and set a pin.
|
||||||
pub(crate) fn change_pw1(pin: Vec<u8>) -> Command {
|
pub(crate) fn change_pw1(pin: Vec<u8>) -> Command {
|
||||||
|
|
|
@ -11,7 +11,7 @@ use anyhow::{anyhow, Result};
|
||||||
use crate::algorithm::{Algo, AlgoInfo, AlgoSimple, RsaAttrs};
|
use crate::algorithm::{Algo, AlgoInfo, AlgoSimple, RsaAttrs};
|
||||||
use crate::apdu::{commands, response::Response};
|
use crate::apdu::{commands, response::Response};
|
||||||
use crate::card_do::{
|
use crate::card_do::{
|
||||||
ApplicationRelatedData, Cardholder, SecuritySupportTemplate, Sex,
|
ApplicationRelatedData, Cardholder, PWStatus, SecuritySupportTemplate, Sex,
|
||||||
};
|
};
|
||||||
use crate::crypto_data::{
|
use crate::crypto_data::{
|
||||||
CardUploadableKey, Cryptogram, EccType, Hash, PublicKeyMaterial,
|
CardUploadableKey, Cryptogram, EccType, Hash, PublicKeyMaterial,
|
||||||
|
@ -450,6 +450,28 @@ impl CardApp {
|
||||||
apdu::send_command(self.card(), fp_cmd, false)?.try_into()
|
apdu::send_command(self.card(), fp_cmd, false)?.try_into()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set PW Status Bytes.
|
||||||
|
///
|
||||||
|
/// If `long` is false, send 1 byte to the card, otherwise 4.
|
||||||
|
/// According to the spec, length information should not be changed.
|
||||||
|
///
|
||||||
|
/// So, effectively, with 'long == false' the setting `pw1_cds_multi`
|
||||||
|
/// can be changed.
|
||||||
|
/// With 'long == true', the settings `pw1_pin_block` and `pw3_pin_block`
|
||||||
|
/// can also be changed.
|
||||||
|
///
|
||||||
|
/// (See OpenPGP card spec, pg. 28)
|
||||||
|
pub fn set_pw_status_bytes(
|
||||||
|
&mut self,
|
||||||
|
pw_status: &PWStatus,
|
||||||
|
long: bool,
|
||||||
|
) -> Result<Response, OpenpgpCardError> {
|
||||||
|
let data = pw_status.serialize_for_put(long);
|
||||||
|
|
||||||
|
let cmd = commands::put_pw_status(data);
|
||||||
|
apdu::send_command(self.card(), cmd, false)?.try_into()
|
||||||
|
}
|
||||||
|
|
||||||
/// Set algorithm attributes [4.4.3.9 Algorithm Attributes]
|
/// Set algorithm attributes [4.4.3.9 Algorithm Attributes]
|
||||||
pub fn set_algorithm_attributes(
|
pub fn set_algorithm_attributes(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -319,16 +319,28 @@ impl From<u8> for Sex {
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct PWStatus {
|
pub struct PWStatus {
|
||||||
pub(crate) pw1_cds_multi: bool,
|
pub(crate) pw1_cds_multi: bool,
|
||||||
pub(crate) pw1_derived: bool,
|
pub(crate) pw1_pin_block: bool,
|
||||||
pub(crate) pw1_len: u8,
|
pub(crate) pw1_len: u8,
|
||||||
pub(crate) rc_len: u8,
|
pub(crate) rc_len: u8,
|
||||||
pub(crate) pw3_derived: bool,
|
pub(crate) pw3_pin_block: bool,
|
||||||
pub(crate) pw3_len: u8,
|
pub(crate) pw3_len: u8,
|
||||||
pub(crate) err_count_pw1: u8,
|
pub(crate) err_count_pw1: u8,
|
||||||
pub(crate) err_count_rst: u8,
|
pub(crate) err_count_rst: u8,
|
||||||
pub(crate) err_count_pw3: u8,
|
pub(crate) err_count_pw3: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PWStatus {
|
||||||
|
pub fn set_pw1_cds_multi(&mut self, val: bool) {
|
||||||
|
self.pw1_cds_multi = val;
|
||||||
|
}
|
||||||
|
pub fn set_pw1_pin_block(&mut self, val: bool) {
|
||||||
|
self.pw1_pin_block = val;
|
||||||
|
}
|
||||||
|
pub fn set_pw3_pin_block(&mut self, val: bool) {
|
||||||
|
self.pw3_pin_block = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Fingerprint
|
/// Fingerprint
|
||||||
#[derive(Clone, Eq, PartialEq)]
|
#[derive(Clone, Eq, PartialEq)]
|
||||||
pub struct Fingerprint([u8; 20]);
|
pub struct Fingerprint([u8; 20]);
|
||||||
|
|
|
@ -10,10 +10,10 @@ impl PWStatus {
|
||||||
pub fn try_from(input: &[u8]) -> Result<Self, OpenpgpCardError> {
|
pub fn try_from(input: &[u8]) -> Result<Self, OpenpgpCardError> {
|
||||||
if input.len() == 7 {
|
if input.len() == 7 {
|
||||||
let pw1_cds_multi = input[0] == 0x01;
|
let pw1_cds_multi = input[0] == 0x01;
|
||||||
let pw1_derived = input[1] & 0x80 != 0;
|
let pw1_pin_block = input[1] & 0x80 != 0;
|
||||||
let pw1_len = input[1] & 0x7f;
|
let pw1_len = input[1] & 0x7f;
|
||||||
let rc_len = input[2];
|
let rc_len = input[2];
|
||||||
let pw3_derived = input[3] & 0x80 != 0;
|
let pw3_pin_block = input[3] & 0x80 != 0;
|
||||||
let pw3_len = input[3] & 0x7f;
|
let pw3_len = input[3] & 0x7f;
|
||||||
let err_count_pw1 = input[4];
|
let err_count_pw1 = input[4];
|
||||||
let err_count_rst = input[5];
|
let err_count_rst = input[5];
|
||||||
|
@ -21,10 +21,10 @@ impl PWStatus {
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
pw1_cds_multi,
|
pw1_cds_multi,
|
||||||
pw1_derived,
|
pw1_pin_block,
|
||||||
pw1_len,
|
pw1_len,
|
||||||
rc_len,
|
rc_len,
|
||||||
pw3_derived,
|
pw3_pin_block,
|
||||||
pw3_len,
|
pw3_len,
|
||||||
err_count_pw1,
|
err_count_pw1,
|
||||||
err_count_rst,
|
err_count_rst,
|
||||||
|
@ -37,4 +37,33 @@ impl PWStatus {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PUT DO for PW Status Bytes accepts either 1 or 4 bytes of data.
|
||||||
|
/// This method generates the 1 byte version for 'long==false' and the
|
||||||
|
/// 4 bytes version for 'long==true'.
|
||||||
|
///
|
||||||
|
/// (See OpenPGP card spec, pg. 28)
|
||||||
|
pub fn serialize_for_put(&self, long: bool) -> Vec<u8> {
|
||||||
|
let mut data = vec![];
|
||||||
|
|
||||||
|
data.push(if !self.pw1_cds_multi { 0 } else { 1 });
|
||||||
|
|
||||||
|
if long {
|
||||||
|
let mut b2 = self.pw1_len;
|
||||||
|
if self.pw1_pin_block {
|
||||||
|
b2 |= 0x80;
|
||||||
|
}
|
||||||
|
data.push(b2);
|
||||||
|
|
||||||
|
data.push(self.rc_len);
|
||||||
|
|
||||||
|
let mut b4 = self.pw3_len;
|
||||||
|
if self.pw3_pin_block {
|
||||||
|
b4 |= 0x80;
|
||||||
|
}
|
||||||
|
data.push(b4);
|
||||||
|
}
|
||||||
|
|
||||||
|
data
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue