This commit is contained in:
pjht 2023-08-28 14:42:25 -05:00
parent 3ddc7edfc5
commit 331f74415a
Signed by: pjht
GPG Key ID: CA239FC6934E6F3A
5 changed files with 116 additions and 51 deletions

View File

@ -1,12 +1,11 @@
use std::{ffi::{CStr, CString}};
use std::ffi::{CStr, CString};
use libfido2_sys::*;
use num_enum::TryFromPrimitive;
use crate::{
check_initialized,
error::{check, Result},
opt_bool_to_fido_opt,
util::{opt_bool_to_fido_opt, check_initialized},
};
#[repr(i32)]
@ -298,18 +297,19 @@ impl CredentialRef {
) -> Result<()> {
let id = id.as_ref();
let name = CString::new(name.as_ref()).unwrap();
let display_name = display_name
.map(|x| CString::new(x).unwrap())
.unwrap_or_default();
let icon = icon.map(|x| CString::new(x).unwrap()).unwrap_or_default();
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 icon = icon.map(|x| CString::new(x).unwrap());
let icon_ptr = icon.as_ref().map_or(std::ptr::null(), |x| x.as_ptr());
unsafe {
check(fido_cred_set_user(
self.as_ptr_mut(),
&id[0],
id.len(),
name.as_ptr(),
display_name.as_ptr(),
icon.as_ptr(),
display_name_ptr,
icon_ptr,
))
}
}

View File

