Skip to content

Commit

Permalink
Use struct instead of builder methods for cred creation/verification
Browse files Browse the repository at this point in the history
  • Loading branch information
PvdBerg1998 committed Jun 29, 2019
1 parent 59ddd20 commit 1cbc8b2
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 103 deletions.
21 changes: 13 additions & 8 deletions examples/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,19 @@ pub fn _main() -> Result<(), FidoError> {
.as_ref()
);

let mut creator = fido.new_credential_creator();
creator.set_type(CredentialType::ES256)?;
creator.set_client_data_hash(&CLIENT_DATA_HASH)?;
creator.set_relying_party(
&CString::new(RELYING_PARTY_ID).unwrap(),
&CString::new(RELYING_PARTY_NAME).unwrap(),
)?;
creator.set_user(&USER_ID, &CString::new(USER_NAME).unwrap(), None, None)?;
let creator = fido.new_credential_creator(CredentialCreationData {
excluded_ids: &[],
credential_type: CredentialType::ES256,
client_data_hash: &CLIENT_DATA_HASH,
relying_party_id: &CString::new(RELYING_PARTY_ID).unwrap(),
relying_party_name: &CString::new(RELYING_PARTY_NAME).unwrap(),
user_id: &USER_ID,
user_name: &CString::new(USER_NAME).unwrap(),
user_display_name: None,
user_image_uri: None,
options: CredentialOptions::empty(),
extensions: CredentialExtensions::empty(),
})?;

let credential = device.request_credential_creation(creator, None)?;
println!("Created credential: {:?}", credential.as_ref());
Expand Down
230 changes: 137 additions & 93 deletions src/credential.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,128 @@ pub struct CredentialRef<'a> {
pub struct CredentialCreator(pub(crate) Credential);
pub struct CredentialVerifier(pub(crate) Credential);

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CredentialCreationData<'a> {
pub excluded_ids: &'a [u8],
pub credential_type: CredentialType,
pub client_data_hash: &'a [u8],
pub relying_party_id: &'a CStr,
pub relying_party_name: &'a CStr,
pub user_id: &'a [u8],
pub user_name: &'a CStr,
pub user_display_name: Option<&'a CStr>,
pub user_image_uri: Option<&'a CStr>,
pub options: CredentialOptions,
pub extensions: CredentialExtensions,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct CredentialVerificationData<'a> {
pub format: CredentialFormat,
pub auth_data: &'a [u8],
pub x509_certificate: &'a [u8],
pub signature: &'a [u8],
pub options: CredentialOptions,
pub extensions: CredentialExtensions,
}

impl CredentialCreator {
pub fn set_excluded(&mut self, excluded_ids: &[u8]) -> Result<()> {
pub(crate) fn new(
mut credential: Credential,
data: CredentialCreationData<'_>,
) -> Result<Self> {
// @TODO propagate location of error
// @FIXME calling this with len==0 results in FIDO_ERR_INTERNAL
if !data.excluded_ids.is_empty() {
credential.set_excluded(data.excluded_ids)?;
}
credential.set_type(data.credential_type)?;
credential.set_client_data_hash(data.client_data_hash)?;
credential.set_relying_party(data.relying_party_id, data.relying_party_name)?;
credential.set_user(
data.user_id,
data.user_name,
data.user_display_name,
data.user_image_uri,
)?;
credential.set_options(data.options)?;
credential.set_extensions(data.extensions)?;
Ok(CredentialCreator(credential))
}
}

impl CredentialVerifier {
pub(crate) fn new(
mut credential: Credential,
data: CredentialVerificationData<'_>,
) -> Result<Self> {
// @TODO propagate location of error
credential.set_format(data.format)?;
credential.set_auth_data(data.auth_data)?;
credential.set_x509_certificate(data.x509_certificate)?;
credential.set_signature(data.signature)?;
credential.set_options(data.options)?;
credential.set_extensions(data.extensions)?;
Ok(CredentialVerifier(credential))
}
}

impl Credential {
pub fn as_ref<'a>(&'a self) -> CredentialRef<'a> {
unsafe {
let credential = self.raw.as_ptr();

let format = fido_cred_fmt(credential)
.as_ref()
.map(|ptr| CStr::from_ptr(ptr))
.unwrap();

let auth_data = fido_cred_authdata_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_authdata_len(credential)))
.unwrap();

