From c30cf5b83aae13a22810a2b9f9351a0af741aa86 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 7 Dec 2019 08:36:46 -0800 Subject: [PATCH] Test YubiKey::verify_pin (--ignored) Adds an off-by-default test that the `YubiKey::verify_pin` function works, and removes it from `untested` gating. --- Cargo.lock | 15 ++++++++------- Cargo.toml | 1 + src/apdu.rs | 1 - src/transaction.rs | 28 +++++++++++++--------------- src/yubikey.rs | 2 -- tests/integration.rs | 25 ++++++++++++++++++------- 6 files changed, 40 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0eb0e1..b8ef964 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,7 +46,7 @@ name = "backtrace-sys" version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -111,7 +111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -143,7 +143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rusticata-macros 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rusticata-macros 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -618,7 +618,7 @@ dependencies = [ [[package]] name = "rusticata-macros" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -830,7 +830,7 @@ dependencies = [ "der-parser 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rusticata-macros 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rusticata-macros 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -855,6 +855,7 @@ dependencies = [ "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "hmac 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "nom 5.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "pbkdf2 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -906,7 +907,7 @@ dependencies = [ "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" -"checksum cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)" = "aa87058dce70a3ff5621797f1506cb837edd02ac4c0ae642b4542dce802908b8" +"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum crypto-mac 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" @@ -965,7 +966,7 @@ dependencies = [ "checksum rsa 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5108a8bbfb84fe77d829d77d5a89255dcd189dfe5c4de5a33d0a47f12808bb15" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum rusticata-macros 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1a2fec406dbe9a6def54a66dadbfa387c7f60e903691b208160d5e9c4586dff9" +"checksum rusticata-macros 2.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "93cca5a839ae468017da70a202f294e3deeda9e7d98f21b83fc5d23e5163b9df" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum safemem 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" "checksum secrecy 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "30e17355cc3cbc217e0bad1a71b38c60ed9ee34bbc3ede7ffb1c4af20f0a14c9" diff --git a/Cargo.toml b/Cargo.toml index 149466b..c444833 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -40,6 +40,7 @@ zeroize = "1" [dev-dependencies] env_logger = "0.7" +lazy_static = "1" [features] untested = [] diff --git a/src/apdu.rs b/src/apdu.rs index 60de357..d7b4dbf 100644 --- a/src/apdu.rs +++ b/src/apdu.rs @@ -84,7 +84,6 @@ impl APDU { } /// Set both parameters for this APDU - #[cfg(feature = "untested")] pub fn params(&mut self, p1: u8, p2: u8) -> &mut Self { self.p1 = p1; self.p2 = p2; diff --git a/src/transaction.rs b/src/transaction.rs index 3c534b0..970ce26 100644 --- a/src/transaction.rs +++ b/src/transaction.rs @@ -1,22 +1,21 @@ //! YubiKey PC/SC transactions -use crate::{ - apdu::{Ins, APDU}, - error::Error, - yubikey::*, -}; #[cfg(feature = "untested")] use crate::{ - apdu::{Response, StatusWords}, - consts::*, + apdu::Response, key::{AlgorithmId, SlotId}, mgm::MgmKey, serialization::*, Buffer, ObjectId, }; +use crate::{ + apdu::{Ins, StatusWords, APDU}, + consts::*, + error::Error, + yubikey::*, +}; use log::{error, trace}; use std::convert::TryInto; -#[cfg(feature = "untested")] use zeroize::Zeroizing; /// Exclusive transaction with the YubiKey's PC/SC card. @@ -25,7 +24,7 @@ pub(crate) struct Transaction<'tx> { } impl<'tx> Transaction<'tx> { - /// Create a new transaction with the given card + /// Create a new transaction with the given card. pub fn new(card: &'tx mut pcsc::Card) -> Result { Ok(Transaction { inner: card.transaction()?, @@ -84,7 +83,7 @@ impl<'tx> Transaction<'tx> { Ok(()) } - /// Get the version of the PIV application installed on the YubiKey + /// Get the version of the PIV application installed on the YubiKey. pub fn get_version(&self) -> Result { // get version from device let response = APDU::new(Ins::GetVersion).transmit(self, 261)?; @@ -100,7 +99,7 @@ impl<'tx> Transaction<'tx> { Ok(Version::new(response.data()[..3].try_into().unwrap())) } - /// Get YubiKey device serial number + /// Get YubiKey device serial number. pub fn get_serial(&self, version: Version) -> Result { let yk_applet = [0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01, 0x01]; @@ -162,7 +161,6 @@ impl<'tx> Transaction<'tx> { } /// Verify device PIN. - #[cfg(feature = "untested")] pub fn verify_pin(&self, pin: &[u8]) -> Result<(), Error> { if pin.len() > CB_PIN_MAX { return Err(Error::SizeError); @@ -190,7 +188,7 @@ impl<'tx> Transaction<'tx> { } } - /// Change the PIN + /// Change the PIN. #[cfg(feature = "untested")] pub fn change_pin(&self, action: i32, current_pin: &[u8], new_pin: &[u8]) -> Result<(), Error> { let mut templ = [0, Ins::ChangeReference.code(), 0, 0x80]; @@ -449,7 +447,7 @@ impl<'tx> Transaction<'tx> { Ok(Response::new(sw.into(), out_data)) } - /// Fetch an object + /// Fetch an object. #[cfg(feature = "untested")] pub fn fetch_object(&self, object_id: ObjectId) -> Result { let mut indata = [0u8; 5]; @@ -493,7 +491,7 @@ impl<'tx> Transaction<'tx> { )) } - /// Save an object + /// Save an object. #[cfg(feature = "untested")] pub fn save_object(&self, object_id: ObjectId, indata: &[u8]) -> Result<(), Error> { let templ = [0, Ins::PutData.code(), 0x3f, 0xff]; diff --git a/src/yubikey.rs b/src/yubikey.rs index 725ccd6..bc62cce 100644 --- a/src/yubikey.rs +++ b/src/yubikey.rs @@ -190,7 +190,6 @@ impl YubiKey { } /// Begin a transaction. - #[cfg(feature = "untested")] pub(crate) fn begin_transaction(&mut self) -> Result, Error> { // TODO(tarcieri): reconnect support Ok(Transaction::new(&mut self.card)?) @@ -330,7 +329,6 @@ impl YubiKey { } /// Verify device PIN. - #[cfg(feature = "untested")] pub fn verify_pin(&mut self, pin: &[u8]) -> Result<(), Error> { { let txn = self.begin_transaction()?; diff --git a/tests/integration.rs b/tests/integration.rs index 968b5f8..6980220 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -3,18 +3,29 @@ #![forbid(unsafe_code)] #![warn(missing_docs, rust_2018_idioms, trivial_casts, unused_qualifications)] -use std::env; +use lazy_static::lazy_static; +use std::{env, sync::Mutex}; use yubikey_piv::YubiKey; -#[test] -#[ignore] -fn connect() { +lazy_static! { + /// Provide thread-safe access to a YubiKey + static ref YUBIKEY: Mutex = init_yubikey(); +} + +/// One-time test initialization and setup +fn init_yubikey() -> Mutex { // Only show logs if `RUST_LOG` is set if env::var("RUST_LOG").is_ok() { env_logger::builder().format_timestamp(None).init(); } - let mut yubikey = YubiKey::open().unwrap(); - dbg!(&yubikey.version()); - dbg!(&yubikey.serial()); + Mutex::new(YubiKey::open().unwrap()) +} + +#[test] +#[ignore] +fn test_verify_pin() { + let mut yubikey = YUBIKEY.lock().unwrap(); + assert!(yubikey.verify_pin(b"000000").is_err()); + assert!(yubikey.verify_pin(b"123456").is_ok()); }