@ -1,3 +1,5 @@
mod info;
use std::{
ffi::{CStr, CString},
fmt::Debug,
@ -9,11 +11,13 @@ use libfido2_sys::*;
use crate::{
assert::Assertion,
check_initialized,
util::check_initialized,
cred::CredentialRef,
error::{check, Result},
};
use self::info::DeviceCborInfo;
#[derive(Clone)]
pub struct DeviceList {
ptr: NonNull<fido_dev_info_t>,
@ -49,6 +53,10 @@ impl DeviceList {
pub fn len(&self) -> usize {
self.len
}
pub fn iter(&self) -> DeviceListIterator<'_> {
DeviceListIterator { info: self, idx: 0 }
}
}
impl Index<usize> for DeviceList {
@ -68,6 +76,24 @@ impl Drop for DeviceList {
}
}
pub struct DeviceListIterator<'a> {
info: &'a DeviceList,
idx: usize
}
impl<'a> Iterator for DeviceListIterator<'a> {
type Item = &'a DeviceInfoRef;
fn next(&mut self) -> Option<Self::Item> {
if self.idx == self.info.len() {
return None;
}
let item = &self.info[self.idx];
self.idx += 1;
Some(item)
}
}
c_type_wrapper_ref!(fido_dev_info_t, DeviceInfo);
@ -116,13 +142,13 @@ impl DeviceInfoRef {
}
}
pub fn open(&self) -> Device {
pub fn open(&self) -> Result<Device> {
unsafe {
let dev_ptr = fido_dev_new_with_info(self.as_ptr());
fido_dev_open_with_info(dev_ptr);
Device {
check(fido_dev_open_with_info(dev_ptr))?;
Ok(Device {
ptr: NonNull::new_unchecked(dev_ptr),
}
})
}
}
}
@ -216,22 +242,31 @@ impl DeviceRef {
}
pub fn get_assert(&mut self, assert: &mut Assertion, pin: Option<&str>) -> Result<()> {
let pin = pin.map(|x| CString::new(x).unwrap()).unwrap_or_default();
let pin = pin.map(|x| CString::new(x).unwrap());
let pin_ptr = pin.as_ref().map_or(std::ptr::null(), |x| x.as_ptr());
unsafe {
check(fido_dev_get_assert(
self.as_ptr_mut(),
assert.as_ptr_mut(),
pin.as_ptr(),
pin_ptr,
))
}
}
//TODO: CBOR info
pub fn get_info(&mut self) -> Result<DeviceCborInfo> {
unsafe {
let info_ptr = fido_cbor_info_new();
check(fido_dev_get_cbor_info(self.as_ptr_mut(), info_ptr))?;
Ok(DeviceCborInfo::from_ptr(info_ptr))
}
}
pub fn set_pin(&mut self, pin: impl AsRef<str>, oldpin: Option<&str>) -> Result<()> {
let pin = CString::new(pin.as_ref()).unwrap();
let oldpin = oldpin.map_or(ptr::null(), |str| str.as_ptr()).cast();
unsafe { check(fido_dev_set_pin(self.as_ptr_mut(), pin.as_ptr(), oldpin)) }
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)) }
}
pub fn get_retry_count(&mut self) -> Result<u32> {
@ -257,14 +292,16 @@ impl DeviceRef {
//TODO: largeBlobs
pub fn make_cred(&mut self, cred: &mut CredentialRef, pin: Option<&str>) -> Result<()> {
let pin = pin.map(|x| CString::new(x).unwrap()).unwrap_or_default();
unsafe {
let pin = pin.map(|x| CString::new(x).unwrap());
let pin_ptr = pin.as_ref().map_or(std::ptr::null(), |x| x.as_ptr());
let res = unsafe {
check(fido_dev_make_cred(
self.as_ptr_mut(),
cred.as_ptr_mut(),
pin.as_ptr(),
pin_ptr,
))
}
};
res
}
}

23
src/device/info.rs Normal file
View File

@ -0,0 +1,23 @@
use std::{collections::HashMap, ffi::CStr};
use libfido2_sys::*;
c_type_wrapper!(fido_cbor_info_t, DeviceCborInfo);
impl DeviceCborInfoRef {
pub fn options(&self) -> HashMap<String, bool> {
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
}
}

View File

@ -1,18 +1,16 @@
use std::sync::atomic::{AtomicBool, Ordering};
use libfido2_sys::{
fido_opt_t_FIDO_OPT_FALSE, fido_opt_t_FIDO_OPT_OMIT, fido_opt_t_FIDO_OPT_TRUE, FIDO_DEBUG,
};
use libfido2_sys::FIDO_DEBUG;
use crate::util::check_initialized;
#[macro_use]
mod macros;
mod util;
pub mod assert;
pub mod cred;
pub mod device;
pub mod error;
use error::{Error, Result};
static FIDO_INITIALIZED: AtomicBool = AtomicBool::new(false);
pub(crate) static FIDO_INITIALIZED: AtomicBool = AtomicBool::new(false);
pub fn fido_init(debug: bool) {
static FIDO_INITIALIZE_STARTED: AtomicBool = AtomicBool::new(false);
@ -30,21 +28,3 @@ pub fn fido_init(debug: bool) {
FIDO_INITIALIZED.store(true, Ordering::Relaxed);
check_initialized().unwrap();
}
fn check_initialized() -> Result<()> {
if !FIDO_INITIALIZED.load(Ordering::Relaxed) {
Err(Error::NotInitialized)
} else {
Ok(())
}
}
fn opt_bool_to_fido_opt(opt: Option<bool>) -> i32 {
match opt {
Some(true) => fido_opt_t_FIDO_OPT_TRUE,
Some(false) => fido_opt_t_FIDO_OPT_FALSE,
None => fido_opt_t_FIDO_OPT_OMIT,
}
}

View File

@ -1,3 +1,28 @@
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 crate::FIDO_INITIALIZED;
use crate::error::{Result, Error};
pub fn check_initialized() -> Result<()> {
if !FIDO_INITIALIZED.load(Ordering::Relaxed) {
Err(Error::NotInitialized)
} else {
Ok(())
}
}
pub fn opt_bool_to_fido_opt(opt: Option<bool>) -> i32 {
match opt {
Some(true) => fido_opt_t_FIDO_OPT_TRUE,
Some(false) => fido_opt_t_FIDO_OPT_FALSE,
None => fido_opt_t_FIDO_OPT_OMIT,
}
}
macro_rules! c_type_wrapper {
($c: ident, $t: ident, free = $f: ident) => {
c_type_wrapper!($c, $t);
@ -17,7 +42,7 @@ macro_rules! c_type_wrapper {
impl $t {
#[allow(unused)]
unsafe fn from_ptr<'a>(ptr: *mut $c) -> Self {
pub unsafe fn from_ptr<'a>(ptr: *mut $c) -> Self {
unsafe {
$t {
ptr: ::core::ptr::NonNull::new_unchecked(ptr),
@ -60,12 +85,12 @@ macro_rules! c_type_wrapper_ref {
pub struct [<$t Ref>](::core::marker::PhantomData<::core::cell::UnsafeCell<*mut ()>>);
impl [<$t Ref>] {
#[allow(unused)]
unsafe fn from_ptr<'a>(ptr: *const $c) -> &'a Self {
pub unsafe fn from_ptr<'a>(ptr: *const $c) -> &'a Self {
unsafe { &*(ptr as *const _) }
}
#[allow(unused)]
unsafe fn from_ptr_mut<'a>(ptr: *mut $c) -> &'a mut Self {
pub unsafe fn from_ptr_mut<'a>(ptr: *mut $c) -> &'a mut Self {
unsafe { &mut *(ptr as *mut _)}
}