diff --git a/src/lib.rs b/src/lib.rs index 0cd7f3a..40cfd72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -31,5 +31,91 @@ mod manager; mod runloop; pub mod u2fprotocol; +use std::ptr; + pub use u2fprotocol::*; pub use manager::U2FManager as U2FManager; + +#[no_mangle] +pub extern "C" fn rust_u2f_mgr_new() -> *mut U2FManager { + let manager = U2FManager::new(); + Box::into_raw(Box::new(manager)) +} + +#[no_mangle] +pub unsafe extern "C" fn rust_u2f_mgr_free(ptr: *mut U2FManager) { + if !ptr.is_null() { + Box::from_raw(ptr); + } +} + +#[no_mangle] +pub unsafe extern "C" fn rust_u2f_mgr_register(ptr: *mut U2FManager, + timeout: u64, + challenge_ptr: *const u8, + challenge_len: usize, + application_ptr: *const u8, + application_len: usize, + registration_ptr: *mut u8, + registration_len: *mut usize, + max_registration_len: usize) { + if ptr.is_null() { + return; // TODO error + } + + let mut mgr = Box::from_raw(ptr); + let challenge = std::slice::from_raw_parts(challenge_ptr, challenge_len); + let application = std::slice::from_raw_parts(application_ptr, application_len); + + let res = mgr.register(timeout, challenge.to_vec(), application.to_vec()); + let _ = Box::into_raw(mgr); + + let res = match res { + Ok(rv) => rv, + _ => return // TODO error + }; + + if res.len() > max_registration_len { + return; // TODO error + } + + *registration_len = res.len(); + ptr::copy_nonoverlapping(res.as_ptr(), registration_ptr, res.len()); +} + +#[no_mangle] +pub unsafe extern "C" fn rust_u2f_mgr_sign(ptr: *mut U2FManager, + timeout: u64, + challenge_ptr: *const u8, + challenge_len: usize, + application_ptr: *const u8, + application_len: usize, + key_handle_ptr: *const u8, + key_handle_len: usize, + signature_ptr: *mut u8, + signature_len: *mut usize, + max_signature_len: usize) { + if ptr.is_null() { + return; // TODO error + } + + let mut mgr = Box::from_raw(ptr); + let challenge = std::slice::from_raw_parts(challenge_ptr, challenge_len); + let application = std::slice::from_raw_parts(application_ptr, application_len); + let key_handle = std::slice::from_raw_parts(key_handle_ptr, key_handle_len); + + let sig = mgr.sign(timeout, challenge.to_vec(), application.to_vec(), key_handle.to_vec()); + let _ = Box::into_raw(mgr); + + let sig = match sig { + Ok(rv) => rv, + _ => return // TODO error + }; + + if sig.len() > max_signature_len { + return; // TODO error + } + + *signature_len = sig.len(); + ptr::copy_nonoverlapping(sig.as_ptr(), signature_ptr, sig.len()); +} diff --git a/src/u2fhid-capi.h b/src/u2fhid-capi.h new file mode 100644 index 0000000..e22594c --- /dev/null +++ b/src/u2fhid-capi.h @@ -0,0 +1,35 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef __U2FHID_CAPI +#define __U2FHID_CAPI +#include +#include "nsString.h" + +extern "C" { + +// NOTE: Preconditions +// * All rust_u2f_mgr* pointers must refer to pointers which are returned +// by rust_u2f_mgr_new, and must be freed with rust_u2f_mgr_free. + +// The `rust_u2f_mgr` opaque type is equivalent to the rust type `::manager::U2FManager` +struct rust_u2f_mgr; + +rust_u2f_mgr* rust_u2f_mgr_new(); +/* unsafe */ void rust_u2f_mgr_free(rust_u2f_mgr* mgr); + +void rust_u2f_mgr_register(rust_u2f_mgr* mgr, uint64_t timeout, + const uint8_t* challenge_ptr, size_t challenge_len, + const uint8_t* application_ptr, size_t application_len, + uint8_t* registration_ptr, size_t* registration_len, size_t max_registration_len); + +void rust_u2f_mgr_sign(rust_u2f_mgr* mgr, uint64_t timeout, + const uint8_t* challenge_ptr, size_t challenge_len, + const uint8_t* application_ptr, size_t application_len, + const uint8_t* key_handle_ptr, size_t key_handle_len, + uint8_t* signature_ptr, size_t* signature_len, size_t max_signature_len); + +} + +#endif // __U2FHID_CAPI