From 4ee3ed91ea173b9939d639c0ddad8a31b8a1313b Mon Sep 17 00:00:00 2001 From: pjht Date: Tue, 29 Aug 2023 09:07:37 -0500 Subject: [PATCH] Add supprt for CBOR authenticator info --- func_avail | 52 +++++++------- src/cred.rs | 23 +++--- src/device.rs | 15 ++-- src/device/info.rs | 171 ++++++++++++++++++++++++++++++++++++++++++--- src/lib.rs | 12 +++- src/util.rs | 22 +++--- 6 files changed, 225 insertions(+), 70 deletions(-) diff --git a/func_avail b/func_avail index 767a1fb..2ff3b18 100644 --- a/func_avail +++ b/func_avail @@ -69,39 +69,39 @@ - fido_bio_template_set_id - fido_bio_template_set_name -- fido_cbor_info_aaguid_len -- fido_cbor_info_aaguid_ptr -- fido_cbor_info_algorithm_cose -- fido_cbor_info_algorithm_count -- fido_cbor_info_algorithm_type -- fido_cbor_info_certs_len -- fido_cbor_info_certs_name_ptr -- fido_cbor_info_certs_value_ptr -- fido_cbor_info_extensions_len -- fido_cbor_info_extensions_ptr +Y fido_cbor_info_aaguid_len +Y fido_cbor_info_aaguid_ptr +Y fido_cbor_info_algorithm_cose +Y fido_cbor_info_algorithm_count +Y fido_cbor_info_algorithm_type +Y fido_cbor_info_certs_len +Y fido_cbor_info_certs_name_ptr +Y fido_cbor_info_certs_value_ptr +Y fido_cbor_info_extensions_len +Y fido_cbor_info_extensions_ptr Y fido_cbor_info_free -- fido_cbor_info_fwversion -- fido_cbor_info_maxcredbloblen -- fido_cbor_info_maxcredcntlst -- fido_cbor_info_maxcredidlen -- fido_cbor_info_maxlargeblob -- fido_cbor_info_maxmsgsiz -- fido_cbor_info_maxrpid_minpinlen -- fido_cbor_info_minpinlen +Y fido_cbor_info_fwversion +Y fido_cbor_info_maxcredbloblen +Y fido_cbor_info_maxcredcntlst +Y fido_cbor_info_maxcredidlen +Y fido_cbor_info_maxlargeblob +Y fido_cbor_info_maxmsgsiz +Y fido_cbor_info_maxrpid_minpinlen +Y fido_cbor_info_minpinlen Y fido_cbor_info_new -- fido_cbor_info_new_pin_required +Y fido_cbor_info_new_pin_required Y fido_cbor_info_options_len Y fido_cbor_info_options_name_ptr Y fido_cbor_info_options_value_ptr -- fido_cbor_info_protocols_len -- fido_cbor_info_protocols_ptr -- fido_cbor_info_rk_remaining -- fido_cbor_info_transports_len -- fido_cbor_info_transports_ptr +Y fido_cbor_info_protocols_len +Y fido_cbor_info_protocols_ptr +Y fido_cbor_info_rk_remaining +Y fido_cbor_info_transports_len +Y fido_cbor_info_transports_ptr - fido_cbor_info_uv_attempts - fido_cbor_info_uv_modality -- fido_cbor_info_versions_len -- fido_cbor_info_versions_ptr +Y fido_cbor_info_versions_len +Y fido_cbor_info_versions_ptr Y fido_cred_aaguid_len Y fido_cred_aaguid_ptr diff --git a/src/cred.rs b/src/cred.rs index cc2f08b..21518bf 100644 --- a/src/cred.rs +++ b/src/cred.rs @@ -5,7 +5,8 @@ use num_enum::TryFromPrimitive; use crate::{ error::{check, Result}, - util::{opt_bool_to_fido_opt, check_initialized}, + util::{check_initialized, opt_bool_to_fido_opt}, + CoseAlg, }; #[repr(i32)] @@ -16,15 +17,6 @@ pub enum CredProtection { UvRequired = FIDO_CRED_PROT_UV_REQUIRED, } -#[repr(i32)] -#[derive(Debug, Clone, Copy, TryFromPrimitive)] -pub enum CredType { - Ecdsa256 = COSE_ES256, - Ecdsa384 = COSE_ES384, - Rsa = COSE_RS256, - Ed25519 = COSE_EDDSA, -} - c_type_wrapper!(fido_cred_t, Credential, free = fido_cred_free); impl Credential { @@ -284,7 +276,7 @@ impl CredentialRef { unsafe { check(fido_cred_set_sig(self.as_ptr_mut(), &sig[0], sig.len())) } } - pub fn set_type(&mut self, typ: CredType) -> Result<()> { + pub fn set_type(&mut self, typ: CoseAlg) -> Result<()> { unsafe { check(fido_cred_set_type(self.as_ptr_mut(), typ as i32)) } } @@ -298,7 +290,9 @@ impl CredentialRef { let id = id.as_ref(); let name = CString::new(name.as_ref()).unwrap(); let display_name = display_name.map(|x| CString::new(x).unwrap()); - let display_name_ptr = display_name.as_ref().map_or(std::ptr::null(), |x| x.as_ptr()); + let display_name_ptr = display_name + .as_ref() + .map_or(std::ptr::null(), |x| x.as_ptr()); let icon = icon.map(|x| CString::new(x).unwrap()); let icon_ptr = icon.as_ref().map_or(std::ptr::null(), |x| x.as_ptr()); @@ -340,13 +334,13 @@ impl CredentialRef { unsafe { fido_cred_sigcount(self.as_ptr()) } } - pub fn get_type(&self) -> Option { + pub fn get_type(&self) -> Option { unsafe { let typ = fido_cred_type(self.as_ptr()); if typ == 0 { None } else { - Some(CredType::try_from(typ).unwrap()) + Some(CoseAlg::try_from(typ).unwrap()) } } } @@ -387,5 +381,4 @@ impl CredentialRef { ) } } - } diff --git a/src/device.rs b/src/device.rs index 8a1790a..8c71c55 100644 --- a/src/device.rs +++ b/src/device.rs @@ -11,9 +11,9 @@ use libfido2_sys::*; use crate::{ assert::Assertion, - util::check_initialized, cred::CredentialRef, error::{check, Result}, + util::check_initialized, }; use self::info::DeviceCborInfo; @@ -78,7 +78,7 @@ impl Drop for DeviceList { pub struct DeviceListIterator<'a> { info: &'a DeviceList, - idx: usize + idx: usize, } impl<'a> Iterator for DeviceListIterator<'a> { @@ -94,7 +94,6 @@ impl<'a> Iterator for DeviceListIterator<'a> { } } - c_type_wrapper_ref!(fido_dev_info_t, DeviceInfo); impl Debug for DeviceInfoRef { @@ -261,12 +260,17 @@ impl DeviceRef { } } - pub fn set_pin(&mut self, pin: impl AsRef, oldpin: Option<&str>) -> Result<()> { let pin = CString::new(pin.as_ref()).unwrap(); let oldpin = oldpin.map(|x| CString::new(x).unwrap()); let oldpin_ptr = oldpin.as_ref().map_or(std::ptr::null(), |x| x.as_ptr()); - unsafe { check(fido_dev_set_pin(self.as_ptr_mut(), pin.as_ptr(), oldpin_ptr)) } + unsafe { + check(fido_dev_set_pin( + self.as_ptr_mut(), + pin.as_ptr(), + oldpin_ptr, + )) + } } pub fn get_retry_count(&mut self) -> Result { @@ -303,5 +307,4 @@ impl DeviceRef { }; res } - } diff --git a/src/device/info.rs b/src/device/info.rs index 0f29ca3..8da42f3 100644 --- a/src/device/info.rs +++ b/src/device/info.rs @@ -2,22 +2,175 @@ use std::{collections::HashMap, ffi::CStr}; use libfido2_sys::*; +use crate::CoseAlg; + c_type_wrapper!(fido_cbor_info_t, DeviceCborInfo, free = fido_cbor_info_free); impl DeviceCborInfoRef { - pub fn options(&self) -> HashMap { + pub fn aaguid(&self) -> &[u8] { + unsafe { + std::slice::from_raw_parts( + fido_cbor_info_aaguid_ptr(self.as_ptr()), + fido_cbor_info_aaguid_len(self.as_ptr()), + ) + } + } + + pub fn algorithms(&self) -> HashMap { let mut map = HashMap::new(); - unsafe{ - let name_ptr = fido_cbor_info_options_name_ptr(self.as_ptr()); - let value_ptr = fido_cbor_info_options_value_ptr(self.as_ptr()); - for i in 0..fido_cbor_info_options_len(self.as_ptr()) { - let key = CStr::from_ptr(*(name_ptr.add(i))).to_string_lossy().to_string(); + unsafe { + for i in 0..fido_cbor_info_algorithm_count(self.as_ptr()) { + let algorithm = fido_cbor_info_algorithm_cose(self.as_ptr(), i); + let type_ptr = fido_cbor_info_algorithm_type(self.as_ptr(), i); + let key = CStr::from_ptr(type_ptr).to_string_lossy().to_string(); + let value = CoseAlg::try_from(algorithm).unwrap(); + map.insert(key, value); + } + } + map + } + + pub fn certs(&self) -> HashMap { + let mut map = HashMap::new(); + unsafe { + let name_ptr = fido_cbor_info_certs_name_ptr(self.as_ptr()); + let value_ptr = fido_cbor_info_certs_value_ptr(self.as_ptr()); + for i in 0..fido_cbor_info_certs_len(self.as_ptr()) { + let key = CStr::from_ptr(*(name_ptr.add(i))) + .to_string_lossy() + .to_string(); let value = *(value_ptr.add(i)); map.insert(key, value); } } map - } + } + + pub fn extensions(&self) -> Vec { + let mut list = Vec::new(); + unsafe { + let extensions_ptr = fido_cbor_info_extensions_ptr(self.as_ptr()); + for i in 0..fido_cbor_info_extensions_len(self.as_ptr()) { + let key = CStr::from_ptr(*(extensions_ptr.add(i))) + .to_string_lossy() + .to_string(); + list.push(key); + } + } + list + } + + pub fn fwversion(&self) -> u64 { + unsafe { fido_cbor_info_fwversion(self.as_ptr()) } + } + + pub fn maxcredbloblen(&self) -> u64 { + unsafe { fido_cbor_info_maxcredbloblen(self.as_ptr()) } + } + + pub fn maxcredcntlst(&self) -> u64 { + unsafe { fido_cbor_info_maxcredcntlst(self.as_ptr()) } + } + + pub fn maxcredidlen(&self) -> u64 { + unsafe { fido_cbor_info_maxcredidlen(self.as_ptr()) } + } + + pub fn maxlargeblob(&self) -> u64 { + unsafe { fido_cbor_info_maxlargeblob(self.as_ptr()) } + } + + pub fn maxmsgsiz(&self) -> u64 { + unsafe { fido_cbor_info_maxmsgsiz(self.as_ptr()) } + } + + pub fn maxrpid_minpinlen(&self) -> u64 { + unsafe { fido_cbor_info_maxrpid_minpinlen(self.as_ptr()) } + } + + pub fn minpinlen(&self) -> u64 { + unsafe { fido_cbor_info_minpinlen(self.as_ptr()) } + } + + pub fn new_pin_required(&self) -> bool { + unsafe { fido_cbor_info_new_pin_required(self.as_ptr()) } + } + + + pub fn options(&self) -> HashMap { + let mut map = HashMap::new(); + unsafe { + let name_ptr = fido_cbor_info_options_name_ptr(self.as_ptr()); + let value_ptr = fido_cbor_info_options_value_ptr(self.as_ptr()); + for i in 0..fido_cbor_info_options_len(self.as_ptr()) { + let key = CStr::from_ptr(*(name_ptr.add(i))) + .to_string_lossy() + .to_string(); + let value = *(value_ptr.add(i)); + map.insert(key, value); + } + } + map + } + + pub fn pin_protocols(&self) -> Vec { + let mut list = Vec::new(); + unsafe { + let protocols_ptr = fido_cbor_info_protocols_ptr(self.as_ptr()); + for i in 0..fido_cbor_info_protocols_len(self.as_ptr()) { + let key = *(protocols_ptr.add(i)); + list.push(key); + } + } + list + } + + pub fn rk_remaining(&self) -> Option { + unsafe { match fido_cbor_info_rk_remaining(self.as_ptr()) { + -1 => None, + x => Some(x as u64), + }} + } + + pub fn transports(&self) -> Vec { + let mut list = Vec::new(); + unsafe { + let transports_ptr = fido_cbor_info_transports_ptr(self.as_ptr()); + for i in 0..fido_cbor_info_transports_len(self.as_ptr()) { + let key = CStr::from_ptr(*(transports_ptr.add(i))) + .to_string_lossy() + .to_string(); + list.push(key); + } + } + list + } + + pub fn uv_attempts(&self) -> Option { + unsafe { match fido_cbor_info_uv_attempts(self.as_ptr()) { + 0 => None, + x => Some(x), + }} + } + + pub fn uv_modality(&self) -> Option { + unsafe { match fido_cbor_info_uv_modality(self.as_ptr()) { + 0 => None, + x => Some(x), + }} + } + + pub fn versions(&self) -> Vec { + let mut list = Vec::new(); + unsafe { + let versions_ptr = fido_cbor_info_versions_ptr(self.as_ptr()); + for i in 0..fido_cbor_info_versions_len(self.as_ptr()) { + let key = CStr::from_ptr(*(versions_ptr.add(i))) + .to_string_lossy() + .to_string(); + list.push(key); + } + } + list + } } - - diff --git a/src/lib.rs b/src/lib.rs index 349310d..5b85ea4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; -use libfido2_sys::FIDO_DEBUG; +use libfido2_sys::*; +use num_enum::TryFromPrimitive; use crate::util::check_initialized; #[macro_use] @@ -10,6 +11,15 @@ pub mod cred; pub mod device; pub mod error; +#[repr(i32)] +#[derive(Debug, Clone, Copy, TryFromPrimitive)] +pub enum CoseAlg { + Ecdsa256 = COSE_ES256, + Ecdsa384 = COSE_ES384, + Rsa = COSE_RS256, + Ed25519 = COSE_EDDSA, +} + pub(crate) static FIDO_INITIALIZED: AtomicBool = AtomicBool::new(false); pub fn fido_init(debug: bool) { diff --git a/src/util.rs b/src/util.rs index 6d27a7d..cfe203d 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,9 +1,9 @@ use std::sync::atomic::Ordering; -use libfido2_sys::{fido_opt_t_FIDO_OPT_TRUE, fido_opt_t_FIDO_OPT_FALSE, fido_opt_t_FIDO_OPT_OMIT}; +use libfido2_sys::{fido_opt_t_FIDO_OPT_FALSE, fido_opt_t_FIDO_OPT_OMIT, fido_opt_t_FIDO_OPT_TRUE}; +use crate::error::{Error, Result}; use crate::FIDO_INITIALIZED; -use crate::error::{Result, Error}; pub fn check_initialized() -> Result<()> { if !FIDO_INITIALIZED.load(Ordering::Relaxed) { @@ -21,16 +21,12 @@ pub fn opt_bool_to_fido_opt(opt: Option) -> i32 { } } - - macro_rules! c_type_wrapper { ($c: ident, $t: ident, free = $f: ident) => { c_type_wrapper!($c, $t); impl ::core::ops::Drop for $t { fn drop(&mut self) { - unsafe { - $f(&mut self.ptr.as_ptr()) - } + unsafe { $f(&mut self.ptr.as_ptr()) } } } }; @@ -43,21 +39,21 @@ macro_rules! c_type_wrapper { impl $t { #[allow(unused)] pub unsafe fn from_ptr<'a>(ptr: *mut $c) -> Self { - unsafe { + unsafe { $t { ptr: ::core::ptr::NonNull::new_unchecked(ptr), - } + } } } #[allow(unused)] pub(crate) fn as_ptr(&self) -> *const $c { - self.ptr.as_ptr() + self.ptr.as_ptr() } #[allow(unused)] pub(crate) fn as_ptr_mut(&mut self) -> *mut $c { - self.ptr.as_ptr() + self.ptr.as_ptr() } } @@ -76,7 +72,7 @@ macro_rules! c_type_wrapper { } c_type_wrapper_ref!($c, $t); } - } + }; } macro_rules! c_type_wrapper_ref { @@ -105,5 +101,5 @@ macro_rules! c_type_wrapper_ref { } } } - } + }; }