Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for multiple Yubikeys and Maintenance #15

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 11 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "yubico_manager"
version = "0.9.0"
version = "0.10.0"
authors = ["Flavio Oliveira <[email protected]>", "Pierre-Étienne Meunier <[email protected]>"]

description = "Yubikey Challenge-Response & Configuration"
Expand All @@ -9,6 +9,8 @@ keywords = ["yubikey", "authentication", "encryption", "configuration", "Challen
categories = ["authentication"]
repository = "https://github.com/wisespace-io/yubico-manager"
readme = "README.md"
edition = "2021"
resolver = "2"

[badges]
travis-ci = { repository = "wisespace-io/yubico-manager" }
Expand All @@ -18,15 +20,15 @@ name = "yubico_manager"
path = "src/lib.rs"

[dependencies]
rand = "0.8.4"
bitflags = "1.2"
rusb = "0.8.1"
rand = "0.8"
bitflags = "2.4"
rusb = "0.9"
structure = "0.1"

aes = "0.7.4"
block-modes = "0.8.1"
hmac = "0.11.0"
sha-1 = "0.9"
aes = "0.8"
block-modes = "0.9"
hmac = "0.12"
sha-1 = "0.10"

[dev-dependencies]
hex = "0.3.2"
hex = "0.4"
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Add this to your Cargo.toml

```toml
[dependencies]
yubico_manager = "0.9"
yubico_manager = "0.10"
```

### Configure Yubikey (HMAC-SHA1 mode)
Expand All @@ -49,10 +49,10 @@ fn main() {
if let Ok(device) = yubi.find_yubikey() {
println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

let config = Config::default()
.set_vendor_id(device.vendor_id)
.set_product_id(device.product_id)
.set_command(Command::Configuration2);
let config = Config::new_from(device)
.set_variable_size(true)
.set_mode(Mode::Sha1)
.set_slot(Slot::Slot2);

let mut rng = thread_rng();

Expand Down Expand Up @@ -94,9 +94,7 @@ fn main() {
if let Ok(device) = yubi.find_yubikey() {
println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

let config = Config::default()
.set_vendor_id(device.vendor_id)
.set_product_id(device.product_id)
let config = Config::new_from(device)
.set_variable_size(true)
.set_mode(Mode::Sha1)
.set_slot(Slot::Slot2);
Expand Down
6 changes: 2 additions & 4 deletions examples/challenge_response_hmac.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ extern crate hex;
extern crate yubico_manager;

use std::ops::Deref;
use yubico_manager::{Yubico};
use yubico_manager::Yubico;
use yubico_manager::config::{Config, Slot, Mode};

fn main() {
Expand All @@ -11,9 +11,7 @@ fn main() {
if let Ok(device) = yubi.find_yubikey() {
println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

let config = Config::default()
.set_vendor_id(device.vendor_id)
.set_product_id(device.product_id)
let config = Config::new_from(device)
.set_variable_size(true)
.set_mode(Mode::Sha1)
.set_slot(Slot::Slot2);
Expand Down
6 changes: 2 additions & 4 deletions examples/challenge_response_otp.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate hex;
extern crate yubico_manager;

use yubico_manager::{Yubico};
use yubico_manager::Yubico;
use yubico_manager::config::{Config, Slot, Mode};

fn main() {
Expand All @@ -10,9 +10,7 @@ fn main() {
if let Ok(device) = yubi.find_yubikey() {
println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

let config = Config::default()
.set_vendor_id(device.vendor_id)
.set_product_id(device.product_id)
let config = Config::new_from(device)
.set_mode(Mode::Otp)
.set_slot(Slot::Slot2);

Expand Down
12 changes: 5 additions & 7 deletions examples/configuration_hmac.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
extern crate rand;
extern crate yubico_manager;

use yubico_manager::{Yubico};
use yubico_manager::Yubico;
use yubico_manager::config::{Config, Command};
use yubico_manager::configure::{ DeviceModeConfig };
use yubico_manager::hmacmode::{ HmacKey };
use yubico_manager::configure::DeviceModeConfig;
use yubico_manager::hmacmode::HmacKey;
use rand::{thread_rng, Rng};
use rand::distributions::{Alphanumeric};
use rand::distributions::Alphanumeric;

fn main() {
let mut yubi = Yubico::new();

if let Ok(device) = yubi.find_yubikey() {
println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

let config = Config::default()
.set_vendor_id(device.vendor_id)
.set_product_id(device.product_id)
let config = Config::new_from(device)
.set_command(Command::Configuration2);

let rng = thread_rng();
Expand Down
10 changes: 4 additions & 6 deletions examples/configuration_otp.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
extern crate yubico_manager;

use yubico_manager::{Yubico};
use yubico_manager::configure::{ DeviceModeConfig };
use yubico_manager::otpmode::{ Aes128Key };
use yubico_manager::Yubico;
use yubico_manager::configure::DeviceModeConfig;
use yubico_manager::otpmode::Aes128Key;
use yubico_manager::config::{Config, Command};

fn main() {
Expand All @@ -11,9 +11,7 @@ fn main() {
if let Ok(device) = yubi.find_yubikey() {
println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

let config = Config::default()
.set_vendor_id(device.vendor_id)
.set_product_id(device.product_id)
let config = Config::new_from(device)
.set_command(Command::Configuration2);

let require_press_button = false;
Expand Down
6 changes: 2 additions & 4 deletions examples/serial_number.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate hex;
extern crate yubico_manager;

use yubico_manager::{Yubico};
use yubico_manager::Yubico;
use yubico_manager::config::{Config, Slot};

fn main() {
Expand All @@ -10,9 +10,7 @@ fn main() {
if let Ok(device) = yubi.find_yubikey() {
println!("Vendor ID: {:?} Product ID {:?}", device.vendor_id, device.product_id);

let config = Config::default()
.set_vendor_id(device.vendor_id)
.set_product_id(device.product_id)
let config = Config::new_from(device)
.set_slot(Slot::Slot2);

match yubi.read_serial_number(config){
Expand Down
26 changes: 8 additions & 18 deletions src/config.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::fmt::Display;

use crate::Yubikey;

#[derive(Clone, Debug, PartialEq)]
pub enum Slot {
Slot1,
Expand Down Expand Up @@ -38,7 +40,7 @@ impl SyncLevel {
}
}

impl Display for SyncLevel{
impl Display for SyncLevel {
fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
write!(f, "{}", self.0)
}
Expand All @@ -62,8 +64,7 @@ pub enum Command {

#[derive(Clone, Debug, PartialEq)]
pub struct Config {
pub product_id: u16,
pub vendor_id: u16,
pub yubikey: Yubikey,
pub variable: bool,
pub slot: Slot,
pub mode: Mode,
Expand All @@ -72,27 +73,16 @@ pub struct Config {

#[allow(dead_code)]
impl Config {
pub fn default() -> Config {
pub fn new_from(yubikey: Yubikey) -> Config {
Config {
product_id: 0x00,
vendor_id: 0x1050,
yubikey: yubikey,
variable: true,
slot: Slot::Slot1,
slot: Slot::Slot2, // Default Slot factory programmed
mode: Mode::Sha1,
command: Command::ChallengeHmac1,
}
}

pub fn set_vendor_id(mut self, vendor_id: u16) -> Self {
self.vendor_id = vendor_id;
self
}

pub fn set_product_id(mut self, product_id: u16) -> Self {
self.product_id = product_id;
self
}

pub fn set_variable_size(mut self, variable: bool) -> Self {
self.variable = variable;
self
Expand All @@ -112,4 +102,4 @@ impl Config {
self.command = command;
self
}
}
}
44 changes: 32 additions & 12 deletions src/configure.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::config::Command;
use crate::hmacmode::HmacKey;
use crate::manager::Frame;
use crate::otpmode::Aes128Key;
use crate::sec::crc16;
use std;
use hmacmode::HmacKey;
use otpmode::Aes128Key;
use sec::crc16;
use manager::Frame;
use config::Command;

const FIXED_SIZE: usize = 16;
const UID_SIZE: usize = 6;
Expand Down Expand Up @@ -46,14 +46,16 @@ impl std::default::Default for DeviceModeConfig {
const SIZEOF_CONFIG: usize = 52;

impl DeviceModeConfig {

#[doc(hidden)]
pub fn to_frame(&mut self, command: Command) -> Frame {
let mut payload = [0; 64];
// First set CRC.
self.crc = {
let first_fields = unsafe {
std::slice::from_raw_parts(self as *const DeviceModeConfig as *const u8, SIZEOF_CONFIG - 2)
std::slice::from_raw_parts(
self as *const DeviceModeConfig as *const u8,
SIZEOF_CONFIG - 2,
)
};
(0xffff - crc16(&first_fields)).to_le()
};
Expand All @@ -71,13 +73,22 @@ impl DeviceModeConfig {
/// mode. This mode has two sub-modes: if `variable` is `true`,
/// the challenges can be of variable length up to 63 bytes. Else,
/// all challenges must be exactly 64 bytes long.
pub fn challenge_response_hmac(&mut self, secret: &HmacKey, variable: bool, button_press: bool) {
pub fn challenge_response_hmac(
&mut self,
secret: &HmacKey,
variable: bool,
button_press: bool,
) {
self.tkt_flags = TicketFlags::empty();
self.cfg_flags = ConfigFlags::empty();
self.ext_flags = ExtendedFlags::empty();

self.tkt_flags.insert(TicketFlags::CHAL_RESP);
self.cfg_flags.insert(if button_press { ConfigFlags::CHAL_HMAC | ConfigFlags::CHAL_BTN_TRIG } else { ConfigFlags::CHAL_HMAC });
self.cfg_flags.insert(if button_press {
ConfigFlags::CHAL_HMAC | ConfigFlags::CHAL_BTN_TRIG
} else {
ConfigFlags::CHAL_HMAC
});
if variable {
self.cfg_flags.insert(ConfigFlags::HMAC_LT64)
} else {
Expand All @@ -89,13 +100,22 @@ impl DeviceModeConfig {
}

/// Sets the configuration in challenge-response, OTP mode.
pub fn challenge_response_otp(&mut self, secret: &Aes128Key, priv_id: &[u8;6], button_press: bool) {
pub fn challenge_response_otp(
&mut self,
secret: &Aes128Key,
priv_id: &[u8; 6],
button_press: bool,
) {
self.tkt_flags = TicketFlags::empty();
self.cfg_flags = ConfigFlags::empty();
self.ext_flags = ExtendedFlags::empty();

self.tkt_flags.insert(TicketFlags::CHAL_RESP);
self.cfg_flags.insert(if button_press { ConfigFlags::CHAL_YUBICO | ConfigFlags::CHAL_BTN_TRIG } else { ConfigFlags::CHAL_YUBICO });
self.cfg_flags.insert(if button_press {
ConfigFlags::CHAL_YUBICO | ConfigFlags::CHAL_BTN_TRIG
} else {
ConfigFlags::CHAL_YUBICO
});

self.uid.copy_from_slice(priv_id);
self.key.copy_from_slice(&secret.0);
Expand Down Expand Up @@ -154,4 +174,4 @@ bitflags! {
const ALLOW_UPDATE = 0x20;
const DORMANT = 0x40;
}
}
}
8 changes: 4 additions & 4 deletions src/hmacmode.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std;
use crate::sec::hmac_sha1;
use rand::Rng;
use sec::hmac_sha1;
use std;

#[derive(Debug)]
pub struct Hmac(pub [u8; 20]);
Expand Down Expand Up @@ -43,11 +43,11 @@ impl HmacKey {
key
}

pub fn generate<R:Rng>(mut rng: R) -> Self {
pub fn generate<R: Rng>(mut rng: R) -> Self {
let mut key = HmacKey([0; 20]);
for i in key.0.iter_mut() {
*i = rng.gen()
}
key
}
}
}
Loading