Remove "get_" prefix from getter function names (to better conform with Rust API Guidelines https://rust-lang.github.io/api-guidelines).
This commit is contained in:
parent
9d87cddb60
commit
ecd862e23f
23 changed files with 298 additions and 281 deletions
|
@ -99,8 +99,8 @@ impl TestCard {
|
||||||
|
|
||||||
for mut ca in PcscClient::cards()? {
|
for mut ca in PcscClient::cards()? {
|
||||||
// Set Card Capabilities (chaining, command length, ..)
|
// Set Card Capabilities (chaining, command length, ..)
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let app_id = ard.get_application_id()?;
|
let app_id = ard.application_id()?;
|
||||||
|
|
||||||
if app_id.ident().as_str() == ident.to_uppercase() {
|
if app_id.ident().as_str() == ident.to_uppercase() {
|
||||||
// println!("opened pcsc card {}", ident);
|
// println!("opened pcsc card {}", ident);
|
||||||
|
|
|
@ -112,10 +112,10 @@ fn check_key_upload_metadata(
|
||||||
ca: &mut CardApp,
|
ca: &mut CardApp,
|
||||||
meta: &[(String, KeyGenerationTime)],
|
meta: &[(String, KeyGenerationTime)],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
|
|
||||||
// check fingerprints
|
// check fingerprints
|
||||||
let card_fp = ard.get_fingerprints()?;
|
let card_fp = ard.fingerprints()?;
|
||||||
|
|
||||||
let sig = card_fp.signature().expect("signature fingerprint");
|
let sig = card_fp.signature().expect("signature fingerprint");
|
||||||
assert_eq!(format!("{:X}", sig), meta[0].0);
|
assert_eq!(format!("{:X}", sig), meta[0].0);
|
||||||
|
@ -129,7 +129,7 @@ fn check_key_upload_metadata(
|
||||||
assert_eq!(format!("{:X}", auth), meta[2].0);
|
assert_eq!(format!("{:X}", auth), meta[2].0);
|
||||||
|
|
||||||
// get_key_generation_times
|
// get_key_generation_times
|
||||||
let card_kg = ard.get_key_generation_times()?;
|
let card_kg = ard.key_generation_times()?;
|
||||||
|
|
||||||
let sig = card_kg.signature().expect("signature creation time");
|
let sig = card_kg.signature().expect("signature creation time");
|
||||||
assert_eq!(sig, &meta[0].1);
|
assert_eq!(sig, &meta[0].1);
|
||||||
|
@ -156,18 +156,18 @@ pub fn test_print_caps(
|
||||||
ca: &mut CardApp,
|
ca: &mut CardApp,
|
||||||
_param: &[&str],
|
_param: &[&str],
|
||||||
) -> Result<TestOutput, TestError> {
|
) -> Result<TestOutput, TestError> {
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
|
|
||||||
let aid = ard.get_application_id()?;
|
let aid = ard.application_id()?;
|
||||||
println!("aid: {:#x?}", aid);
|
println!("aid: {:#x?}", aid);
|
||||||
|
|
||||||
let hist = ard.get_historical()?;
|
let hist = ard.historical_bytes()?;
|
||||||
println!("hist: {:#?}", hist);
|
println!("hist: {:#?}", hist);
|
||||||
|
|
||||||
let ecap = ard.get_extended_capabilities()?;
|
let ecap = ard.extended_capabilities()?;
|
||||||
println!("ecap: {:#?}", ecap);
|
println!("ecap: {:#?}", ecap);
|
||||||
|
|
||||||
let eli = ard.get_extended_length_information()?;
|
let eli = ard.extended_length_information()?;
|
||||||
println!("eli: {:#?}", eli);
|
println!("eli: {:#?}", eli);
|
||||||
|
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
|
@ -177,14 +177,14 @@ pub fn test_print_algo_info(
|
||||||
ca: &mut CardApp,
|
ca: &mut CardApp,
|
||||||
_param: &[&str],
|
_param: &[&str],
|
||||||
) -> Result<TestOutput, TestError> {
|
) -> Result<TestOutput, TestError> {
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
|
|
||||||
let dec = ard.get_algorithm_attributes(KeyType::Decryption)?;
|
let dec = ard.algorithm_attributes(KeyType::Decryption)?;
|
||||||
println!("Current algorithm for the decrypt slot: {}", dec);
|
println!("Current algorithm for the decrypt slot: {}", dec);
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
let algo = ca.get_algo_info();
|
let algo = ca.algorithm_information();
|
||||||
if let Ok(Some(algo)) = algo {
|
if let Ok(Some(algo)) = algo {
|
||||||
println!("Card algorithm list:\n{}", algo);
|
println!("Card algorithm list:\n{}", algo);
|
||||||
}
|
}
|
||||||
|
@ -275,12 +275,12 @@ pub fn test_get_pub(
|
||||||
ca: &mut CardApp,
|
ca: &mut CardApp,
|
||||||
_param: &[&str],
|
_param: &[&str],
|
||||||
) -> Result<TestOutput, TestError> {
|
) -> Result<TestOutput, TestError> {
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let key_gen = ard.get_key_generation_times()?;
|
let key_gen = ard.key_generation_times()?;
|
||||||
|
|
||||||
// --
|
// --
|
||||||
|
|
||||||
let sig = ca.get_pub_key(KeyType::Signing)?;
|
let sig = ca.public_key(KeyType::Signing)?;
|
||||||
let ts = key_gen.signature().unwrap().get().into();
|
let ts = key_gen.signature().unwrap().get().into();
|
||||||
let key = public_key_material_to_key(&sig, KeyType::Signing, ts)?;
|
let key = public_key_material_to_key(&sig, KeyType::Signing, ts)?;
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ pub fn test_get_pub(
|
||||||
|
|
||||||
// --
|
// --
|
||||||
|
|
||||||
let dec = ca.get_pub_key(KeyType::Decryption)?;
|
let dec = ca.public_key(KeyType::Decryption)?;
|
||||||
let ts = key_gen.decryption().unwrap().get().into();
|
let ts = key_gen.decryption().unwrap().get().into();
|
||||||
let key = public_key_material_to_key(&dec, KeyType::Decryption, ts)?;
|
let key = public_key_material_to_key(&dec, KeyType::Decryption, ts)?;
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ pub fn test_get_pub(
|
||||||
|
|
||||||
// --
|
// --
|
||||||
|
|
||||||
let auth = ca.get_pub_key(KeyType::Authentication)?;
|
let auth = ca.public_key(KeyType::Authentication)?;
|
||||||
let ts = key_gen.authentication().unwrap().get().into();
|
let ts = key_gen.authentication().unwrap().get().into();
|
||||||
let key = public_key_material_to_key(&auth, KeyType::Authentication, ts)?;
|
let key = public_key_material_to_key(&auth, KeyType::Authentication, ts)?;
|
||||||
|
|
||||||
|
@ -342,7 +342,7 @@ pub fn test_set_user_data(
|
||||||
ca.set_url("https://duckduckgo.com/")?;
|
ca.set_url("https://duckduckgo.com/")?;
|
||||||
|
|
||||||
// read all the fields back again, expect equal data
|
// read all the fields back again, expect equal data
|
||||||
let ch = ca.get_cardholder_related_data()?;
|
let ch = ca.cardholder_related_data()?;
|
||||||
|
|
||||||
assert_eq!(ch.name(), Some("Bar<<Foo"));
|
assert_eq!(ch.name(), Some("Bar<<Foo"));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -351,7 +351,7 @@ pub fn test_set_user_data(
|
||||||
);
|
);
|
||||||
assert_eq!(ch.sex(), Some(Sex::Female));
|
assert_eq!(ch.sex(), Some(Sex::Female));
|
||||||
|
|
||||||
let url = ca.get_url()?;
|
let url = ca.url()?;
|
||||||
assert_eq!(url, "https://duckduckgo.com/".to_string());
|
assert_eq!(url, "https://duckduckgo.com/".to_string());
|
||||||
|
|
||||||
Ok(vec![])
|
Ok(vec![])
|
||||||
|
@ -365,7 +365,7 @@ pub fn test_private_data(
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
let d = ca.get_private(1)?;
|
let d = ca.private_use_do(1)?;
|
||||||
println!("data 1 {:?}", d);
|
println!("data 1 {:?}", d);
|
||||||
|
|
||||||
ca.verify_pw1("123456")?;
|
ca.verify_pw1("123456")?;
|
||||||
|
@ -378,13 +378,13 @@ pub fn test_private_data(
|
||||||
ca.set_private(2, "Foo bar2!".as_bytes().to_vec())?;
|
ca.set_private(2, "Foo bar2!".as_bytes().to_vec())?;
|
||||||
ca.set_private(4, "Foo bar4!".as_bytes().to_vec())?;
|
ca.set_private(4, "Foo bar4!".as_bytes().to_vec())?;
|
||||||
|
|
||||||
let d = ca.get_private(1)?;
|
let d = ca.private_use_do(1)?;
|
||||||
println!("data 1 {:?}", d);
|
println!("data 1 {:?}", d);
|
||||||
let d = ca.get_private(2)?;
|
let d = ca.private_use_do(2)?;
|
||||||
println!("data 2 {:?}", d);
|
println!("data 2 {:?}", d);
|
||||||
let d = ca.get_private(3)?;
|
let d = ca.private_use_do(3)?;
|
||||||
println!("data 3 {:?}", d);
|
println!("data 3 {:?}", d);
|
||||||
let d = ca.get_private(4)?;
|
let d = ca.private_use_do(4)?;
|
||||||
println!("data 4 {:?}", d);
|
println!("data 4 {:?}", d);
|
||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
|
@ -398,7 +398,7 @@ pub fn test_cardholder_cert(
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
match ca.get_cardholder_certificate() {
|
match ca.cardholder_certificate() {
|
||||||
Ok(res) => out
|
Ok(res) => out
|
||||||
.push(TestResult::Text(format!("got cert {:x?}", res.get_data()))),
|
.push(TestResult::Text(format!("got cert {:x?}", res.get_data()))),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -425,7 +425,7 @@ pub fn test_cardholder_cert(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let res = ca.get_cardholder_certificate()?;
|
let res = ca.cardholder_certificate()?;
|
||||||
out.push(TestResult::Text("get cert ok".to_string()));
|
out.push(TestResult::Text("get cert ok".to_string()));
|
||||||
|
|
||||||
if res.get_data() != data {
|
if res.get_data() != data {
|
||||||
|
@ -455,8 +455,8 @@ pub fn test_pw_status(
|
||||||
) -> Result<TestOutput, TestError> {
|
) -> Result<TestOutput, TestError> {
|
||||||
let mut out = vec![];
|
let mut out = vec![];
|
||||||
|
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let mut pws = ard.get_pw_status_bytes()?;
|
let mut pws = ard.pw_status_bytes()?;
|
||||||
|
|
||||||
println!("pws {:?}", pws);
|
println!("pws {:?}", pws);
|
||||||
|
|
||||||
|
@ -467,8 +467,8 @@ pub fn test_pw_status(
|
||||||
|
|
||||||
ca.set_pw_status_bytes(&pws, false)?;
|
ca.set_pw_status_bytes(&pws, false)?;
|
||||||
|
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let pws = ard.get_pw_status_bytes()?;
|
let pws = ard.pw_status_bytes()?;
|
||||||
println!("pws {:?}", pws);
|
println!("pws {:?}", pws);
|
||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
|
@ -519,7 +519,7 @@ pub fn test_verify(
|
||||||
|
|
||||||
ca.set_name("Admin<<Hello")?;
|
ca.set_name("Admin<<Hello")?;
|
||||||
|
|
||||||
let cardholder = ca.get_cardholder_related_data()?;
|
let cardholder = ca.cardholder_related_data()?;
|
||||||
assert_eq!(cardholder.name(), Some("Admin<<Hello"));
|
assert_eq!(cardholder.name(), Some("Admin<<Hello"));
|
||||||
|
|
||||||
ca.verify_pw1("123456")?;
|
ca.verify_pw1("123456")?;
|
||||||
|
@ -537,7 +537,7 @@ pub fn test_verify(
|
||||||
|
|
||||||
ca.set_name("There<<Hello")?;
|
ca.set_name("There<<Hello")?;
|
||||||
|
|
||||||
let cardholder = ca.get_cardholder_related_data()?;
|
let cardholder = ca.cardholder_related_data()?;
|
||||||
assert_eq!(cardholder.name(), Some("There<<Hello"));
|
assert_eq!(cardholder.name(), Some("There<<Hello"));
|
||||||
|
|
||||||
Ok(out)
|
Ok(out)
|
||||||
|
@ -673,8 +673,8 @@ pub fn run_test(
|
||||||
param: &[&str],
|
param: &[&str],
|
||||||
) -> Result<TestOutput, TestError> {
|
) -> Result<TestOutput, TestError> {
|
||||||
let mut ca = card.get_card_app()?;
|
let mut ca = card.get_card_app()?;
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let _app_id = ard.get_application_id()?;
|
let _app_id = ard.application_id()?;
|
||||||
|
|
||||||
t(&mut ca, param)
|
t(&mut ca, param)
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ pub(crate) fn upload_subkeys(
|
||||||
KeyType::Decryption,
|
KeyType::Decryption,
|
||||||
KeyType::Authentication,
|
KeyType::Authentication,
|
||||||
] {
|
] {
|
||||||
if let Some(vka) = sq_util::get_subkey_by_type(cert, policy, *kt)? {
|
if let Some(vka) = sq_util::subkey_by_type(cert, policy, *kt)? {
|
||||||
// store fingerprint as return-value
|
// store fingerprint as return-value
|
||||||
let fp = vka.fingerprint().to_hex();
|
let fp = vka.fingerprint().to_hex();
|
||||||
// store key creation time as return-value
|
// store key creation time as return-value
|
||||||
|
|
|
@ -48,7 +48,7 @@ pub struct Open<'a> {
|
||||||
|
|
||||||
impl<'a> Open<'a> {
|
impl<'a> Open<'a> {
|
||||||
pub fn new(card_app: &'a mut CardApp) -> Result<Self, Error> {
|
pub fn new(card_app: &'a mut CardApp) -> Result<Self, Error> {
|
||||||
let ard = card_app.get_application_related_data()?;
|
let ard = card_app.application_related_data()?;
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
card_app,
|
card_app,
|
||||||
|
@ -210,17 +210,17 @@ impl<'a> Open<'a> {
|
||||||
pub fn application_identifier(
|
pub fn application_identifier(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<ApplicationIdentifier, Error> {
|
) -> Result<ApplicationIdentifier, Error> {
|
||||||
self.ard.get_application_id()
|
self.ard.application_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn historical_bytes(&self) -> Result<HistoricalBytes, Error> {
|
pub fn historical_bytes(&self) -> Result<HistoricalBytes, Error> {
|
||||||
self.ard.get_historical()
|
self.ard.historical_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extended_length_information(
|
pub fn extended_length_information(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<ExtendedLengthInfo>> {
|
) -> Result<Option<ExtendedLengthInfo>> {
|
||||||
self.ard.get_extended_length_information()
|
self.ard.extended_length_information()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -236,20 +236,20 @@ impl<'a> Open<'a> {
|
||||||
pub fn extended_capabilities(
|
pub fn extended_capabilities(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<ExtendedCapabilities, Error> {
|
) -> Result<ExtendedCapabilities, Error> {
|
||||||
self.ard.get_extended_capabilities()
|
self.ard.extended_capabilities()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> {
|
pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> {
|
||||||
self.ard.get_algorithm_attributes(key_type)
|
self.ard.algorithm_attributes(key_type)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PW status Bytes
|
/// PW status Bytes
|
||||||
pub fn pw_status_bytes(&self) -> Result<PWStatusBytes> {
|
pub fn pw_status_bytes(&self) -> Result<PWStatusBytes> {
|
||||||
self.ard.get_pw_status_bytes()
|
self.ard.pw_status_bytes()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fingerprints(&self) -> Result<KeySet<Fingerprint>, Error> {
|
pub fn fingerprints(&self) -> Result<KeySet<Fingerprint>, Error> {
|
||||||
self.ard.get_fingerprints()
|
self.ard.fingerprints()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -260,7 +260,7 @@ impl<'a> Open<'a> {
|
||||||
pub fn key_generation_times(
|
pub fn key_generation_times(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<KeySet<KeyGenerationTime>, Error> {
|
) -> Result<KeySet<KeyGenerationTime>, Error> {
|
||||||
self.ard.get_key_generation_times()
|
self.ard.key_generation_times()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
|
@ -295,21 +295,21 @@ impl<'a> Open<'a> {
|
||||||
// --- URL (5f50) ---
|
// --- URL (5f50) ---
|
||||||
|
|
||||||
pub fn url(&mut self) -> Result<String> {
|
pub fn url(&mut self) -> Result<String> {
|
||||||
self.card_app.get_url()
|
self.card_app.url()
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cardholder related data (65) ---
|
// --- cardholder related data (65) ---
|
||||||
pub fn cardholder_related_data(
|
pub fn cardholder_related_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<CardholderRelatedData> {
|
) -> Result<CardholderRelatedData> {
|
||||||
self.card_app.get_cardholder_related_data()
|
self.card_app.cardholder_related_data()
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- security support template (7a) ---
|
// --- security support template (7a) ---
|
||||||
pub fn security_support_template(
|
pub fn security_support_template(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<SecuritySupportTemplate> {
|
) -> Result<SecuritySupportTemplate> {
|
||||||
self.card_app.get_security_support_template()
|
self.card_app.security_support_template()
|
||||||
}
|
}
|
||||||
|
|
||||||
// DO "Algorithm Information" (0xFA)
|
// DO "Algorithm Information" (0xFA)
|
||||||
|
@ -323,21 +323,21 @@ impl<'a> Open<'a> {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.card_app.get_algo_info()
|
self.card_app.algorithm_information()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Firmware Version, YubiKey specific (?)
|
/// Firmware Version, YubiKey specific (?)
|
||||||
pub fn firmware_version(&mut self) -> Result<Vec<u8>> {
|
pub fn firmware_version(&mut self) -> Result<Vec<u8>> {
|
||||||
self.card_app.get_firmware_version()
|
self.card_app.firmware_version()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
|
|
||||||
pub fn get_pub_key(
|
pub fn public_key(
|
||||||
&mut self,
|
&mut self,
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
) -> Result<PublicKeyMaterial> {
|
) -> Result<PublicKeyMaterial> {
|
||||||
self.card_app.get_pub_key(key_type).map_err(|e| e.into())
|
self.card_app.public_key(key_type).map_err(|e| e.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------
|
// ----------
|
||||||
|
@ -396,7 +396,7 @@ pub struct Admin<'app, 'open> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'app, 'open> Admin<'app, 'open> {
|
impl<'app, 'open> Admin<'app, 'open> {
|
||||||
pub fn get_open(&'_ mut self) -> &mut Open<'app> {
|
pub fn as_open(&'_ mut self) -> &mut Open<'app> {
|
||||||
self.oc
|
self.oc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,8 @@ impl<'a> CardDecryptor<'a> {
|
||||||
policy: &dyn Policy,
|
policy: &dyn Policy,
|
||||||
) -> Result<CardDecryptor<'a>, Error> {
|
) -> Result<CardDecryptor<'a>, Error> {
|
||||||
// Get the fingerprint for the decryption key from the card.
|
// Get the fingerprint for the decryption key from the card.
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let fps = ard.get_fingerprints()?;
|
let fps = ard.fingerprints()?;
|
||||||
let fp = fps.decryption();
|
let fp = fps.decryption();
|
||||||
|
|
||||||
if let Some(fp) = fp {
|
if let Some(fp) = fp {
|
||||||
|
|
|
@ -119,21 +119,21 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let p = StandardPolicy::new();
|
let p = StandardPolicy::new();
|
||||||
|
|
||||||
if let Some(vka) =
|
if let Some(vka) =
|
||||||
sq_util::get_subkey_by_type(&cert, &p, KeyType::Signing)?
|
sq_util::subkey_by_type(&cert, &p, KeyType::Signing)?
|
||||||
{
|
{
|
||||||
println!("Upload signing key");
|
println!("Upload signing key");
|
||||||
admin.upload_key(vka, KeyType::Signing, None)?;
|
admin.upload_key(vka, KeyType::Signing, None)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(vka) =
|
if let Some(vka) =
|
||||||
sq_util::get_subkey_by_type(&cert, &p, KeyType::Decryption)?
|
sq_util::subkey_by_type(&cert, &p, KeyType::Decryption)?
|
||||||
{
|
{
|
||||||
println!("Upload decryption key");
|
println!("Upload decryption key");
|
||||||
admin.upload_key(vka, KeyType::Decryption, None)?;
|
admin.upload_key(vka, KeyType::Decryption, None)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(vka) =
|
if let Some(vka) =
|
||||||
sq_util::get_subkey_by_type(&cert, &p, KeyType::Authentication)?
|
sq_util::subkey_by_type(&cert, &p, KeyType::Authentication)?
|
||||||
{
|
{
|
||||||
println!("Upload auth key");
|
println!("Upload auth key");
|
||||||
admin.upload_key(vka, KeyType::Authentication, None)?;
|
admin.upload_key(vka, KeyType::Authentication, None)?;
|
||||||
|
|
|
@ -51,7 +51,7 @@ impl SequoiaKey {
|
||||||
/// Implement the `CardUploadableKey` trait that openpgp-card uses to
|
/// Implement the `CardUploadableKey` trait that openpgp-card uses to
|
||||||
/// upload (sub)keys to a card.
|
/// upload (sub)keys to a card.
|
||||||
impl CardUploadableKey for SequoiaKey {
|
impl CardUploadableKey for SequoiaKey {
|
||||||
fn get_key(&self) -> Result<PrivateKeyMaterial> {
|
fn private_key(&self) -> Result<PrivateKeyMaterial> {
|
||||||
// Decrypt key with password, if set
|
// Decrypt key with password, if set
|
||||||
let key = match &self.password {
|
let key = match &self.password {
|
||||||
None => self.key.clone(),
|
None => self.key.clone(),
|
||||||
|
@ -116,7 +116,7 @@ impl CardUploadableKey for SequoiaKey {
|
||||||
|
|
||||||
/// Number of non-leap seconds since January 1, 1970 0:00:00 UTC
|
/// Number of non-leap seconds since January 1, 1970 0:00:00 UTC
|
||||||
/// (aka "UNIX timestamp")
|
/// (aka "UNIX timestamp")
|
||||||
fn get_ts(&self) -> KeyGenerationTime {
|
fn timestamp(&self) -> KeyGenerationTime {
|
||||||
let ts: Timestamp = Timestamp::try_from(self.key.creation_time())
|
let ts: Timestamp = Timestamp::try_from(self.key.creation_time())
|
||||||
.expect("Creation time cannot be converted into u32 timestamp");
|
.expect("Creation time cannot be converted into u32 timestamp");
|
||||||
let ts: u32 = ts.into();
|
let ts: u32 = ts.into();
|
||||||
|
@ -124,7 +124,7 @@ impl CardUploadableKey for SequoiaKey {
|
||||||
ts.into()
|
ts.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_fp(&self) -> Result<Fingerprint, Error> {
|
fn fingerprint(&self) -> Result<Fingerprint, Error> {
|
||||||
let fp = self.key.fingerprint();
|
let fp = self.key.fingerprint();
|
||||||
fp.as_bytes().try_into()
|
fp.as_bytes().try_into()
|
||||||
}
|
}
|
||||||
|
@ -161,32 +161,32 @@ impl SqRSA {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RSAKey for SqRSA {
|
impl RSAKey for SqRSA {
|
||||||
fn get_e(&self) -> &[u8] {
|
fn e(&self) -> &[u8] {
|
||||||
self.e.value()
|
self.e.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_p(&self) -> &[u8] {
|
fn p(&self) -> &[u8] {
|
||||||
self.p.value()
|
self.p.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_q(&self) -> &[u8] {
|
fn q(&self) -> &[u8] {
|
||||||
self.q.value()
|
self.q.value()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pq(&self) -> Box<[u8]> {
|
fn pq(&self) -> Box<[u8]> {
|
||||||
let (_, _, inv) = self.nettle.d_crt();
|
let (_, _, inv) = self.nettle.d_crt();
|
||||||
inv
|
inv
|
||||||
}
|
}
|
||||||
fn get_dp1(&self) -> Box<[u8]> {
|
fn dp1(&self) -> Box<[u8]> {
|
||||||
let (dp, _, _) = self.nettle.d_crt();
|
let (dp, _, _) = self.nettle.d_crt();
|
||||||
dp
|
dp
|
||||||
}
|
}
|
||||||
fn get_dq1(&self) -> Box<[u8]> {
|
fn dq1(&self) -> Box<[u8]> {
|
||||||
let (_, dq, _) = self.nettle.d_crt();
|
let (_, dq, _) = self.nettle.d_crt();
|
||||||
dq
|
dq
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_n(&self) -> &[u8] {
|
fn n(&self) -> &[u8] {
|
||||||
self.n.value()
|
self.n.value()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,11 +217,11 @@ impl SqEccKey {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EccKey for SqEccKey {
|
impl EccKey for SqEccKey {
|
||||||
fn get_oid(&self) -> &[u8] {
|
fn oid(&self) -> &[u8] {
|
||||||
self.curve.oid()
|
self.curve.oid()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_private(&self) -> Vec<u8> {
|
fn private(&self) -> Vec<u8> {
|
||||||
// FIXME: padding for 25519?
|
// FIXME: padding for 25519?
|
||||||
match self.curve {
|
match self.curve {
|
||||||
Curve::NistP256 => self.private.value_padded(0x20).to_vec(),
|
Curve::NistP256 => self.private.value_padded(0x20).to_vec(),
|
||||||
|
@ -231,12 +231,12 @@ impl EccKey for SqEccKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_public(&self) -> Vec<u8> {
|
fn public(&self) -> Vec<u8> {
|
||||||
// FIXME: padding?
|
// FIXME: padding?
|
||||||
self.public.value().to_vec()
|
self.public.value().to_vec()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_type(&self) -> EccType {
|
fn ecc_type(&self) -> EccType {
|
||||||
self.ecc_type
|
self.ecc_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,8 @@ impl<'a> CardSigner<'a> {
|
||||||
policy: &dyn Policy,
|
policy: &dyn Policy,
|
||||||
) -> Result<CardSigner<'a>, Error> {
|
) -> Result<CardSigner<'a>, Error> {
|
||||||
// Get the fingerprint for the signing key from the card.
|
// Get the fingerprint for the signing key from the card.
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let fps = ard.get_fingerprints()?;
|
let fps = ard.fingerprints()?;
|
||||||
let fp = fps.signature();
|
let fp = fps.signature();
|
||||||
|
|
||||||
if let Some(fp) = fp {
|
if let Some(fp) = fp {
|
||||||
|
|
|
@ -30,7 +30,7 @@ use openpgp_card::{Error, KeyType};
|
||||||
///
|
///
|
||||||
/// Returns Ok(None), if no such (sub)key exists.
|
/// Returns Ok(None), if no such (sub)key exists.
|
||||||
/// If multiple suitable (sub)keys are found, an error is returned.
|
/// If multiple suitable (sub)keys are found, an error is returned.
|
||||||
pub fn get_subkey_by_type<'a>(
|
pub fn subkey_by_type<'a>(
|
||||||
cert: &'a Cert,
|
cert: &'a Cert,
|
||||||
policy: &'a dyn Policy,
|
policy: &'a dyn Policy,
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
|
@ -64,7 +64,7 @@ pub fn get_subkey_by_type<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve a private (sub)key from a Cert, by fingerprint.
|
/// Retrieve a private (sub)key from a Cert, by fingerprint.
|
||||||
pub fn get_priv_subkey_by_fingerprint<'a>(
|
pub fn private_subkey_by_fingerprint<'a>(
|
||||||
cert: &'a Cert,
|
cert: &'a Cert,
|
||||||
policy: &'a dyn Policy,
|
policy: &'a dyn Policy,
|
||||||
fingerprint: &str,
|
fingerprint: &str,
|
||||||
|
|
|
@ -60,7 +60,7 @@ impl From<&str> for AlgoSimple {
|
||||||
|
|
||||||
impl AlgoSimple {
|
impl AlgoSimple {
|
||||||
/// Get corresponding EccType by KeyType (except for Curve25519)
|
/// Get corresponding EccType by KeyType (except for Curve25519)
|
||||||
fn get_ecc_type(key_type: KeyType) -> EccType {
|
fn ecc_type(key_type: KeyType) -> EccType {
|
||||||
match key_type {
|
match key_type {
|
||||||
KeyType::Signing
|
KeyType::Signing
|
||||||
| KeyType::Authentication
|
| KeyType::Authentication
|
||||||
|
@ -70,7 +70,7 @@ impl AlgoSimple {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get corresponding EccType by KeyType for Curve25519
|
/// Get corresponding EccType by KeyType for Curve25519
|
||||||
fn get_ecc_type_25519(key_type: KeyType) -> EccType {
|
fn ecc_type_25519(key_type: KeyType) -> EccType {
|
||||||
match key_type {
|
match key_type {
|
||||||
KeyType::Signing
|
KeyType::Signing
|
||||||
| KeyType::Authentication
|
| KeyType::Authentication
|
||||||
|
@ -80,7 +80,7 @@ impl AlgoSimple {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get corresponding Curve by KeyType for 25519 (Ed25519 vs Cv25519)
|
/// Get corresponding Curve by KeyType for 25519 (Ed25519 vs Cv25519)
|
||||||
fn get_curve_for_25519(key_type: KeyType) -> Curve {
|
fn curve_for_25519(key_type: KeyType) -> Curve {
|
||||||
match key_type {
|
match key_type {
|
||||||
KeyType::Signing
|
KeyType::Signing
|
||||||
| KeyType::Authentication
|
| KeyType::Authentication
|
||||||
|
@ -89,7 +89,7 @@ impl AlgoSimple {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_algo(&self, key_type: KeyType) -> Algo {
|
pub(crate) fn as_algo(&self, key_type: KeyType) -> Algo {
|
||||||
match self {
|
match self {
|
||||||
Self::RSA1k(e) => Algo::Rsa(RsaAttrs {
|
Self::RSA1k(e) => Algo::Rsa(RsaAttrs {
|
||||||
len_n: 1024,
|
len_n: 1024,
|
||||||
|
@ -113,22 +113,22 @@ impl AlgoSimple {
|
||||||
}),
|
}),
|
||||||
Self::NIST256 => Algo::Ecc(EccAttrs {
|
Self::NIST256 => Algo::Ecc(EccAttrs {
|
||||||
curve: Curve::NistP256r1,
|
curve: Curve::NistP256r1,
|
||||||
ecc_type: Self::get_ecc_type(key_type),
|
ecc_type: Self::ecc_type(key_type),
|
||||||
import_format: None,
|
import_format: None,
|
||||||
}),
|
}),
|
||||||
Self::NIST384 => Algo::Ecc(EccAttrs {
|
Self::NIST384 => Algo::Ecc(EccAttrs {
|
||||||
curve: Curve::NistP384r1,
|
curve: Curve::NistP384r1,
|
||||||
ecc_type: Self::get_ecc_type(key_type),
|
ecc_type: Self::ecc_type(key_type),
|
||||||
import_format: None,
|
import_format: None,
|
||||||
}),
|
}),
|
||||||
Self::NIST521 => Algo::Ecc(EccAttrs {
|
Self::NIST521 => Algo::Ecc(EccAttrs {
|
||||||
curve: Curve::NistP521r1,
|
curve: Curve::NistP521r1,
|
||||||
ecc_type: Self::get_ecc_type(key_type),
|
ecc_type: Self::ecc_type(key_type),
|
||||||
import_format: None,
|
import_format: None,
|
||||||
}),
|
}),
|
||||||
Self::Curve25519 => Algo::Ecc(EccAttrs {
|
Self::Curve25519 => Algo::Ecc(EccAttrs {
|
||||||
curve: Self::get_curve_for_25519(key_type),
|
curve: Self::curve_for_25519(key_type),
|
||||||
ecc_type: Self::get_ecc_type_25519(key_type),
|
ecc_type: Self::ecc_type_25519(key_type),
|
||||||
import_format: None,
|
import_format: None,
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
|
@ -198,7 +198,7 @@ impl fmt::Display for Algo {
|
||||||
impl Algo {
|
impl Algo {
|
||||||
/// Get a DO representation of the Algo, for setting algorithm
|
/// Get a DO representation of the Algo, for setting algorithm
|
||||||
/// attributes on the card.
|
/// attributes on the card.
|
||||||
pub(crate) fn get_data(&self) -> Result<Vec<u8>, Error> {
|
pub(crate) fn to_data_object(&self) -> Result<Vec<u8>, Error> {
|
||||||
match self {
|
match self {
|
||||||
Algo::Rsa(rsa) => Self::rsa_algo_attrs(rsa),
|
Algo::Rsa(rsa) => Self::rsa_algo_attrs(rsa),
|
||||||
Algo::Ecc(ecc) => Self::ecc_algo_attrs(ecc.oid(), ecc.ecc_type()),
|
Algo::Ecc(ecc) => Self::ecc_algo_attrs(ecc.oid(), ecc.ecc_type()),
|
||||||
|
|
|
@ -87,7 +87,7 @@ fn send_command_low_level(
|
||||||
expect_response: Expect,
|
expect_response: Expect,
|
||||||
) -> Result<Vec<u8>, Error> {
|
) -> Result<Vec<u8>, Error> {
|
||||||
let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) =
|
let (ext_support, chaining_support, mut max_cmd_bytes, max_rsp_bytes) =
|
||||||
if let Some(caps) = card_client.get_caps() {
|
if let Some(caps) = card_client.card_caps() {
|
||||||
log::debug!("found card caps data!");
|
log::debug!("found card caps data!");
|
||||||
|
|
||||||
(
|
(
|
||||||
|
|
|
@ -32,17 +32,17 @@ fn get_data(tag: &[u8]) -> Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET DO "Application related data"
|
/// GET DO "Application related data"
|
||||||
pub(crate) fn get_application_data() -> Command {
|
pub(crate) fn application_related_data() -> Command {
|
||||||
get_data(&[0x6E])
|
get_data(&[0x6E])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET DO "private use"
|
/// GET DO "private use"
|
||||||
pub(crate) fn get_private_do(num: u8) -> Command {
|
pub(crate) fn private_do(num: u8) -> Command {
|
||||||
get_data(&[0x01, num])
|
get_data(&[0x01, num])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET DO "Uniform resource locator"
|
/// GET DO "Uniform resource locator"
|
||||||
pub(crate) fn get_url() -> Command {
|
pub(crate) fn url() -> Command {
|
||||||
get_data(&[0x5F, 0x50])
|
get_data(&[0x5F, 0x50])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,22 +52,22 @@ pub(crate) fn cardholder_related_data() -> Command {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET DO "Security support template"
|
/// GET DO "Security support template"
|
||||||
pub(crate) fn get_security_support_template() -> Command {
|
pub(crate) fn security_support_template() -> Command {
|
||||||
get_data(&[0x7A])
|
get_data(&[0x7A])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET DO "Cardholder certificate"
|
/// GET DO "Cardholder certificate"
|
||||||
pub(crate) fn get_cardholder_certificate() -> Command {
|
pub(crate) fn cardholder_certificate() -> Command {
|
||||||
get_data(&[0x7F, 0x21])
|
get_data(&[0x7F, 0x21])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET DO "List of supported Algorithm attributes"
|
/// GET DO "List of supported Algorithm attributes"
|
||||||
pub(crate) fn get_algo_list() -> Command {
|
pub(crate) fn algo_list() -> Command {
|
||||||
get_data(&[0xFA])
|
get_data(&[0xFA])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GET Firmware Version (yubikey specific?)
|
/// GET Firmware Version (yubikey specific?)
|
||||||
pub(crate) fn get_firmware_version() -> Command {
|
pub(crate) fn firmware_version() -> Command {
|
||||||
Command::new(0x00, 0xF1, 0x00, 0x00, vec![])
|
Command::new(0x00, 0xF1, 0x00, 0x00, vec![])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ impl CardApp {
|
||||||
pub fn initialize(card_client: CardClientBox) -> Result<Self> {
|
pub fn initialize(card_client: CardClientBox) -> Result<Self> {
|
||||||
let mut ca = Self { card_client };
|
let mut ca = Self { card_client };
|
||||||
|
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
ca.init_caps(&ard)?;
|
ca.init_caps(&ard)?;
|
||||||
|
|
||||||
Ok(ca)
|
Ok(ca)
|
||||||
|
@ -70,18 +70,18 @@ impl CardApp {
|
||||||
let mut ext_support = false;
|
let mut ext_support = false;
|
||||||
let mut chaining_support = false;
|
let mut chaining_support = false;
|
||||||
|
|
||||||
if let Ok(hist) = ard.get_historical() {
|
if let Ok(hist) = ard.historical_bytes() {
|
||||||
if let Some(cc) = hist.get_card_capabilities() {
|
if let Some(cc) = hist.card_capabilities() {
|
||||||
chaining_support = cc.get_command_chaining();
|
chaining_support = cc.command_chaining();
|
||||||
ext_support = cc.get_extended_lc_le();
|
ext_support = cc.extended_lc_le();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let ext_cap = ard.get_extended_capabilities()?;
|
let ext_cap = ard.extended_capabilities()?;
|
||||||
|
|
||||||
let (max_cmd_bytes, max_rsp_bytes) =
|
let (max_cmd_bytes, max_rsp_bytes) =
|
||||||
// FIXME: handle cmd/resp limits in ex-cap, for card <3.0 (?)
|
// FIXME: handle cmd/resp limits in ex-cap, for card <3.0 (?)
|
||||||
if let Ok(Some(eli)) = ard.get_extended_length_information() {
|
if let Ok(Some(eli)) = ard.extended_length_information() {
|
||||||
(eli.max_command_bytes(), eli.max_response_bytes())
|
(eli.max_command_bytes(), eli.max_response_bytes())
|
||||||
} else if let (Some(cmd), Some(rsp))
|
} else if let (Some(cmd), Some(rsp))
|
||||||
= (ext_cap.max_cmd_len(), ext_cap.max_resp_len()) {
|
= (ext_cap.max_cmd_len(), ext_cap.max_resp_len()) {
|
||||||
|
@ -90,9 +90,9 @@ impl CardApp {
|
||||||
(255, 255)
|
(255, 255)
|
||||||
};
|
};
|
||||||
|
|
||||||
let pw_status = ard.get_pw_status_bytes()?;
|
let pw_status = ard.pw_status_bytes()?;
|
||||||
let pw1_max = pw_status.get_pw1_max_len();
|
let pw1_max = pw_status.pw1_max_len();
|
||||||
let pw3_max = pw_status.get_pw3_max_len();
|
let pw3_max = pw_status.pw3_max_len();
|
||||||
|
|
||||||
let caps = CardCaps {
|
let caps = CardCaps {
|
||||||
ext_support,
|
ext_support,
|
||||||
|
@ -103,7 +103,7 @@ impl CardApp {
|
||||||
pw3_max_len: pw3_max,
|
pw3_max_len: pw3_max,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.card_client.init_caps(caps);
|
self.card_client.init_card_caps(caps);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -115,10 +115,10 @@ impl CardApp {
|
||||||
/// (This data should probably be cached in a higher layer. Some parts of
|
/// (This data should probably be cached in a higher layer. Some parts of
|
||||||
/// it are needed regularly, and it does not usually change during
|
/// it are needed regularly, and it does not usually change during
|
||||||
/// normal use of a card.)
|
/// normal use of a card.)
|
||||||
pub fn get_application_related_data(
|
pub fn application_related_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<ApplicationRelatedData> {
|
) -> Result<ApplicationRelatedData> {
|
||||||
let ad = commands::get_application_data();
|
let ad = commands::application_related_data();
|
||||||
let resp = apdu::send_command(self.card_client(), ad, true)?;
|
let resp = apdu::send_command(self.card_client(), ad, true)?;
|
||||||
let value = Value::from(resp.data()?, true)?;
|
let value = Value::from(resp.data()?, true)?;
|
||||||
|
|
||||||
|
@ -130,42 +130,42 @@ impl CardApp {
|
||||||
/// Get data from "private use" DO.
|
/// Get data from "private use" DO.
|
||||||
///
|
///
|
||||||
/// `num` must be between 1 and 4.
|
/// `num` must be between 1 and 4.
|
||||||
pub fn get_private(&mut self, num: u8) -> Result<Vec<u8>> {
|
pub fn private_use_do(&mut self, num: u8) -> Result<Vec<u8>> {
|
||||||
assert!((1..=4).contains(&num));
|
assert!((1..=4).contains(&num));
|
||||||
|
|
||||||
let cmd = commands::get_private_do(num);
|
let cmd = commands::private_do(num);
|
||||||
let resp = apdu::send_command(self.card_client(), cmd, true)?;
|
let resp = apdu::send_command(self.card_client(), cmd, true)?;
|
||||||
|
|
||||||
Ok(resp.data()?.to_vec())
|
Ok(resp.data()?.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_ca_fingerprints() {
|
fn ca_fingerprints() {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_key_information() {
|
fn key_information() {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_uif_pso_cds() {
|
fn uif_pso_cds() {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_uif_pso_dec() {
|
fn uif_pso_dec() {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_uif_pso_aut() {
|
fn uif_pso_aut() {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_uif_attestation() {
|
fn uif_attestation() {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,17 +173,16 @@ impl CardApp {
|
||||||
|
|
||||||
// --- login data (5e) ---
|
// --- login data (5e) ---
|
||||||
|
|
||||||
// --- URL (5f50) ---
|
/// Get URL (5f50)
|
||||||
|
pub fn url(&mut self) -> Result<String> {
|
||||||
pub fn get_url(&mut self) -> Result<String> {
|
|
||||||
let resp =
|
let resp =
|
||||||
apdu::send_command(self.card_client(), commands::get_url(), true)?;
|
apdu::send_command(self.card_client(), commands::url(), true)?;
|
||||||
|
|
||||||
Ok(String::from_utf8_lossy(resp.data()?).to_string())
|
Ok(String::from_utf8_lossy(resp.data()?).to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- cardholder related data (65) ---
|
/// Get cardholder related data (65)
|
||||||
pub fn get_cardholder_related_data(
|
pub fn cardholder_related_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<CardholderRelatedData> {
|
) -> Result<CardholderRelatedData> {
|
||||||
let crd = commands::cardholder_related_data();
|
let crd = commands::cardholder_related_data();
|
||||||
|
@ -193,11 +192,11 @@ impl CardApp {
|
||||||
CardholderRelatedData::try_from(resp.data()?)
|
CardholderRelatedData::try_from(resp.data()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- security support template (7a) ---
|
/// Get security support template (7a)
|
||||||
pub fn get_security_support_template(
|
pub fn security_support_template(
|
||||||
&mut self,
|
&mut self,
|
||||||
) -> Result<SecuritySupportTemplate> {
|
) -> Result<SecuritySupportTemplate> {
|
||||||
let sst = commands::get_security_support_template();
|
let sst = commands::security_support_template();
|
||||||
let resp = apdu::send_command(self.card_client(), sst, true)?;
|
let resp = apdu::send_command(self.card_client(), sst, true)?;
|
||||||
resp.check_ok()?;
|
resp.check_ok()?;
|
||||||
|
|
||||||
|
@ -224,16 +223,16 @@ impl CardApp {
|
||||||
///
|
///
|
||||||
/// Call select_data() before calling this fn, to select a particular
|
/// Call select_data() before calling this fn, to select a particular
|
||||||
/// certificate (if the card supports multiple certificates).
|
/// certificate (if the card supports multiple certificates).
|
||||||
pub fn get_cardholder_certificate(&mut self) -> Result<Response, Error> {
|
pub fn cardholder_certificate(&mut self) -> Result<Response, Error> {
|
||||||
let cmd = commands::get_cardholder_certificate();
|
let cmd = commands::cardholder_certificate();
|
||||||
apdu::send_command(self.card_client(), cmd, true)?.try_into()
|
apdu::send_command(self.card_client(), cmd, true)?.try_into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DO "Algorithm Information"
|
/// Get "Algorithm Information"
|
||||||
pub fn get_algo_info(&mut self) -> Result<Option<AlgoInfo>> {
|
pub fn algorithm_information(&mut self) -> Result<Option<AlgoInfo>> {
|
||||||
let resp = apdu::send_command(
|
let resp = apdu::send_command(
|
||||||
self.card_client(),
|
self.card_client(),
|
||||||
commands::get_algo_list(),
|
commands::algo_list(),
|
||||||
true,
|
true,
|
||||||
)?;
|
)?;
|
||||||
resp.check_ok()?;
|
resp.check_ok()?;
|
||||||
|
@ -243,10 +242,10 @@ impl CardApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Firmware Version (YubiKey specific (?))
|
/// Firmware Version (YubiKey specific (?))
|
||||||
pub fn get_firmware_version(&mut self) -> Result<Vec<u8>> {
|
pub fn firmware_version(&mut self) -> Result<Vec<u8>> {
|
||||||
let resp = apdu::send_command(
|
let resp = apdu::send_command(
|
||||||
self.card_client(),
|
self.card_client(),
|
||||||
commands::get_firmware_version(),
|
commands::firmware_version(),
|
||||||
true,
|
true,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -702,10 +701,8 @@ impl CardApp {
|
||||||
.copied()
|
.copied()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let time_cmd = commands::put_data(
|
let time_cmd =
|
||||||
&[key_type.get_timestamp_put_tag()],
|
commands::put_data(&[key_type.timestamp_put_tag()], time_value);
|
||||||
time_value,
|
|
||||||
);
|
|
||||||
|
|
||||||
apdu::send_command(self.card_client(), time_cmd, false)?.try_into()
|
apdu::send_command(self.card_client(), time_cmd, false)?.try_into()
|
||||||
}
|
}
|
||||||
|
@ -716,7 +713,7 @@ impl CardApp {
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
let fp_cmd = commands::put_data(
|
let fp_cmd = commands::put_data(
|
||||||
&[key_type.get_fingerprint_put_tag()],
|
&[key_type.fingerprint_put_tag()],
|
||||||
fp.as_bytes().to_vec(),
|
fp.as_bytes().to_vec(),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -766,8 +763,8 @@ impl CardApp {
|
||||||
) -> Result<Response, Error> {
|
) -> Result<Response, Error> {
|
||||||
// Command to PUT the algorithm attributes
|
// Command to PUT the algorithm attributes
|
||||||
let cmd = commands::put_data(
|
let cmd = commands::put_data(
|
||||||
&[key_type.get_algorithm_tag()],
|
&[key_type.algorithm_tag()],
|
||||||
algo.get_data()?,
|
algo.to_data_object()?,
|
||||||
);
|
);
|
||||||
|
|
||||||
apdu::send_command(self.card_client(), cmd, false)?.try_into()
|
apdu::send_command(self.card_client(), cmd, false)?.try_into()
|
||||||
|
@ -790,7 +787,7 @@ impl CardApp {
|
||||||
key: Box<dyn CardUploadableKey>,
|
key: Box<dyn CardUploadableKey>,
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let algo_list = self.get_algo_info();
|
let algo_list = self.algorithm_information();
|
||||||
|
|
||||||
// An error is ok - it's fine if a card doesn't offer a list of
|
// An error is ok - it's fine if a card doesn't offer a list of
|
||||||
// supported algorithms
|
// supported algorithms
|
||||||
|
@ -832,7 +829,7 @@ impl CardApp {
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
algo: AlgoSimple,
|
algo: AlgoSimple,
|
||||||
) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
|
) -> Result<(PublicKeyMaterial, KeyGenerationTime), Error> {
|
||||||
let algo = algo.get_algo(key_type);
|
let algo = algo.as_algo(key_type);
|
||||||
self.generate_key(fp_from_pub, key_type, Some(&algo))
|
self.generate_key(fp_from_pub, key_type, Some(&algo))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -842,10 +839,10 @@ impl CardApp {
|
||||||
/// OpenPGP key data structure).
|
/// OpenPGP key data structure).
|
||||||
/// This data from the card is insufficient to create a typical
|
/// This data from the card is insufficient to create a typical
|
||||||
/// full public key.
|
/// full public key.
|
||||||
pub fn get_pub_key(
|
pub fn public_key(
|
||||||
&mut self,
|
&mut self,
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
) -> Result<PublicKeyMaterial, Error> {
|
) -> Result<PublicKeyMaterial, Error> {
|
||||||
keys::get_pub_key(self, key_type)
|
keys::public_key(self, key_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,8 @@ mod pw_status;
|
||||||
pub struct ApplicationRelatedData(pub(crate) Tlv);
|
pub struct ApplicationRelatedData(pub(crate) Tlv);
|
||||||
|
|
||||||
impl ApplicationRelatedData {
|
impl ApplicationRelatedData {
|
||||||
/// Application identifier (AID), ISO 7816-4
|
/// Get application identifier (AID), ISO 7816-4
|
||||||
pub fn get_application_id(&self) -> Result<ApplicationIdentifier, Error> {
|
pub fn application_id(&self) -> Result<ApplicationIdentifier, Error> {
|
||||||
// get from cached "application related data"
|
// get from cached "application related data"
|
||||||
let aid = self.0.find(&[0x4f].into());
|
let aid = self.0.find(&[0x4f].into());
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ impl ApplicationRelatedData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Historical bytes
|
/// Get historical bytes
|
||||||
pub fn get_historical(&self) -> Result<HistoricalBytes, Error> {
|
pub fn historical_bytes(&self) -> Result<HistoricalBytes, Error> {
|
||||||
// get from cached "application related data"
|
// get from cached "application related data"
|
||||||
let hist = self.0.find(&[0x5f, 0x52].into());
|
let hist = self.0.find(&[0x5f, 0x52].into());
|
||||||
|
|
||||||
|
@ -58,9 +58,9 @@ impl ApplicationRelatedData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended length information (ISO 7816-4) with maximum number of
|
/// Get extended length information (ISO 7816-4), which
|
||||||
/// bytes for command and response.
|
/// contains maximum number of bytes for command and response.
|
||||||
pub fn get_extended_length_information(
|
pub fn extended_length_information(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<Option<ExtendedLengthInfo>> {
|
) -> Result<Option<ExtendedLengthInfo>> {
|
||||||
// get from cached "application related data"
|
// get from cached "application related data"
|
||||||
|
@ -78,21 +78,21 @@ impl ApplicationRelatedData {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_general_feature_management() -> Option<bool> {
|
fn general_feature_management() -> Option<bool> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn get_discretionary_data_objects() {
|
fn discretionary_data_objects() {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extended Capabilities
|
/// Get extended Capabilities
|
||||||
pub fn get_extended_capabilities(
|
pub fn extended_capabilities(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<ExtendedCapabilities, Error> {
|
) -> Result<ExtendedCapabilities, Error> {
|
||||||
// FIXME: caching?
|
// FIXME: caching?
|
||||||
let app_id = self.get_application_id()?;
|
let app_id = self.application_id()?;
|
||||||
let version = app_id.version();
|
let version = app_id.version();
|
||||||
|
|
||||||
// get from cached "application related data"
|
// get from cached "application related data"
|
||||||
|
@ -108,10 +108,10 @@ impl ApplicationRelatedData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Algorithm attributes (for each key type)
|
/// Get algorithm attributes (for each key type)
|
||||||
pub fn get_algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> {
|
pub fn algorithm_attributes(&self, key_type: KeyType) -> Result<Algo> {
|
||||||
// get from cached "application related data"
|
// get from cached "application related data"
|
||||||
let aa = self.0.find(&[key_type.get_algorithm_tag()].into());
|
let aa = self.0.find(&[key_type.algorithm_tag()].into());
|
||||||
|
|
||||||
if let Some(aa) = aa {
|
if let Some(aa) = aa {
|
||||||
Algo::try_from(&aa.serialize()[..])
|
Algo::try_from(&aa.serialize()[..])
|
||||||
|
@ -123,8 +123,8 @@ impl ApplicationRelatedData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// PW status Bytes
|
/// Get PW status Bytes
|
||||||
pub fn get_pw_status_bytes(&self) -> Result<PWStatusBytes> {
|
pub fn pw_status_bytes(&self) -> Result<PWStatusBytes> {
|
||||||
// get from cached "application related data"
|
// get from cached "application related data"
|
||||||
let psb = self.0.find(&[0xc4].into());
|
let psb = self.0.find(&[0xc4].into());
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ impl ApplicationRelatedData {
|
||||||
|
|
||||||
/// Fingerprint, per key type.
|
/// Fingerprint, per key type.
|
||||||
/// Zero bytes indicate a not defined private key.
|
/// Zero bytes indicate a not defined private key.
|
||||||
pub fn get_fingerprints(&self) -> Result<KeySet<Fingerprint>, Error> {
|
pub fn fingerprints(&self) -> Result<KeySet<Fingerprint>, Error> {
|
||||||
// Get from cached "application related data"
|
// Get from cached "application related data"
|
||||||
let fp = self.0.find(&[0xc5].into());
|
let fp = self.0.find(&[0xc5].into());
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ impl ApplicationRelatedData {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generation dates/times of key pairs
|
/// Generation dates/times of key pairs
|
||||||
pub fn get_key_generation_times(
|
pub fn key_generation_times(
|
||||||
&self,
|
&self,
|
||||||
) -> Result<KeySet<KeyGenerationTime>, Error> {
|
) -> Result<KeySet<KeyGenerationTime>, Error> {
|
||||||
let kg = self.0.find(&[0xcd].into());
|
let kg = self.0.find(&[0xcd].into());
|
||||||
|
@ -184,7 +184,7 @@ pub struct SecuritySupportTemplate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SecuritySupportTemplate {
|
impl SecuritySupportTemplate {
|
||||||
pub fn get_signature_count(&self) -> u32 {
|
pub fn signature_count(&self) -> u32 {
|
||||||
self.dsc
|
self.dsc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,39 +335,57 @@ pub struct PWStatusBytes {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PWStatusBytes {
|
impl PWStatusBytes {
|
||||||
pub fn set_pw1_cds_valid_once(&mut self, val: bool) {
|
/// Set format of PW1:
|
||||||
self.pw1_cds_valid_once = val;
|
/// `false` for UTF-8 or derived password,
|
||||||
}
|
/// `true` for PIN block format 2.
|
||||||
pub fn set_pw1_pin_block(&mut self, val: bool) {
|
pub fn set_pw1_pin_block(&mut self, val: bool) {
|
||||||
self.pw1_pin_block = val;
|
self.pw1_pin_block = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set format of PW3:
|
||||||
|
/// `false` for UTF-8 or derived password,
|
||||||
|
/// `true` for PIN block format 2.
|
||||||
pub fn set_pw3_pin_block(&mut self, val: bool) {
|
pub fn set_pw3_pin_block(&mut self, val: bool) {
|
||||||
self.pw3_pin_block = val;
|
self.pw3_pin_block = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pw1_cds_valid_once(&self) -> bool {
|
/// Is PW1 (no. 81) only valid for one PSO:CDS command?
|
||||||
|
pub fn pw1_cds_valid_once(&self) -> bool {
|
||||||
self.pw1_cds_valid_once
|
self.pw1_cds_valid_once
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pw1_max_len(&self) -> u8 {
|
/// Configure if PW1 (no. 81) is only valid for one PSO:CDS command.
|
||||||
|
pub fn set_pw1_cds_valid_once(&mut self, val: bool) {
|
||||||
|
self.pw1_cds_valid_once = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Max length of PW1
|
||||||
|
pub fn pw1_max_len(&self) -> u8 {
|
||||||
self.pw1_len_format & 0x7f
|
self.pw1_len_format & 0x7f
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_rc_max_len(&self) -> u8 {
|
/// Max length of Resetting Code (RC) for PW1
|
||||||
|
pub fn rc_max_len(&self) -> u8 {
|
||||||
self.rc_len
|
self.rc_len
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pw3_max_len(&self) -> u8 {
|
/// Max length of PW3
|
||||||
|
pub fn pw3_max_len(&self) -> u8 {
|
||||||
self.pw3_len_format & 0x7f
|
self.pw3_len_format & 0x7f
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_err_count_pw1(&self) -> u8 {
|
/// Error counter of PW1 (if 0, then PW1 is blocked).
|
||||||
|
pub fn err_count_pw1(&self) -> u8 {
|
||||||
self.err_count_pw1
|
self.err_count_pw1
|
||||||
}
|
}
|
||||||
pub fn get_err_count_rst(&self) -> u8 {
|
|
||||||
|
/// Error counter of Resetting Code (RC) (if 0, then RC is blocked).
|
||||||
|
pub fn err_count_rc(&self) -> u8 {
|
||||||
self.err_count_rst
|
self.err_count_rst
|
||||||
}
|
}
|
||||||
pub fn get_err_count_pw3(&self) -> u8 {
|
|
||||||
|
/// Error counter of PW3 (if 0, then PW3 is blocked).
|
||||||
|
pub fn err_count_pw3(&self) -> u8 {
|
||||||
self.err_count_pw3
|
self.err_count_pw3
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use crate::card_do::{algo_attrs, complete};
|
||||||
use crate::KeyType;
|
use crate::KeyType;
|
||||||
|
|
||||||
impl AlgoInfo {
|
impl AlgoInfo {
|
||||||
pub fn get_by_keytype(&self, kt: KeyType) -> Vec<&Algo> {
|
pub fn filter_by_keytype(&self, kt: KeyType) -> Vec<&Algo> {
|
||||||
self.0
|
self.0
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(k, _)| *k == kt)
|
.filter(|(k, _)| *k == kt)
|
||||||
|
|
|
@ -9,15 +9,15 @@ use anyhow::{anyhow, Result};
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
impl CardCapabilities {
|
impl CardCapabilities {
|
||||||
pub fn get_command_chaining(&self) -> bool {
|
pub fn command_chaining(&self) -> bool {
|
||||||
self.command_chaining
|
self.command_chaining
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_extended_lc_le(&self) -> bool {
|
pub fn extended_lc_le(&self) -> bool {
|
||||||
self.extended_lc_le
|
self.extended_lc_le
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_extended_length_information(&self) -> bool {
|
pub fn extended_length_information(&self) -> bool {
|
||||||
self.extended_length_information
|
self.extended_length_information
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ fn split_tl(tl: u8) -> (u8, u8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HistoricalBytes {
|
impl HistoricalBytes {
|
||||||
pub fn get_card_capabilities(&self) -> Option<&CardCapabilities> {
|
pub fn card_capabilities(&self) -> Option<&CardCapabilities> {
|
||||||
self.cc.as_ref()
|
self.cc.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,13 +65,13 @@ pub enum Cryptogram<'a> {
|
||||||
/// to an OpenPGP card
|
/// to an OpenPGP card
|
||||||
pub trait CardUploadableKey {
|
pub trait CardUploadableKey {
|
||||||
/// private key data
|
/// private key data
|
||||||
fn get_key(&self) -> Result<PrivateKeyMaterial>;
|
fn private_key(&self) -> Result<PrivateKeyMaterial>;
|
||||||
|
|
||||||
/// timestamp of (sub)key creation
|
/// timestamp of (sub)key creation
|
||||||
fn get_ts(&self) -> KeyGenerationTime;
|
fn timestamp(&self) -> KeyGenerationTime;
|
||||||
|
|
||||||
/// fingerprint
|
/// fingerprint
|
||||||
fn get_fp(&self) -> Result<Fingerprint, Error>;
|
fn fingerprint(&self) -> Result<Fingerprint, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Algorithm-independent container for private key material to upload to
|
/// Algorithm-independent container for private key material to upload to
|
||||||
|
@ -88,15 +88,15 @@ pub trait RSAKey {
|
||||||
// FIXME: use a mechanism like sequoia_openpgp::crypto::mem::Protected
|
// FIXME: use a mechanism like sequoia_openpgp::crypto::mem::Protected
|
||||||
// for private key material?
|
// for private key material?
|
||||||
|
|
||||||
fn get_e(&self) -> &[u8];
|
fn e(&self) -> &[u8];
|
||||||
fn get_p(&self) -> &[u8];
|
fn p(&self) -> &[u8];
|
||||||
fn get_q(&self) -> &[u8];
|
fn q(&self) -> &[u8];
|
||||||
|
|
||||||
fn get_pq(&self) -> Box<[u8]>;
|
fn pq(&self) -> Box<[u8]>;
|
||||||
fn get_dp1(&self) -> Box<[u8]>;
|
fn dp1(&self) -> Box<[u8]>;
|
||||||
fn get_dq1(&self) -> Box<[u8]>;
|
fn dq1(&self) -> Box<[u8]>;
|
||||||
|
|
||||||
fn get_n(&self) -> &[u8];
|
fn n(&self) -> &[u8];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ECC-specific container for private key material to upload to an OpenPGP
|
/// ECC-specific container for private key material to upload to an OpenPGP
|
||||||
|
@ -105,10 +105,10 @@ pub trait EccKey {
|
||||||
// FIXME: use a mechanism like sequoia_openpgp::crypto::mem::Protected
|
// FIXME: use a mechanism like sequoia_openpgp::crypto::mem::Protected
|
||||||
// for private key material?
|
// for private key material?
|
||||||
|
|
||||||
fn get_oid(&self) -> &[u8];
|
fn oid(&self) -> &[u8];
|
||||||
fn get_private(&self) -> Vec<u8>;
|
fn private(&self) -> Vec<u8>;
|
||||||
fn get_public(&self) -> Vec<u8>;
|
fn public(&self) -> Vec<u8>;
|
||||||
fn get_type(&self) -> EccType;
|
fn ecc_type(&self) -> EccType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Algorithm-independent container for public key material retrieved from
|
/// Algorithm-independent container for public key material retrieved from
|
||||||
|
|
|
@ -43,8 +43,8 @@ pub(crate) fn gen_key_with_metadata(
|
||||||
// Set algo on card if it's Some
|
// Set algo on card if it's Some
|
||||||
if let Some(target_algo) = algo {
|
if let Some(target_algo) = algo {
|
||||||
// FIXME: caching
|
// FIXME: caching
|
||||||
let ard = card_app.get_application_related_data()?; // no caching, here!
|
let ard = card_app.application_related_data()?; // no caching, here!
|
||||||
let ecap = ard.get_extended_capabilities()?;
|
let ecap = ard.extended_capabilities()?;
|
||||||
|
|
||||||
// Only set algo if card supports setting of algo attr
|
// Only set algo if card supports setting of algo attr
|
||||||
if ecap.algo_attrs_changeable() {
|
if ecap.algo_attrs_changeable() {
|
||||||
|
@ -65,8 +65,8 @@ pub(crate) fn gen_key_with_metadata(
|
||||||
}
|
}
|
||||||
|
|
||||||
// get new state of algo
|
// get new state of algo
|
||||||
let ard = card_app.get_application_related_data()?; // no caching, here!
|
let ard = card_app.application_related_data()?; // no caching, here!
|
||||||
let cur_algo = ard.get_algorithm_attributes(key_type)?;
|
let cur_algo = ard.algorithm_attributes(key_type)?;
|
||||||
|
|
||||||
// generate key
|
// generate key
|
||||||
let tlv = generate_asymmetric_key_pair(card_app, key_type)?;
|
let tlv = generate_asymmetric_key_pair(card_app, key_type)?;
|
||||||
|
@ -132,7 +132,7 @@ pub(crate) fn generate_asymmetric_key_pair(
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
) -> Result<Tlv, Error> {
|
) -> Result<Tlv, Error> {
|
||||||
// generate key
|
// generate key
|
||||||
let crt = get_crt(key_type)?;
|
let crt = control_reference_template(key_type)?;
|
||||||
let gen_key_cmd = commands::gen_key(crt.serialize().to_vec());
|
let gen_key_cmd = commands::gen_key(crt.serialize().to_vec());
|
||||||
|
|
||||||
let resp = apdu::send_command(card_app.card_client(), gen_key_cmd, true)?;
|
let resp = apdu::send_command(card_app.card_client(), gen_key_cmd, true)?;
|
||||||
|
@ -149,16 +149,16 @@ pub(crate) fn generate_asymmetric_key_pair(
|
||||||
/// in the card or imported")
|
/// in the card or imported")
|
||||||
///
|
///
|
||||||
/// (See 7.2.14 GENERATE ASYMMETRIC KEY PAIR)
|
/// (See 7.2.14 GENERATE ASYMMETRIC KEY PAIR)
|
||||||
pub(crate) fn get_pub_key(
|
pub(crate) fn public_key(
|
||||||
card_app: &mut CardApp,
|
card_app: &mut CardApp,
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
) -> Result<PublicKeyMaterial, Error> {
|
) -> Result<PublicKeyMaterial, Error> {
|
||||||
// get current algo
|
// get current algo
|
||||||
let ard = card_app.get_application_related_data()?; // FIXME: caching
|
let ard = card_app.application_related_data()?; // FIXME: caching
|
||||||
let algo = ard.get_algorithm_attributes(key_type)?;
|
let algo = ard.algorithm_attributes(key_type)?;
|
||||||
|
|
||||||
// get public key
|
// get public key
|
||||||
let crt = get_crt(key_type)?;
|
let crt = control_reference_template(key_type)?;
|
||||||
let get_pub_key_cmd = commands::get_pub_key(crt.serialize().to_vec());
|
let get_pub_key_cmd = commands::get_pub_key(crt.serialize().to_vec());
|
||||||
|
|
||||||
let resp =
|
let resp =
|
||||||
|
@ -183,9 +183,9 @@ pub(crate) fn key_import(
|
||||||
algo_list: Option<AlgoInfo>,
|
algo_list: Option<AlgoInfo>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
// FIXME: caching?
|
// FIXME: caching?
|
||||||
let ard = card_app.get_application_related_data()?;
|
let ard = card_app.application_related_data()?;
|
||||||
|
|
||||||
let (algo, key_cmd) = match key.get_key()? {
|
let (algo, key_cmd) = match key.private_key()? {
|
||||||
PrivateKeyMaterial::R(rsa_key) => {
|
PrivateKeyMaterial::R(rsa_key) => {
|
||||||
let rsa_attrs =
|
let rsa_attrs =
|
||||||
determine_rsa_attrs(&ard, &*rsa_key, key_type, algo_list)?;
|
determine_rsa_attrs(&ard, &*rsa_key, key_type, algo_list)?;
|
||||||
|
@ -204,19 +204,19 @@ pub(crate) fn key_import(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let fp = key.get_fp()?;
|
let fp = key.fingerprint()?;
|
||||||
|
|
||||||
// Now that we have marshalled all necessary information, perform all
|
// Now that we have marshalled all necessary information, perform all
|
||||||
// set-operations on the card.
|
// set-operations on the card.
|
||||||
|
|
||||||
// Only set algo attrs if "Extended Capabilities" lists the feature
|
// Only set algo attrs if "Extended Capabilities" lists the feature
|
||||||
if ard.get_extended_capabilities()?.algo_attrs_changeable() {
|
if ard.extended_capabilities()?.algo_attrs_changeable() {
|
||||||
card_app.set_algorithm_attributes(key_type, &algo)?;
|
card_app.set_algorithm_attributes(key_type, &algo)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
apdu::send_command(card_app.card_client(), key_cmd, false)?.check_ok()?;
|
apdu::send_command(card_app.card_client(), key_cmd, false)?.check_ok()?;
|
||||||
card_app.set_fingerprint(fp, key_type)?;
|
card_app.set_fingerprint(fp, key_type)?;
|
||||||
card_app.set_creation_time(key.get_ts(), key_type)?;
|
card_app.set_creation_time(key.timestamp(), key_type)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -234,7 +234,7 @@ fn determine_rsa_attrs(
|
||||||
) -> Result<RsaAttrs> {
|
) -> Result<RsaAttrs> {
|
||||||
// RSA bitsize
|
// RSA bitsize
|
||||||
// (round up to 4-bytes, in case the key has 8+ leading zeros)
|
// (round up to 4-bytes, in case the key has 8+ leading zeros)
|
||||||
let rsa_bits = (((rsa_key.get_n().len() * 8 + 31) / 32) * 32) as u16;
|
let rsa_bits = (((rsa_key.n().len() * 8 + 31) / 32) * 32) as u16;
|
||||||
|
|
||||||
// Figure out suitable RSA algorithm parameters:
|
// Figure out suitable RSA algorithm parameters:
|
||||||
|
|
||||||
|
@ -242,11 +242,11 @@ fn determine_rsa_attrs(
|
||||||
let rsa_attrs = if let Some(algo_list) = algo_list {
|
let rsa_attrs = if let Some(algo_list) = algo_list {
|
||||||
// Yes -> Look up the parameters for key_type and rsa_bits.
|
// Yes -> Look up the parameters for key_type and rsa_bits.
|
||||||
// (Or error, if the list doesn't have an entry for rsa_bits)
|
// (Or error, if the list doesn't have an entry for rsa_bits)
|
||||||
get_card_algo_rsa(algo_list, key_type, rsa_bits)?
|
card_algo_rsa(algo_list, key_type, rsa_bits)?
|
||||||
} else {
|
} else {
|
||||||
// No -> Get the current algorithm attributes for key_type.
|
// No -> Get the current algorithm attributes for key_type.
|
||||||
|
|
||||||
let algo = ard.get_algorithm_attributes(key_type)?;
|
let algo = ard.algorithm_attributes(key_type)?;
|
||||||
|
|
||||||
// Is the algorithm on the card currently set to RSA?
|
// Is the algorithm on the card currently set to RSA?
|
||||||
if let Algo::Rsa(rsa) = algo {
|
if let Algo::Rsa(rsa) = algo {
|
||||||
|
@ -280,7 +280,7 @@ fn determine_ecc_attrs(
|
||||||
) -> Result<EccAttrs> {
|
) -> Result<EccAttrs> {
|
||||||
// If we have an algo_list, refuse upload if oid is not listed
|
// If we have an algo_list, refuse upload if oid is not listed
|
||||||
if let Some(algo_list) = algo_list {
|
if let Some(algo_list) = algo_list {
|
||||||
let oid = ecc_key.get_oid();
|
let oid = ecc_key.oid();
|
||||||
let algos = check_card_algo_ecc(algo_list, key_type, oid);
|
let algos = check_card_algo_ecc(algo_list, key_type, oid);
|
||||||
if algos.is_empty() {
|
if algos.is_empty() {
|
||||||
// If oid is not in algo_list, return error.
|
// If oid is not in algo_list, return error.
|
||||||
|
@ -298,8 +298,8 @@ fn determine_ecc_attrs(
|
||||||
|
|
||||||
if !algos.is_empty() {
|
if !algos.is_empty() {
|
||||||
return Ok(EccAttrs::new(
|
return Ok(EccAttrs::new(
|
||||||
ecc_key.get_type(),
|
ecc_key.ecc_type(),
|
||||||
Curve::try_from(ecc_key.get_oid())?,
|
Curve::try_from(ecc_key.oid())?,
|
||||||
algos[0].import_format(),
|
algos[0].import_format(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -309,14 +309,14 @@ fn determine_ecc_attrs(
|
||||||
// (Do cards that support ecc but have no algo_list exist?)
|
// (Do cards that support ecc but have no algo_list exist?)
|
||||||
|
|
||||||
Ok(EccAttrs::new(
|
Ok(EccAttrs::new(
|
||||||
ecc_key.get_type(),
|
ecc_key.ecc_type(),
|
||||||
Curve::try_from(ecc_key.get_oid())?,
|
Curve::try_from(ecc_key.oid())?,
|
||||||
None,
|
None,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Look up RsaAttrs parameters in algo_list based on key_type and rsa_bits
|
/// Look up RsaAttrs parameters in algo_list based on key_type and rsa_bits
|
||||||
fn get_card_algo_rsa(
|
fn card_algo_rsa(
|
||||||
algo_list: AlgoInfo,
|
algo_list: AlgoInfo,
|
||||||
key_type: KeyType,
|
key_type: KeyType,
|
||||||
rsa_bits: u16,
|
rsa_bits: u16,
|
||||||
|
@ -324,7 +324,7 @@ fn get_card_algo_rsa(
|
||||||
// Find suitable algorithm parameters (from card's list of algorithms).
|
// Find suitable algorithm parameters (from card's list of algorithms).
|
||||||
|
|
||||||
// Get Algos for this keytype
|
// Get Algos for this keytype
|
||||||
let keytype_algos: Vec<_> = algo_list.get_by_keytype(key_type);
|
let keytype_algos: Vec<_> = algo_list.filter_by_keytype(key_type);
|
||||||
// Get RSA algo attributes
|
// Get RSA algo attributes
|
||||||
let rsa_algos: Vec<_> = keytype_algos
|
let rsa_algos: Vec<_> = keytype_algos
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -363,7 +363,7 @@ fn check_card_algo_ecc(
|
||||||
// Find suitable algorithm parameters (from card's list of algorithms).
|
// Find suitable algorithm parameters (from card's list of algorithms).
|
||||||
|
|
||||||
// Get Algos for this keytype
|
// Get Algos for this keytype
|
||||||
let keytype_algos: Vec<_> = algo_list.get_by_keytype(key_type);
|
let keytype_algos: Vec<_> = algo_list.filter_by_keytype(key_type);
|
||||||
|
|
||||||
// Get attributes
|
// Get attributes
|
||||||
let ecc_algos: Vec<_> = keytype_algos
|
let ecc_algos: Vec<_> = keytype_algos
|
||||||
|
@ -409,7 +409,7 @@ fn rsa_key_import_cmd(
|
||||||
cpkt_data.push(len_e_bytes);
|
cpkt_data.push(len_e_bytes);
|
||||||
|
|
||||||
// Push e, padded with zero bytes from the left
|
// Push e, padded with zero bytes from the left
|
||||||
let e_as_bytes = rsa_key.get_e();
|
let e_as_bytes = rsa_key.e();
|
||||||
|
|
||||||
if len_e_bytes as usize > e_as_bytes.len() {
|
if len_e_bytes as usize > e_as_bytes.len() {
|
||||||
key_data.extend(vec![0; len_e_bytes as usize - e_as_bytes.len()]);
|
key_data.extend(vec![0; len_e_bytes as usize - e_as_bytes.len()]);
|
||||||
|
@ -434,25 +434,25 @@ fn rsa_key_import_cmd(
|
||||||
|
|
||||||
// FIXME: do p/q need to be padded from the left when many leading
|
// FIXME: do p/q need to be padded from the left when many leading
|
||||||
// bits are zero?
|
// bits are zero?
|
||||||
key_data.extend(rsa_key.get_p().iter());
|
key_data.extend(rsa_key.p().iter());
|
||||||
key_data.extend(rsa_key.get_q().iter());
|
key_data.extend(rsa_key.q().iter());
|
||||||
|
|
||||||
// import format requires chinese remainder theorem fields
|
// import format requires chinese remainder theorem fields
|
||||||
if rsa_attrs.import_format() == 2 || rsa_attrs.import_format() == 3 {
|
if rsa_attrs.import_format() == 2 || rsa_attrs.import_format() == 3 {
|
||||||
// PQ: 1/q mod p
|
// PQ: 1/q mod p
|
||||||
let pq = rsa_key.get_pq();
|
let pq = rsa_key.pq();
|
||||||
cpkt_data.push(0x94);
|
cpkt_data.push(0x94);
|
||||||
cpkt_data.extend(&tlv_encode_length(pq.len() as u16));
|
cpkt_data.extend(&tlv_encode_length(pq.len() as u16));
|
||||||
key_data.extend(pq.iter());
|
key_data.extend(pq.iter());
|
||||||
|
|
||||||
// DP1: d mod (p - 1)
|
// DP1: d mod (p - 1)
|
||||||
let dp1 = rsa_key.get_dp1();
|
let dp1 = rsa_key.dp1();
|
||||||
cpkt_data.push(0x95);
|
cpkt_data.push(0x95);
|
||||||
cpkt_data.extend(&tlv_encode_length(dp1.len() as u16));
|
cpkt_data.extend(&tlv_encode_length(dp1.len() as u16));
|
||||||
key_data.extend(dp1.iter());
|
key_data.extend(dp1.iter());
|
||||||
|
|
||||||
// DQ1: d mod (q - 1)
|
// DQ1: d mod (q - 1)
|
||||||
let dq1 = rsa_key.get_dq1();
|
let dq1 = rsa_key.dq1();
|
||||||
cpkt_data.push(0x96);
|
cpkt_data.push(0x96);
|
||||||
cpkt_data.extend(&tlv_encode_length(dq1.len() as u16));
|
cpkt_data.extend(&tlv_encode_length(dq1.len() as u16));
|
||||||
key_data.extend(dq1.iter());
|
key_data.extend(dq1.iter());
|
||||||
|
@ -460,7 +460,7 @@ fn rsa_key_import_cmd(
|
||||||
|
|
||||||
// import format requires modulus n field
|
// import format requires modulus n field
|
||||||
if rsa_attrs.import_format() == 1 || rsa_attrs.import_format() == 3 {
|
if rsa_attrs.import_format() == 1 || rsa_attrs.import_format() == 3 {
|
||||||
let n = rsa_key.get_n();
|
let n = rsa_key.n();
|
||||||
cpkt_data.push(0x97);
|
cpkt_data.push(0x97);
|
||||||
cpkt_data.extend(&tlv_encode_length(n.len() as u16));
|
cpkt_data.extend(&tlv_encode_length(n.len() as u16));
|
||||||
key_data.extend(n.iter());
|
key_data.extend(n.iter());
|
||||||
|
@ -471,7 +471,7 @@ fn rsa_key_import_cmd(
|
||||||
let cpk = Tlv::new([0x5F, 0x48], Value::S(key_data));
|
let cpk = Tlv::new([0x5F, 0x48], Value::S(key_data));
|
||||||
|
|
||||||
// "Control Reference Template"
|
// "Control Reference Template"
|
||||||
let crt = get_crt(key_type)?;
|
let crt = control_reference_template(key_type)?;
|
||||||
|
|
||||||
// "Extended header list (DO 4D)"
|
// "Extended header list (DO 4D)"
|
||||||
let ehl = Tlv::new([0x4d], Value::C(vec![crt, cpkt, cpk]));
|
let ehl = Tlv::new([0x4d], Value::C(vec![crt, cpkt, cpk]));
|
||||||
|
@ -486,7 +486,7 @@ fn ecc_key_import_cmd(
|
||||||
ecc_key: Box<dyn EccKey>,
|
ecc_key: Box<dyn EccKey>,
|
||||||
ecc_attrs: &EccAttrs,
|
ecc_attrs: &EccAttrs,
|
||||||
) -> Result<Command, Error> {
|
) -> Result<Command, Error> {
|
||||||
let private = ecc_key.get_private();
|
let private = ecc_key.private();
|
||||||
|
|
||||||
// Collect data for "Cardholder private key template" DO (7F48)
|
// Collect data for "Cardholder private key template" DO (7F48)
|
||||||
//
|
//
|
||||||
|
@ -507,7 +507,7 @@ fn ecc_key_import_cmd(
|
||||||
|
|
||||||
// Process "public", if the import format requires it
|
// Process "public", if the import format requires it
|
||||||
if ecc_attrs.import_format() == Some(0xff) {
|
if ecc_attrs.import_format() == Some(0xff) {
|
||||||
let p = ecc_key.get_public();
|
let p = ecc_key.public();
|
||||||
|
|
||||||
cpkt_data.push(0x99);
|
cpkt_data.push(0x99);
|
||||||
cpkt_data.extend_from_slice(&tlv_encode_length(p.len() as u16));
|
cpkt_data.extend_from_slice(&tlv_encode_length(p.len() as u16));
|
||||||
|
@ -524,7 +524,7 @@ fn ecc_key_import_cmd(
|
||||||
let cpk = Tlv::new([0x5F, 0x48], Value::S(key_data));
|
let cpk = Tlv::new([0x5F, 0x48], Value::S(key_data));
|
||||||
|
|
||||||
// "Control Reference Template"
|
// "Control Reference Template"
|
||||||
let crt = get_crt(key_type)?;
|
let crt = control_reference_template(key_type)?;
|
||||||
|
|
||||||
// "Extended header list (DO 4D)" (contains the three inner TLV)
|
// "Extended header list (DO 4D)" (contains the three inner TLV)
|
||||||
let ehl = Tlv::new([0x4d], Value::C(vec![crt, cpkt, cpk]));
|
let ehl = Tlv::new([0x4d], Value::C(vec![crt, cpkt, cpk]));
|
||||||
|
@ -534,7 +534,7 @@ fn ecc_key_import_cmd(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get "Control Reference Template" Tlv for `key_type`
|
/// Get "Control Reference Template" Tlv for `key_type`
|
||||||
fn get_crt(key_type: KeyType) -> Result<Tlv, Error> {
|
fn control_reference_template(key_type: KeyType) -> Result<Tlv, Error> {
|
||||||
// "Control Reference Template" (0xB8 | 0xB6 | 0xA4)
|
// "Control Reference Template" (0xB8 | 0xB6 | 0xA4)
|
||||||
let tag = match key_type {
|
let tag = match key_type {
|
||||||
KeyType::Decryption => 0xB8,
|
KeyType::Decryption => 0xB8,
|
||||||
|
|
|
@ -63,13 +63,13 @@ pub trait CardClient {
|
||||||
/// process: the information about the card's capabilities is typically
|
/// process: the information about the card's capabilities is typically
|
||||||
/// requested from the card using the same CardClient instance, before
|
/// requested from the card using the same CardClient instance, before
|
||||||
/// the card's capabilities have been initialized.
|
/// the card's capabilities have been initialized.
|
||||||
fn init_caps(&mut self, caps: CardCaps);
|
fn init_card_caps(&mut self, caps: CardCaps);
|
||||||
|
|
||||||
/// Request the card's capabilities
|
/// Request the card's capabilities
|
||||||
///
|
///
|
||||||
/// (apdu serialization makes use of this information, e.g. to
|
/// (apdu serialization makes use of this information, e.g. to
|
||||||
/// determine if extended length can be used)
|
/// determine if extended length can be used)
|
||||||
fn get_caps(&self) -> Option<&CardCaps>;
|
fn card_caps(&self) -> Option<&CardCaps>;
|
||||||
|
|
||||||
/// If a CardClient implementation introduces an additional,
|
/// If a CardClient implementation introduces an additional,
|
||||||
/// backend-specific limit for maximum number of bytes per command,
|
/// backend-specific limit for maximum number of bytes per command,
|
||||||
|
@ -131,19 +131,19 @@ pub struct CardCaps {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CardCaps {
|
impl CardCaps {
|
||||||
pub fn get_ext_support(&self) -> bool {
|
pub fn ext_support(&self) -> bool {
|
||||||
self.ext_support
|
self.ext_support
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_max_rsp_bytes(&self) -> u16 {
|
pub fn max_rsp_bytes(&self) -> u16 {
|
||||||
self.max_rsp_bytes
|
self.max_rsp_bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pw1_max_len(&self) -> u8 {
|
pub fn pw1_max_len(&self) -> u8 {
|
||||||
self.pw1_max_len
|
self.pw1_max_len
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_pw3_max_len(&self) -> u8 {
|
pub fn pw3_max_len(&self) -> u8 {
|
||||||
self.pw3_max_len
|
self.pw3_max_len
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,7 +160,7 @@ pub enum KeyType {
|
||||||
|
|
||||||
impl KeyType {
|
impl KeyType {
|
||||||
/// Get C1/C2/C3/DA values for this KeyTypes, to use as Tag
|
/// Get C1/C2/C3/DA values for this KeyTypes, to use as Tag
|
||||||
fn get_algorithm_tag(&self) -> u8 {
|
fn algorithm_tag(&self) -> u8 {
|
||||||
use KeyType::*;
|
use KeyType::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
|
@ -175,7 +175,7 @@ impl KeyType {
|
||||||
///
|
///
|
||||||
/// (NOTE: these Tags are only used for "PUT DO", but GETting
|
/// (NOTE: these Tags are only used for "PUT DO", but GETting
|
||||||
/// fingerprint information from the card uses the combined Tag C5)
|
/// fingerprint information from the card uses the combined Tag C5)
|
||||||
fn get_fingerprint_put_tag(&self) -> u8 {
|
fn fingerprint_put_tag(&self) -> u8 {
|
||||||
use KeyType::*;
|
use KeyType::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
|
@ -190,7 +190,7 @@ impl KeyType {
|
||||||
///
|
///
|
||||||
/// (NOTE: these Tags are only used for "PUT DO", but GETting
|
/// (NOTE: these Tags are only used for "PUT DO", but GETting
|
||||||
/// timestamp information from the card uses the combined Tag CD)
|
/// timestamp information from the card uses the combined Tag CD)
|
||||||
fn get_timestamp_put_tag(&self) -> u8 {
|
fn timestamp_put_tag(&self) -> u8 {
|
||||||
use KeyType::*;
|
use KeyType::*;
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -45,8 +45,8 @@ impl PcscClient {
|
||||||
if Self::select(&mut card).is_ok() {
|
if Self::select(&mut card).is_ok() {
|
||||||
let mut ca = card.into_card_app()?;
|
let mut ca = card.into_card_app()?;
|
||||||
|
|
||||||
let ard = ca.get_application_related_data()?;
|
let ard = ca.application_related_data()?;
|
||||||
let aid = ard.get_application_id()?;
|
let aid = ard.application_id()?;
|
||||||
|
|
||||||
if aid.ident() == ident.to_ascii_uppercase() {
|
if aid.ident() == ident.to_ascii_uppercase() {
|
||||||
return Ok(ca);
|
return Ok(ca);
|
||||||
|
@ -155,7 +155,7 @@ impl PcscClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the minimum pin length for pin_id.
|
/// Get the minimum pin length for pin_id.
|
||||||
fn get_min_len(&self, pin_id: u8) -> Result<u8> {
|
fn min_pin_len(&self, pin_id: u8) -> Result<u8> {
|
||||||
match pin_id {
|
match pin_id {
|
||||||
0x81 | 0x82 => Ok(6),
|
0x81 | 0x82 => Ok(6),
|
||||||
0x83 => Ok(8),
|
0x83 => Ok(8),
|
||||||
|
@ -163,11 +163,11 @@ impl PcscClient {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Get the maximum pin length for pin_id.
|
/// Get the maximum pin length for pin_id.
|
||||||
fn get_max_len(&self, pin_id: u8) -> Result<u8> {
|
fn max_pin_len(&self, pin_id: u8) -> Result<u8> {
|
||||||
if let Some(card_caps) = self.card_caps {
|
if let Some(card_caps) = self.card_caps {
|
||||||
match pin_id {
|
match pin_id {
|
||||||
0x81 | 0x82 => Ok(card_caps.get_pw1_max_len()),
|
0x81 | 0x82 => Ok(card_caps.pw1_max_len()),
|
||||||
0x83 => Ok(card_caps.get_pw3_max_len()),
|
0x83 => Ok(card_caps.pw3_max_len()),
|
||||||
_ => Err(anyhow!("Unexpected pin_id {}", pin_id)),
|
_ => Err(anyhow!("Unexpected pin_id {}", pin_id)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -221,11 +221,11 @@ impl CardClient for PcscClient {
|
||||||
Ok(resp.to_vec())
|
Ok(resp.to_vec())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_caps(&mut self, caps: CardCaps) {
|
fn init_card_caps(&mut self, caps: CardCaps) {
|
||||||
self.card_caps = Some(caps);
|
self.card_caps = Some(caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_caps(&self) -> Option<&CardCaps> {
|
fn card_caps(&self) -> Option<&CardCaps> {
|
||||||
self.card_caps.as_ref()
|
self.card_caps.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,8 +238,8 @@ impl CardClient for PcscClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pinpad_verify(&mut self, pin_id: u8) -> Result<Vec<u8>> {
|
fn pinpad_verify(&mut self, pin_id: u8) -> Result<Vec<u8>> {
|
||||||
let pin_min_size = self.get_min_len(pin_id)?;
|
let pin_min_size = self.min_pin_len(pin_id)?;
|
||||||
let pin_max_size = self.get_max_len(pin_id)?;
|
let pin_max_size = self.max_pin_len(pin_id)?;
|
||||||
|
|
||||||
// Default to varlen, for now.
|
// Default to varlen, for now.
|
||||||
// (NOTE: Some readers don't support varlen, and need explicit length
|
// (NOTE: Some readers don't support varlen, and need explicit length
|
||||||
|
@ -329,8 +329,8 @@ impl CardClient for PcscClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pinpad_modify(&mut self, pin_id: u8) -> Result<Vec<u8>> {
|
fn pinpad_modify(&mut self, pin_id: u8) -> Result<Vec<u8>> {
|
||||||
let pin_min_size = self.get_min_len(pin_id)?;
|
let pin_min_size = self.min_pin_len(pin_id)?;
|
||||||
let pin_max_size = self.get_max_len(pin_id)?;
|
let pin_max_size = self.max_pin_len(pin_id)?;
|
||||||
|
|
||||||
// Default to varlen, for now.
|
// Default to varlen, for now.
|
||||||
// (NOTE: Some readers don't support varlen, and need explicit length
|
// (NOTE: Some readers don't support varlen, and need explicit length
|
||||||
|
|
|
@ -201,11 +201,11 @@ impl CardClient for ScdClient {
|
||||||
|
|
||||||
// (Unwrap is ok here, not having a card_caps is fine)
|
// (Unwrap is ok here, not having a card_caps is fine)
|
||||||
let ext = if self.card_caps.is_some()
|
let ext = if self.card_caps.is_some()
|
||||||
&& self.card_caps.unwrap().get_ext_support()
|
&& self.card_caps.unwrap().ext_support()
|
||||||
{
|
{
|
||||||
// If we know about card_caps, and can do extended length we
|
// If we know about card_caps, and can do extended length we
|
||||||
// set "exlen" accordingly ...
|
// set "exlen" accordingly ...
|
||||||
format!("--exlen={} ", self.card_caps.unwrap().get_max_rsp_bytes())
|
format!("--exlen={} ", self.card_caps.unwrap().max_rsp_bytes())
|
||||||
} else {
|
} else {
|
||||||
// ... otherwise don't send "exlen" to scdaemon
|
// ... otherwise don't send "exlen" to scdaemon
|
||||||
"".to_string()
|
"".to_string()
|
||||||
|
@ -249,11 +249,11 @@ impl CardClient for ScdClient {
|
||||||
Err(Error::InternalError(anyhow!("no response found")))
|
Err(Error::InternalError(anyhow!("no response found")))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_caps(&mut self, caps: CardCaps) {
|
fn init_card_caps(&mut self, caps: CardCaps) {
|
||||||
self.card_caps = Some(caps);
|
self.card_caps = Some(caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_caps(&self) -> Option<&CardCaps> {
|
fn card_caps(&self) -> Option<&CardCaps> {
|
||||||
self.card_caps.as_ref()
|
self.card_caps.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -74,12 +74,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
cli::AdminCommand::Name { name } => {
|
cli::AdminCommand::Name { name } => {
|
||||||
let mut admin = util::get_admin(&mut open, admin_pin)?;
|
let mut admin =
|
||||||
|
util::verify_to_admin(&mut open, admin_pin)?;
|
||||||
|
|
||||||
let _ = admin.set_name(&name)?;
|
let _ = admin.set_name(&name)?;
|
||||||
}
|
}
|
||||||
cli::AdminCommand::Url { url } => {
|
cli::AdminCommand::Url { url } => {
|
||||||
let mut admin = util::get_admin(&mut open, admin_pin)?;
|
let mut admin =
|
||||||
|
util::verify_to_admin(&mut open, admin_pin)?;
|
||||||
|
|
||||||
let _ = admin.set_url(&url)?;
|
let _ = admin.set_url(&url)?;
|
||||||
}
|
}
|
||||||
|
@ -90,7 +92,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
auth_fp,
|
auth_fp,
|
||||||
} => {
|
} => {
|
||||||
let key = Cert::from_file(keyfile)?;
|
let key = Cert::from_file(keyfile)?;
|
||||||
let admin = util::get_admin(&mut open, admin_pin)?;
|
let admin = util::verify_to_admin(&mut open, admin_pin)?;
|
||||||
|
|
||||||
if (&sig_fp, &dec_fp, &auth_fp) == (&None, &None, &None) {
|
if (&sig_fp, &dec_fp, &auth_fp) == (&None, &None, &None) {
|
||||||
// If no fingerprint has been provided, we check if
|
// If no fingerprint has been provided, we check if
|
||||||
|
@ -224,7 +226,7 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
|
||||||
println! {" algorithm: {}", open.algorithm_attributes(KeyType::Signing)?};
|
println! {" algorithm: {}", open.algorithm_attributes(KeyType::Signing)?};
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
if let Ok(pkm) = open.get_pub_key(KeyType::Signing) {
|
if let Ok(pkm) = open.public_key(KeyType::Signing) {
|
||||||
println! {" public key material: {}", pkm};
|
println! {" public key material: {}", pkm};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -240,7 +242,7 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
|
||||||
println! {" algorithm: {}", open.algorithm_attributes(KeyType::Decryption)?};
|
println! {" algorithm: {}", open.algorithm_attributes(KeyType::Decryption)?};
|
||||||
|
|
||||||
if verbose {
|
if verbose {
|
||||||
if let Ok(pkm) = open.get_pub_key(KeyType::Decryption) {
|
if let Ok(pkm) = open.public_key(KeyType::Decryption) {
|
||||||
println! {" public key material: {}", pkm};
|
println! {" public key material: {}", pkm};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +257,7 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
|
||||||
}
|
}
|
||||||
println! {" algorithm: {}", open.algorithm_attributes(KeyType::Authentication)?};
|
println! {" algorithm: {}", open.algorithm_attributes(KeyType::Authentication)?};
|
||||||
if verbose {
|
if verbose {
|
||||||
if let Ok(pkm) = open.get_pub_key(KeyType::Authentication) {
|
if let Ok(pkm) = open.public_key(KeyType::Authentication) {
|
||||||
println! {" public key material: {}", pkm};
|
println! {" public key material: {}", pkm};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -265,21 +267,21 @@ fn print_status(ident: Option<String>, verbose: bool) -> Result<()> {
|
||||||
println!();
|
println!();
|
||||||
|
|
||||||
let sst = open.security_support_template()?;
|
let sst = open.security_support_template()?;
|
||||||
println!("Signature counter: {}", sst.get_signature_count());
|
println!("Signature counter: {}", sst.signature_count());
|
||||||
|
|
||||||
let pws = open.pw_status_bytes()?;
|
let pws = open.pw_status_bytes()?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"Signature pin only valid once: {}",
|
"Signature pin only valid once: {}",
|
||||||
pws.get_pw1_cds_valid_once()
|
pws.pw1_cds_valid_once()
|
||||||
);
|
);
|
||||||
|
|
||||||
println!("Password validation retry count:");
|
println!("Password validation retry count:");
|
||||||
println!(
|
println!(
|
||||||
" user pw: {}, reset: {}, admin pw: {}",
|
" user pw: {}, reset: {}, admin pw: {}",
|
||||||
pws.get_err_count_pw1(),
|
pws.err_count_pw1(),
|
||||||
pws.get_err_count_rst(),
|
pws.err_count_rc(),
|
||||||
pws.get_err_count_pw3(),
|
pws.err_count_pw3(),
|
||||||
);
|
);
|
||||||
|
|
||||||
// FIXME: add General key info; login data; KDF setting
|
// FIXME: add General key info; login data; KDF setting
|
||||||
|
@ -318,7 +320,7 @@ fn decrypt(
|
||||||
let mut card = util::open_card(ident)?;
|
let mut card = util::open_card(ident)?;
|
||||||
let mut open = Open::new(&mut card)?;
|
let mut open = Open::new(&mut card)?;
|
||||||
|
|
||||||
let mut user = util::get_user(&mut open, pin_file)?;
|
let mut user = util::verify_to_user(&mut open, pin_file)?;
|
||||||
let d = user.decryptor(&cert, &p)?;
|
let d = user.decryptor(&cert, &p)?;
|
||||||
|
|
||||||
let db = DecryptorBuilder::from_reader(input)?;
|
let db = DecryptorBuilder::from_reader(input)?;
|
||||||
|
@ -343,7 +345,7 @@ fn sign_detached(
|
||||||
let mut card = util::open_card(ident)?;
|
let mut card = util::open_card(ident)?;
|
||||||
let mut open = Open::new(&mut card)?;
|
let mut open = Open::new(&mut card)?;
|
||||||
|
|
||||||
let mut sign = util::get_sign(&mut open, pin_file)?;
|
let mut sign = util::verify_to_sign(&mut open, pin_file)?;
|
||||||
let s = sign.signer(&cert, &p)?;
|
let s = sign.signer(&cert, &p)?;
|
||||||
|
|
||||||
let message = Armorer::new(Message::new(std::io::stdout())).build()?;
|
let message = Armorer::new(Message::new(std::io::stdout())).build()?;
|
||||||
|
@ -364,11 +366,11 @@ fn factory_reset(ident: &str) -> Result<()> {
|
||||||
fn key_import_yolo(mut admin: Admin, key: &Cert) -> Result<()> {
|
fn key_import_yolo(mut admin: Admin, key: &Cert) -> Result<()> {
|
||||||
let p = StandardPolicy::new();
|
let p = StandardPolicy::new();
|
||||||
|
|
||||||
let sig = sq_util::get_subkey_by_type(key, &p, KeyType::Signing)?;
|
let sig = sq_util::subkey_by_type(key, &p, KeyType::Signing)?;
|
||||||
|
|
||||||
let dec = sq_util::get_subkey_by_type(key, &p, KeyType::Decryption)?;
|
let dec = sq_util::subkey_by_type(key, &p, KeyType::Decryption)?;
|
||||||
|
|
||||||
let auth = sq_util::get_subkey_by_type(key, &p, KeyType::Authentication)?;
|
let auth = sq_util::subkey_by_type(key, &p, KeyType::Authentication)?;
|
||||||
|
|
||||||
if let Some(sig) = sig {
|
if let Some(sig) = sig {
|
||||||
println!("Uploading {} as signing key", sig.fingerprint());
|
println!("Uploading {} as signing key", sig.fingerprint());
|
||||||
|
@ -397,7 +399,7 @@ fn key_import_explicit(
|
||||||
|
|
||||||
if let Some(sig_fp) = sig_fp {
|
if let Some(sig_fp) = sig_fp {
|
||||||
if let Some(sig) =
|
if let Some(sig) =
|
||||||
sq_util::get_priv_subkey_by_fingerprint(key, &p, &sig_fp)?
|
sq_util::private_subkey_by_fingerprint(key, &p, &sig_fp)?
|
||||||
{
|
{
|
||||||
println!("Uploading {} as signing key", sig.fingerprint());
|
println!("Uploading {} as signing key", sig.fingerprint());
|
||||||
admin.upload_key(sig, KeyType::Signing, None)?;
|
admin.upload_key(sig, KeyType::Signing, None)?;
|
||||||
|
@ -408,7 +410,7 @@ fn key_import_explicit(
|
||||||
|
|
||||||
if let Some(dec_fp) = dec_fp {
|
if let Some(dec_fp) = dec_fp {
|
||||||
if let Some(dec) =
|
if let Some(dec) =
|
||||||
sq_util::get_priv_subkey_by_fingerprint(key, &p, &dec_fp)?
|
sq_util::private_subkey_by_fingerprint(key, &p, &dec_fp)?
|
||||||
{
|
{
|
||||||
println!("Uploading {} as decryption key", dec.fingerprint());
|
println!("Uploading {} as decryption key", dec.fingerprint());
|
||||||
admin.upload_key(dec, KeyType::Decryption, None)?;
|
admin.upload_key(dec, KeyType::Decryption, None)?;
|
||||||
|
@ -419,7 +421,7 @@ fn key_import_explicit(
|
||||||
|
|
||||||
if let Some(auth_fp) = auth_fp {
|
if let Some(auth_fp) = auth_fp {
|
||||||
if let Some(auth) =
|
if let Some(auth) =
|
||||||
sq_util::get_priv_subkey_by_fingerprint(key, &p, &auth_fp)?
|
sq_util::private_subkey_by_fingerprint(key, &p, &auth_fp)?
|
||||||
{
|
{
|
||||||
println!("Uploading {} as authentication key", auth.fingerprint());
|
println!("Uploading {} as authentication key", auth.fingerprint());
|
||||||
admin.upload_key(auth, KeyType::Authentication, None)?;
|
admin.upload_key(auth, KeyType::Authentication, None)?;
|
||||||
|
@ -473,7 +475,7 @@ fn generate_keys(
|
||||||
// 2) Then, generate keys on the card.
|
// 2) Then, generate keys on the card.
|
||||||
// We need "admin" access to the card for this).
|
// We need "admin" access to the card for this).
|
||||||
let (key_sig, key_dec, key_aut) = {
|
let (key_sig, key_dec, key_aut) = {
|
||||||
if let Ok(mut admin) = util::get_admin(&mut open, pw3_path) {
|
if let Ok(mut admin) = util::verify_to_admin(&mut open, pw3_path) {
|
||||||
gen_subkeys(&mut admin, decrypt, auth, algos)?
|
gen_subkeys(&mut admin, decrypt, auth, algos)?
|
||||||
} else {
|
} else {
|
||||||
return Err(anyhow!("Failed to open card in admin mode."));
|
return Err(anyhow!("Failed to open card in admin mode."));
|
||||||
|
@ -484,7 +486,7 @@ fn generate_keys(
|
||||||
// need "signing" access to the card (to make binding signatures within
|
// need "signing" access to the card (to make binding signatures within
|
||||||
// the Cert).
|
// the Cert).
|
||||||
let pin = if let Some(pw1) = pw1_path {
|
let pin = if let Some(pw1) = pw1_path {
|
||||||
Some(util::get_pin(&pw1)?)
|
Some(util::load_pin(&pw1)?)
|
||||||
} else {
|
} else {
|
||||||
if open.feature_pinpad_verify() {
|
if open.feature_pinpad_verify() {
|
||||||
println!();
|
println!();
|
||||||
|
|
|
@ -16,12 +16,12 @@ pub(crate) fn open_card(ident: &str) -> Result<CardApp, Error> {
|
||||||
PcscClient::open_by_ident(ident)
|
PcscClient::open_by_ident(ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_user<'app, 'open>(
|
pub(crate) fn verify_to_user<'app, 'open>(
|
||||||
open: &'app mut Open<'app>,
|
open: &'app mut Open<'app>,
|
||||||
pin_file: Option<PathBuf>,
|
pin_file: Option<PathBuf>,
|
||||||
) -> Result<User<'app, 'open>, Box<dyn std::error::Error>> {
|
) -> Result<User<'app, 'open>, Box<dyn std::error::Error>> {
|
||||||
if let Some(path) = pin_file {
|
if let Some(path) = pin_file {
|
||||||
open.verify_user(&get_pin(&path)?)?;
|
open.verify_user(&load_pin(&path)?)?;
|
||||||
} else {
|
} else {
|
||||||
if !open.feature_pinpad_verify() {
|
if !open.feature_pinpad_verify() {
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
|
@ -39,12 +39,12 @@ pub(crate) fn get_user<'app, 'open>(
|
||||||
.ok_or_else(|| anyhow!("Couldn't get user access").into())
|
.ok_or_else(|| anyhow!("Couldn't get user access").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_sign<'app, 'open>(
|
pub(crate) fn verify_to_sign<'app, 'open>(
|
||||||
open: &'app mut Open<'app>,
|
open: &'app mut Open<'app>,
|
||||||
pin_file: Option<PathBuf>,
|
pin_file: Option<PathBuf>,
|
||||||
) -> Result<Sign<'app, 'open>, Box<dyn std::error::Error>> {
|
) -> Result<Sign<'app, 'open>, Box<dyn std::error::Error>> {
|
||||||
if let Some(path) = pin_file {
|
if let Some(path) = pin_file {
|
||||||
open.verify_user_for_signing(&get_pin(&path)?)?;
|
open.verify_user_for_signing(&load_pin(&path)?)?;
|
||||||
} else {
|
} else {
|
||||||
if !open.feature_pinpad_verify() {
|
if !open.feature_pinpad_verify() {
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
|
@ -62,12 +62,12 @@ pub(crate) fn get_sign<'app, 'open>(
|
||||||
|
|
||||||
// pub fn admin_card<'b>(&'b mut self) -> Option<Admin<'a, 'b>> {
|
// pub fn admin_card<'b>(&'b mut self) -> Option<Admin<'a, 'b>> {
|
||||||
|
|
||||||
pub(crate) fn get_admin<'app, 'open>(
|
pub(crate) fn verify_to_admin<'app, 'open>(
|
||||||
open: &'open mut Open<'app>,
|
open: &'open mut Open<'app>,
|
||||||
pin_file: Option<PathBuf>,
|
pin_file: Option<PathBuf>,
|
||||||
) -> Result<Admin<'app, 'open>, Box<dyn std::error::Error>> {
|
) -> Result<Admin<'app, 'open>, Box<dyn std::error::Error>> {
|
||||||
if let Some(path) = pin_file {
|
if let Some(path) = pin_file {
|
||||||
open.verify_admin(&get_pin(&path)?)?;
|
open.verify_admin(&load_pin(&path)?)?;
|
||||||
} else {
|
} else {
|
||||||
if !open.feature_pinpad_verify() {
|
if !open.feature_pinpad_verify() {
|
||||||
return Err(anyhow!(
|
return Err(anyhow!(
|
||||||
|
@ -84,7 +84,7 @@ pub(crate) fn get_admin<'app, 'open>(
|
||||||
.ok_or_else(|| anyhow!("Couldn't get admin access").into())
|
.ok_or_else(|| anyhow!("Couldn't get admin access").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_pin(pin_file: &Path) -> Result<String> {
|
pub(crate) fn load_pin(pin_file: &Path) -> Result<String> {
|
||||||
let pin = std::fs::read_to_string(pin_file)?;
|
let pin = std::fs::read_to_string(pin_file)?;
|
||||||
Ok(pin.trim().to_string())
|
Ok(pin.trim().to_string())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue