Skip to content

Commit c179798

Browse files
committed
feat: keep pin in CredentialManagement and zeroized after drop
1 parent df78f25 commit c179798

File tree

3 files changed

+30
-27
lines changed

3 files changed

+30
-27
lines changed

fido2-rs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ bitflags = "2.6.0"
1515
libfido2-sys = { version = "0.3.0", path = "../libfido2-sys" }
1616
openssl = "0.10.68"
1717
foreign-types = "=0.3.1"
18+
zeroize = "1.8.1"
1819

1920
[dev-dependencies]
2021
anyhow = "1.0.91"

fido2-rs/src/credman.rs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use std::borrow::Cow;
2-
use std::ffi::CStr;
2+
use std::ffi::{CStr, CString};
33
use std::marker::PhantomData;
44
use std::ops::Index;
55
use std::ptr::NonNull;
66

77
use foreign_types::{ForeignType, ForeignTypeRef};
8+
use zeroize::Zeroizing;
89

910
use crate::credentials::{Credential, CredentialRef};
1011
use crate::device::Device;
@@ -16,17 +17,20 @@ pub struct CredentialManagement<'a> {
1617
pub(crate) ptr: NonNull<ffi::fido_credman_metadata_t>,
1718

1819
dev: &'a Device,
20+
21+
pin: Zeroizing<CString>,
1922
}
2023

2124
impl<'a> CredentialManagement<'a> {
22-
pub(crate) fn new(device: &Device) -> CredentialManagement {
23-
unsafe {
24-
let ptr = ffi::fido_credman_metadata_new();
25-
26-
CredentialManagement {
27-
ptr: NonNull::new_unchecked(ptr),
28-
dev: device,
29-
}
25+
pub(crate) fn new(
26+
ptr: NonNull<ffi::fido_credman_metadata_t>,
27+
device: &Device,
28+
pin: Zeroizing<CString>,
29+
) -> CredentialManagement {
30+
CredentialManagement {
31+
ptr,
32+
dev: device,
33+
pin,
3034
}
3135
}
3236

@@ -41,11 +45,8 @@ impl<'a> CredentialManagement<'a> {
4145
}
4246

4347
/// Get information about relying parties with resident credentials in dev.
44-
///
45-
/// A valid pin must be provided.
46-
pub fn get_rp(&self, pin: &str) -> Result<IterRP<'a>> {
47-
let pin = std::ffi::CString::new(pin)?;
48-
let pin_ptr = pin.as_ptr();
48+
pub fn get_rp(&self) -> Result<IterRP<'a>> {
49+
let pin_ptr = self.pin.as_ptr();
4950

5051
unsafe {
5152
let p = ffi::fido_credman_rp_new();
@@ -68,12 +69,9 @@ impl<'a> CredentialManagement<'a> {
6869
}
6970

7071
/// Get resident credentials belonging to rp (relying parties) in dev.
71-
///
72-
/// A valid pin must be provided.
73-
pub fn get_rk<'i, I: Into<Cow<'i, CStr>>>(&self, rp: I, pin: &str) -> Result<CredManRK<'a>> {
72+
pub fn get_rk<'i, I: Into<Cow<'i, CStr>>>(&self, rp: I) -> Result<CredManRK<'a>> {
7473
let rp = rp.into();
75-
let pin = std::ffi::CString::new(pin)?;
76-
let pin_ptr = pin.as_ptr();
74+
let pin_ptr = self.pin.as_ptr();
7775

7876
unsafe {
7977
let rk = ffi::fido_credman_rk_new();
@@ -97,9 +95,8 @@ impl<'a> CredentialManagement<'a> {
9795
///
9896
/// # Arguments
9997
/// * `cred_id` - credential id
100-
pub fn delete_rk(&self, cred_id: &[u8], pin: &str) -> Result<()> {
101-
let pin = std::ffi::CString::new(pin)?;
102-
let pin_ptr = pin.as_ptr();
98+
pub fn delete_rk(&self, cred_id: &[u8]) -> Result<()> {
99+
let pin_ptr = self.pin.as_ptr();
103100

104101
unsafe {
105102
check(ffi::fido_credman_del_dev_rk(
@@ -120,9 +117,8 @@ impl<'a> CredentialManagement<'a> {
120117
/// See [Credential::set_id] and [Credential::set_user] for details.
121118
///
122119
/// Only a credential's user attributes (name, display name) may be updated at this time.
123-
pub fn set_rk(&self, cred: &Credential, pin: &str) -> Result<()> {
124-
let pin = std::ffi::CString::new(pin)?;
125-
let pin_ptr = pin.as_ptr();
120+
pub fn set_rk(&self, cred: &Credential) -> Result<()> {
121+
let pin_ptr = self.pin.as_ptr();
126122

127123
unsafe {
128124
check(ffi::fido_credman_set_dev_rk(

fido2-rs/src/device.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use ffi::fido_dev_t;
99
use std::ffi::{CStr, CString};
1010
use std::marker::PhantomData;
1111
use std::ptr::NonNull;
12+
use zeroize::Zeroizing;
1213

1314
/// Device list.
1415
///
@@ -381,24 +382,29 @@ impl Device {
381382
///
382383
/// A valid pin must be provided. If the device does not support credential management,
383384
/// or an error happened, error will be returned.
385+
///
386+
/// **Pin will be kept in memory and zeroized securely when the returned CredentialManagement is dropped.**
384387
pub fn credman(&self, pin: &str) -> Result<CredentialManagement> {
385388
if !self.supports_credman() {
386389
return Err(Error::Unsupported);
387390
}
388391

389-
let credman = CredentialManagement::new(&self);
392+
let ptr = unsafe { ffi::fido_credman_metadata_new() };
390393

391394
let pin = CString::new(pin)?;
392395
let pin_ptr = pin.as_ptr();
393396

394397
unsafe {
395398
check(ffi::fido_credman_get_dev_metadata(
396399
self.ptr.as_ptr(),
397-
credman.ptr.as_ptr(),
400+
ptr,
398401
pin_ptr,
399402
))?;
400403
}
401404

405+
let ptr = unsafe { NonNull::new_unchecked(ptr) };
406+
let credman = CredentialManagement::new(ptr, &self, Zeroizing::new(pin));
407+
402408
Ok(credman)
403409
}
404410
}

0 commit comments

Comments
 (0)