Add attestation support
This commit is contained in:
parent
d04e75ce3b
commit
29fc403d81
76
func_avail
76
func_avail
@ -1,43 +1,43 @@
|
||||
- fido_assert_allow_cred
|
||||
- fido_assert_authdata_len
|
||||
- fido_assert_authdata_ptr
|
||||
- fido_assert_blob_len
|
||||
- fido_assert_blob_ptr
|
||||
- fido_assert_clientdata_hash_len
|
||||
- fido_assert_clientdata_hash_ptr
|
||||
- fido_assert_count
|
||||
Y fido_assert_authdata_len
|
||||
Y fido_assert_authdata_ptr
|
||||
Y fido_assert_blob_len
|
||||
Y fido_assert_blob_ptr
|
||||
Y fido_assert_clientdata_hash_len
|
||||
Y fido_assert_clientdata_hash_ptr
|
||||
Y fido_assert_count
|
||||
- fido_assert_empty_allow_list
|
||||
- fido_assert_flags
|
||||
- fido_assert_free
|
||||
- fido_assert_hmac_secret_len
|
||||
- fido_assert_hmac_secret_ptr
|
||||
- fido_assert_id_len
|
||||
- fido_assert_id_ptr
|
||||
- fido_assert_largeblob_key_len
|
||||
- fido_assert_largeblob_key_ptr
|
||||
- fido_assert_new
|
||||
- fido_assert_rp_id
|
||||
- fido_assert_set_authdata
|
||||
- fido_assert_set_authdata_raw
|
||||
- fido_assert_set_clientdata
|
||||
- fido_assert_set_clientdata_hash
|
||||
- fido_assert_set_count
|
||||
- fido_assert_set_extensions
|
||||
- fido_assert_set_hmac_salt
|
||||
- fido_assert_set_hmac_secret
|
||||
- fido_assert_set_rp
|
||||
- fido_assert_set_sig
|
||||
- fido_assert_set_up
|
||||
- fido_assert_set_uv
|
||||
- fido_assert_sig_len
|
||||
- fido_assert_sig_ptr
|
||||
- fido_assert_sigcount
|
||||
- fido_assert_user_display_name
|
||||
- fido_assert_user_icon
|
||||
- fido_assert_user_id_len
|
||||
- fido_assert_user_id_ptr
|
||||
- fido_assert_user_name
|
||||
- fido_assert_verify
|
||||
Y fido_assert_flags
|
||||
Y fido_assert_free
|
||||
Y fido_assert_hmac_secret_len
|
||||
Y fido_assert_hmac_secret_ptr
|
||||
Y fido_assert_id_len
|
||||
Y fido_assert_id_ptr
|
||||
Y fido_assert_largeblob_key_len
|
||||
Y fido_assert_largeblob_key_ptr
|
||||
Y fido_assert_new
|
||||
Y fido_assert_rp_id
|
||||
Y fido_assert_set_authdata
|
||||
Y fido_assert_set_authdata_raw
|
||||
Y fido_assert_set_clientdata
|
||||
Y fido_assert_set_clientdata_hash
|
||||
Y fido_assert_set_count
|
||||
Y fido_assert_set_extensions
|
||||
Y fido_assert_set_hmac_salt
|
||||
Y fido_assert_set_hmac_secret
|
||||
Y fido_assert_set_rp
|
||||
Y fido_assert_set_sig
|
||||
Y fido_assert_set_up
|
||||
Y fido_assert_set_uv
|
||||
Y fido_assert_sig_len
|
||||
Y fido_assert_sig_ptr
|
||||
Y fido_assert_sigcount
|
||||
Y fido_assert_user_display_name
|
||||
Y fido_assert_user_icon
|
||||
Y fido_assert_user_id_len
|
||||
Y fido_assert_user_id_ptr
|
||||
Y fido_assert_user_name
|
||||
Y fido_assert_verify
|
||||
|
||||
- fido_bio_dev_enroll_begin
|
||||
- fido_bio_dev_enroll_cancel
|
||||
|
306
src/assert.rs
306
src/assert.rs
@ -1,3 +1,309 @@
|
||||
use std::ffi::{CStr, CString};
|
||||
|
||||
use crate::{
|
||||
error::{check, Result},
|
||||
pkey::PubKey,
|
||||
util::{check_initialized, opt_bool_to_fido_opt},
|
||||
CoseAlg,
|
||||
};
|
||||
use libfido2_sys::*;
|
||||
|
||||
c_type_wrapper!(fido_assert_t, Assertion, free = fido_assert_free);
|
||||
|
||||
impl Assertion {
|
||||
pub fn new(&self) -> Result<Self> {
|
||||
check_initialized()?;
|
||||
unsafe { Ok(Self::from_ptr(fido_assert_new())) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AssertionRef {
|
||||
pub fn authdata(&self, idx: usize) -> Option<&[u8]> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
if fido_assert_authdata_ptr(self.as_ptr(), idx).is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::slice::from_raw_parts(
|
||||
fido_assert_authdata_ptr(self.as_ptr(), idx),
|
||||
fido_assert_authdata_len(self.as_ptr(), idx),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn blob(&self, idx: usize) -> Option<&[u8]> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
if fido_assert_blob_ptr(self.as_ptr(), idx).is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::slice::from_raw_parts(
|
||||
fido_assert_blob_ptr(self.as_ptr(), idx),
|
||||
fido_assert_blob_len(self.as_ptr(), idx),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clientdata_hash(&self) -> Option<&[u8]> {
|
||||
unsafe {
|
||||
if fido_assert_clientdata_hash_ptr(self.as_ptr()).is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::slice::from_raw_parts(
|
||||
fido_assert_clientdata_hash_ptr(self.as_ptr()),
|
||||
fido_assert_clientdata_hash_len(self.as_ptr()),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn count(&self) -> usize {
|
||||
unsafe { fido_assert_count(self.as_ptr()) }
|
||||
}
|
||||
|
||||
pub fn flags(&self, idx: usize) -> u8 {
|
||||
assert!(idx < self.count());
|
||||
unsafe { fido_assert_flags(self.as_ptr(), idx) }
|
||||
}
|
||||
|
||||
pub fn hmac_secret(&self, idx: usize) -> Option<&[u8]> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
if fido_assert_hmac_secret_ptr(self.as_ptr(), idx).is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::slice::from_raw_parts(
|
||||
fido_assert_hmac_secret_ptr(self.as_ptr(), idx),
|
||||
fido_assert_hmac_secret_len(self.as_ptr(), idx),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id(&self, idx: usize) -> Option<&[u8]> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
if fido_assert_id_ptr(self.as_ptr(), idx).is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::slice::from_raw_parts(
|
||||
fido_assert_id_ptr(self.as_ptr(), idx),
|
||||
fido_assert_id_len(self.as_ptr(), idx),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn largeblob_key(&self, idx: usize) -> &[u8] {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
std::slice::from_raw_parts(
|
||||
fido_assert_largeblob_key_ptr(self.as_ptr(), idx),
|
||||
fido_assert_largeblob_key_len(self.as_ptr(), idx),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rp_id(&self) -> Option<&str> {
|
||||
unsafe {
|
||||
let ptr = fido_assert_rp_id(self.as_ptr());
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(ptr).to_str().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_authdata(&mut self, idx: usize, data: &[u8]) -> Result<()> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
check(fido_assert_set_authdata(
|
||||
self.as_ptr_mut(),
|
||||
idx,
|
||||
&data[0],
|
||||
data.len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_authdata_raw(&mut self, idx: usize, data: &[u8]) -> Result<()> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
check(fido_assert_set_authdata_raw(
|
||||
self.as_ptr_mut(),
|
||||
idx,
|
||||
&data[0],
|
||||
data.len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clientdata(&mut self, data: &[u8]) -> Result<()> {
|
||||
unsafe {
|
||||
check(fido_assert_set_clientdata(
|
||||
self.as_ptr_mut(),
|
||||
&data[0],
|
||||
data.len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_clientdata_hash(&mut self, hash: &[u8]) -> Result<()> {
|
||||
unsafe {
|
||||
check(fido_assert_set_clientdata_hash(
|
||||
self.as_ptr_mut(),
|
||||
&hash[0],
|
||||
hash.len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_count(&mut self, count: usize) -> Result<()> {
|
||||
unsafe { check(fido_assert_set_count(self.as_ptr_mut(), count)) }
|
||||
}
|
||||
|
||||
pub fn set_extensions(&mut self, extensions: i32) -> Result<()> {
|
||||
unsafe { check(fido_assert_set_extensions(self.as_ptr_mut(), extensions)) }
|
||||
}
|
||||
|
||||
pub fn set_hmac_salt(&mut self, data: &[u8]) -> Result<()> {
|
||||
unsafe {
|
||||
check(fido_assert_set_hmac_salt(
|
||||
self.as_ptr_mut(),
|
||||
&data[0],
|
||||
data.len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_hmac_secret(&mut self, idx: usize, data: &[u8]) -> Result<()> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
check(fido_assert_set_hmac_secret(
|
||||
self.as_ptr_mut(),
|
||||
idx,
|
||||
&data[0],
|
||||
data.len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_rp(&mut self, rp: impl AsRef<str>) -> Result<()> {
|
||||
let rp = CString::new(rp.as_ref()).unwrap();
|
||||
unsafe { check(fido_assert_set_rp(self.as_ptr_mut(), rp.as_ptr())) }
|
||||
}
|
||||
|
||||
pub fn set_sig(&mut self, idx: usize, data: &[u8]) -> Result<()> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
check(fido_assert_set_sig(
|
||||
self.as_ptr_mut(),
|
||||
idx,
|
||||
&data[0],
|
||||
data.len(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_up(&mut self, up: Option<bool>) -> Result<()> {
|
||||
unsafe {
|
||||
check(fido_assert_set_up(
|
||||
self.as_ptr_mut(),
|
||||
opt_bool_to_fido_opt(up),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_uv(&mut self, uv: Option<bool>) -> Result<()> {
|
||||
unsafe {
|
||||
check(fido_assert_set_uv(
|
||||
self.as_ptr_mut(),
|
||||
opt_bool_to_fido_opt(uv),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sig(&self, idx: usize) -> Option<&[u8]> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
if fido_assert_sig_ptr(self.as_ptr(), idx).is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::slice::from_raw_parts(
|
||||
fido_assert_sig_ptr(self.as_ptr(), idx),
|
||||
fido_assert_sig_len(self.as_ptr(), idx),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sigcount(&self, idx: usize) -> u32 {
|
||||
assert!(idx < self.count());
|
||||
unsafe { fido_assert_sigcount(self.as_ptr(), idx) }
|
||||
}
|
||||
|
||||
pub fn user_display_name(&self, idx: usize) -> Option<&str> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
let ptr = fido_assert_user_display_name(self.as_ptr(), idx);
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(ptr).to_str().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_icon(&self, idx: usize) -> Option<&str> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
let ptr = fido_assert_user_icon(self.as_ptr(), idx);
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(ptr).to_str().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_id(&self, idx: usize) -> Option<&[u8]> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
if fido_assert_user_id_ptr(self.as_ptr(), idx).is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(std::slice::from_raw_parts(
|
||||
fido_assert_user_id_ptr(self.as_ptr(), idx),
|
||||
fido_assert_user_id_len(self.as_ptr(), idx),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn user_name(&self, idx: usize) -> Option<&str> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
let ptr = fido_assert_user_name(self.as_ptr(), idx);
|
||||
if ptr.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(CStr::from_ptr(ptr).to_str().unwrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn verify(&self, idx: usize, alg: CoseAlg, pubkey: PubKey) -> Result<()> {
|
||||
assert!(idx < self.count());
|
||||
unsafe {
|
||||
check(fido_assert_verify(
|
||||
self.as_ptr(),
|
||||
idx,
|
||||
alg as i32,
|
||||
pubkey.as_ptr(),
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use std::{
|
||||
ffi::{CStr, CString},
|
||||
fmt::Debug,
|
||||
ops::Index,
|
||||
ptr::{self, NonNull},
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use libfido2_sys::*;
|
||||
|
@ -96,7 +96,6 @@ impl DeviceCborInfoRef {
|
||||
unsafe { fido_cbor_info_new_pin_required(self.as_ptr()) }
|
||||
}
|
||||
|
||||
|
||||
pub fn options(&self) -> HashMap<String, bool> {
|
||||
let mut map = HashMap::new();
|
||||
unsafe {
|
||||
@ -126,10 +125,12 @@ impl DeviceCborInfoRef {
|
||||
}
|
||||
|
||||
pub fn rk_remaining(&self) -> Option<u64> {
|
||||
unsafe { match fido_cbor_info_rk_remaining(self.as_ptr()) {
|
||||
-1 => None,
|
||||
x => Some(x as u64),
|
||||
}}
|
||||
unsafe {
|
||||
match fido_cbor_info_rk_remaining(self.as_ptr()) {
|
||||
-1 => None,
|
||||
x => Some(x as u64),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transports(&self) -> Vec<String> {
|
||||
@ -147,20 +148,24 @@ impl DeviceCborInfoRef {
|
||||
}
|
||||
|
||||
pub fn uv_attempts(&self) -> Option<u64> {
|
||||
unsafe { match fido_cbor_info_uv_attempts(self.as_ptr()) {
|
||||
0 => None,
|
||||
x => Some(x),
|
||||
}}
|
||||
unsafe {
|
||||
match fido_cbor_info_uv_attempts(self.as_ptr()) {
|
||||
0 => None,
|
||||
x => Some(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn uv_modality(&self) -> Option<u64> {
|
||||
unsafe { match fido_cbor_info_uv_modality(self.as_ptr()) {
|
||||
0 => None,
|
||||
x => Some(x),
|
||||
}}
|
||||
unsafe {
|
||||
match fido_cbor_info_uv_modality(self.as_ptr()) {
|
||||
0 => None,
|
||||
x => Some(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn versions(&self) -> Vec<String> {
|
||||
pub fn versions(&self) -> Vec<String> {
|
||||
let mut list = Vec::new();
|
||||
unsafe {
|
||||
let versions_ptr = fido_cbor_info_versions_ptr(self.as_ptr());
|
||||
|
@ -10,6 +10,7 @@ pub mod assert;
|
||||
pub mod cred;
|
||||
pub mod device;
|
||||
pub mod error;
|
||||
pub mod pkey;
|
||||
|
||||
#[repr(i32)]
|
||||
#[derive(Debug, Clone, Copy, TryFromPrimitive)]
|
||||
|
97
src/pkey.rs
Normal file
97
src/pkey.rs
Normal file
@ -0,0 +1,97 @@
|
||||
use std::ffi::c_void;
|
||||
|
||||
use libfido2_sys::*;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::util::check_initialized;
|
||||
|
||||
c_type_wrapper!(eddsa_pk_t, Ec25519PubKey, free = eddsa_pk_free);
|
||||
c_type_wrapper!(es256_pk_t, Ecdsa256PubKey, free = es256_pk_free);
|
||||
c_type_wrapper!(es384_pk, Ecdsa384PubKey, free = es384_pk_free);
|
||||
c_type_wrapper!(rs256_pk, Rsa256PubKey, free = rs256_pk_free);
|
||||
|
||||
impl Ec25519PubKey {
|
||||
pub fn new(data: &[u8]) -> Result<Self> {
|
||||
check_initialized()?;
|
||||
unsafe {
|
||||
let ptr = eddsa_pk_new();
|
||||
eddsa_pk_from_ptr(ptr, &data[0] as *const u8 as *const c_void, data.len());
|
||||
Ok(Self::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ecdsa256PubKey {
|
||||
pub fn new(data: &[u8]) -> Result<Self> {
|
||||
check_initialized()?;
|
||||
unsafe {
|
||||
let ptr = es256_pk_new();
|
||||
es256_pk_from_ptr(ptr, &data[0] as *const u8 as *const c_void, data.len());
|
||||
Ok(Self::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Ecdsa384PubKey {
|
||||
pub fn new(data: &[u8]) -> Result<Self> {
|
||||
check_initialized()?;
|
||||
unsafe {
|
||||
let ptr = es384_pk_new();
|
||||
es384_pk_from_ptr(ptr, &data[0] as *const u8 as *const c_void, data.len());
|
||||
Ok(Self::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Rsa256PubKey {
|
||||
pub fn new(data: &[u8]) -> Result<Self> {
|
||||
check_initialized()?;
|
||||
unsafe {
|
||||
let ptr = rs256_pk_new();
|
||||
rs256_pk_from_ptr(ptr, &data[0] as *const u8 as *const c_void, data.len());
|
||||
Ok(Self::from_ptr(ptr))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum PubKey {
|
||||
Ec25519(Ec25519PubKey),
|
||||
Ecdsa256(Ecdsa256PubKey),
|
||||
Ecdsa384(Ecdsa384PubKey),
|
||||
Rsa256PubKey(Rsa256PubKey),
|
||||
}
|
||||
|
||||
impl From<Rsa256PubKey> for PubKey {
|
||||
fn from(v: Rsa256PubKey) -> Self {
|
||||
Self::Rsa256PubKey(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ecdsa384PubKey> for PubKey {
|
||||
fn from(v: Ecdsa384PubKey) -> Self {
|
||||
Self::Ecdsa384(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ecdsa256PubKey> for PubKey {
|
||||
fn from(v: Ecdsa256PubKey) -> Self {
|
||||
Self::Ecdsa256(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Ec25519PubKey> for PubKey {
|
||||
fn from(v: Ec25519PubKey) -> Self {
|
||||
Self::Ec25519(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl PubKey {
|
||||
pub(crate) fn as_ptr(&self) -> *const c_void {
|
||||
match self {
|
||||
PubKey::Ec25519(pk) => pk.as_ptr() as *const c_void,
|
||||
PubKey::Ecdsa256(pk) => pk.as_ptr() as *const c_void,
|
||||
PubKey::Ecdsa384(pk) => pk.as_ptr() as *const c_void,
|
||||
PubKey::Rsa256PubKey(pk) => pk.as_ptr() as *const c_void,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user