Add documentation, limit visibilities.
This commit is contained in:
parent
cc16e7976b
commit
421ffe3599
5 changed files with 68 additions and 48 deletions
|
@ -1,6 +1,14 @@
|
|||
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
//! Data structures that define OpenPGP algorithms.
|
||||
//!
|
||||
//! [`Algo`] and its components model "Algorithm Attributes" as described in
|
||||
//! the OpenPGP card specification.
|
||||
//!
|
||||
//! [`AlgoSimple`] offers a shorthand for specifying an algorithm,
|
||||
//! specifically for key generation on the card.
|
||||
|
||||
use crate::{EccType, KeyType};
|
||||
use anyhow::anyhow;
|
||||
use std::convert::TryFrom;
|
||||
|
@ -111,9 +119,24 @@ impl AlgoSimple {
|
|||
}
|
||||
}
|
||||
|
||||
/// "Algorithm Information"
|
||||
///
|
||||
/// Modern cards provide a list of supported algorithms for each key type.
|
||||
/// The list specifies which "Algorithm Attributes" can be set for key
|
||||
/// generation or key import.
|
||||
///
|
||||
/// (This feature was introduced in OpenPGP card v3.4)
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct AlgoInfo(pub(crate) Vec<(KeyType, Algo)>);
|
||||
|
||||
/// "Algorithm Attributes"
|
||||
///
|
||||
/// An `Algo` describes the algorithm settings for a key on the card.
|
||||
///
|
||||
/// This setting specifies the data format of:
|
||||
/// - Key import
|
||||
/// - Key generation
|
||||
/// - Export of public key data from the card (e.g. after key generation)
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum Algo {
|
||||
Rsa(RsaAttrs),
|
||||
|
@ -137,6 +160,7 @@ impl fmt::Display for Algo {
|
|||
}
|
||||
}
|
||||
|
||||
/// RSA specific attributes of [`Algo`] ("Algorithm Attributes")
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct RsaAttrs {
|
||||
pub len_n: u16,
|
||||
|
@ -144,6 +168,7 @@ pub struct RsaAttrs {
|
|||
pub import_format: u8,
|
||||
}
|
||||
|
||||
/// ECC specific attributes of [`Algo`] ("Algorithm Attributes")
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct EccAttrs {
|
||||
pub ecc_type: EccType,
|
||||
|
|
|
@ -6,7 +6,7 @@ use anyhow::Result;
|
|||
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Command {
|
||||
pub(crate) struct Command {
|
||||
// Class byte (CLA)
|
||||
pub cla: u8,
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
/// APDU Commands for OpenPGP card operations
|
||||
//! Commands for the OpenPGP card application
|
||||
|
||||
use crate::apdu::command::Command;
|
||||
|
||||
/// Select the OpenPGP applet
|
||||
pub fn select_openpgp() -> Command {
|
||||
/// Select the OpenPGP application
|
||||
pub(crate) fn select_openpgp() -> Command {
|
||||
Command::new(
|
||||
0x00,
|
||||
0xA4,
|
||||
|
@ -16,63 +17,63 @@ pub fn select_openpgp() -> Command {
|
|||
}
|
||||
|
||||
/// Get DO "Application related data"
|
||||
pub fn get_application_data() -> Command {
|
||||
pub(crate) fn get_application_data() -> Command {
|
||||
Command::new(0x00, 0xCA, 0x00, 0x6E, vec![])
|
||||
}
|
||||
|
||||
/// Get DO "Uniform resource locator"
|
||||
pub fn get_url() -> Command {
|
||||
pub(crate) fn get_url() -> Command {
|
||||
Command::new(0x00, 0xCA, 0x5F, 0x50, vec![])
|
||||
}
|
||||
|
||||
/// Get DO "Cardholder related data"
|
||||
pub fn cardholder_related_data() -> Command {
|
||||
pub(crate) fn cardholder_related_data() -> Command {
|
||||
Command::new(0x00, 0xCA, 0x00, 0x65, vec![])
|
||||
}
|
||||
|
||||
/// Get DO "Security support template"
|
||||
pub fn get_security_support_template() -> Command {
|
||||
pub(crate) fn get_security_support_template() -> Command {
|
||||
Command::new(0x00, 0xCA, 0x00, 0x7A, vec![])
|
||||
}
|
||||
|
||||
/// Get DO "List of supported Algorithm attributes"
|
||||
pub fn get_algo_list() -> Command {
|
||||
pub(crate) fn get_algo_list() -> Command {
|
||||
Command::new(0x00, 0xCA, 0x00, 0xFA, vec![])
|
||||
}
|
||||
|
||||
/// GET RESPONSE
|
||||
pub fn get_response() -> Command {
|
||||
pub(crate) fn get_response() -> Command {
|
||||
Command::new(0x00, 0xC0, 0x00, 0x00, vec![])
|
||||
}
|
||||
|
||||
/// VERIFY pin for PW1 (81)
|
||||
pub fn verify_pw1_81(pin: Vec<u8>) -> Command {
|
||||
pub(crate) fn verify_pw1_81(pin: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x20, 0x00, 0x81, pin)
|
||||
}
|
||||
|
||||
/// VERIFY pin for PW1 (82)
|
||||
pub fn verify_pw1_82(pin: Vec<u8>) -> Command {
|
||||
pub(crate) fn verify_pw1_82(pin: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x20, 0x00, 0x82, pin)
|
||||
}
|
||||
|
||||
/// VERIFY pin for PW3 (83)
|
||||
pub fn verify_pw3(pin: Vec<u8>) -> Command {
|
||||
pub(crate) fn verify_pw3(pin: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x20, 0x00, 0x83, pin)
|
||||
}
|
||||
|
||||
/// TERMINATE DF
|
||||
pub fn terminate_df() -> Command {
|
||||
pub(crate) fn terminate_df() -> Command {
|
||||
Command::new(0x00, 0xe6, 0x00, 0x00, vec![])
|
||||
}
|
||||
|
||||
/// ACTIVATE FILE
|
||||
pub fn activate_file() -> Command {
|
||||
pub(crate) fn activate_file() -> Command {
|
||||
Command::new(0x00, 0x44, 0x00, 0x00, vec![])
|
||||
}
|
||||
|
||||
/// 7.2.8 PUT DATA,
|
||||
/// ('tag' must consist of either one or two bytes)
|
||||
pub fn put_data(tag: &[u8], data: Vec<u8>) -> Command {
|
||||
pub(crate) fn put_data(tag: &[u8], data: Vec<u8>) -> Command {
|
||||
assert!(!tag.is_empty() && tag.len() <= 2);
|
||||
|
||||
let (p1, p2) = if tag.len() == 2 {
|
||||
|
@ -84,33 +85,33 @@ pub fn put_data(tag: &[u8], data: Vec<u8>) -> Command {
|
|||
}
|
||||
|
||||
/// PUT DO Name
|
||||
pub fn put_name(name: Vec<u8>) -> Command {
|
||||
pub(crate) fn put_name(name: Vec<u8>) -> Command {
|
||||
put_data(&[0x5b], name)
|
||||
}
|
||||
|
||||
/// PUT DO Language preferences
|
||||
pub fn put_lang(lang: Vec<u8>) -> Command {
|
||||
pub(crate) fn put_lang(lang: Vec<u8>) -> Command {
|
||||
put_data(&[0x5f, 0x2d], lang)
|
||||
}
|
||||
|
||||
/// PUT DO Sex
|
||||
pub fn put_sex(sex: u8) -> Command {
|
||||
pub(crate) fn put_sex(sex: u8) -> Command {
|
||||
put_data(&[0x5f, 0x35], vec![sex])
|
||||
}
|
||||
|
||||
/// PUT DO Uniform resource locator (URL)
|
||||
pub fn put_url(url: Vec<u8>) -> Command {
|
||||
pub(crate) fn put_url(url: Vec<u8>) -> Command {
|
||||
put_data(&[0x5f, 0x50], url)
|
||||
}
|
||||
|
||||
/// Change PW1 (user pin).
|
||||
/// This can be used to reset the counter and set a pin.
|
||||
pub fn change_pw1(pin: Vec<u8>) -> Command {
|
||||
pub(crate) fn change_pw1(pin: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x2C, 0x02, 0x81, pin)
|
||||
}
|
||||
|
||||
/// Change PW3 (admin pin)
|
||||
pub fn change_pw3(oldpin: Vec<u8>, newpin: Vec<u8>) -> Command {
|
||||
pub(crate) fn change_pw3(oldpin: Vec<u8>, newpin: Vec<u8>) -> Command {
|
||||
let mut fullpin = oldpin;
|
||||
fullpin.extend(newpin.iter());
|
||||
|
||||
|
@ -118,21 +119,29 @@ pub fn change_pw3(oldpin: Vec<u8>, newpin: Vec<u8>) -> Command {
|
|||
}
|
||||
|
||||
/// Creates new APDU for decryption operation
|
||||
pub fn decryption(data: Vec<u8>) -> Command {
|
||||
pub(crate) fn decryption(data: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x2A, 0x80, 0x86, data)
|
||||
}
|
||||
|
||||
/// Creates new APDU for decryption operation
|
||||
pub fn signature(data: Vec<u8>) -> Command {
|
||||
pub(crate) fn signature(data: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x2A, 0x9e, 0x9a, data)
|
||||
}
|
||||
|
||||
/// Creates new APDU for "GENERATE ASYMMETRIC KEY PAIR"
|
||||
pub fn gen_key(data: Vec<u8>) -> Command {
|
||||
pub(crate) fn gen_key(data: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x47, 0x80, 0x00, data)
|
||||
}
|
||||
|
||||
/// Creates new APDU for "Reading of public key template"
|
||||
pub fn get_pub_key(data: Vec<u8>) -> Command {
|
||||
pub(crate) fn get_pub_key(data: Vec<u8>) -> Command {
|
||||
Command::new(0x00, 0x47, 0x81, 0x00, data)
|
||||
}
|
||||
|
||||
/// Creates new APDU for key import
|
||||
pub(crate) fn key_import(data: Vec<u8>) -> Command {
|
||||
// The key import uses a PUT DATA command with odd INS (DB) and an
|
||||
// Extended header list (DO 4D) as described in ISO 7816-8
|
||||
|
||||
Command::new(0x00, 0xDB, 0x3F, 0xFF, data)
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// SPDX-FileCopyrightText: 2021 Heiko Schaefer <heiko@schaefer.name>
|
||||
// SPDX-License-Identifier: MIT OR Apache-2.0
|
||||
|
||||
pub mod command;
|
||||
pub mod commands;
|
||||
//! Commands and responses to commands ("Application Protocol Data Unit")
|
||||
|
||||
pub(crate) mod command;
|
||||
pub(crate) mod commands;
|
||||
pub mod response;
|
||||
|
||||
use anyhow::Result;
|
||||
|
|
|
@ -341,16 +341,8 @@ fn ecc_key_cmd(
|
|||
// "Extended header list (DO 4D)" (contains the three inner TLV)
|
||||
let ehl = Tlv(Tag(vec![0x4d]), TlvEntry::C(vec![crt, cpkt, cpk]));
|
||||
|
||||
// The key import uses a PUT DATA command with odd INS (DB) and an
|
||||
// Extended header list (DO 4D) as described in ISO 7816-8
|
||||
|
||||
Ok(Command::new(
|
||||
0x00,
|
||||
0xDB,
|
||||
0x3F,
|
||||
0xFF,
|
||||
ehl.serialize().to_vec(),
|
||||
))
|
||||
// key import command
|
||||
Ok(commands::key_import(ehl.serialize().to_vec()))
|
||||
}
|
||||
|
||||
fn get_crt(key_type: KeyType) -> Result<Tlv, OpenpgpCardError> {
|
||||
|
@ -430,16 +422,8 @@ fn rsa_key_cmd(
|
|||
// "Extended header list (DO 4D)"
|
||||
let ehl = Tlv(Tag(vec![0x4d]), TlvEntry::C(vec![crt, cpkt, cpk]));
|
||||
|
||||
// The key import uses a PUT DATA command with odd INS (DB) and an
|
||||
// Extended header list (DO 4D) as described in ISO 7816-8
|
||||
|
||||
Ok(Command::new(
|
||||
0x00,
|
||||
0xDB,
|
||||
0x3F,
|
||||
0xFF,
|
||||
ehl.serialize().to_vec(),
|
||||
))
|
||||
// key import command
|
||||
Ok(commands::key_import(ehl.serialize().to_vec()))
|
||||
}
|
||||
|
||||
fn copy_key_to_card(
|
||||
|
|
Loading…
Reference in a new issue