Test Key::list

Adds a live-against-the-device test which ensures keys can be
successfully listed.
This commit is contained in:
Tony Arcieri
2019-12-07 09:42:18 -08:00
parent cb9d5221b2
commit d1d384d304
9 changed files with 55 additions and 37 deletions
-2
View File
@@ -71,7 +71,6 @@ impl APDU {
}
/// Set this APDU's class
#[cfg(feature = "untested")]
pub fn cla(&mut self, value: u8) -> &mut Self {
self.cla = value;
self
@@ -267,7 +266,6 @@ pub(crate) struct Response {
impl Response {
/// Create a new response from the given status words and buffer
#[cfg(feature = "untested")]
pub fn new(status_words: StatusWords, data: Vec<u8>) -> Response {
Response { status_words, data }
}
+3
View File
@@ -143,6 +143,7 @@ impl Certificate {
}
/// Write this certificate into the YubiKey in the given slot
#[cfg(feature = "untested")]
pub fn write(&self, yubikey: &mut YubiKey, slot: SlotId, certinfo: u8) -> Result<(), Error> {
let max_size = yubikey.obj_size_max();
let txn = yubikey.begin_transaction()?;
@@ -150,6 +151,7 @@ impl Certificate {
}
/// Delete a certificate located at the given slot of the given YubiKey
#[cfg(feature = "untested")]
pub fn delete(yubikey: &mut YubiKey, slot: SlotId) -> Result<(), Error> {
let max_size = yubikey.obj_size_max();
let txn = yubikey.begin_transaction()?;
@@ -236,6 +238,7 @@ pub(crate) fn read_certificate(txn: &Transaction<'_>, slot: SlotId) -> Result<Bu
}
/// Write certificate
#[cfg(feature = "untested")]
pub(crate) fn write_certificate(
txn: &Transaction<'_>,
slot: SlotId,
+28 -18
View File
@@ -38,18 +38,24 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use crate::{
apdu::{Ins, StatusWords},
certificate::{self, Certificate},
consts::*,
error::Error,
yubikey::YubiKey,
ObjectId,
};
use log::debug;
use std::convert::TryFrom;
#[cfg(feature = "untested")]
use crate::{
apdu::{Ins, StatusWords},
consts::*,
policy::{PinPolicy, TouchPolicy},
serialization::*,
settings,
yubikey::YubiKey,
Buffer, ObjectId,
settings, Buffer,
};
use log::{debug, error, warn};
use std::convert::TryFrom;
#[cfg(feature = "untested")]
use log::{error, warn};
/// Slot identifiers.
/// <https://developers.yubico.com/PIV/Introduction/Certificate_slots.html>
@@ -312,6 +318,7 @@ impl From<AlgorithmId> for u8 {
}
}
#[cfg(feature = "untested")]
impl AlgorithmId {
/// Writes the `AlgorithmId` in the format the YubiKey expects during key generation.
pub(crate) fn write(self, buf: &mut [u8]) -> usize {
@@ -367,19 +374,9 @@ impl Key {
}
}
// Keygen messages
// TODO(tarcieri): extract these into an I18N-handling type?
const SZ_SETTING_ROCA: &str = "Enable_Unsafe_Keygen_ROCA";
const SZ_ROCA_ALLOW_USER: &str =
"was permitted by an end-user configuration setting, but is not recommended.";
const SZ_ROCA_ALLOW_ADMIN: &str =
"was permitted by an administrator configuration setting, but is not recommended.";
const SZ_ROCA_BLOCK_USER: &str = "was blocked due to an end-user configuration setting.";
const SZ_ROCA_BLOCK_ADMIN: &str = "was blocked due to an administrator configuration setting.";
const SZ_ROCA_DEFAULT: &str = "was permitted by default, but is not recommended. The default behavior will change in a future Yubico release.";
/// Information about a generated key
// TODO(tarcieri): this could use some more work
#[cfg(feature = "untested")]
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum GeneratedKey {
/// RSA keys
@@ -403,6 +400,7 @@ pub enum GeneratedKey {
},
}
#[cfg(feature = "untested")]
impl GeneratedKey {
/// Get the algorithm
pub fn algorithm(&self) -> AlgorithmId {
@@ -414,6 +412,7 @@ impl GeneratedKey {
}
/// Generate key
#[cfg(feature = "untested")]
#[allow(clippy::cognitive_complexity)]
pub fn generate(
yubikey: &mut YubiKey,
@@ -422,6 +421,17 @@ pub fn generate(
pin_policy: PinPolicy,
touch_policy: TouchPolicy,
) -> Result<GeneratedKey, Error> {
// Keygen messages
// TODO(tarcieri): extract these into an I18N-handling type?
const SZ_SETTING_ROCA: &str = "Enable_Unsafe_Keygen_ROCA";
const SZ_ROCA_ALLOW_USER: &str =
"was permitted by an end-user configuration setting, but is not recommended.";
const SZ_ROCA_ALLOW_ADMIN: &str =
"was permitted by an administrator configuration setting, but is not recommended.";
const SZ_ROCA_BLOCK_USER: &str = "was blocked due to an end-user configuration setting.";
const SZ_ROCA_BLOCK_ADMIN: &str = "was blocked due to an administrator configuration setting.";
const SZ_ROCA_DEFAULT: &str = "was permitted by default, but is not recommended. The default behavior will change in a future Yubico release.";
let setting_roca: settings::BoolValue;
match algorithm {
-4
View File
@@ -138,7 +138,6 @@
mod apdu;
#[cfg(feature = "untested")]
pub mod cccid;
#[cfg(feature = "untested")]
pub mod certificate;
#[cfg(feature = "untested")]
pub mod chuid;
@@ -148,7 +147,6 @@ pub mod consts;
#[cfg(feature = "untested")]
pub mod container;
pub mod error;
#[cfg(feature = "untested")]
pub mod key;
#[cfg(feature = "untested")]
mod metadata;
@@ -156,10 +154,8 @@ mod metadata;
pub mod mgm;
#[cfg(feature = "untested")]
pub mod msroots;
#[cfg(feature = "untested")]
pub mod policy;
pub mod readers;
#[cfg(feature = "untested")]
mod serialization;
#[cfg(feature = "untested")]
pub mod settings;
+2
View File
@@ -35,6 +35,7 @@ impl From<PinPolicy> for u8 {
impl PinPolicy {
/// Writes the `PinPolicy` in the format the YubiKey expects during key generation or
/// importation.
#[cfg(feature = "untested")]
pub(crate) fn write(self, buf: &mut [u8]) -> usize {
match self {
PinPolicy::Default => 0,
@@ -84,6 +85,7 @@ impl From<TouchPolicy> for u8 {
impl TouchPolicy {
/// Writes the `TouchPolicy` in the format the YubiKey expects during key generation
/// or importation.
#[cfg(feature = "untested")]
pub(crate) fn write(self, buf: &mut [u8]) -> usize {
match self {
TouchPolicy::Default => 0,
+1
View File
@@ -35,6 +35,7 @@ use crate::{consts::*, ObjectId};
// TODO(tarcieri): refactor these into better serializers/message builders
/// Set length
#[cfg(feature = "untested")]
pub(crate) fn set_length(buffer: &mut [u8], length: usize) -> usize {
if length < 0x80 {
buffer[0] = length as u8;
+8 -9
View File
@@ -1,23 +1,24 @@
//! YubiKey PC/SC transactions
#[cfg(feature = "untested")]
use crate::{
apdu::Response,
key::{AlgorithmId, SlotId},
mgm::MgmKey,
serialization::*,
Buffer, ObjectId,
};
use crate::{
apdu::{Ins, StatusWords, APDU},
consts::*,
error::Error,
serialization::*,
yubikey::*,
Buffer, ObjectId,
};
use log::{error, trace};
use std::convert::TryInto;
use zeroize::Zeroizing;
#[cfg(feature = "untested")]
use crate::{
key::{AlgorithmId, SlotId},
mgm::MgmKey,
};
/// Exclusive transaction with the YubiKey's PC/SC card.
pub(crate) struct Transaction<'tx> {
inner: pcsc::Transaction<'tx>,
@@ -364,7 +365,6 @@ impl<'tx> Transaction<'tx> {
/// messages into smaller APDU-sized messages (using the provided APDU
/// template to construct them), and then sending those via
/// [`Transaction::transmit`].
#[cfg(feature = "untested")]
pub fn transfer_data(
&self,
templ: &[u8],
@@ -448,7 +448,6 @@ impl<'tx> Transaction<'tx> {
}
/// Fetch an object.
#[cfg(feature = "untested")]
pub fn fetch_object(&self, object_id: ObjectId) -> Result<Buffer, Error> {
let mut indata = [0u8; 5];
let templ = [0, Ins::GetData.code(), 0x3f, 0xff];