diff --git a/examples/lakers-c-native/main.c b/examples/lakers-c-native/main.c index fa765f1c..35b87549 100644 --- a/examples/lakers-c-native/main.c +++ b/examples/lakers-c-native/main.c @@ -112,9 +112,9 @@ int main(void) // lakers init puts("loading credentials."); - CredentialRPK cred_i = {0}, cred_r = {0}; - credential_rpk_new(&cred_i, CRED_I, 107); - credential_rpk_new(&cred_r, CRED_R, 84); + CredentialC cred_i = {0}, cred_r = {0}; + credential_new(&cred_i, CRED_I, 107); + credential_new(&cred_r, CRED_R, 84); puts("creating edhoc initiator."); EdhocInitiator initiator = {0}; initiator_new(&initiator); @@ -153,7 +153,7 @@ int main(void) memcpy(message_2.content, coap_response_payload, coap_response_payload_len); EADItemC ead_2 = {0}; uint8_t c_r; - CredentialRPK id_cred_r = {0}; + CredentialC id_cred_r = {0}; #ifdef LAKERS_EAD_AUTHZ // res = initiator_parse_message_2(&initiator, &message_2, &cred_r, &c_r, &id_cred_r, &ead_2); res = initiator_parse_message_2(&initiator, &message_2, &c_r, &id_cred_r, &ead_2); @@ -166,14 +166,15 @@ int main(void) return 1; } // FIXME: failing on native when cred_expected is NULL (memory allocation of 48 bytes failed) - res = credential_check_or_fetch(&cred_r, &id_cred_r); + CredentialC fetched_cred_r = {0}; + res = credential_check_or_fetch(&cred_r, &id_cred_r, &fetched_cred_r); if (res != 0) { printf("Error handling credential: %d\n", res); return 1; } #ifdef LAKERS_EAD_AUTHZ puts("processing ead2"); - res = authz_device_process_ead_2(&device, &ead_2, &id_cred_r); + res = authz_device_process_ead_2(&device, &ead_2, &fetched_cred_r); if (res != 0) { printf("Error process ead2 (authz): %d\n", res); return 1; @@ -181,7 +182,7 @@ int main(void) puts("ead-authz voucher received and validated"); } #endif - res = initiator_verify_message_2(&initiator, &I, &cred_i, &id_cred_r); + res = initiator_verify_message_2(&initiator, &I, &cred_i, &fetched_cred_r); if (res != 0) { printf("Error verify msg2: %d\n", res); return 1; diff --git a/lakers-c/cbindgen.toml b/lakers-c/cbindgen.toml index 3354f038..18aa3a1f 100644 --- a/lakers-c/cbindgen.toml +++ b/lakers-c/cbindgen.toml @@ -14,3 +14,8 @@ cpp_compat = true [parse.expand] all_features = true + +[export] +include = [ + "CredentialC" +] diff --git a/lakers-c/src/ead_authz.rs b/lakers-c/src/ead_authz.rs index 85feae2b..0d72715f 100644 --- a/lakers-c/src/ead_authz.rs +++ b/lakers-c/src/ead_authz.rs @@ -57,12 +57,13 @@ pub unsafe extern "C" fn authz_device_process_ead_2( // input parans device_c: *mut EadAuthzDevice, ead_2_c: *mut EADItemC, - cred_v: *mut CredentialRPK, + cred_v: *mut CredentialC, ) -> i8 { let crypto = &mut default_crypto(); let device = &(*device_c); let ead_2 = (*ead_2_c).to_rust(); - let cred_v = (*cred_v).value.as_slice(); + let cred_v = (*cred_v).to_rust(); + let cred_v = cred_v.bytes.as_slice(); match device.wait_ead2.process_ead_2(crypto, ead_2, cred_v) { Ok(device) => { (*device_c).done = device; diff --git a/lakers-c/src/initiator.rs b/lakers-c/src/initiator.rs index da99a4a3..3d3802b3 100644 --- a/lakers-c/src/initiator.rs +++ b/lakers-c/src/initiator.rs @@ -1,5 +1,5 @@ use lakers::{ - EdhocInitiator as EdhocInitiatorRust, // alias to conflict with the C-compatible struct + // EdhocInitiator as EdhocInitiatorRust, // alias to conflict with the C-compatible struct *, }; use lakers_crypto::{default_crypto, CryptoTrait}; @@ -15,7 +15,7 @@ pub struct EdhocInitiator { pub wait_m2: WaitM2, pub processing_m2: ProcessingM2C, pub processed_m2: ProcessedM2, - pub cred_i: *mut CredentialRPK, + pub cred_i: *mut CredentialC, pub completed: Completed, } @@ -86,7 +86,7 @@ pub unsafe extern "C" fn initiator_parse_message_2( message_2: *const EdhocMessageBuffer, // output params c_r_out: *mut u8, - id_cred_r_out: *mut CredentialRPK, + id_cred_r_out: *mut IdCred, ead_2_c_out: *mut EADItemC, ) -> i8 { // this is a parsing function, so all output parameters are mandatory @@ -129,8 +129,8 @@ pub unsafe extern "C" fn initiator_verify_message_2( // input params initiator_c: *mut EdhocInitiator, i: *const BytesP256ElemLen, - mut cred_i: *mut CredentialRPK, - valid_cred_r: *mut CredentialRPK, + cred_i: *mut CredentialC, + valid_cred_r: *mut CredentialC, ) -> i8 { if initiator_c.is_null() || i.is_null() { return -1; @@ -139,7 +139,7 @@ pub unsafe extern "C" fn initiator_verify_message_2( let state = core::ptr::read(&(*initiator_c).processing_m2).to_rust(); - match i_verify_message_2(&state, crypto, *valid_cred_r, &(*i)) { + match i_verify_message_2(&state, crypto, (*valid_cred_r).to_rust(), &(*i)) { Ok(state) => { (*initiator_c).processed_m2 = state; (*initiator_c).cred_i = cred_i; @@ -176,7 +176,7 @@ pub unsafe extern "C" fn initiator_prepare_message_3( match i_prepare_message_3( &state, crypto, - *(*initiator_c).cred_i, + (*(*initiator_c).cred_i).to_rust(), cred_transfer, &ead_3, ) { diff --git a/lakers-c/src/lib.rs b/lakers-c/src/lib.rs index 1476e30c..8cf80f79 100644 --- a/lakers-c/src/lib.rs +++ b/lakers-c/src/lib.rs @@ -59,6 +59,7 @@ pub struct ProcessingM2C { pub g_y: BytesP256ElemLen, pub plaintext_2: EdhocMessageBuffer, pub c_r: u8, + pub id_cred_r: IdCred, pub ead_2: *mut EADItemC, } @@ -72,6 +73,7 @@ impl Default for ProcessingM2C { g_y: Default::default(), plaintext_2: Default::default(), c_r: Default::default(), + id_cred_r: Default::default(), ead_2: core::ptr::null_mut(), } } @@ -87,6 +89,7 @@ impl ProcessingM2C { g_y: self.g_y, plaintext_2: self.plaintext_2, c_r: ConnId::from_int_raw(self.c_r), + id_cred_r: self.id_cred_r.clone(), ead_2: if self.ead_2.is_null() { None } else { @@ -110,19 +113,50 @@ impl ProcessingM2C { let c_r = processing_m2.c_r.as_slice(); assert_eq!(c_r.len(), 1, "C API only supports short C_R"); (*processing_m2_c).c_r = c_r[0]; + (*processing_m2_c).id_cred_r = processing_m2.id_cred_r; + } +} + +#[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] +pub struct CredentialC { + pub bytes: BufferCred, + pub key: CredentialKey, + /// differs from Rust: here we assume the kid is always present + /// this is to simplify the C API, since C doesn't support Option + /// the alternative would be to use a pointer, but then we need to care about memory management + pub kid: BufferKid, + pub cred_type: CredentialType, +} + +impl CredentialC { + pub fn to_rust(&self) -> Credential { + Credential { + bytes: self.bytes, + key: self.key, + kid: Some(self.kid), + cred_type: self.cred_type, + } + } + + pub unsafe fn copy_into_c(cred: Credential, cred_c: *mut CredentialC) { + (*cred_c).bytes = cred.bytes; + (*cred_c).key = cred.key; + (*cred_c).kid = cred.kid.unwrap(); + (*cred_c).cred_type = cred.cred_type; } } #[no_mangle] -pub unsafe extern "C" fn credential_rpk_new( - cred: *mut CredentialRPK, +pub unsafe extern "C" fn credential_new( + cred: *mut CredentialC, value: *const u8, value_len: usize, ) -> i8 { let value = core::slice::from_raw_parts(value, value_len); - match CredentialRPK::new(EdhocMessageBuffer::new_from_slice(value).unwrap()) { - Ok(cred_rpk) => { - *cred = cred_rpk; + match Credential::parse_ccs(value) { + Ok(cred_parsed) => { + CredentialC::copy_into_c(cred_parsed, cred); 0 } Err(_) => -1, @@ -131,19 +165,20 @@ pub unsafe extern "C" fn credential_rpk_new( #[no_mangle] pub unsafe extern "C" fn credential_check_or_fetch( - cred_expected: *mut CredentialRPK, - id_cred_received: *mut CredentialRPK, + cred_expected: *mut CredentialC, + id_cred_received: *mut IdCred, + cred_out: *mut CredentialC, ) -> i8 { let cred_expected = if cred_expected.is_null() { None } else { - Some(*cred_expected) + Some((*cred_expected).to_rust()) }; let id_cred_received_value = *id_cred_received; match credential_check_or_fetch_rust(cred_expected, id_cred_received_value) { Ok(valid_cred) => { - *id_cred_received = valid_cred; + CredentialC::copy_into_c(valid_cred, cred_out); 0 } Err(err) => err as i8, diff --git a/shared/cbindgen.toml b/shared/cbindgen.toml index e3392a2a..ff11b562 100644 --- a/shared/cbindgen.toml +++ b/shared/cbindgen.toml @@ -17,7 +17,10 @@ cpp_compat = true [export] include = [ "EdhocMessageBuffer", "BytesMac", "BytesMac2", - "EADItemC", "CredentialRPK", "CredentialTransfer", + "EADItemC", + "EdhocBuffer", "BufferKid", "BufferCred", "BufferIdCred", + "CredentialKey", "CredentialType", "IdCred", + "CredentialTransfer", "InitiatorStart", "WaitM2", "Completed", "ProcessedM2", "EdhocInitiatorC", "EdhocInitiatorWaitM2C", "EdhocInitiatorProcessingM2C", "EdhocInitiatorProcessedM2C", "EdhocInitiatorDoneC", ] diff --git a/shared/src/buffer.rs b/shared/src/buffer.rs index e4f60770..b60078b8 100644 --- a/shared/src/buffer.rs +++ b/shared/src/buffer.rs @@ -17,8 +17,8 @@ pub enum EdhocBufferError { /// so that in the future it can be hot-swappable by the application. // TODO: replace EdhocMessageBuffer with EdhocBuffer all over the library // NOTE: how would this const generic thing work across the C and Python bindings? -#[repr(C)] #[derive(PartialEq, Debug, Copy, Clone)] +#[repr(C)] pub struct EdhocBuffer { pub content: [u8; N], pub len: usize, diff --git a/shared/src/cred.rs b/shared/src/cred.rs index 700ff374..393816c9 100644 --- a/shared/src/cred.rs +++ b/shared/src/cred.rs @@ -7,6 +7,7 @@ pub type BytesKeyAES128 = [u8; 16]; pub type BytesKeyEC2 = [u8; 32]; #[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] pub enum CredentialKey { Symmetric(BytesKeyAES128), EC2Compact(BytesKeyEC2), @@ -14,6 +15,7 @@ pub enum CredentialKey { } #[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] pub enum CredentialType { CCS, #[allow(non_camel_case_types)] @@ -41,6 +43,7 @@ impl From for IdCredType { /// /// Possible values include key IDs, credentials by value and others. #[derive(Clone, Copy, Debug, Default, PartialEq)] +#[repr(C)] pub struct IdCred { /// The value is always stored in the ID_CRED_x form as a serialized one-element dictionary; /// while this technically wastes two bytes, it has the convenient property of having the full @@ -137,8 +140,8 @@ impl IdCred { /// Experimental support for CCS_PSK credentials is also available. // TODO: add back support for C and Python bindings #[cfg_attr(feature = "python-bindings", pyclass)] -// #[repr(C)] #[derive(Clone, Copy, Debug, PartialEq)] +#[repr(C)] pub struct Credential { /// Original bytes of the credential, CBOR-encoded ///