aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobin Krahl <robin.krahl@ireas.org>2019-01-14 15:26:02 +0000
committerRobin Krahl <robin.krahl@ireas.org>2019-01-14 16:28:58 +0100
commit0262ed2e614e9222b69970289a32ddb3683b3535 (patch)
tree6fe55a9854e8c61daf7bdec9b636260aa2b92253
parent6ea73f29daa5db0215663a0a38334b764863671d (diff)
downloadnitrokey-rs-0262ed2e614e9222b69970289a32ddb3683b3535.tar.gz
nitrokey-rs-0262ed2e614e9222b69970289a32ddb3683b3535.tar.bz2
Add the get_production_info method to the Storage struct
The get_production_info method maps to the NK_get_production_info function of libnitrokey. The Storage firmware supports two query modes: with or without a write test. libnitrokey only performs the query without write test, so the fields that are only set for the write test are ignored in our implementation. This affects: - user and admin retry counts - smart card ID - SD card size
-rw-r--r--CHANGELOG.md3
-rw-r--r--TODO.md1
-rw-r--r--src/device.rs93
-rw-r--r--src/lib.rs4
-rw-r--r--tests/device.rs21
5 files changed, 119 insertions, 3 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 72e6986..7281f78 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,6 @@
+# Unreleased
+- Add the `get_production_info` method to the `Storage` struct.
+
# v0.3.2 (2019-01-12)
- Make three additional error codes known: `CommandError::StringTooLong`,
`CommandError::InvalidHexString` and `CommandError::TargetBufferTooSmall`.
diff --git a/TODO.md b/TODO.md
index 7c8c5e6..5a122f8 100644
--- a/TODO.md
+++ b/TODO.md
@@ -7,7 +7,6 @@
- `NK_get_progress_bar_value`
- `NK_list_devices_by_cpuID`
- `NK_connect_with_ID`
- - `NK_get_storage_production_info`
- Fix timing issues with the `totp_no_pin` and `totp_pin` test cases.
- Clear passwords from memory.
- Find a nicer syntax for the `write_config` test.
diff --git a/src/device.rs b/src/device.rs
index f247f58..4032db6 100644
--- a/src/device.rs
+++ b/src/device.rs
@@ -208,6 +208,38 @@ pub struct VolumeStatus {
pub active: bool,
}
+/// Information about the SD card in a Storage device.
+#[derive(Debug)]
+pub struct SdCardData {
+ /// The serial number of the SD card.
+ pub serial_number: u32,
+ /// The size of the SD card in GB.
+ pub size: u8,
+ /// The year the card was manufactured, e. g. 17 for 2017.
+ pub manufacturing_year: u8,
+ /// The month the card was manufactured.
+ pub manufacturing_month: u8,
+ /// The OEM ID.
+ pub oem: u16,
+ /// The manufacturer ID.
+ pub manufacturer: u8,
+}
+
+#[derive(Debug)]
+/// Production information for a Storage device.
+pub struct StorageProductionInfo {
+ /// The major firmware version, e. g. 0 in v0.40.
+ pub firmware_version_major: u8,
+ /// The minor firmware version, e. g. 40 in v0.40.
+ pub firmware_version_minor: u8,
+ /// The internal firmware version.
+ pub firmware_version_internal: u8,
+ /// The serial number of the CPU.
+ pub serial_number_cpu: u32,
+ /// Information about the SD card.
+ pub sd_card: SdCardData,
+}
+
/// The status of a Nitrokey Storage device.
#[derive(Debug)]
pub struct StorageStatus {
@@ -1166,6 +1198,48 @@ impl Storage {
result.and(Ok(StorageStatus::from(raw_status)))
}
+ /// Returns the production information for the connected storage device.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # use nitrokey::CommandError;
+ ///
+ /// fn use_volume() {}
+ ///
+ /// # fn try_main() -> Result<(), CommandError> {
+ /// let device = nitrokey::Storage::connect()?;
+ /// match device.get_production_info() {
+ /// Ok(data) => {
+ /// println!("SD card ID: {:#x}", data.sd_card.serial_number);
+ /// println!("SD card size: {} GB", data.sd_card.size);
+ /// },
+ /// Err(err) => println!("Could not get Storage production info: {}", err),
+ /// };
+ /// # Ok(())
+ /// # }
+ /// ```
+ pub fn get_production_info(&self) -> Result<StorageProductionInfo, CommandError> {
+ let mut raw_data = nitrokey_sys::NK_storage_ProductionTest {
+ FirmwareVersion_au8: [0, 2],
+ FirmwareVersionInternal_u8: 0,
+ SD_Card_Size_u8: 0,
+ CPU_CardID_u32: 0,
+ SmartCardID_u32: 0,
+ SD_CardID_u32: 0,
+ SC_UserPwRetryCount: 0,
+ SC_AdminPwRetryCount: 0,
+ SD_Card_ManufacturingYear_u8: 0,
+ SD_Card_ManufacturingMonth_u8: 0,
+ SD_Card_OEM_u16: 0,
+ SD_WriteSpeed_u16: 0,
+ SD_Card_Manufacturer_u8: 0,
+ };
+ let raw_result = unsafe { nitrokey_sys::NK_get_storage_production_info(&mut raw_data) };
+ let result = get_command_result(raw_result);
+ result.and(Ok(StorageProductionInfo::from(raw_data)))
+ }
+
/// Blinks the red and green LED alternatively and infinitely until the device is reconnected.
pub fn wink(&self) -> Result<(), CommandError> {
get_command_result(unsafe { nitrokey_sys::NK_wink() })
@@ -1209,6 +1283,25 @@ impl Device for Storage {
impl GenerateOtp for Storage {}
+impl From<nitrokey_sys::NK_storage_ProductionTest> for StorageProductionInfo {
+ fn from(data: nitrokey_sys::NK_storage_ProductionTest) -> Self {
+ Self {
+ firmware_version_major: data.FirmwareVersion_au8[0],
+ firmware_version_minor: data.FirmwareVersion_au8[1],
+ firmware_version_internal: data.FirmwareVersionInternal_u8,
+ serial_number_cpu: data.CPU_CardID_u32,
+ sd_card: SdCardData {
+ serial_number: data.SD_CardID_u32,
+ size: data.SD_Card_Size_u8,
+ manufacturing_year: data.SD_Card_ManufacturingYear_u8,
+ manufacturing_month: data.SD_Card_ManufacturingMonth_u8,
+ oem: data.SD_Card_OEM_u16,
+ manufacturer: data.SD_Card_Manufacturer_u8,
+ }
+ }
+ }
+}
+
impl From<nitrokey_sys::NK_storage_status> for StorageStatus {
fn from(status: nitrokey_sys::NK_storage_status) -> Self {
StorageStatus {
diff --git a/src/lib.rs b/src/lib.rs
index c50b713..c4e55b1 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -98,8 +98,8 @@ use nitrokey_sys;
pub use crate::auth::{Admin, Authenticate, User};
pub use crate::config::Config;
pub use crate::device::{
- connect, connect_model, Device, DeviceWrapper, Model, Pro, Storage, StorageStatus, VolumeMode,
- VolumeStatus,
+ connect, connect_model, Device, DeviceWrapper, Model, Pro, SdCardData, Storage,
+ StorageProductionInfo, StorageStatus, VolumeMode, VolumeStatus,
};
pub use crate::otp::{ConfigureOtp, GenerateOtp, OtpMode, OtpSlotData};
pub use crate::pws::{GetPasswordSafe, PasswordSafe, SLOT_COUNT};
diff --git a/tests/device.rs b/tests/device.rs
index e40ae12..915bd3a 100644
--- a/tests/device.rs
+++ b/tests/device.rs
@@ -439,6 +439,27 @@ fn get_storage_status(device: Storage) {
}
#[test_device]
+fn get_production_info(device: Storage) {
+ let info = device.get_production_info().unwrap();
+ assert_eq!(0, info.firmware_version_major);
+ assert!(info.firmware_version_minor != 0);
+ assert!(info.serial_number_cpu != 0);
+ assert!(info.sd_card.serial_number != 0);
+ assert!(info.sd_card.size > 0);
+ assert!(info.sd_card.manufacturing_year > 10);
+ assert!(info.sd_card.manufacturing_year < 100);
+ // TODO: month value is not valid atm
+ // assert!(info.sd_card.manufacturing_month < 12);
+ assert!(info.sd_card.oem != 0);
+ assert!(info.sd_card.manufacturer != 0);
+
+ let status = device.get_status().unwrap();
+ assert_eq!(status.firmware_version_major, info.firmware_version_major);
+ assert_eq!(status.firmware_version_minor, info.firmware_version_minor);
+ assert_eq!(status.serial_number_sd_card, info.sd_card.serial_number);
+}
+
+#[test_device]
fn export_firmware(device: Storage) {
assert_eq!(
Err(CommandError::WrongPassword),