implement fido 2.1
This commit is contained in:
parent
80c175077f
commit
bb202c8a54
39
src/cbor.rs
39
src/cbor.rs
@ -274,6 +274,12 @@ pub struct GetInfoResponse {
|
|||||||
pub options: OptionsInfo,
|
pub options: OptionsInfo,
|
||||||
pub max_msg_size: u16,
|
pub max_msg_size: u16,
|
||||||
pub pin_protocols: Vec<u8>,
|
pub pin_protocols: Vec<u8>,
|
||||||
|
pub max_credential_count_in_list: Option<u32>,
|
||||||
|
pub max_credential_id_len: Option<u32>,
|
||||||
|
pub transports: Vec<String>,
|
||||||
|
pub algorithms: Vec<CoseKey>,
|
||||||
|
pub max_authenticator_config_len: Option<u32>,
|
||||||
|
pub default_cred_protect: Option<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GetInfoResponse {
|
impl GetInfoResponse {
|
||||||
@ -282,28 +288,49 @@ impl GetInfoResponse {
|
|||||||
if status != 0 {
|
if status != 0 {
|
||||||
Err(FidoErrorKind::CborError(CborErrorCode::from(status)))?
|
Err(FidoErrorKind::CborError(CborErrorCode::from(status)))?
|
||||||
}
|
}
|
||||||
let mut decoder = Decoder::new(Config::default(), reader);
|
let mut generic = GenericDecoder::new(Config::default(), reader);
|
||||||
let mut response = GetInfoResponse::default();
|
let mut response = GetInfoResponse::default();
|
||||||
for _ in 0..decoder.object()? {
|
for _ in 0..generic.borrow_mut().object()? {
|
||||||
match decoder.u8()? {
|
match generic.borrow_mut().u8()? {
|
||||||
0x01 => {
|
0x01 => {
|
||||||
|
let decoder = generic.borrow_mut();
|
||||||
for _ in 0..decoder.array()? {
|
for _ in 0..decoder.array()? {
|
||||||
response.versions.push(decoder.text()?);
|
response.versions.push(decoder.text()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x02 => {
|
0x02 => {
|
||||||
|
let decoder = generic.borrow_mut();
|
||||||
for _ in 0..decoder.array()? {
|
for _ in 0..decoder.array()? {
|
||||||
response.extensions.push(decoder.text()?);
|
response.extensions.push(decoder.text()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0x03 => response.aaguid.copy_from_slice(&decoder.bytes()?[..]),
|
0x03 => response
|
||||||
0x04 => response.options = OptionsInfo::decode(&mut decoder)?,
|
.aaguid
|
||||||
0x05 => response.max_msg_size = decoder.u16()?,
|
.copy_from_slice(&generic.borrow_mut().bytes()?[..]),
|
||||||
|
0x04 => response.options = OptionsInfo::decode(&mut generic.borrow_mut())?,
|
||||||
|
0x05 => response.max_msg_size = generic.borrow_mut().u16()?,
|
||||||
0x06 => {
|
0x06 => {
|
||||||
|
let decoder = generic.borrow_mut();
|
||||||
for _ in 0..decoder.array()? {
|
for _ in 0..decoder.array()? {
|
||||||
response.pin_protocols.push(decoder.u8()?);
|
response.pin_protocols.push(decoder.u8()?);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
0x07 => response.max_credential_count_in_list = Some(generic.borrow_mut().u32()?),
|
||||||
|
0x08 => response.max_credential_id_len = Some(generic.borrow_mut().u32()?),
|
||||||
|
0x09 => {
|
||||||
|
let decoder = generic.borrow_mut();
|
||||||
|
for _ in 0..decoder.array()? {
|
||||||
|
response.transports.push(decoder.text()?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x0A => {
|
||||||
|
for _ in 0..generic.borrow_mut().array()? {
|
||||||
|
response.algorithms.push(CoseKey::decode(&mut generic)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0x0B => response.max_authenticator_config_len = Some(generic.borrow_mut().u32()?),
|
||||||
|
|
||||||
|
0x0C => response.default_cred_protect = Some(generic.borrow_mut().u8()?),
|
||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
25
src/lib.rs
25
src/lib.rs
@ -75,6 +75,7 @@ use self::hid_linux as hid;
|
|||||||
use self::packet::CtapCommand;
|
use self::packet::CtapCommand;
|
||||||
pub use self::util::*;
|
pub use self::util::*;
|
||||||
use crate::cbor::{AuthenticatorData, GetAssertionRequest};
|
use crate::cbor::{AuthenticatorData, GetAssertionRequest};
|
||||||
|
use crate::packet::CtapStatus;
|
||||||
use failure::{Fail, ResultExt};
|
use failure::{Fail, ResultExt};
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
@ -117,7 +118,7 @@ pub struct FidoCancelHandle {
|
|||||||
|
|
||||||
impl FidoCancelHandle {
|
impl FidoCancelHandle {
|
||||||
pub fn cancel(&mut self) -> FidoResult<()> {
|
pub fn cancel(&mut self) -> FidoResult<()> {
|
||||||
let payload = &[1u8];
|
let payload = &[];
|
||||||
let to_send = payload.len() as u16;
|
let to_send = payload.len() as u16;
|
||||||
let max_payload = (self.packet_size - 7) as usize;
|
let max_payload = (self.packet_size - 7) as usize;
|
||||||
let (frame, payload) = payload.split_at(cmp::min(payload.len(), max_payload));
|
let (frame, payload) = payload.split_at(cmp::min(payload.len(), max_payload));
|
||||||
@ -538,6 +539,26 @@ impl FidoDevice {
|
|||||||
.map(|cred| (cred, response.auth_data))
|
.map(|cred| (cred, response.auth_data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn ping(&mut self, data: &[u8]) -> FidoResult<Vec<u8>> {
|
||||||
|
self.exchange(CtapCommand::Ping, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wink(&mut self) -> FidoResult<()> {
|
||||||
|
self.send(&CtapCommand::Wink, &[]).map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lock(&mut self, time_sec: u8) -> FidoResult<()> {
|
||||||
|
self.exchange(CtapCommand::Lock, &[time_sec]).map(|_| ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn keepalive(&mut self) -> FidoResult<CtapStatus> {
|
||||||
|
self.exchange(CtapCommand::Keepalive, &[])?
|
||||||
|
.first()
|
||||||
|
.cloned()
|
||||||
|
.and_then(CtapStatus::from_u8)
|
||||||
|
.ok_or(FidoError::from(FidoErrorKind::CborDecode))
|
||||||
|
}
|
||||||
|
|
||||||
fn cbor(&mut self, request: cbor::Request) -> FidoResult<cbor::Response> {
|
fn cbor(&mut self, request: cbor::Request) -> FidoResult<cbor::Response> {
|
||||||
let mut buf = Cursor::new(Vec::new());
|
let mut buf = Cursor::new(Vec::new());
|
||||||
request
|
request
|
||||||
@ -556,7 +577,7 @@ impl FidoDevice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn send(&mut self, cmd: &CtapCommand, payload: &[u8]) -> FidoResult<()> {
|
fn send(&mut self, cmd: &CtapCommand, payload: &[u8]) -> FidoResult<()> {
|
||||||
if payload.is_empty() || payload.len() > u16::MAX as usize {
|
if payload.len() > u16::MAX as usize {
|
||||||
Err(FidoErrorKind::WritePacket)?
|
Err(FidoErrorKind::WritePacket)?
|
||||||
}
|
}
|
||||||
let to_send = payload.len() as u16;
|
let to_send = payload.len() as u16;
|
||||||
|
@ -13,7 +13,7 @@ use std::io::{Read, Write};
|
|||||||
static FRAME_INIT: u8 = 0x80;
|
static FRAME_INIT: u8 = 0x80;
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(FromPrimitive, ToPrimitive, PartialEq)]
|
#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq)]
|
||||||
pub enum CtapCommand {
|
pub enum CtapCommand {
|
||||||
Invalid = 0x00,
|
Invalid = 0x00,
|
||||||
Ping = 0x01,
|
Ping = 0x01,
|
||||||
@ -36,6 +36,13 @@ impl CtapCommand {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(u8)]
|
||||||
|
#[derive(Debug, FromPrimitive, ToPrimitive, PartialEq)]
|
||||||
|
pub enum CtapStatus {
|
||||||
|
Processing = 0x01,
|
||||||
|
AwaitingUserPresence = 0x02,
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(FromPrimitive, Fail, Debug)]
|
#[derive(FromPrimitive, Fail, Debug)]
|
||||||
pub enum CtapError {
|
pub enum CtapError {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user