From b23296e1cc47cf5350835d8a8cca6eb6f5d7d270 Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Thu, 10 Sep 2020 12:20:13 +0200 Subject: Add fill command to overwrite SD card This patch adds the fill command that overwrites the SD card with random data. Similar to the reset command, we always require the user to enter the admin PIN even if is cached. --- CHANGELOG.md | 2 ++ doc/nitrocli.1 | 10 ++++++++++ doc/nitrocli.1.pdf | Bin 42316 -> 42979 bytes src/args.rs | 2 ++ src/commands.rs | 33 +++++++++++++++++++++++++++++++++ src/tests/fill.rs | 15 +++++++++++++++ src/tests/mod.rs | 1 + 7 files changed, 63 insertions(+) create mode 100644 src/tests/fill.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 19f0189..8672e03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ Unreleased ---------- +- Added the `fill` command that fills the SD card of a Nitrokey Storage device + with random data - Added SD card usage information to the output of the `status` command for Storage devices diff --git a/doc/nitrocli.1 b/doc/nitrocli.1 index fb207c4..fd04d45 100644 --- a/doc/nitrocli.1 +++ b/doc/nitrocli.1 @@ -136,6 +136,16 @@ open. .TP \fBnitrocli hidden close Close a hidden volume. +.TP +\fBnitrocli fill\fR +Fills the SD card with random data, overwriting all existing data. +This operation takes about one hour to finish for a 16 GiB SD card. +It cannot be canceled, even if the \fBnitrocli\fR process is terminated before +it finishes. + +This command requires the admin PIN. +To avoid accidental calls of this command, the user has to enter the PIN even +if it has been cached. .SS One-time passwords The Nitrokey Pro and the Nitrokey Storage support the generation of one-time diff --git a/doc/nitrocli.1.pdf b/doc/nitrocli.1.pdf index c5fce65..d04fe02 100644 Binary files a/doc/nitrocli.1.pdf and b/doc/nitrocli.1.pdf differ diff --git a/src/args.rs b/src/args.rs index 80abe17..4947825 100644 --- a/src/args.rs +++ b/src/args.rs @@ -79,6 +79,8 @@ Command! { Config(ConfigArgs) => |ctx, args: ConfigArgs| args.subcmd.execute(ctx), /// Interacts with the device's encrypted volume Encrypted(EncryptedArgs) => |ctx, args: EncryptedArgs| args.subcmd.execute(ctx), + /// Fills the SD card with random data + Fill => crate::commands::fill, /// Interacts with the device's hidden volume Hidden(HiddenArgs) => |ctx, args: HiddenArgs| args.subcmd.execute(ctx), /// Lists the attached Nitrokey devices diff --git a/src/commands.rs b/src/commands.rs index d81e095..cf3b94f 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -469,6 +469,39 @@ pub fn list(ctx: &mut Context<'_>, no_connect: bool) -> anyhow::Result<()> { Ok(()) } +/// Fill the SD card with random data +pub fn fill(ctx: &mut Context<'_>) -> anyhow::Result<()> { + with_storage_device(ctx, |ctx, mut device| { + let pin_entry = pinentry::PinEntry::from(args::PinType::Admin, &device)?; + + // Similar to reset, we want the user to re-enter the admin PIN even if is cached to avoid + // accidental data loss. + pinentry::clear(&pin_entry).context("Failed to clear cached secret")?; + + try_with_pin(ctx, &pin_entry, |pin| { + device.fill_sd_card(&pin).context("Failed to fill SD card") + })?; + + let mut last_progress = 0; + loop { + let status = device + .get_operation_status() + .context("Failed to query operation status")?; + match status { + nitrokey::OperationStatus::Ongoing(progress) => { + if last_progress != progress { + println!(ctx, "{}/100", progress)?; + } + last_progress = progress; + } + nitrokey::OperationStatus::Idle => break, + }; + } + + Ok(()) + }) +} + /// Perform a factory reset. pub fn reset(ctx: &mut Context<'_>) -> anyhow::Result<()> { with_device(ctx, |ctx, mut device| { diff --git a/src/tests/fill.rs b/src/tests/fill.rs new file mode 100644 index 0000000..70ea081 --- /dev/null +++ b/src/tests/fill.rs @@ -0,0 +1,15 @@ +// fill.rs + +// Copyright (C) 2020 The Nitrocli Developers +// SPDX-License-Identifier: GPL-3.0-or-later + +use super::*; + +// Ignore this test as it takes about one hour to execute +#[ignore] +#[test_device(storage)] +fn fill(model: nitrokey::Model) -> anyhow::Result<()> { + let res = Nitrocli::new().model(model).handle(&["fill"]); + assert!(res.is_ok()); + Ok(()) +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs index 631ffb0..e0a5b9a 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -9,6 +9,7 @@ use nitrokey_test::test as test_device; mod config; mod encrypted; +mod fill; mod hidden; mod list; mod lock; -- cgit v1.2.1