let client_data_hash = fido_cred_clientdata_hash_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_clientdata_hash_len(credential)))
.unwrap();

let id = fido_cred_id_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_id_len(credential)))
.unwrap();

let public_key = fido_cred_pubkey_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_pubkey_len(credential)))
.unwrap();

let signature = fido_cred_sig_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_sig_len(credential)))
.unwrap();

let x509_certificate = fido_cred_x5c_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_x5c_len(credential)))
.unwrap();

CredentialRef {
format,
auth_data,
client_data_hash,
id,
public_key,
signature,
x509_certificate,
}
}
}

fn set_excluded(&mut self, excluded_ids: &[u8]) -> Result<()> {
unsafe {
match fido_cred_exclude(
self.0.raw.as_ptr_mut(),
self.raw.as_ptr_mut(),
excluded_ids as *const _ as *const _,
excluded_ids.len(),
) {
Expand All @@ -38,21 +155,19 @@ impl CredentialCreator {
}
}

/// # Remarks
/// - This method can only be called once and will return an error afterwards @TODO why?
pub fn set_type(&mut self, credential_type: CredentialType) -> Result<()> {
fn set_type(&mut self, credential_type: CredentialType) -> Result<()> {
unsafe {
match fido_cred_set_type(self.0.raw.as_ptr_mut(), credential_type as raw::c_int) {
match fido_cred_set_type(self.raw.as_ptr_mut(), credential_type as raw::c_int) {
FIDO_OK => Ok(()),
err => Err(FidoError(err)),
}
}
}

pub fn set_client_data_hash(&mut self, client_data_hash: &[u8]) -> Result<()> {
fn set_client_data_hash(&mut self, client_data_hash: &[u8]) -> Result<()> {
unsafe {
match fido_cred_set_clientdata_hash(
self.0.raw.as_ptr_mut(),
self.raw.as_ptr_mut(),
client_data_hash as *const _ as *const _,
client_data_hash.len(),
) {
Expand All @@ -62,60 +177,50 @@ impl CredentialCreator {
}
}

pub fn set_relying_party(&mut self, id: &CStr, name: &CStr) -> Result<()> {
fn set_relying_party(&mut self, id: &CStr, name: &CStr) -> Result<()> {
unsafe {
match fido_cred_set_rp(self.0.raw.as_ptr_mut(), id.as_ptr(), name.as_ptr()) {
match fido_cred_set_rp(self.raw.as_ptr_mut(), id.as_ptr(), name.as_ptr()) {
FIDO_OK => Ok(()),
err => Err(FidoError(err)),
}
}
}

pub fn set_user(
fn set_user(
&mut self,
user_id: &[u8],
name: &CStr,
display_name: Option<&CStr>,
account_image_uri: Option<&CStr>,
image_uri: Option<&CStr>,
) -> Result<()> {
unsafe {
match fido_cred_set_user(
self.0.raw.as_ptr_mut(),
self.raw.as_ptr_mut(),
user_id as *const _ as *const _,
user_id.len(),
name.as_ptr(),
display_name.map(CStr::as_ptr).unwrap_or(ptr::null()),
account_image_uri.map(CStr::as_ptr).unwrap_or(ptr::null()),
image_uri.map(CStr::as_ptr).unwrap_or(ptr::null()),
) {
FIDO_OK => Ok(()),
err => Err(FidoError(err)),
}
}
}

pub fn set_options(&mut self, options: CredentialOptions) -> Result<()> {
self.0.set_options(options)
}

pub fn set_extensions(&mut self, extensions: CredentialExtensions) -> Result<()> {
self.0.set_extensions(extensions)
}
}

impl CredentialVerifier {
pub fn set_format(&mut self, fmt: CredentialFormat) -> Result<()> {
fn set_format(&mut self, fmt: CredentialFormat) -> Result<()> {
unsafe {
match fido_cred_set_fmt(self.0.raw.as_ptr_mut(), fmt.to_ffi()) {
match fido_cred_set_fmt(self.raw.as_ptr_mut(), fmt.to_ffi()) {
FIDO_OK => Ok(()),
err => Err(FidoError(err)),
}
}
}

pub fn set_auth_data(&mut self, auth_data: &[u8]) -> Result<()> {
fn set_auth_data(&mut self, auth_data: &[u8]) -> Result<()> {
unsafe {
match fido_cred_set_authdata(
self.0.raw.as_ptr_mut(),
self.raw.as_ptr_mut(),
auth_data as *const _ as *const _,
auth_data.len(),
) {
Expand All @@ -125,10 +230,10 @@ impl CredentialVerifier {
}
}

pub fn set_x509_certificate(&mut self, x509_certificate: &[u8]) -> Result<()> {
fn set_x509_certificate(&mut self, x509_certificate: &[u8]) -> Result<()> {
unsafe {
match fido_cred_set_x509(
self.0.raw.as_ptr_mut(),
self.raw.as_ptr_mut(),
x509_certificate as *const _ as *const _,
x509_certificate.len(),
) {
Expand All @@ -138,10 +243,10 @@ impl CredentialVerifier {
}
}

pub fn set_signature(&mut self, signature: &[u8]) -> Result<()> {
fn set_signature(&mut self, signature: &[u8]) -> Result<()> {
unsafe {
match fido_cred_set_sig(
self.0.raw.as_ptr_mut(),
self.raw.as_ptr_mut(),
signature as *const _ as *const _,
signature.len(),
) {
Expand All @@ -151,67 +256,6 @@ impl CredentialVerifier {
}
}

pub fn set_options(&mut self, options: CredentialOptions) -> Result<()> {
self.0.set_options(options)
}

pub fn set_extensions(&mut self, extensions: CredentialExtensions) -> Result<()> {
self.0.set_extensions(extensions)
}
}

impl Credential {
pub fn as_ref<'a>(&'a self) -> CredentialRef<'a> {
unsafe {
let credential = self.raw.as_ptr();

let format = fido_cred_fmt(credential)
.as_ref()
.map(|ptr| CStr::from_ptr(ptr))
.unwrap();

let auth_data = fido_cred_authdata_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_authdata_len(credential)))
.unwrap();

let client_data_hash = fido_cred_clientdata_hash_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_clientdata_hash_len(credential)))
.unwrap();

let id = fido_cred_id_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_id_len(credential)))
.unwrap();

let public_key = fido_cred_pubkey_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_pubkey_len(credential)))
.unwrap();

let signature = fido_cred_sig_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_sig_len(credential)))
.unwrap();

let x509_certificate = fido_cred_x5c_ptr(credential)
.as_ref()
.map(|ptr| slice::from_raw_parts(ptr, fido_cred_x5c_len(credential)))
.unwrap();

CredentialRef {
format,
auth_data,
client_data_hash,
id,
public_key,
signature,
x509_certificate,
}
}
}

fn set_options(&mut self, options: CredentialOptions) -> Result<()> {
unsafe {
match fido_cred_set_options(
Expand Down
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,11 @@ impl Fido {
/// Creates a new [`CredentialCreator`].
///
/// [`CredentialCreator`]: struct.CredentialCreator.html
pub fn new_credential_creator(&self) -> CredentialCreator {
CredentialCreator(self.allocate_credential())
pub fn new_credential_creator(
&self,
data: CredentialCreationData<'_>,
) -> Result<CredentialCreator> {
CredentialCreator::new(self.allocate_credential(), data)
}

/// Creates a new [`CredentialVerifier`].
Expand Down

0 comments on commit 1cbc8b2

Please sign in to comment.