Skip to content

Commit

Permalink
Add FFI call to fetch mTLS identities and to provision PIV slot (#56)
Browse files Browse the repository at this point in the history
* Add FFI call to fetch mTLS identities

* Add PIV util call

* Fix comment
  • Loading branch information
timweri authored Dec 16, 2024
1 parent 6a9dc76 commit 1993699
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 0 deletions.
30 changes: 30 additions & 0 deletions rustica-agent/src/ffi/enrollment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,33 @@ pub unsafe extern "C" fn generate_and_enroll(
error!("All servers failed to register key");
false
}

#[no_mangle]
// Provision a new nistp384 key in the given slot
pub unsafe extern "C" fn provision_piv(
yubikey_serial: u32,
slot: u8,
subject: *const c_char,
pin: *const c_char,
management_key: *const c_char,
) -> bool {
let alg = AlgorithmId::EccP384;
let slot = SlotId::try_from(slot).unwrap();

println!("Provisioning new PIV key in slot {:?}", slot);

let pin = CStr::from_ptr(pin);
let management_key = CStr::from_ptr(management_key);
let management_key = hex::decode(&management_key.to_str().unwrap()).unwrap();
let subject = CStr::from_ptr(subject);
let policy = TouchPolicy::Always;

let mut yk = Yubikey::open(yubikey_serial).unwrap();

if yk.unlock(pin.to_str().unwrap().as_bytes(), &management_key).is_err() {
println!("Could not unlock key");
return false
}

yk.provision(&slot, subject.to_str().unwrap(), alg, policy, PinPolicy::Never).is_ok()
}
4 changes: 4 additions & 0 deletions rustica-agent/src/ffi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod allowed_signer;
mod signing;
mod utils;
mod yubikey_utils;
mod mtls;

use std::ffi::{c_char, c_long, CStr};

Expand All @@ -25,6 +26,9 @@ pub use utils::*;
/// For functions that handle YubiKey specific functionality (generally PIV)
pub use yubikey_utils::*;

/// For functions that handle mTLS configs
pub use mtls::*;

use crate::config::UpdatableConfiguration;

#[no_mangle]
Expand Down
50 changes: 50 additions & 0 deletions rustica-agent/src/ffi/mtls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
use crate::config::UpdatableConfiguration;
use std::{ffi::{c_char, CStr, CString}, ptr::null};

#[no_mangle]
/// Read the mTLS identities of the primary server (the first one) given a config path
pub unsafe extern "C" fn ffi_get_identities_of_primary_server(config_path: *const c_char) -> *const c_char {
let cf = CStr::from_ptr(config_path);
let config_path = match cf.to_str() {
Err(_) => return null(),
Ok(s) => s,
};

let updatable_configuration = match UpdatableConfiguration::new(config_path) {

Ok(c) => c,
Err(e) => {
error!("Configuration was invalid: {e}");
return null();
}
};

let server = match updatable_configuration.get_configuration().servers.first() {
Some(s) => &s.mtls_cert,
None => return null(),
};

let cert = match x509_parser::pem::parse_x509_pem(server.as_bytes()) {
Err(e) => {
error!("Unable to parse mTLS cert PEM: {e}");
return null();
},
Ok((_, s)) => s,
};

let subject = match cert.parse_x509() {
Err(e) => {
error!("Unable to parse mTLS cert: {e}");
return null();
},
Ok(c) => c.tbs_certificate.subject().to_string(),
};

match CString::new(subject) {
Err(e) => {
error!("Unable to marshall subject to CString: {e}");
return null();
},
Ok(s) => s.into_raw(),
}
}

0 comments on commit 1993699

Please sign in to comment.