Test Config::get
Tests reading configuration from a live device:
Config { protected_data_available: false, puk_blocked: false, puk_noblock_on_upgrade: false, pin_last_changed: 0, mgm_type: Manual }
This commit is contained in:
@@ -68,7 +68,7 @@ functions of the YubiKey:
|
||||
| ⚠️ | `cccid` | [#21] | Cardholder Capability Container (CCC) IDs |
|
||||
| 🚧️ | `certificate` | [#22] | Certificates for stored keys |
|
||||
| ⚠️ | `chuid` | [#23] | Cardholder Unique Identifier (CHUID) |
|
||||
| ⚠️ | `config` | [#24] | Support for reading on-key configuration |
|
||||
| ✅️ | `config` | [#24] | Support for reading on-key configuration |
|
||||
| ⚠️ | `container` | [#25] | MS Container Map Records |
|
||||
| 🚧 | `key` | [#26] | Crypto key management: list, generate, import |
|
||||
| ⚠️ | `mgm` | [#26] | Management Key (MGM) support: set, get, derive |
|
||||
@@ -78,6 +78,7 @@ Legend:
|
||||
|
||||
| | Description |
|
||||
|----|------------------------------------|
|
||||
| ✅ | Working |
|
||||
| 🚧 | Testing and validation in progress |
|
||||
| ⚠️ | Untested support |
|
||||
|
||||
|
||||
+14
-6
@@ -32,10 +32,13 @@
|
||||
|
||||
use crate::{consts::*, error::Error, metadata, mgm::MgmType, yubikey::YubiKey};
|
||||
use log::error;
|
||||
use std::convert::TryInto;
|
||||
use std::{
|
||||
convert::TryInto,
|
||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
/// Config
|
||||
#[derive(Copy, Clone)]
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Config {
|
||||
/// Protected data available
|
||||
protected_data_available: bool,
|
||||
@@ -47,7 +50,7 @@ pub struct Config {
|
||||
puk_noblock_on_upgrade: bool,
|
||||
|
||||
/// PIN last changed
|
||||
pin_last_changed: u32,
|
||||
pin_last_changed: Option<SystemTime>,
|
||||
|
||||
/// MGM type
|
||||
mgm_type: MgmType,
|
||||
@@ -60,7 +63,7 @@ impl Config {
|
||||
protected_data_available: false,
|
||||
puk_blocked: false,
|
||||
puk_noblock_on_upgrade: false,
|
||||
pin_last_changed: 0,
|
||||
pin_last_changed: None,
|
||||
mgm_type: MgmType::Manual,
|
||||
};
|
||||
|
||||
@@ -93,8 +96,13 @@ impl Config {
|
||||
if item.len() != CB_ADMIN_TIMESTAMP {
|
||||
error!("pin timestamp in admin metadata is an invalid size");
|
||||
} else {
|
||||
// TODO(tarcieri): double check this is little endian
|
||||
config.pin_last_changed = u32::from_le_bytes(item.try_into().unwrap());
|
||||
// TODO(tarcieri): double-check endianness is correct
|
||||
let pin_last_changed = u32::from_le_bytes(item.try_into().unwrap());
|
||||
|
||||
if pin_last_changed != 0 {
|
||||
config.pin_last_changed =
|
||||
Some(UNIX_EPOCH + Duration::from_secs(pin_last_changed as u64));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,16 +141,13 @@ pub mod cccid;
|
||||
pub mod certificate;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod chuid;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod config;
|
||||
pub mod consts;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod container;
|
||||
pub mod error;
|
||||
pub mod key;
|
||||
#[cfg(feature = "untested")]
|
||||
mod metadata;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod mgm;
|
||||
#[cfg(feature = "untested")]
|
||||
pub mod msroots;
|
||||
|
||||
@@ -31,6 +31,8 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use crate::{consts::*, error::Error, serialization::*, transaction::Transaction, Buffer};
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
use zeroize::Zeroizing;
|
||||
|
||||
/// Get metadata item
|
||||
@@ -64,6 +66,7 @@ pub(crate) fn get_item(data: &[u8], tag: u8) -> Result<&[u8], Error> {
|
||||
}
|
||||
|
||||
/// Set metadata item
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn set_item(
|
||||
data: &mut [u8],
|
||||
pcb_data: &mut usize,
|
||||
@@ -191,6 +194,7 @@ pub(crate) fn read(txn: &Transaction<'_>, tag: u8) -> Result<Buffer, Error> {
|
||||
}
|
||||
|
||||
/// Write metadata
|
||||
#[cfg(feature = "untested")]
|
||||
pub(crate) fn write(txn: &Transaction<'_>, tag: u8, data: &[u8]) -> Result<(), Error> {
|
||||
let mut buf = Zeroizing::new(vec![0u8; CB_OBJ_MAX]);
|
||||
|
||||
@@ -218,6 +222,7 @@ pub(crate) fn write(txn: &Transaction<'_>, tag: u8, data: &[u8]) -> Result<(), E
|
||||
}
|
||||
|
||||
/// Get the size of a length tag for the given length
|
||||
#[cfg(feature = "untested")]
|
||||
fn get_length_size(length: usize) -> usize {
|
||||
if length < 0x80 {
|
||||
1
|
||||
|
||||
+18
-6
@@ -30,18 +30,25 @@
|
||||
// (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::{consts::*, error::Error, metadata, yubikey::YubiKey};
|
||||
use crate::{consts::*, error::Error};
|
||||
use getrandom::getrandom;
|
||||
use log::error;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
|
||||
#[cfg(feature = "untested")]
|
||||
use crate::{metadata, yubikey::YubiKey};
|
||||
#[cfg(feature = "untested")]
|
||||
use des::{
|
||||
block_cipher_trait::{generic_array::GenericArray, BlockCipher},
|
||||
TdesEde3,
|
||||
};
|
||||
use getrandom::getrandom;
|
||||
#[cfg(feature = "untested")]
|
||||
use hmac::Hmac;
|
||||
use log::error;
|
||||
#[cfg(feature = "untested")]
|
||||
use pbkdf2::pbkdf2;
|
||||
#[cfg(feature = "untested")]
|
||||
use sha1::Sha1;
|
||||
use std::convert::{TryFrom, TryInto};
|
||||
use zeroize::{Zeroize, Zeroizing};
|
||||
|
||||
/// Default MGM key configured on all YubiKeys
|
||||
const DEFAULT_MGM_KEY: [u8; DES_LEN_3DES] = [
|
||||
@@ -50,7 +57,6 @@ const DEFAULT_MGM_KEY: [u8; DES_LEN_3DES] = [
|
||||
|
||||
/// Management Key (MGM) key types (manual/derived/protected)
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
#[allow(non_camel_case_types)]
|
||||
pub enum MgmType {
|
||||
/// Manual
|
||||
Manual = 0,
|
||||
@@ -107,6 +113,7 @@ impl MgmKey {
|
||||
}
|
||||
|
||||
/// Get derived management key (MGM)
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn get_derived(yubikey: &mut YubiKey, pin: &[u8]) -> Result<Self, Error> {
|
||||
let txn = yubikey.begin_transaction()?;
|
||||
|
||||
@@ -131,6 +138,7 @@ impl MgmKey {
|
||||
}
|
||||
|
||||
/// Get protected management key (MGM)
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn get_protected(yubikey: &mut YubiKey) -> Result<Self, Error> {
|
||||
let txn = yubikey.begin_transaction()?;
|
||||
|
||||
@@ -158,12 +166,14 @@ impl MgmKey {
|
||||
}
|
||||
|
||||
/// Set the management key (MGM)
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn set(&self, yubikey: &mut YubiKey, touch: Option<u8>) -> Result<(), Error> {
|
||||
let txn = yubikey.begin_transaction()?;
|
||||
txn.set_mgm_key(&self, touch)
|
||||
}
|
||||
|
||||
/// Set protected management key (MGM)
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn set_protected(&self, yubikey: &mut YubiKey) -> Result<(), Error> {
|
||||
let mut data = Zeroizing::new(vec![0u8; CB_BUF_MAX]);
|
||||
|
||||
@@ -254,6 +264,7 @@ impl MgmKey {
|
||||
}
|
||||
|
||||
/// Encrypt with 3DES key
|
||||
#[cfg(feature = "untested")]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub(crate) fn encrypt(&self, input: &[u8; DES_LEN_DES]) -> [u8; DES_LEN_DES] {
|
||||
let mut output = input.to_owned();
|
||||
@@ -263,6 +274,7 @@ impl MgmKey {
|
||||
}
|
||||
|
||||
/// Decrypt with 3DES key
|
||||
#[cfg(feature = "untested")]
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
pub(crate) fn decrypt(&self, input: &[u8; DES_LEN_DES]) -> [u8; DES_LEN_DES] {
|
||||
let mut output = input.to_owned();
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
use crate::{
|
||||
config::Config,
|
||||
error::Error,
|
||||
readers::{Reader, Readers},
|
||||
transaction::Transaction,
|
||||
@@ -200,6 +201,11 @@ impl YubiKey {
|
||||
self.serial
|
||||
}
|
||||
|
||||
/// Get device configuration.
|
||||
pub fn config(&mut self) -> Result<Config, Error> {
|
||||
Config::get(self)
|
||||
}
|
||||
|
||||
/// Authenticate to the card using the provided management key (MGM).
|
||||
#[cfg(feature = "untested")]
|
||||
pub fn authenticate(&mut self, mgm_key: MgmKey) -> Result<(), Error> {
|
||||
|
||||
+24
-3
@@ -27,14 +27,23 @@ fn init_yubikey() -> Mutex<YubiKey> {
|
||||
Mutex::new(yubikey)
|
||||
}
|
||||
|
||||
//
|
||||
// Device config support
|
||||
//
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_verify_pin() {
|
||||
fn test_get_config() {
|
||||
let mut yubikey = YUBIKEY.lock().unwrap();
|
||||
assert!(yubikey.verify_pin(b"000000").is_err());
|
||||
assert!(yubikey.verify_pin(b"123456").is_ok());
|
||||
let config_result = yubikey.config();
|
||||
assert!(config_result.is_ok());
|
||||
trace!("config: {:?}", config_result.unwrap());
|
||||
}
|
||||
|
||||
//
|
||||
// Cryptographic key support
|
||||
//
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn test_list_keys() {
|
||||
@@ -43,3 +52,15 @@ fn test_list_keys() {
|
||||
assert!(keys_result.is_ok());
|
||||
trace!("keys: {:?}", keys_result.unwrap());
|
||||
}
|
||||
|
||||
//
|
||||
// PIN support
|
||||
//
|
||||
|
||||
#[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());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user