From de5ae8656387267bb4614bbab6b62784323f23c0 Mon Sep 17 00:00:00 2001 From: Daniel Mueller Date: Sun, 26 Mar 2017 17:31:28 -0700 Subject: Discover and open nictrokey using libhidapi This change uses the 'hid' crate to discover and open the Nitrokey Storage device. 'hid' is a wrapper around libhidapi (its libusb back-end in particular). Being a command line application some sort of parameter handling needs to happen. The approach we take is very simple for now to minimize the number of dependencies: we just compare the first argument against the expected ones and raise an error if no match was found. Because we only have positional arguments right now this is all we need. --- nitrocli/Cargo.lock | 65 ++++++++++++++++++++++++++++++++++++ nitrocli/Cargo.toml | 22 +++++++++++++ nitrocli/src/error.rs | 45 +++++++++++++++++++++++++ nitrocli/src/main.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++- nitrocli/src/nitrokey.rs | 24 ++++++++++++++ 5 files changed, 240 insertions(+), 1 deletion(-) create mode 100644 nitrocli/src/error.rs create mode 100644 nitrocli/src/nitrokey.rs diff --git a/nitrocli/Cargo.lock b/nitrocli/Cargo.lock index 8da0130..6a6d315 100644 --- a/nitrocli/Cargo.lock +++ b/nitrocli/Cargo.lock @@ -1,4 +1,69 @@ [root] name = "nitrocli" version = "0.1.0" +dependencies = [ + "gcc 0.3.45", + "hid 0.3.0", + "hidapi-sys 0.1.2", + "libc 0.2.21", + "pkg-config 0.3.9", +] +[[package]] +name = "gcc" +version = "0.3.45" + +[[package]] +name = "gcc" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "gcc 0.3.45" + +[[package]] +name = "hid" +version = "0.3.0" +dependencies = [ + "hidapi-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hidapi-sys" +version = "0.1.2" +dependencies = [ + "gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hidapi-sys" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "hidapi-sys 0.1.2" + +[[package]] +name = "libc" +version = "0.2.21" + +[[package]] +name = "libc" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "libc 0.2.21" + +[[package]] +name = "pkg-config" +version = "0.3.9" + +[[package]] +name = "pkg-config" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +replace = "pkg-config 0.3.9" + +[metadata] +"checksum gcc 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "40899336fb50db0c78710f53e87afc54d8c7266fb76262fecc78ca1a7f09deae" +"checksum hidapi-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "63829a2802510a8a4e3a52e1fa2fb969b8cd0826da65e04d79bd095eae21e050" +"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135" +"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" diff --git a/nitrocli/Cargo.toml b/nitrocli/Cargo.toml index ceaf276..1ee63fb 100644 --- a/nitrocli/Cargo.toml +++ b/nitrocli/Cargo.toml @@ -29,3 +29,25 @@ keywords = ["hid", "nitrokey", "nitrokey-storage", "usb", "cli"] description = """ A command line tool for interacting with the Nitrokey Storage device. """ + +[dependencies.gcc] +path = "../gcc" + +[dependencies.hid] +path = "../hid" + +[dependencies.hidapi-sys] +path = "../hidapi-sys" + +[dependencies.libc] +path = "../libc" + +[dependencies.pkg-config] +path = "../pkg-config" + +[replace] +"gcc:0.3.45" = { path = "../gcc" } +"hid:0.3.0" = { path = "../hid" } +"hidapi-sys:0.1.2" = { path = "../hidapi-sys" } +"libc:0.2.21" = { path = "../libc" } +"pkg-config:0.3.9" = { path = "../pkg-config" } diff --git a/nitrocli/src/error.rs b/nitrocli/src/error.rs new file mode 100644 index 0000000..65992f0 --- /dev/null +++ b/nitrocli/src/error.rs @@ -0,0 +1,45 @@ +// error.rs + +// ************************************************************************* +// * Copyright (C) 2017 Daniel Mueller (deso@posteo.net) * +// * * +// * This program is free software: you can redistribute it and/or modify * +// * it under the terms of the GNU General Public License as published by * +// * the Free Software Foundation, either version 3 of the License, or * +// * (at your option) any later version. * +// * * +// * This program is distributed in the hope that it will be useful, * +// * but WITHOUT ANY WARRANTY; without even the implied warranty of * +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +// * GNU General Public License for more details. * +// * * +// * You should have received a copy of the GNU General Public License * +// * along with this program. If not, see . * +// ************************************************************************* + +use libhid; +use std::fmt; + + +#[derive(Debug)] +pub enum Error { + HidError(libhid::Error), + Error(String), +} + + +impl From for Error { + fn from(e: libhid::Error) -> Error { + return Error::HidError(e); + } +} + + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *&self { + &Error::HidError(ref e) => return write!(f, "hidapi error: {}", e), + &Error::Error(ref e) => return write!(f, "{}", e), + } + } +} diff --git a/nitrocli/src/main.rs b/nitrocli/src/main.rs index 57e6a7a..bdbfe37 100644 --- a/nitrocli/src/main.rs +++ b/nitrocli/src/main.rs @@ -18,7 +18,90 @@ // ************************************************************************* +#![deny(missing_docs)] + +//! Nitrocli is a program providing a command line interface to certain +//! commands of the Nitrokey Storage device. + +extern crate hid as libhid; + + +mod error; +mod nitrokey; + +use error::Error; +use std::process; +use std::result; + +type Result = result::Result; +type NitroFunc = Fn(&mut libhid::Handle) -> Result<()>; + + +/// Find and open the nitrokey device and execute a function on it. +fn nitrokey_do(function: &NitroFunc) -> Result<()> { + let hid = libhid::init()?; + // The Manager::find method is plain stupid as it still returns an + // iterable. Using it does not help in more concise error handling. + for device in hid.devices() { + if device.vendor_id() == nitrokey::VID && device.product_id() == nitrokey::PID { + return function(&mut device.open()?); + } + } + return Err(Error::Error("Nitrokey device not found".to_string())); +} + + +/// Open the encrypted volume on the nitrokey. +fn open() -> Result<()> { + return nitrokey_do(&|handle| { + println!("Found nitrokey. Opening encrypted volume..."); + return Ok(()); + }); +} + + +/// Close the previously opened encrypted volume. +fn close() -> Result<()> { + return nitrokey_do(&|handle| { + println!("Found nitrokey. Closing encrypted volume..."); + return Ok(()); + }); +} + + +// A macro for generating a match of the different supported commands. +// Each supplied command is converted into a string and matched against. +macro_rules! commands { + ( $str:expr, [ $( $command:expr), *] ) => { + match &*$str.to_string() { + $( + stringify!($command) => { + if let Err(err) = $command() { + println!("{}", err); + return 1 + } + return 0 + }, + )* + x => { + println!("Invalid command: {}", x); + println!("Available commands: {}", stringify!( $($command)* )); + return 1 + }, + } + } +} + +fn run() -> i32 { + let argv: Vec = std::env::args().collect(); + if argv.len() != 2 { + println!("Usage: {} ", argv[0]); + return 1; + } + + commands!(&argv[1], [open, close]); +} fn main() { - println!("Hello, world!"); + process::exit(run()); } diff --git a/nitrocli/src/nitrokey.rs b/nitrocli/src/nitrokey.rs new file mode 100644 index 0000000..763bc4c --- /dev/null +++ b/nitrocli/src/nitrokey.rs @@ -0,0 +1,24 @@ +// nitrokey.rs + +// ************************************************************************* +// * Copyright (C) 2017 Daniel Mueller (deso@posteo.net) * +// * * +// * This program is free software: you can redistribute it and/or modify * +// * it under the terms of the GNU General Public License as published by * +// * the Free Software Foundation, either version 3 of the License, or * +// * (at your option) any later version. * +// * * +// * This program is distributed in the hope that it will be useful, * +// * but WITHOUT ANY WARRANTY; without even the implied warranty of * +// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +// * GNU General Public License for more details. * +// * * +// * You should have received a copy of the GNU General Public License * +// * along with this program. If not, see . * +// ************************************************************************* + + +// The Nitrokey Storage vendor ID. +pub const VID: u16 = 0x20A0; +// The Nitrokey Storage product ID. +pub const PID: u16 = 0x4109; -- cgit v1.2.3