From feb6f7be519aeb7689b470eee7fdeabf213cb80e Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Sat, 7 Aug 2021 00:18:13 +0200 Subject: [PATCH] Implement get_pub_key() --- card-functionality/src/main.rs | 46 +++++++++++++++++++++++++++++++ openpgp-card/src/apdu/commands.rs | 5 ++++ openpgp-card/src/card_app.rs | 7 +++++ openpgp-card/src/keys.rs | 24 +++++++++++++++- 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/card-functionality/src/main.rs b/card-functionality/src/main.rs index ccec2d2..219b98c 100644 --- a/card-functionality/src/main.rs +++ b/card-functionality/src/main.rs @@ -31,6 +31,7 @@ use std::time::SystemTime; use thiserror::Error; use sequoia_openpgp::parse::Parse; +use sequoia_openpgp::types::Timestamp; use sequoia_openpgp::Cert; use openpgp_card::card_app::CardApp; @@ -233,6 +234,46 @@ fn test_keygen( Ok(vec![]) } +/// Construct public key based on data from the card +fn test_get_pub( + ca: &mut CardApp, + _param: &[&str], +) -> Result { + let ard = ca.get_app_data()?; + let key_gen = CardApp::get_key_generation_times(&ard)?; + + // -- + + let sig = ca.get_pub_key(KeyType::Signing)?; + let ts = Timestamp::from(key_gen.signature().unwrap().get()).into(); + let key = openpgp_card_sequoia::public_key_material_to_key(&sig, ts)?; + + println!(" sig key data from card -> {:x?}", key); + + // -- + + let dec = ca.get_pub_key(KeyType::Decryption)?; + let ts = Timestamp::from(key_gen.decryption().unwrap().get()).into(); + let key = openpgp_card_sequoia::public_key_material_to_key(&dec, ts)?; + + println!(" dec key data from card -> {:x?}", key); + + // -- + + let auth = ca.get_pub_key(KeyType::Authentication)?; + let ts = Timestamp::from(key_gen.authentication().unwrap().get()).into(); + let key = openpgp_card_sequoia::public_key_material_to_key(&auth, ts)?; + + println!(" auth key data from card -> {:x?}", key); + + // FIXME: assert that key FP is equal to FP from card + + // ca.generate_key(fp, KeyType::Decryption)?; + // ca.generate_key(fp, KeyType::Authentication)?; + + Ok(vec![]) +} + fn test_reset( ca: &mut CardApp, _param: &[&str], @@ -358,6 +399,11 @@ fn main() -> Result<()> { for mut card in cards { println!("** Run tests on card {:?} **", card); + println!("Get pubkey"); + let _ = run_test(&mut card, test_get_pub, &[])?; + + panic!(); + // println!("Caps"); // let _ = run_test(&mut card, test_print_caps, &[])?; // diff --git a/openpgp-card/src/apdu/commands.rs b/openpgp-card/src/apdu/commands.rs index 4621906..c43ff6b 100644 --- a/openpgp-card/src/apdu/commands.rs +++ b/openpgp-card/src/apdu/commands.rs @@ -131,3 +131,8 @@ pub fn signature(data: Vec) -> Command { pub fn gen_key(data: Vec) -> Command { Command::new(0x00, 0x47, 0x80, 0x00, data) } + +/// Creates new APDU for "Reading of public key template" +pub fn get_pub_key(data: Vec) -> Command { + Command::new(0x00, 0x47, 0x81, 0x00, data) +} diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index e54bdb1..f68505a 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -572,4 +572,11 @@ impl CardApp { // FIXME: specify algo; pass in algo list? keys::gen_key_with_metadata(self, fp_from_pub, key_type) } + + pub fn get_pub_key( + &mut self, + key_type: KeyType, + ) -> Result { + keys::get_pub_key(self, key_type) + } } diff --git a/openpgp-card/src/keys.rs b/openpgp-card/src/keys.rs index 294e91c..c7997e1 100644 --- a/openpgp-card/src/keys.rs +++ b/openpgp-card/src/keys.rs @@ -19,7 +19,8 @@ use crate::{ RSAKey, }; -/// `fp_from_pub` calculates the fingerprint for a public key data object +/// `gen_key_with_metadata` calculates the fingerprint for a public key +/// data object pub(crate) fn gen_key_with_metadata( card_app: &mut CardApp, fp_from_pub: fn(&PublicKeyMaterial, SystemTime) -> Result<[u8; 20]>, @@ -116,6 +117,27 @@ pub(crate) fn gen_key( Ok(pubkey) } +pub(crate) fn get_pub_key( + card_app: &mut CardApp, + key_type: KeyType, +) -> Result { + println!("get pub key for {:?}", key_type); + + let card_client = card_app.card(); + + // get public key + let crt = get_crt(key_type)?; + let get_pub_key_cmd = commands::get_pub_key(crt.serialize().to_vec()); + + let resp = apdu::send_command(card_client, get_pub_key_cmd, true)?; + resp.check_ok()?; + + let tlv = Tlv::try_from(resp.data()?)?; + let pubkey = tlv_to_pubkey(&tlv)?; + + Ok(pubkey) +} + /// Upload an explicitly selected Key to the card as a specific KeyType. /// /// The client needs to make sure that the key is suitable for `key_type`.