From 780b6e724cbb158fbf99a4596b18b89257752698 Mon Sep 17 00:00:00 2001 From: Heiko Schaefer Date: Wed, 25 Aug 2021 13:59:53 +0200 Subject: [PATCH] Implement get_cardholder_certificate()/set_cardholder_certificate() and select_data(). --- openpgp-card/src/apdu/commands.rs | 29 ++++++++++++++++------ openpgp-card/src/card_app.rs | 41 ++++++++++++++++++++++++++++++- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/openpgp-card/src/apdu/commands.rs b/openpgp-card/src/apdu/commands.rs index c552f7a..efebec6 100644 --- a/openpgp-card/src/apdu/commands.rs +++ b/openpgp-card/src/apdu/commands.rs @@ -30,32 +30,37 @@ fn get_data(tag: &[u8]) -> Command { Command::new(0x00, 0xCA, p1, p2, vec![]) } -/// Get DO "Application related data" +/// GET DO "Application related data" pub(crate) fn get_application_data() -> Command { get_data(&[0x6E]) } -/// Get DO "private use" +/// GET DO "private use" pub(crate) fn get_private_do(num: u8) -> Command { get_data(&[0x01, num]) } -/// Get DO "Uniform resource locator" +/// GET DO "Uniform resource locator" pub(crate) fn get_url() -> Command { get_data(&[0x5F, 0x50]) } -/// Get DO "Cardholder related data" +/// GET DO "Cardholder related data" pub(crate) fn cardholder_related_data() -> Command { get_data(&[0x65]) } -/// Get DO "Security support template" +/// GET DO "Security support template" pub(crate) fn get_security_support_template() -> Command { get_data(&[0x7A]) } -/// Get DO "List of supported Algorithm attributes" +/// GET DO "Cardholder certificate" +pub(crate) fn get_cardholder_certificate() -> Command { + get_data(&[0x7F, 0x21]) +} + +/// GET DO "List of supported Algorithm attributes" pub(crate) fn get_algo_list() -> Command { get_data(&[0xFA]) } @@ -65,6 +70,11 @@ pub(crate) fn get_response() -> Command { Command::new(0x00, 0xC0, 0x00, 0x00, vec![]) } +/// SELECT DATA +pub(crate) fn select_data(num: u8, data: Vec) -> Command { + Command::new(0x00, 0xA5, num, 0x04, data) +} + /// VERIFY pin for PW1 (81) pub(crate) fn verify_pw1_81(pin: Vec) -> Command { Command::new(0x00, 0x20, 0x00, 0x81, pin) @@ -103,7 +113,7 @@ pub(crate) fn put_data(tag: &[u8], data: Vec) -> Command { Command::new(0x00, 0xda, p1, p2, data) } -/// Put DO "private use" +/// PUT DO "private use" pub(crate) fn put_private_do(num: u8, data: Vec) -> Command { put_data(&[0x01, num], data) } @@ -133,6 +143,11 @@ pub(crate) fn put_pw_status(data: Vec) -> Command { put_data(&[0xc4], data) } +/// PUT DO "Cardholder certificate" +pub(crate) fn put_cardholder_certificate(data: Vec) -> Command { + put_data(&[0x7F, 0x21], data) +} + /// Change PW1 (user pin). /// This can be used to reset the counter and set a pin. pub(crate) fn change_pw1(pin: Vec) -> Command { diff --git a/openpgp-card/src/card_app.rs b/openpgp-card/src/card_app.rs index 2c5426d..2c433f3 100644 --- a/openpgp-card/src/card_app.rs +++ b/openpgp-card/src/card_app.rs @@ -195,7 +195,18 @@ impl CardApp { } } - // DO "Algorithm Information" (0xFA) + /// Get cardholder certificate (each for AUT, DEC and SIG). + /// + /// Call select_data() before calling this fn, to select a particular + /// certificate (if the card supports multiple certificates). + pub fn get_cardholder_certificate( + &mut self, + ) -> Result { + let cmd = commands::get_cardholder_certificate(); + apdu::send_command(&mut self.card_client, cmd, true)?.try_into() + } + + /// DO "Algorithm Information" (0xFA) pub fn list_supported_algo(&mut self) -> Result> { let resp = apdu::send_command( &mut self.card_client, @@ -208,6 +219,22 @@ impl CardApp { Ok(Some(ai)) } + pub fn select_data( + &mut self, + num: u8, + tag: &[u8], + ) -> Result { + let tlv = Tlv( + Tag(vec![0x60]), + TlvEntry::C(vec![Tlv(Tag(vec![0x5c]), TlvEntry::S(tag.to_vec()))]), + ); + + let data = tlv.serialize(); + + let cmd = commands::select_data(num, data); + apdu::send_command(&mut self.card_client, cmd, true)?.try_into() + } + // ---------- /// Delete all state on this OpenPGP card @@ -493,6 +520,18 @@ impl CardApp { apdu::send_command(self.card(), cmd, false)?.try_into() } + /// Set cardholder certificate (for AUT, DEC or SIG). + /// + /// Call select_data() before calling this fn, to select a particular + /// certificate (if the card supports multiple certificates). + pub fn set_cardholder_certificate( + &mut self, + data: Vec, + ) -> Result { + let cmd = commands::put_cardholder_certificate(data); + apdu::send_command(&mut self.card_client, cmd, false)?.try_into() + } + /// Set algorithm attributes [4.4.3.9 Algorithm Attributes] pub fn set_algorithm_attributes( &mut self,