From e6cea2eca6752f4bff413d008b4ce391ef273152 Mon Sep 17 00:00:00 2001 From: "Tony Arcieri (iqlusion)" Date: Mon, 12 Jul 2021 10:42:55 -0700 Subject: [PATCH] Rename `key` module to `piv` (#277) Now that the crate is named `yubikey` rather than `yubikey-piv`, it makes more sense to call this module out as PIV-related functionality. --- cli/src/commands/status.rs | 2 +- cli/src/lib.rs | 2 +- src/certificate.rs | 4 ++-- src/lib.rs | 38 +++++++++++++++++++++++--------------- src/mscmap.rs | 2 +- src/{key.rs => piv.rs} | 31 ++++++++++++++++++------------- src/transaction.rs | 2 +- src/yubikey.rs | 8 +++++++- tests/integration.rs | 4 ++-- 9 files changed, 56 insertions(+), 37 deletions(-) rename src/{key.rs => piv.rs} (97%) diff --git a/cli/src/commands/status.rs b/cli/src/commands/status.rs index 74538f9..9e1ca6d 100644 --- a/cli/src/commands/status.rs +++ b/cli/src/commands/status.rs @@ -4,7 +4,7 @@ use crate::terminal::STDOUT; use gumdrop::Options; use std::io::{self, Write}; use termcolor::{ColorSpec, StandardStreamLock, WriteColor}; -use yubikey::{key::*, YubiKey}; +use yubikey::{piv::*, YubiKey}; use crate::print_cert_info; diff --git a/cli/src/lib.rs b/cli/src/lib.rs index 115d93e..f4e962b 100644 --- a/cli/src/lib.rs +++ b/cli/src/lib.rs @@ -20,7 +20,7 @@ use std::str; use subtle_encoding::hex; use termcolor::{ColorSpec, StandardStreamLock, WriteColor}; use x509_parser::parse_x509_certificate; -use yubikey::{certificate::Certificate, key::*, YubiKey}; +use yubikey::{certificate::Certificate, piv::*, YubiKey}; /// Write information about certificate found in slot a la yubico-piv-tool output. pub fn print_cert_info( diff --git a/src/certificate.rs b/src/certificate.rs index feefe42..31b228a 100644 --- a/src/certificate.rs +++ b/src/certificate.rs @@ -32,7 +32,7 @@ use crate::{ error::{Error, Result}, - key::{sign_data, AlgorithmId, SlotId}, + piv::{sign_data, AlgorithmId, SlotId}, serialization::*, transaction::Transaction, yubikey::YubiKey, @@ -597,7 +597,7 @@ mod read_pki { use rsa::{BigUint, RSAPublicKey}; use super::{OID_NIST_P256, OID_NIST_P384}; - use crate::{key::AlgorithmId, Error, Result}; + use crate::{piv::AlgorithmId, Error, Result}; /// From [RFC 8017](https://tools.ietf.org/html/rfc8017#appendix-A.1.1): /// ```text diff --git a/src/lib.rs b/src/lib.rs index 81dc54e..7903c8a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,10 +1,16 @@ -//! [YubiKey] PIV: [Personal Identity Verification][PIV] support for -//! [Yubico] devices using the Personal Computer/Smart Card ([PC/SC]) +//! **yubikey.rs**: pure Rust cross-platform host-side driver for [YubiKey] +//! devices from [Yubico] using the Personal Computer/Smart Card ([PC/SC]) //! interface as provided by the [`pcsc` crate]. //! -//! **PIV** is a [NIST] standard for both *signing* and *encryption* +//! # Features +//! +//! ## Personal Identity Verification (PIV) +//! +//! [PIV] is a [NIST] standard for both *signing* and *encryption* //! using SmartCards and SmartCard-based hardware tokens like YubiKeys. //! +//! PIV-related functionality can be found in the [`piv`] module. +//! //! This library natively implements the protocol used to manage and //! utilize PIV encryption and signing keys which can be generated, imported, //! and stored on YubiKey devices. @@ -12,11 +18,11 @@ //! See [Yubico's guide to PIV-enabled YubiKeys][yk-guide] for more information //! on which devices support PIV and the available functionality. //! -//! ## Minimum Supported Rust Version +//! # Minimum Supported Rust Version //! //! Rust **1.51** or newer. //! -//! ## Supported YubiKeys +//! # Supported YubiKeys //! //! - [YubiKey 4] series //! - [YubiKey 5] series @@ -24,7 +30,7 @@ //! NOTE: Nano and USB-C variants of the above are also supported. //! Pre-YK4 [YubiKey NEO] series is **NOT** supported. //! -//! ## Supported Algorithms +//! # Supported Algorithms //! //! - **Authentication**: `3DES` //! - **Encryption**: `RSA1024`, `RSA2048`, `ECCP256`, `ECCP384` @@ -34,7 +40,7 @@ //! //! NOTE: RSASSA-PSS signatures and RSA-OAEP encryption may be supportable (TBD) //! -//! ## History +//! # History //! //! This library is a Rust translation of the [yubico-piv-tool] utility by //! Yubico, which was originally written in C. It was mechanically translated @@ -45,25 +51,26 @@ //! the YubiKey implementation of PIV works in general, see the //! [Yubico PIV Tool Command Line Guide][piv-tool-guide]. //! -//! ## Security Warning +//! # Security Warning //! //! No security audits of this crate have ever been performed. Presently it is in //! an experimental stage and may still contain high-severity issues. //! //! USE AT YOUR OWN RISK! //! -//! ## Code of Conduct +//! # Code of Conduct //! //! We abide by the [Contributor Covenant][cc-md] and ask that you do as well. //! //! For more information, please see [CODE_OF_CONDUCT.md][cc-md]. //! -//! ## License +//! # License //! //! **yubikey.rs** is a fork of and originally a mechanical translation from -//! Yubico's [yubico-piv-tool], a C library/CLI program. The original library -//! was licensed under a [2-Clause BSD License][BSDL], which this library inherits -//! as a derived work. +//! Yubico's [yubico-piv-tool], a C library/CLI program. +//! +//! The original library was licensed under a [2-Clause BSD License][BSDL], +//! which this library inherits as a derived work. //! //! [YubiKey]: https://www.yubico.com/products/yubikey-hardware/ //! [PIV]: https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-73-4.pdf @@ -126,13 +133,13 @@ pub mod certificate; mod chuid; mod config; mod error; -pub mod key; mod metadata; mod mgm; #[cfg(feature = "untested")] mod mscmap; #[cfg(feature = "untested")] mod msroots; +pub mod piv; mod policy; pub mod readers; mod serialization; @@ -145,8 +152,8 @@ pub use crate::{ chuid::ChuId, config::Config, error::{Error, Result}, - key::Key, mgm::{MgmKey, MgmType}, + piv::Key, policy::{PinPolicy, TouchPolicy}, readers::Readers, settings::{SettingSource, SettingValue}, @@ -183,6 +190,7 @@ pub(crate) const TAG_PROTECTED_MGM: u8 = 0x89; pub(crate) const PIV_AID: [u8; 5] = [0xa0, 0x00, 0x00, 0x03, 0x08]; /// MGMT Applet ID. +/// /// #[cfg(feature = "untested")] pub(crate) const MGMT_AID: [u8; 8] = [0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17]; diff --git a/src/mscmap.rs b/src/mscmap.rs index 1716996..3f0c2fd 100644 --- a/src/mscmap.rs +++ b/src/mscmap.rs @@ -30,7 +30,7 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use crate::{key::SlotId, serialization::*, Error, Result, YubiKey, CB_OBJ_MAX}; +use crate::{piv::SlotId, serialization::*, Error, Result, YubiKey, CB_OBJ_MAX}; use log::error; use std::convert::{TryFrom, TryInto}; diff --git a/src/key.rs b/src/piv.rs similarity index 97% rename from src/key.rs rename to src/piv.rs index d5dc1e7..dcd226b 100644 --- a/src/key.rs +++ b/src/piv.rs @@ -1,11 +1,16 @@ -//! PIV cryptographic keys stored in a YubiKey. +//! Personal Identity Verification (PIV) cryptographic keys stored in a YubiKey. +//! +//! Support for public-key cryptography using keys stored within the PIV +//! slots of a YubiKey. //! //! Supported algorithms: //! -//! - **Encryption**: `RSA1024`, `RSA2048`, `ECCP256`, `ECCP384` +//! - **Encryption**: +//! - RSA: `RSA1024`, `RSA2048` +//! - ECC: `ECCP256`, `ECCP384` (i.e. NIST curves: P-256, P-384) //! - **Signatures**: //! - RSASSA-PKCS#1v1.5: `RSA1024`, `RSA2048` -//! - ECDSA: `ECCP256`, `ECCP384` +//! - ECDSA: `ECCP256`, `ECCP384` (NIST curves: P-256, P-384) // Adapted from yubico-piv-tool: // @@ -50,7 +55,7 @@ use crate::{ use elliptic_curve::sec1::EncodedPoint as EcPublicKey; use log::{debug, error, warn}; use rsa::{BigUint, RSAPublicKey}; -use std::convert::TryFrom; +use std::{convert::TryFrom, str::FromStr}; #[cfg(feature = "untested")] use { @@ -146,17 +151,17 @@ impl From for u8 { } } -impl TryFrom for SlotId { - type Error = Error; +impl FromStr for SlotId { + type Err = Error; - fn try_from(s: String) -> Result { - match s.as_ref() { + fn from_str(s: &str) -> Result { + match s { "9a" => Ok(SlotId::Authentication), "9c" => Ok(SlotId::Signature), "9d" => Ok(SlotId::KeyManagement), "9e" => Ok(SlotId::CardAuthentication), "f9" => Ok(SlotId::Attestation), - _ => RetiredSlotId::try_from(s).map(SlotId::Retired), + _ => s.parse().map(SlotId::Retired), } } } @@ -231,11 +236,11 @@ impl TryFrom for RetiredSlotId { } } -impl TryFrom for RetiredSlotId { - type Error = Error; +impl FromStr for RetiredSlotId { + type Err = Error; - fn try_from(value: String) -> Result { - match value.as_ref() { + fn from_str(value: &str) -> Result { + match value { "82" => Ok(RetiredSlotId::R1), "83" => Ok(RetiredSlotId::R2), "84" => Ok(RetiredSlotId::R3), diff --git a/src/transaction.rs b/src/transaction.rs index 8116f8a..8302d0b 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -4,7 +4,7 @@ use crate::{ apdu::Response, apdu::{Apdu, Ins, StatusWords}, error::{Error, Result}, - key::{AlgorithmId, SlotId}, + piv::{AlgorithmId, SlotId}, serialization::*, yubikey::*, Buffer, ObjectId, CB_BUF_MAX, CB_OBJ_MAX, PIV_AID, YK_AID, diff --git a/src/yubikey.rs b/src/yubikey.rs index cb9f9e1..5f75553 100644 --- a/src/yubikey.rs +++ b/src/yubikey.rs @@ -37,6 +37,7 @@ use crate::{ config::Config, error::{Error, Result}, mgm::MgmKey, + piv, readers::{Reader, Readers}, transaction::Transaction, }; @@ -319,7 +320,12 @@ impl YubiKey { Ok(()) } - /// Deauthenticate + /// Get the PIV keys contained in this YubiKey. + pub fn piv_keys(&mut self) -> Result> { + piv::Key::list(self) + } + + /// Deauthenticate. #[cfg(feature = "untested")] #[cfg_attr(docsrs, doc(cfg(feature = "untested")))] pub fn deauthenticate(&mut self) -> Result<()> { diff --git a/tests/integration.rs b/tests/integration.rs index 810c477..1c650d8 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -12,7 +12,7 @@ use std::{convert::TryInto, env, sync::Mutex}; use x509::RelativeDistinguishedName; use yubikey::{ certificate::{Certificate, PublicKeyInfo}, - key::{self, AlgorithmId, Key, RetiredSlotId, SlotId}, + piv::{self, AlgorithmId, Key, RetiredSlotId, SlotId}, Error, MgmKey, PinPolicy, TouchPolicy, YubiKey, }; @@ -154,7 +154,7 @@ fn generate_self_signed_cert(algorithm: AlgorithmId) -> Certificate { let slot = SlotId::Retired(RetiredSlotId::R1); // Generate a new key in the selected slot. - let generated = key::generate( + let generated = piv::generate( &mut yubikey, slot, algorithm,