Skip to content

Commit

Permalink
implement solokey random
Browse files Browse the repository at this point in the history
  • Loading branch information
micolous committed Oct 26, 2023
1 parent 1c14942 commit 057d3c6
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 6 deletions.
21 changes: 20 additions & 1 deletion fido-key-manager/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,8 +201,11 @@ pub enum Opt {
/// Updates user information for a discoverable credential on this token.
UpdateCredentialUser(UpdateCredentialUserOpt),
#[cfg(feature = "solokey")]
/// Gets info about a connected SoloKey.
/// Gets info about a connected SoloKey 2 or Trussed device.
SoloKeyInfo(InfoOpt),
#[cfg(feature = "solokey")]
/// Gets some random bytes from a connected SoloKey 2 or Trussed device.
SoloKeyRandom,
}

#[derive(Debug, clap::Parser)]
Expand Down Expand Up @@ -689,6 +692,7 @@ async fn main() {

#[cfg(feature = "solokey")]
Opt::SoloKeyInfo(o) => {
println!("Looking for SoloKey 2 or Trussed devices...");
while let Some(event) = stream.next().await {
match event {
TokenEvent::Added(t) => {
Expand All @@ -697,6 +701,7 @@ async fn main() {
None => continue,
};

// TODO: filter this to just SoloKey devices in a safe way
let uuid = match authenticator.get_solokey_uuid().await {
Ok(v) => v,
Err(WebauthnCError::NotSupported)
Expand Down Expand Up @@ -751,5 +756,19 @@ async fn main() {
}
}
}

#[cfg(feature = "solokey")]
Opt::SoloKeyRandom => {
// TODO: filter this to just SoloKey devices in a safe way
println!("Insert a SoloKey 2 or Trussed device...");
let mut token: CtapAuthenticator<AnyToken, Cli> =
select_one_device(stream, &ui).await.unwrap();

let r = token
.get_solokey_random()
.await
.expect("Error getting random data");
println!("Random bytes: {}", hex::encode(r));
}
}
}
14 changes: 11 additions & 3 deletions webauthn-authenticator-rs/src/ctap2/solokey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@ use super::Ctap20Authenticator;
/// Protocol notes are in [`crate::transport::solokey`].
#[async_trait]
pub trait SoloKeyAuthenticator {
/// Gets the device's lock (secure boot) status.
/// Gets a SoloKey's lock (secure boot) status.
async fn get_solokey_lock(&mut self) -> Result<bool, WebauthnCError>;

/// Gets the device-specific UUID of a SoloKey token.
/// Gets some random bytes from a SoloKey.
async fn get_solokey_random(&mut self) -> Result<[u8; 57], WebauthnCError>;

/// Gets a SoloKey's UUID.
async fn get_solokey_uuid(&mut self) -> Result<Uuid, WebauthnCError>;

/// Gets the version of a SoloKey token.
/// Gets a SoloKey's firmware version.
async fn get_solokey_version(&mut self) -> Result<u32, WebauthnCError>;
}

Expand All @@ -38,6 +41,11 @@ impl<'a, T: Token + SoloKeyToken, U: UiCallback> SoloKeyAuthenticator
self.token.get_solokey_lock().await
}

#[inline]
async fn get_solokey_random(&mut self) -> Result<[u8; 57], WebauthnCError> {
self.token.get_solokey_random().await
}

#[inline]
async fn get_solokey_uuid(&mut self) -> Result<Uuid, WebauthnCError> {
self.token.get_solokey_uuid().await
Expand Down
17 changes: 16 additions & 1 deletion webauthn-authenticator-rs/src/transport/solokey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ use crate::prelude::WebauthnCError;
use super::AnyToken;

#[cfg(all(feature = "usb", feature = "vendor-solokey"))]
pub const CMD_RAND: u8 = super::TYPE_INIT | 0x60;
pub const CMD_RANDOM: u8 = super::TYPE_INIT | 0x60;

#[cfg(all(feature = "usb", feature = "vendor-solokey"))]
pub const CMD_VERSION: u8 = super::TYPE_INIT | 0x61;
Expand All @@ -50,6 +50,9 @@ pub trait SoloKeyToken {
/// See [`SoloKeyAuthenticator::get_solokey_lock()`](crate::ctap2::SoloKeyAuthenticator::get_solokey_lock).
async fn get_solokey_lock(&mut self) -> Result<bool, WebauthnCError>;

/// See [`SoloKeyAuthenticator::get_solokey_random()`](crate::ctap2::SoloKeyAuthenticator::get_solokey_random).
async fn get_solokey_random(&mut self) -> Result<[u8; 57], WebauthnCError>;

/// See [`SoloKeyAuthenticator::get_solokey_version()`](crate::ctap2::SoloKeyAuthenticator::get_solokey_version).
async fn get_solokey_version(&mut self) -> Result<u32, WebauthnCError>;

Expand All @@ -71,6 +74,18 @@ impl SoloKeyToken for AnyToken {
}
}

async fn get_solokey_random(&mut self) -> Result<[u8; 57], WebauthnCError> {
match self {
AnyToken::Stub => unimplemented!(),
#[cfg(feature = "bluetooth")]
AnyToken::Bluetooth(_) => Err(WebauthnCError::NotSupported),
#[cfg(feature = "nfc")]
AnyToken::Nfc(_) => Err(WebauthnCError::NotSupported),
#[cfg(feature = "usb")]
AnyToken::Usb(u) => u.get_solokey_random().await,
}
}

async fn get_solokey_version(&mut self) -> Result<u32, WebauthnCError> {
match self {
AnyToken::Stub => unimplemented!(),
Expand Down
24 changes: 23 additions & 1 deletion webauthn-authenticator-rs/src/usb/solokey.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use uuid::Uuid;
use crate::{
prelude::WebauthnCError,
transport::{
solokey::{SoloKeyToken, CMD_LOCK, CMD_UUID, CMD_VERSION},
solokey::{SoloKeyToken, CMD_LOCK, CMD_RANDOM, CMD_UUID, CMD_VERSION},
types::{U2FError, U2FHID_ERROR},
},
usb::framing::U2FHIDFrame,
Expand Down Expand Up @@ -39,6 +39,28 @@ impl SoloKeyToken for USBToken {
}
}

async fn get_solokey_random(&mut self) -> Result<[u8; 57], WebauthnCError> {
let cmd = U2FHIDFrame {
cid: self.cid,
cmd: CMD_RANDOM,
len: 0,
data: vec![],
};
self.send_one(&cmd).await?;

let r = self.recv_one().await?;
match r.cmd {
CMD_RANDOM => r
.data
.try_into()
.map_err(|_| WebauthnCError::InvalidMessageLength),

U2FHID_ERROR => Err(U2FError::from(r.data.as_slice()).into()),

_ => Err(WebauthnCError::UnexpectedState),
}
}

async fn get_solokey_version(&mut self) -> Result<u32, WebauthnCError> {
let cmd = U2FHIDFrame {
cid: self.cid,
Expand Down

0 comments on commit 057d3c6

Please sign in to comment.