From 3cb8954687d4642b57118a538db2dfbf2899bf92 Mon Sep 17 00:00:00 2001 From: chrysn Date: Sat, 7 Oct 2023 16:35:21 +0200 Subject: [PATCH 1/8] refactor!: Move crypto operations into a trait. This is incomplete in two aspects: * it only adjusts the hacspec and psa crypto backends, and * it still goes through the edhoc-crypto crate to create import-based dispatch. It also does not do a full cargo-fmt, because this allows the delta of this commit to be small. --- Cargo.toml | 1 + crypto/Cargo.toml | 2 + .../edhoc-crypto-cryptocell310-sys/Cargo.toml | 1 + .../edhoc-crypto-cryptocell310-sys/src/lib.rs | 57 +++++----- crypto/edhoc-crypto-hacspec/Cargo.toml | 1 + crypto/edhoc-crypto-hacspec/src/lib.rs | 26 +++-- crypto/edhoc-crypto-psa/Cargo.toml | 1 + crypto/edhoc-crypto-psa/src/lib.rs | 102 ++++++++++-------- crypto/edhoc-crypto-trait/Cargo.toml | 7 ++ crypto/edhoc-crypto-trait/src/lib.rs | 31 ++++++ crypto/src/lib.rs | 27 ++++- examples/edhoc-rs-no_std/Cargo.toml | 1 + examples/edhoc-rs-no_std/src/main.rs | 9 +- lib/src/c_wrapper.rs | 4 +- lib/src/edhoc.rs | 30 +++--- lib/src/lib.rs | 13 +-- 16 files changed, 204 insertions(+), 109 deletions(-) create mode 100644 crypto/edhoc-crypto-trait/Cargo.toml create mode 100644 crypto/edhoc-crypto-trait/src/lib.rs diff --git a/Cargo.toml b/Cargo.toml index 37212ef4..0e16567f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "crypto/edhoc-crypto-hacspec", "crypto/edhoc-crypto-psa", "crypto/edhoc-crypto-cryptocell310-sys", + "crypto/edhoc-crypto-trait", "examples/coap", "examples/edhoc-rs-no_std", "examples/edhoc-rs-cc2538", diff --git a/crypto/Cargo.toml b/crypto/Cargo.toml index 7a27aa8c..2856c2fa 100644 --- a/crypto/Cargo.toml +++ b/crypto/Cargo.toml @@ -9,6 +9,8 @@ description = "EDHOC crypto library dispatch crate" [dependencies] edhoc-consts = { path = "../consts", default-features = false } +edhoc-crypto-trait.path = "./edhoc-crypto-trait" + # hacspec edhoc-crypto-hacspec = { path = "./edhoc-crypto-hacspec", optional = true } diff --git a/crypto/edhoc-crypto-cryptocell310-sys/Cargo.toml b/crypto/edhoc-crypto-cryptocell310-sys/Cargo.toml index 03739a11..239166fe 100644 --- a/crypto/edhoc-crypto-cryptocell310-sys/Cargo.toml +++ b/crypto/edhoc-crypto-cryptocell310-sys/Cargo.toml @@ -9,6 +9,7 @@ links = "nrf_cc310_0.9.13" [dependencies] edhoc-consts = { path = "../../consts" } +edhoc-crypto-trait.path = "../edhoc-crypto-trait" [build-dependencies] bindgen = "0.63.0" diff --git a/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs b/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs index be73d460..b4f51da3 100644 --- a/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs +++ b/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs @@ -8,6 +8,8 @@ include!(concat!(env!("OUT_DIR"), "/bindings.rs")); use core::ffi::c_void; use edhoc_consts::*; +use edhoc_crypto_trait::Crypto as CryptoTrait; + fn convert_array(input: &[u32]) -> [u8; SHA256_DIGEST_LEN] { assert!(input.len() == SHA256_DIGEST_LEN / 4); @@ -18,7 +20,11 @@ fn convert_array(input: &[u32]) -> [u8; SHA256_DIGEST_LEN] { output } -pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { +pub struct Crypto; + +impl CryptoTrait for Crypto { + +fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; unsafe { @@ -33,7 +39,7 @@ pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashL convert_array(&buffer[0..SHA256_DIGEST_LEN / 4]) } -pub fn hkdf_expand( +fn hkdf_expand( prk: &BytesHashLen, info: &BytesMaxInfoBuffer, info_len: usize, @@ -58,7 +64,7 @@ pub fn hkdf_expand( buffer } -pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { +fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { // Implementation of HKDF-Extract as per RFC 5869 // TODO generalize if salt is not provided @@ -67,7 +73,7 @@ pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen output } -pub fn aes_ccm_encrypt_tag_8( +fn aes_ccm_encrypt_tag_8( key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -104,7 +110,7 @@ pub fn aes_ccm_encrypt_tag_8( output } -pub fn aes_ccm_decrypt_tag_8( +fn aes_ccm_decrypt_tag_8( key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -142,7 +148,7 @@ pub fn aes_ccm_decrypt_tag_8( } } -pub fn p256_ecdh( +fn p256_ecdh( private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen, ) -> BytesP256ElemLen { @@ -195,24 +201,7 @@ pub fn p256_ecdh( output } -fn hmac_sha256(message: &mut [u8], mut key: [u8; SHA256_DIGEST_LEN]) -> BytesHashLen { - let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; - - unsafe { - CRYS_HMAC( - CRYS_HASH_OperationMode_t_CRYS_HASH_SHA256_mode, - key.as_mut_ptr(), - key.len() as u16, - message.as_mut_ptr(), - message.len(), - buffer.as_mut_ptr(), - ); - } - - convert_array(&buffer[..SHA256_DIGEST_LEN / 4]) -} - -pub fn get_random_byte() -> u8 { +fn get_random_byte() -> u8 { let mut rnd_context = CRYS_RND_State_t::default(); let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); unsafe { @@ -233,7 +222,7 @@ pub fn get_random_byte() -> u8 { buffer[0] } -pub fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { +fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { let mut rnd_context = CRYS_RND_State_t::default(); let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); unsafe { @@ -293,3 +282,21 @@ pub fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { (private_key, public_key) } +} + +fn hmac_sha256(message: &mut [u8], mut key: [u8; SHA256_DIGEST_LEN]) -> BytesHashLen { + let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; + + unsafe { + CRYS_HMAC( + CRYS_HASH_OperationMode_t_CRYS_HASH_SHA256_mode, + key.as_mut_ptr(), + key.len() as u16, + message.as_mut_ptr(), + message.len(), + buffer.as_mut_ptr(), + ); + } + + convert_array(&buffer[..SHA256_DIGEST_LEN / 4]) +} diff --git a/crypto/edhoc-crypto-hacspec/Cargo.toml b/crypto/edhoc-crypto-hacspec/Cargo.toml index df741064..1d4eda20 100644 --- a/crypto/edhoc-crypto-hacspec/Cargo.toml +++ b/crypto/edhoc-crypto-hacspec/Cargo.toml @@ -8,6 +8,7 @@ description = "EDHOC crypto library hacspec backend" [dependencies] edhoc-consts = { path = "../../consts", default-features = false } +edhoc-crypto-trait.path = "../edhoc-crypto-trait" hacspec-lib = { version = "0.1.0-beta.1", default-features = false } hacspec-p256 = { version = "0.1.0" } hacspec-hkdf = { version = "0.1.0" } diff --git a/crypto/edhoc-crypto-hacspec/src/lib.rs b/crypto/edhoc-crypto-hacspec/src/lib.rs index 350fe741..bc8dcb0e 100644 --- a/crypto/edhoc-crypto-hacspec/src/lib.rs +++ b/crypto/edhoc-crypto-hacspec/src/lib.rs @@ -9,6 +9,8 @@ use hacspec_p256::*; use hacspec_sha256::*; use rand::Rng; +use edhoc_crypto_trait::Crypto as CryptoTrait; + // Types and functions to aid in translation between the hacspec and non-hacspec world // TODO: the `array!` construct is not needed anymore. @@ -70,7 +72,11 @@ type BufferPlaintext3Hacspec = EdhocMessageBufferHacspec; // Public functions -pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { +pub struct Crypto; + +impl CryptoTrait for Crypto { + +fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { let message: BytesMaxBufferHacspec = BytesMaxBufferHacspec::from_public_slice(message); let output = @@ -79,7 +85,7 @@ pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashL output.to_public_array() } -pub fn hkdf_expand( +fn hkdf_expand( prk: &BytesHashLen, info: &BytesMaxInfoBuffer, info_len: usize, @@ -102,7 +108,7 @@ pub fn hkdf_expand( output.to_public_array() } -pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { +fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { let output = BytesHashLenHacspec::from_seq(&extract( &ByteSeq::from_slice(&BytesHashLenHacspec::from_public_slice(salt), 0, salt.len()), &ByteSeq::from_slice( @@ -114,7 +120,7 @@ pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen output.to_public_array() } -pub fn aes_ccm_encrypt_tag_8( +fn aes_ccm_encrypt_tag_8( key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -137,7 +143,7 @@ pub fn aes_ccm_encrypt_tag_8( output.to_public_buffer() } -pub fn aes_ccm_decrypt_tag_8( +fn aes_ccm_decrypt_tag_8( key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -162,7 +168,7 @@ pub fn aes_ccm_decrypt_tag_8( } } -pub fn p256_ecdh( +fn p256_ecdh( private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen, ) -> BytesP256ElemLen { @@ -184,12 +190,12 @@ pub fn p256_ecdh( } #[cfg(not(feature = "hacspec-pure"))] -pub fn get_random_byte() -> u8 { +fn get_random_byte() -> u8 { rand::thread_rng().gen::() } #[cfg(not(feature = "hacspec-pure"))] -pub fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { +fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { // generate a private key let mut private_key = BytesP256ElemLenHacspec::new(); loop { @@ -209,13 +215,15 @@ pub fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { (private_key.to_public_array(), public_key.to_public_array()) } +} + #[cfg(test)] mod tests { use super::*; #[test] fn test_p256_keys() { - let (x, g_x) = p256_generate_key_pair(); + let (x, g_x) = Crypto::p256_generate_key_pair(); assert_eq!(x.len(), 32); assert_eq!(g_x.len(), 32); diff --git a/crypto/edhoc-crypto-psa/Cargo.toml b/crypto/edhoc-crypto-psa/Cargo.toml index d3df8a5e..3f66bd25 100644 --- a/crypto/edhoc-crypto-psa/Cargo.toml +++ b/crypto/edhoc-crypto-psa/Cargo.toml @@ -8,6 +8,7 @@ description = "EDHOC crypto library PSA backend" [dependencies] edhoc-consts = { path = "../../consts" } +edhoc-crypto-trait.path = "../edhoc-crypto-trait" psa-crypto = { version = "0.9.2" } [features] diff --git a/crypto/edhoc-crypto-psa/src/lib.rs b/crypto/edhoc-crypto-psa/src/lib.rs index 938ba1dc..c5c8df94 100644 --- a/crypto/edhoc-crypto-psa/src/lib.rs +++ b/crypto/edhoc-crypto-psa/src/lib.rs @@ -7,6 +7,8 @@ use psa_crypto::types::algorithm::Hash; use psa_crypto::types::algorithm::{Aead, AeadWithDefaultLengthTag, KeyAgreement, RawKeyAgreement}; use psa_crypto::types::key::{Attributes, EccFamily, Lifetime, Policy, Type, UsageFlags}; +use edhoc_crypto_trait::Crypto as CryptoTrait; + #[no_mangle] pub extern "C" fn mbedtls_hardware_poll( data: *mut ::core::ffi::c_void, @@ -20,7 +22,11 @@ pub extern "C" fn mbedtls_hardware_poll( 0i32 } -pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { +pub struct Crypto; + +impl CryptoTrait for Crypto { + +fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { let hash_alg = Hash::Sha256; let mut hash: [u8; SHA256_DIGEST_LEN] = [0; SHA256_DIGEST_LEN]; psa_crypto::init().unwrap(); @@ -29,7 +35,9 @@ pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashL hash } -pub fn hkdf_expand( +// FIXME: Together with hkdf_extract, and the hmac_sha256 helper, this could be a provided +// function. +fn hkdf_expand( prk: &BytesHashLen, info: &BytesMaxInfoBuffer, info_len: usize, @@ -68,7 +76,7 @@ pub fn hkdf_expand( output } -pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { +fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { // Implementation of HKDF-Extract as per RFC 5869 // TODO generalize if salt is not provided @@ -77,7 +85,7 @@ pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen output } -pub fn aes_ccm_encrypt_tag_8( +fn aes_ccm_encrypt_tag_8( key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -118,7 +126,7 @@ pub fn aes_ccm_encrypt_tag_8( output_buffer } -pub fn aes_ccm_decrypt_tag_8( +fn aes_ccm_decrypt_tag_8( key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -161,7 +169,7 @@ pub fn aes_ccm_decrypt_tag_8( } } -pub fn p256_ecdh( +fn p256_ecdh( private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen, ) -> BytesP256ElemLen { @@ -193,7 +201,46 @@ pub fn p256_ecdh( output_buffer } -pub fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLen { +fn get_random_byte() -> u8 { + psa_crypto::init().unwrap(); + let mut buffer = [0u8; 1]; + generate_random(&mut buffer); // TODO: check return value + buffer[0] +} + +fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { + let alg = RawKeyAgreement::Ecdh; + let mut usage_flags: UsageFlags = UsageFlags::default(); + usage_flags.set_export(); + usage_flags.set_derive(); + let attributes = Attributes { + key_type: Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + }, + bits: 256, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags, + permitted_algorithms: KeyAgreement::Raw(alg).into(), + }, + }; + + psa_crypto::init().unwrap(); + + let key_id = key_management::generate(attributes, None).unwrap(); + let mut private_key: [u8; P256_ELEM_LEN] = [0; P256_ELEM_LEN]; + key_management::export(key_id, &mut private_key).unwrap(); + + let mut public_key: [u8; P256_ELEM_LEN * 2 + 1] = [0; P256_ELEM_LEN * 2 + 1]; // allocate buffer for: sign, x, and y coordinates + key_management::export_public(key_id, &mut public_key).unwrap(); + let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // return only the x coordinate + + (private_key, public_key) +} + +} + +fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLen { // implementation of HMAC as per RFC2104 const IPAD: [u8; 64] = [0x36; 64]; @@ -217,7 +264,7 @@ pub fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLe s2[64..64 + message.len()].copy_from_slice(message); // (4) apply H to the stream generated in step (3) - let ih = sha256_digest(&s2, 64 + message.len()); + let ih = Crypto::sha256_digest(&s2, 64 + message.len()); // (5) XOR (bitwise exclusive-OR) the B byte string computed in // step (1) with opad @@ -231,48 +278,11 @@ pub fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLe // (7) apply H to the stream generated in step (6) and output // the result - let oh = sha256_digest(&s5, 3 * SHA256_DIGEST_LEN); + let oh = Crypto::sha256_digest(&s5, 3 * SHA256_DIGEST_LEN); oh } -pub fn get_random_byte() -> u8 { - psa_crypto::init().unwrap(); - let mut buffer = [0u8; 1]; - generate_random(&mut buffer); // TODO: check return value - buffer[0] -} - -pub fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { - let alg = RawKeyAgreement::Ecdh; - let mut usage_flags: UsageFlags = UsageFlags::default(); - usage_flags.set_export(); - usage_flags.set_derive(); - let attributes = Attributes { - key_type: Type::EccKeyPair { - curve_family: EccFamily::SecpR1, - }, - bits: 256, - lifetime: Lifetime::Volatile, - policy: Policy { - usage_flags, - permitted_algorithms: KeyAgreement::Raw(alg).into(), - }, - }; - - psa_crypto::init().unwrap(); - - let key_id = key_management::generate(attributes, None).unwrap(); - let mut private_key: [u8; P256_ELEM_LEN] = [0; P256_ELEM_LEN]; - key_management::export(key_id, &mut private_key).unwrap(); - - let mut public_key: [u8; P256_ELEM_LEN * 2 + 1] = [0; P256_ELEM_LEN * 2 + 1]; // allocate buffer for: sign, x, and y coordinates - key_management::export_public(key_id, &mut public_key).unwrap(); - let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // return only the x coordinate - - (private_key, public_key) -} - #[cfg(test)] mod tests { use super::*; diff --git a/crypto/edhoc-crypto-trait/Cargo.toml b/crypto/edhoc-crypto-trait/Cargo.toml new file mode 100644 index 00000000..9f02aaba --- /dev/null +++ b/crypto/edhoc-crypto-trait/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "edhoc-crypto-trait" +version = "0.1.0" +edition = "2021" + +[dependencies] +edhoc-consts = { path = "../../consts", default-features = false } diff --git a/crypto/edhoc-crypto-trait/src/lib.rs b/crypto/edhoc-crypto-trait/src/lib.rs new file mode 100644 index 00000000..9863b7be --- /dev/null +++ b/crypto/edhoc-crypto-trait/src/lib.rs @@ -0,0 +1,31 @@ +//! Cryptography trait back-end for the edhoc-crypto crate +#![no_std] + +use edhoc_consts::*; + +pub trait Crypto { + fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen; + fn hkdf_expand( + prk: &BytesHashLen, + info: &BytesMaxInfoBuffer, + info_len: usize, + length: usize, + ) -> BytesMaxBuffer; + fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen; + fn aes_ccm_encrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + plaintext: &BufferPlaintext3, + ) -> BufferCiphertext3; + fn aes_ccm_decrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + ciphertext: &BufferCiphertext3, + ) -> Result; + fn p256_ecdh(private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen) + -> BytesP256ElemLen; + fn get_random_byte() -> u8; + fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen); +} diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index 5c300559..2ab28510 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -1,13 +1,34 @@ +//! Cryptography dispatch for the edhoc-rs crate +//! +//! This crate is used by edhoc-rs to decide which cryptographic back-end to use. Its presence +//! avoids the need for all edhoc-rs types to be generic over a back-end, which would then be +//! provided by the user at initialization time. On the long run, its type may turn into a +//! default associated type. #![no_std] +/// Convenience re-export +pub use edhoc_crypto_trait::Crypto as CryptoTrait; + #[cfg(feature = "hacspec")] -pub use edhoc_crypto_hacspec::*; +pub type Crypto = edhoc_crypto_hacspec::Crypto; +// FIXME: Does not work with crypto-as-trait yet #[cfg(feature = "cc2538")] pub use edhoc_crypto_cc2538::*; #[cfg(any(feature = "psa", feature = "psa-rust",))] -pub use edhoc_crypto_psa::*; +pub type Crypto = edhoc_crypto_psa::Crypto; #[cfg(any(feature = "cryptocell310", feature = "cryptocell310-rust"))] -pub use edhoc_crypto_cryptocell310::*; +pub type Crypto = edhoc_crypto_cryptocell310::Crypto; + +/// See test_implements_crypto +#[allow(dead_code)] +fn test_helper() {} + +/// Ensure at build time that whichever type as selected for Crypto actually implements the Crypto +/// trait, and that one is actually defined. +#[allow(dead_code)] +fn test_implements_crypto() { + test_helper::() +} diff --git a/examples/edhoc-rs-no_std/Cargo.toml b/examples/edhoc-rs-no_std/Cargo.toml index 99fac08e..eae4f8a5 100644 --- a/examples/edhoc-rs-no_std/Cargo.toml +++ b/examples/edhoc-rs-no_std/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] edhoc-rs = { path = "../../lib", default-features = false } +edhoc-crypto = { path = "../../crypto", default-features = false } hexlit = "0.5.3" # depend on an allocator diff --git a/examples/edhoc-rs-no_std/src/main.rs b/examples/edhoc-rs-no_std/src/main.rs index 6d543789..d6be5370 100644 --- a/examples/edhoc-rs-no_std/src/main.rs +++ b/examples/edhoc-rs-no_std/src/main.rs @@ -13,6 +13,7 @@ use panic_semihosting as _; #[cfg(feature = "rtt")] use rtt_target::{rprintln as println, rtt_init_print}; +use edhoc_crypto::{Crypto, CryptoTrait}; use edhoc_rs::*; extern crate alloc; @@ -80,11 +81,11 @@ fn main() -> ! { println!("Test test_new_initiator passed."); fn test_p256_keys() { - let (x, g_x) = p256_generate_key_pair(); - let (y, g_y) = p256_generate_key_pair(); + let (x, g_x) = Crypto::p256_generate_key_pair(); + let (y, g_y) = Crypto::p256_generate_key_pair(); - let g_xy = p256_ecdh(&x, &g_y); - let g_yx = p256_ecdh(&y, &g_x); + let g_xy = Crypto::p256_ecdh(&x, &g_y); + let g_yx = Crypto::p256_ecdh(&y, &g_x); assert_eq!(g_xy, g_yx); } diff --git a/lib/src/c_wrapper.rs b/lib/src/c_wrapper.rs index b22f672f..c394c7f1 100644 --- a/lib/src/c_wrapper.rs +++ b/lib/src/c_wrapper.rs @@ -3,6 +3,8 @@ use core::{slice, str}; use edhoc_consts::*; use hexlit::hex; +use edhoc_crypto::{Crypto, CryptoTrait}; + // Panic handler for cortex-m targets #[cfg(any(feature = "crypto-cryptocell310", feature = "crypto-psa-baremetal"))] use panic_semihosting as _; @@ -10,7 +12,7 @@ use panic_semihosting as _; // This function is mainly used to test the C wrapper #[no_mangle] pub extern "C" fn p256_generate_key_pair_from_c(out_private_key: *mut u8, out_public_key: *mut u8) { - let (private_key, public_key) = edhoc_crypto::p256_generate_key_pair(); + let (private_key, public_key) = Crypto::p256_generate_key_pair(); unsafe { // copy the arrays to the pointers received from C diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index 9a4dc799..8d6209f5 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -131,7 +131,7 @@ pub fn r_process_message_1( let mut message_1_buf: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; message_1_buf[..message_1.len] .copy_from_slice(&message_1.content[..message_1.len]); - h_message_1 = sha256_digest(&message_1_buf, message_1.len); + h_message_1 = Crypto::sha256_digest(&message_1_buf, message_1.len); error = EDHOCError::Success; current_state = EDHOCState::ProcessedMessage1; @@ -413,7 +413,7 @@ pub fn i_prepare_message_1( message_1_buf[..message_1.len].copy_from_slice(&message_1.content[..message_1.len]); // hash message_1 here to avoid saving the whole message in the state - h_message_1 = sha256_digest(&message_1_buf, message_1.len); + h_message_1 = Crypto::sha256_digest(&message_1_buf, message_1.len); error = EDHOCError::Success; current_state = EDHOCState::WaitMessage2; @@ -1004,7 +1004,7 @@ fn compute_th_2(g_y: &BytesP256ElemLen, h_message_1: &BytesHashLen) -> BytesHash let len = 4 + P256_ELEM_LEN + SHA256_DIGEST_LEN; - let th_2 = sha256_digest(&message, len); + let th_2 = Crypto::sha256_digest(&message, len); th_2 } @@ -1024,7 +1024,7 @@ fn compute_th_3( message[2 + th_2.len() + plaintext_2.len..2 + th_2.len() + plaintext_2.len + cred_r.len()] .copy_from_slice(cred_r); - let output = sha256_digest(&message, th_2.len() + 2 + plaintext_2.len + cred_r.len()); + let output = Crypto::sha256_digest(&message, th_2.len() + 2 + plaintext_2.len + cred_r.len()); output } @@ -1044,7 +1044,7 @@ fn compute_th_4( message[2 + th_3.len() + plaintext_3.len..2 + th_3.len() + plaintext_3.len + cred_i.len()] .copy_from_slice(cred_i); - let output = sha256_digest(&message, th_3.len() + 2 + plaintext_3.len + cred_i.len()); + let output = Crypto::sha256_digest(&message, th_3.len() + 2 + plaintext_3.len + cred_i.len()); output } @@ -1080,7 +1080,7 @@ fn edhoc_kdf( info_len = info_len + 2; } - let output = hkdf_expand(prk, &info, info_len, length); + let output = Crypto::hkdf_expand(prk, &info, info_len, length); output } @@ -1208,7 +1208,7 @@ fn encrypt_message_3( let (k_3, iv_3) = compute_k_3_iv_3(prk_3e2m, th_3); - let ciphertext_3 = aes_ccm_encrypt_tag_8(&k_3, &iv_3, &enc_structure, plaintext_3); + let ciphertext_3 = Crypto::aes_ccm_encrypt_tag_8(&k_3, &iv_3, &enc_structure, plaintext_3); output.content[1..output.len].copy_from_slice(&ciphertext_3.content[..ciphertext_3.len]); @@ -1234,7 +1234,7 @@ fn decrypt_message_3( let enc_structure = encode_enc_structure(th_3); - let p3 = aes_ccm_decrypt_tag_8(&k_3, &iv_3, &enc_structure, &ciphertext_3); + let p3 = Crypto::aes_ccm_decrypt_tag_8(&k_3, &iv_3, &enc_structure, &ciphertext_3); if p3.is_ok() { error = EDHOCError::Success; @@ -1429,8 +1429,8 @@ fn compute_prk_4e3m( g_y: &BytesP256ElemLen, ) -> BytesHashLen { // compute g_rx from static R's public key and private ephemeral key - let g_iy = p256_ecdh(i, g_y); - let prk_4e3m = hkdf_extract(salt_4e3m, &g_iy); + let g_iy = Crypto::p256_ecdh(i, g_y); + let prk_4e3m = Crypto::hkdf_extract(salt_4e3m, &g_iy); prk_4e3m } @@ -1459,8 +1459,8 @@ fn compute_prk_3e2m( g_r: &BytesP256ElemLen, ) -> BytesHashLen { // compute g_rx from static R's public key and private ephemeral key - let g_rx = p256_ecdh(x, g_r); - let prk_3e2m = hkdf_extract(salt_3e2m, &g_rx); + let g_rx = Crypto::p256_ecdh(x, g_r); + let prk_3e2m = Crypto::hkdf_extract(salt_3e2m, &g_rx); prk_3e2m } @@ -1471,9 +1471,9 @@ fn compute_prk_2e( th_2: &BytesHashLen, ) -> BytesHashLen { // compute the shared secret - let g_xy = p256_ecdh(x, g_y); + let g_xy = Crypto::p256_ecdh(x, g_y); // compute prk_2e as PRK_2e = HMAC-SHA-256( salt, G_XY ) - let prk_2e = hkdf_extract(th_2, &g_xy); + let prk_2e = Crypto::hkdf_extract(th_2, &g_xy); prk_2e } @@ -1590,7 +1590,7 @@ mod tests { #[test] fn test_ecdh() { - let g_xy = p256_ecdh(&X_TV, &G_Y_TV); + let g_xy = Crypto::p256_ecdh(&X_TV, &G_Y_TV); assert_eq!(g_xy, G_XY_TV); } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 19cc1ead..c5806ab4 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,8 +1,9 @@ #![cfg_attr(not(test), no_std)] pub use { - edhoc_consts::State as EdhocState, edhoc_consts::*, edhoc_crypto::*, - EdhocInitiatorState as EdhocInitiator, EdhocResponderState as EdhocResponder, + edhoc_consts::State as EdhocState, edhoc_consts::*, edhoc_crypto::Crypto, + edhoc_crypto::CryptoTrait, EdhocInitiatorState as EdhocInitiator, + EdhocResponderState as EdhocResponder, }; #[cfg(any(feature = "ead-none", feature = "ead-zeroconf"))] @@ -96,7 +97,7 @@ impl<'a> EdhocResponderState<'a> { self: &mut EdhocResponderState<'a>, c_r: u8, ) -> Result { - let (y, g_y) = edhoc_crypto::p256_generate_key_pair(); + let (y, g_y) = Crypto::p256_generate_key_pair(); match r_prepare_message_2( self.state, @@ -223,7 +224,7 @@ impl<'a> EdhocInitiatorState<'a> { self: &mut EdhocInitiatorState<'a>, c_i: u8, ) -> Result { - let (x, g_x) = edhoc_crypto::p256_generate_key_pair(); + let (x, g_x) = Crypto::p256_generate_key_pair(); match i_prepare_message_1(self.state, x, g_x, c_i) { Ok((state, message_1)) => { @@ -327,9 +328,9 @@ pub fn generate_connection_identifier_cbor() -> u8 { /// generates an identifier that can be serialized as a single CBOR integer, i.e. -24 <= x <= 23 pub fn generate_connection_identifier() -> i8 { - let mut conn_id = edhoc_crypto::get_random_byte() as i8; + let mut conn_id = Crypto::get_random_byte() as i8; while conn_id < -24 || conn_id > 23 { - conn_id = edhoc_crypto::get_random_byte() as i8; + conn_id = Crypto::get_random_byte() as i8; } conn_id } From 82d40fea7920fe3a4687e50babd0c11669da007f Mon Sep 17 00:00:00 2001 From: chrysn Date: Sat, 7 Oct 2023 16:57:03 +0200 Subject: [PATCH 2/8] chore: cargo fmt --- .../edhoc-crypto-cryptocell310-sys/src/lib.rs | 457 +++++++++--------- crypto/edhoc-crypto-hacspec/src/lib.rs | 236 +++++---- crypto/edhoc-crypto-psa/src/lib.rs | 396 +++++++-------- 3 files changed, 543 insertions(+), 546 deletions(-) diff --git a/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs b/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs index b4f51da3..9b09803c 100644 --- a/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs +++ b/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs @@ -23,265 +23,264 @@ fn convert_array(input: &[u32]) -> [u8; SHA256_DIGEST_LEN] { pub struct Crypto; impl CryptoTrait for Crypto { + fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; + + unsafe { + CRYS_HASH( + CRYS_HASH_OperationMode_t_CRYS_HASH_SHA256_mode, + message.clone().as_mut_ptr(), + message_len, + buffer.as_mut_ptr(), + ); + } -fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { - let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; - - unsafe { - CRYS_HASH( - CRYS_HASH_OperationMode_t_CRYS_HASH_SHA256_mode, - message.clone().as_mut_ptr(), - message_len, - buffer.as_mut_ptr(), - ); + convert_array(&buffer[0..SHA256_DIGEST_LEN / 4]) } - convert_array(&buffer[0..SHA256_DIGEST_LEN / 4]) -} + fn hkdf_expand( + prk: &BytesHashLen, + info: &BytesMaxInfoBuffer, + info_len: usize, + length: usize, + ) -> BytesMaxBuffer { + let mut buffer = [0x00u8; MAX_BUFFER_LEN]; + unsafe { + CRYS_HKDF_KeyDerivFunc( + CRYS_HKDF_HASH_OpMode_t_CRYS_HKDF_HASH_SHA256_mode, + core::ptr::null_mut(), + 0 as usize, + prk.clone().as_mut_ptr(), + prk.len() as u32, + info.clone().as_mut_ptr(), + info_len as u32, + buffer.as_mut_ptr(), + length as u32, + SaSiBool_SASI_TRUE, + ); + } -fn hkdf_expand( - prk: &BytesHashLen, - info: &BytesMaxInfoBuffer, - info_len: usize, - length: usize, -) -> BytesMaxBuffer { - let mut buffer = [0x00u8; MAX_BUFFER_LEN]; - unsafe { - CRYS_HKDF_KeyDerivFunc( - CRYS_HKDF_HASH_OpMode_t_CRYS_HKDF_HASH_SHA256_mode, - core::ptr::null_mut(), - 0 as usize, - prk.clone().as_mut_ptr(), - prk.len() as u32, - info.clone().as_mut_ptr(), - info_len as u32, - buffer.as_mut_ptr(), - length as u32, - SaSiBool_SASI_TRUE, - ); + buffer } - buffer -} - -fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { - // Implementation of HKDF-Extract as per RFC 5869 - - // TODO generalize if salt is not provided - let output = hmac_sha256(&mut ikm.clone()[..], *salt); - - output -} + fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { + // Implementation of HKDF-Extract as per RFC 5869 -fn aes_ccm_encrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &BytesEncStructureLen, - plaintext: &BufferPlaintext3, -) -> BufferCiphertext3 { - let mut output: BufferCiphertext3 = BufferCiphertext3::new(); - let mut tag: CRYS_AESCCM_Mac_Res_t = Default::default(); - let mut aesccm_key: CRYS_AESCCM_Key_t = Default::default(); - - aesccm_key[0..AES_CCM_KEY_LEN].copy_from_slice(&key[..]); - - let err = unsafe { - CC_AESCCM( - SaSiAesEncryptMode_t_SASI_AES_ENCRYPT, - aesccm_key.as_mut_ptr(), - CRYS_AESCCM_KeySize_t_CRYS_AES_Key128BitSize, - iv.clone().as_mut_ptr(), - iv.len() as u8, - ad.clone().as_mut_ptr(), - ad.len() as u32, - plaintext.content.clone().as_mut_ptr(), - plaintext.len as u32, - output.content.as_mut_ptr(), - AES_CCM_TAG_LEN as u8, // authentication tag length - tag.as_mut_ptr(), - 0 as u32, // CCM - ) - }; - - output.content[plaintext.len..plaintext.len + AES_CCM_TAG_LEN] - .copy_from_slice(&tag[..AES_CCM_TAG_LEN]); - output.len = plaintext.len + AES_CCM_TAG_LEN; + // TODO generalize if salt is not provided + let output = hmac_sha256(&mut ikm.clone()[..], *salt); - output -} - -fn aes_ccm_decrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &BytesEncStructureLen, - ciphertext: &BufferCiphertext3, -) -> Result { - let mut output: BufferPlaintext3 = BufferPlaintext3::new(); - let mut aesccm_key: CRYS_AESCCM_Key_t = Default::default(); - - aesccm_key[0..AES_CCM_KEY_LEN].copy_from_slice(&key[..]); + output + } - let mut err = EDHOCError::MacVerificationFailed; + fn aes_ccm_encrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + plaintext: &BufferPlaintext3, + ) -> BufferCiphertext3 { + let mut output: BufferCiphertext3 = BufferCiphertext3::new(); + let mut tag: CRYS_AESCCM_Mac_Res_t = Default::default(); + let mut aesccm_key: CRYS_AESCCM_Key_t = Default::default(); + + aesccm_key[0..AES_CCM_KEY_LEN].copy_from_slice(&key[..]); + + let err = unsafe { + CC_AESCCM( + SaSiAesEncryptMode_t_SASI_AES_ENCRYPT, + aesccm_key.as_mut_ptr(), + CRYS_AESCCM_KeySize_t_CRYS_AES_Key128BitSize, + iv.clone().as_mut_ptr(), + iv.len() as u8, + ad.clone().as_mut_ptr(), + ad.len() as u32, + plaintext.content.clone().as_mut_ptr(), + plaintext.len as u32, + output.content.as_mut_ptr(), + AES_CCM_TAG_LEN as u8, // authentication tag length + tag.as_mut_ptr(), + 0 as u32, // CCM + ) + }; + + output.content[plaintext.len..plaintext.len + AES_CCM_TAG_LEN] + .copy_from_slice(&tag[..AES_CCM_TAG_LEN]); + output.len = plaintext.len + AES_CCM_TAG_LEN; + + output + } - unsafe { - match CC_AESCCM( - SaSiAesEncryptMode_t_SASI_AES_DECRYPT, - aesccm_key.as_mut_ptr(), - CRYS_AESCCM_KeySize_t_CRYS_AES_Key128BitSize, - iv.clone().as_mut_ptr(), - iv.len() as u8, - ad.clone().as_mut_ptr(), - ad.len() as u32, - ciphertext.content.clone().as_mut_ptr(), - (ciphertext.len - AES_CCM_TAG_LEN) as u32, - output.content.as_mut_ptr(), - AES_CCM_TAG_LEN as u8, // authentication tag length - ciphertext.content.clone()[ciphertext.len - AES_CCM_TAG_LEN..].as_mut_ptr(), - 0 as u32, // CCM - ) { - CRYS_OK => { - output.len = ciphertext.len - AES_CCM_TAG_LEN; - Ok(output) + fn aes_ccm_decrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + ciphertext: &BufferCiphertext3, + ) -> Result { + let mut output: BufferPlaintext3 = BufferPlaintext3::new(); + let mut aesccm_key: CRYS_AESCCM_Key_t = Default::default(); + + aesccm_key[0..AES_CCM_KEY_LEN].copy_from_slice(&key[..]); + + let mut err = EDHOCError::MacVerificationFailed; + + unsafe { + match CC_AESCCM( + SaSiAesEncryptMode_t_SASI_AES_DECRYPT, + aesccm_key.as_mut_ptr(), + CRYS_AESCCM_KeySize_t_CRYS_AES_Key128BitSize, + iv.clone().as_mut_ptr(), + iv.len() as u8, + ad.clone().as_mut_ptr(), + ad.len() as u32, + ciphertext.content.clone().as_mut_ptr(), + (ciphertext.len - AES_CCM_TAG_LEN) as u32, + output.content.as_mut_ptr(), + AES_CCM_TAG_LEN as u8, // authentication tag length + ciphertext.content.clone()[ciphertext.len - AES_CCM_TAG_LEN..].as_mut_ptr(), + 0 as u32, // CCM + ) { + CRYS_OK => { + output.len = ciphertext.len - AES_CCM_TAG_LEN; + Ok(output) + } + _ => Err(EDHOCError::MacVerificationFailed), } - _ => Err(EDHOCError::MacVerificationFailed), } } -} - -fn p256_ecdh( - private_key: &BytesP256ElemLen, - public_key: &BytesP256ElemLen, -) -> BytesP256ElemLen { - let mut output = [0x0u8; P256_ELEM_LEN]; - let mut output_len: u32 = output.len() as u32; - let mut tmp: CRYS_ECDH_TempData_t = Default::default(); + fn p256_ecdh( + private_key: &BytesP256ElemLen, + public_key: &BytesP256ElemLen, + ) -> BytesP256ElemLen { + let mut output = [0x0u8; P256_ELEM_LEN]; + let mut output_len: u32 = output.len() as u32; + + let mut tmp: CRYS_ECDH_TempData_t = Default::default(); + + let mut public_key_compressed = [0x0u8; P256_ELEM_LEN + 1]; + public_key_compressed[0] = 0x02; + public_key_compressed[1..].copy_from_slice(&public_key[..]); + + let mut public_key_cc310: CRYS_ECPKI_UserPublKey_t = Default::default(); + + let mut domain = + unsafe { CRYS_ECPKI_GetEcDomain(CRYS_ECPKI_DomainID_t_CRYS_ECPKI_DomainID_secp256r1) }; + + unsafe { + _DX_ECPKI_BuildPublKey( + domain, + public_key_compressed.as_mut_ptr(), + (P256_ELEM_LEN + 1) as u32, + EC_PublKeyCheckMode_t_CheckPointersAndSizesOnly, + &mut public_key_cc310, + core::ptr::null_mut(), + ); + } - let mut public_key_compressed = [0x0u8; P256_ELEM_LEN + 1]; - public_key_compressed[0] = 0x02; - public_key_compressed[1..].copy_from_slice(&public_key[..]); + let mut private_key_cc310: CRYS_ECPKI_UserPrivKey_t = Default::default(); - let mut public_key_cc310: CRYS_ECPKI_UserPublKey_t = Default::default(); + unsafe { + CRYS_ECPKI_BuildPrivKey( + domain, + private_key.clone().as_mut_ptr(), + P256_ELEM_LEN as u32, + &mut private_key_cc310, + ); + } - let mut domain = - unsafe { CRYS_ECPKI_GetEcDomain(CRYS_ECPKI_DomainID_t_CRYS_ECPKI_DomainID_secp256r1) }; + unsafe { + CRYS_ECDH_SVDP_DH( + &mut public_key_cc310, + &mut private_key_cc310, + output.as_mut_ptr(), + &mut output_len, + &mut tmp, + ); + } - unsafe { - _DX_ECPKI_BuildPublKey( - domain, - public_key_compressed.as_mut_ptr(), - (P256_ELEM_LEN + 1) as u32, - EC_PublKeyCheckMode_t_CheckPointersAndSizesOnly, - &mut public_key_cc310, - core::ptr::null_mut(), - ); + output } - let mut private_key_cc310: CRYS_ECPKI_UserPrivKey_t = Default::default(); - - unsafe { - CRYS_ECPKI_BuildPrivKey( - domain, - private_key.clone().as_mut_ptr(), - P256_ELEM_LEN as u32, - &mut private_key_cc310, - ); - } - - unsafe { - CRYS_ECDH_SVDP_DH( - &mut public_key_cc310, - &mut private_key_cc310, - output.as_mut_ptr(), - &mut output_len, - &mut tmp, - ); + fn get_random_byte() -> u8 { + let mut rnd_context = CRYS_RND_State_t::default(); + let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); + unsafe { + SaSi_LibInit(); + CRYS_RndInit( + &mut rnd_context as *mut _ as *mut c_void, + &mut rnd_work_buffer as *mut _, + ); + } + let mut buffer = [0u8; 1]; + unsafe { + CRYS_RND_GenerateVector( + &mut rnd_context as *mut _ as *mut c_void, + 1, + buffer.as_mut_ptr(), + ); + } + buffer[0] } - output -} - -fn get_random_byte() -> u8 { - let mut rnd_context = CRYS_RND_State_t::default(); - let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); - unsafe { - SaSi_LibInit(); - CRYS_RndInit( - &mut rnd_context as *mut _ as *mut c_void, - &mut rnd_work_buffer as *mut _, - ); - } - let mut buffer = [0u8; 1]; - unsafe { - CRYS_RND_GenerateVector( - &mut rnd_context as *mut _ as *mut c_void, - 1, - buffer.as_mut_ptr(), - ); - } - buffer[0] -} + fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { + let mut rnd_context = CRYS_RND_State_t::default(); + let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); + unsafe { + SaSi_LibInit(); + CRYS_RndInit( + &mut rnd_context as *mut _ as *mut c_void, + &mut rnd_work_buffer as *mut _, + ); + } + let rnd_generate_vect_func: SaSiRndGenerateVectWorkFunc_t = Some(CRYS_RND_GenerateVector); + let mut curve_256 = + unsafe { CRYS_ECPKI_GetEcDomain(CRYS_ECPKI_DomainID_t_CRYS_ECPKI_DomainID_secp256r1) }; + let mut crys_private_key: *mut CRYS_ECPKI_UserPrivKey_t = + &mut CRYS_ECPKI_UserPrivKey_t::default(); + let mut crys_public_key: *mut CRYS_ECPKI_UserPublKey_t = + &mut CRYS_ECPKI_UserPublKey_t::default(); + let mut temp_data: *mut CRYS_ECPKI_KG_TempData_t = &mut CRYS_ECPKI_KG_TempData_t::default(); + let mut temp_fips_buffer: *mut CRYS_ECPKI_KG_FipsContext_t = + &mut CRYS_ECPKI_KG_FipsContext_t::default(); + + unsafe { + CRYS_ECPKI_GenKeyPair( + &mut rnd_context as *mut _ as *mut c_void, + rnd_generate_vect_func, + curve_256, + crys_private_key, + crys_public_key, + temp_data, + temp_fips_buffer, + ); + } -fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { - let mut rnd_context = CRYS_RND_State_t::default(); - let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); - unsafe { - SaSi_LibInit(); - CRYS_RndInit( - &mut rnd_context as *mut _ as *mut c_void, - &mut rnd_work_buffer as *mut _, - ); - } - let rnd_generate_vect_func: SaSiRndGenerateVectWorkFunc_t = Some(CRYS_RND_GenerateVector); - let mut curve_256 = - unsafe { CRYS_ECPKI_GetEcDomain(CRYS_ECPKI_DomainID_t_CRYS_ECPKI_DomainID_secp256r1) }; - let mut crys_private_key: *mut CRYS_ECPKI_UserPrivKey_t = - &mut CRYS_ECPKI_UserPrivKey_t::default(); - let mut crys_public_key: *mut CRYS_ECPKI_UserPublKey_t = - &mut CRYS_ECPKI_UserPublKey_t::default(); - let mut temp_data: *mut CRYS_ECPKI_KG_TempData_t = &mut CRYS_ECPKI_KG_TempData_t::default(); - let mut temp_fips_buffer: *mut CRYS_ECPKI_KG_FipsContext_t = - &mut CRYS_ECPKI_KG_FipsContext_t::default(); + let mut private_key: [u8; P256_ELEM_LEN] = [0x0; P256_ELEM_LEN]; + let mut key_size: u32 = P256_ELEM_LEN.try_into().unwrap(); - unsafe { - CRYS_ECPKI_GenKeyPair( - &mut rnd_context as *mut _ as *mut c_void, - rnd_generate_vect_func, - curve_256, - crys_private_key, - crys_public_key, - temp_data, - temp_fips_buffer, - ); - } + unsafe { + CRYS_ECPKI_ExportPrivKey(crys_private_key, private_key.as_mut_ptr(), &mut key_size); + } - let mut private_key: [u8; P256_ELEM_LEN] = [0x0; P256_ELEM_LEN]; - let mut key_size: u32 = P256_ELEM_LEN.try_into().unwrap(); + // let private_key = BytesP256ElemLen::from_public_slice(&private_key[..]); - unsafe { - CRYS_ECPKI_ExportPrivKey(crys_private_key, private_key.as_mut_ptr(), &mut key_size); - } + let mut public_key: [u8; P256_ELEM_LEN + 1] = [0x0; P256_ELEM_LEN + 1]; + let mut key_size: u32 = (P256_ELEM_LEN as u32) + 1; + let compressed_flag: CRYS_ECPKI_PointCompression_t = + CRYS_ECPKI_PointCompression_t_CRYS_EC_PointCompressed; - // let private_key = BytesP256ElemLen::from_public_slice(&private_key[..]); + unsafe { + CRYS_ECPKI_ExportPublKey( + crys_public_key, + compressed_flag, + public_key.as_mut_ptr(), + &mut key_size, + ); + } - let mut public_key: [u8; P256_ELEM_LEN + 1] = [0x0; P256_ELEM_LEN + 1]; - let mut key_size: u32 = (P256_ELEM_LEN as u32) + 1; - let compressed_flag: CRYS_ECPKI_PointCompression_t = - CRYS_ECPKI_PointCompression_t_CRYS_EC_PointCompressed; + let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // discard sign byte - unsafe { - CRYS_ECPKI_ExportPublKey( - crys_public_key, - compressed_flag, - public_key.as_mut_ptr(), - &mut key_size, - ); + (private_key, public_key) } - - let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // discard sign byte - - (private_key, public_key) -} } fn hmac_sha256(message: &mut [u8], mut key: [u8; SHA256_DIGEST_LEN]) -> BytesHashLen { diff --git a/crypto/edhoc-crypto-hacspec/src/lib.rs b/crypto/edhoc-crypto-hacspec/src/lib.rs index bc8dcb0e..f35b9372 100644 --- a/crypto/edhoc-crypto-hacspec/src/lib.rs +++ b/crypto/edhoc-crypto-hacspec/src/lib.rs @@ -75,146 +75,144 @@ type BufferPlaintext3Hacspec = EdhocMessageBufferHacspec; pub struct Crypto; impl CryptoTrait for Crypto { + fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + let message: BytesMaxBufferHacspec = BytesMaxBufferHacspec::from_public_slice(message); -fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { - let message: BytesMaxBufferHacspec = BytesMaxBufferHacspec::from_public_slice(message); + let output = + BytesHashLenHacspec::from_seq(&hash(&ByteSeq::from_slice(&message, 0, message_len))); - let output = - BytesHashLenHacspec::from_seq(&hash(&ByteSeq::from_slice(&message, 0, message_len))); + output.to_public_array() + } - output.to_public_array() -} + fn hkdf_expand( + prk: &BytesHashLen, + info: &BytesMaxInfoBuffer, + info_len: usize, + length: usize, + ) -> BytesMaxBuffer { + let mut output = BytesMaxBufferHacspec::new(); + output = output.update( + 0, + &expand( + &ByteSeq::from_slice(&BytesHashLenHacspec::from_public_slice(prk), 0, prk.len()), + &ByteSeq::from_slice( + &BytesMaxInfoBufferHacspec::from_public_slice(info), + 0, + info_len, + ), + length, + ) + .unwrap(), + ); + output.to_public_array() + } -fn hkdf_expand( - prk: &BytesHashLen, - info: &BytesMaxInfoBuffer, - info_len: usize, - length: usize, -) -> BytesMaxBuffer { - let mut output = BytesMaxBufferHacspec::new(); - output = output.update( - 0, - &expand( - &ByteSeq::from_slice(&BytesHashLenHacspec::from_public_slice(prk), 0, prk.len()), + fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { + let output = BytesHashLenHacspec::from_seq(&extract( + &ByteSeq::from_slice(&BytesHashLenHacspec::from_public_slice(salt), 0, salt.len()), &ByteSeq::from_slice( - &BytesMaxInfoBufferHacspec::from_public_slice(info), + &BytesP256ElemLenHacspec::from_public_slice(ikm), 0, - info_len, + ikm.len(), ), - length, - ) - .unwrap(), - ); - output.to_public_array() -} - -fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { - let output = BytesHashLenHacspec::from_seq(&extract( - &ByteSeq::from_slice(&BytesHashLenHacspec::from_public_slice(salt), 0, salt.len()), - &ByteSeq::from_slice( - &BytesP256ElemLenHacspec::from_public_slice(ikm), - 0, - ikm.len(), - ), - )); - output.to_public_array() -} + )); + output.to_public_array() + } -fn aes_ccm_encrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &BytesEncStructureLen, - plaintext: &BufferPlaintext3, -) -> BufferCiphertext3 { - let plaintext = BufferPlaintext3Hacspec::from_public_buffer(plaintext); - - let output = BufferCiphertext3Hacspec::from_seq(&encrypt_ccm( - ByteSeq::from_slice( - &BytesEncStructureLenHacspec::from_public_slice(ad), - 0, - ad.len(), - ), - ByteSeq::from_slice(&BytesCcmIvLenHacspec::from_public_slice(iv), 0, iv.len()), - ByteSeq::from_slice(&plaintext.content, 0, plaintext.len), - Key128::from_slice(&BytesCcmKeyLenHacspec::from_public_slice(key), 0, key.len()), - AES_CCM_TAG_LEN, - )); - - output.to_public_buffer() -} + fn aes_ccm_encrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + plaintext: &BufferPlaintext3, + ) -> BufferCiphertext3 { + let plaintext = BufferPlaintext3Hacspec::from_public_buffer(plaintext); + + let output = BufferCiphertext3Hacspec::from_seq(&encrypt_ccm( + ByteSeq::from_slice( + &BytesEncStructureLenHacspec::from_public_slice(ad), + 0, + ad.len(), + ), + ByteSeq::from_slice(&BytesCcmIvLenHacspec::from_public_slice(iv), 0, iv.len()), + ByteSeq::from_slice(&plaintext.content, 0, plaintext.len), + Key128::from_slice(&BytesCcmKeyLenHacspec::from_public_slice(key), 0, key.len()), + AES_CCM_TAG_LEN, + )); -fn aes_ccm_decrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &BytesEncStructureLen, - ciphertext: &BufferCiphertext3, -) -> Result { - let ciphertext = BufferCiphertext3Hacspec::from_public_buffer(ciphertext); - - match decrypt_ccm( - ByteSeq::from_slice( - &BytesEncStructureLenHacspec::from_public_slice(ad), - 0, - ad.len(), - ), - ByteSeq::from_slice(&BytesCcmIvLenHacspec::from_public_slice(iv), 0, iv.len()), - Key128::from_slice(&BytesCcmKeyLenHacspec::from_public_slice(key), 0, key.len()), - ByteSeq::from_slice(&ciphertext.content, 0, ciphertext.len), - ciphertext.len, - AES_CCM_TAG_LEN, - ) { - Ok(p) => Ok(BufferPlaintext3Hacspec::from_seq(&p).to_public_buffer()), - Err(_) => Err(EDHOCError::MacVerificationFailed), + output.to_public_buffer() } -} -fn p256_ecdh( - private_key: &BytesP256ElemLen, - public_key: &BytesP256ElemLen, -) -> BytesP256ElemLen { - let private_key = BytesP256ElemLenHacspec::from_public_slice(private_key); - let public_key = BytesP256ElemLenHacspec::from_public_slice(public_key); + fn aes_ccm_decrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + ciphertext: &BufferCiphertext3, + ) -> Result { + let ciphertext = BufferCiphertext3Hacspec::from_public_buffer(ciphertext); + + match decrypt_ccm( + ByteSeq::from_slice( + &BytesEncStructureLenHacspec::from_public_slice(ad), + 0, + ad.len(), + ), + ByteSeq::from_slice(&BytesCcmIvLenHacspec::from_public_slice(iv), 0, iv.len()), + Key128::from_slice(&BytesCcmKeyLenHacspec::from_public_slice(key), 0, key.len()), + ByteSeq::from_slice(&ciphertext.content, 0, ciphertext.len), + ciphertext.len, + AES_CCM_TAG_LEN, + ) { + Ok(p) => Ok(BufferPlaintext3Hacspec::from_seq(&p).to_public_buffer()), + Err(_) => Err(EDHOCError::MacVerificationFailed), + } + } - let scalar = P256Scalar::from_byte_seq_be(&private_key); - let point = ( - P256FieldElement::from_byte_seq_be(&public_key), - p256_calculate_w(P256FieldElement::from_byte_seq_be(&public_key)), - ); + fn p256_ecdh( + private_key: &BytesP256ElemLen, + public_key: &BytesP256ElemLen, + ) -> BytesP256ElemLen { + let private_key = BytesP256ElemLenHacspec::from_public_slice(private_key); + let public_key = BytesP256ElemLenHacspec::from_public_slice(public_key); - // we only care about the x coordinate - let (x, _y) = p256_point_mul(scalar, point).unwrap(); + let scalar = P256Scalar::from_byte_seq_be(&private_key); + let point = ( + P256FieldElement::from_byte_seq_be(&public_key), + p256_calculate_w(P256FieldElement::from_byte_seq_be(&public_key)), + ); - let secret = BytesP256ElemLenHacspec::from_seq(&x.to_byte_seq_be()); + // we only care about the x coordinate + let (x, _y) = p256_point_mul(scalar, point).unwrap(); - secret.to_public_array() -} + let secret = BytesP256ElemLenHacspec::from_seq(&x.to_byte_seq_be()); -#[cfg(not(feature = "hacspec-pure"))] -fn get_random_byte() -> u8 { - rand::thread_rng().gen::() -} + secret.to_public_array() + } -#[cfg(not(feature = "hacspec-pure"))] -fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { - // generate a private key - let mut private_key = BytesP256ElemLenHacspec::new(); - loop { - for i in 0..private_key.len() { - private_key[i] = U8(rand::thread_rng().gen::()); - } - if p256_validate_private_key(&ByteSeq::from_slice(&private_key, 0, private_key.len())) { - break; - } + #[cfg(not(feature = "hacspec-pure"))] + fn get_random_byte() -> u8 { + rand::thread_rng().gen::() } - // obtain the corresponding public key - let scalar = P256Scalar::from_byte_seq_be(&private_key); - let public_key_point = p256_point_mul_base(scalar).unwrap(); - let public_key = BytesP256ElemLenHacspec::from_seq(&public_key_point.0.to_byte_seq_be()); + #[cfg(not(feature = "hacspec-pure"))] + fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { + // generate a private key + let mut private_key = BytesP256ElemLenHacspec::new(); + loop { + for i in 0..private_key.len() { + private_key[i] = U8(rand::thread_rng().gen::()); + } + if p256_validate_private_key(&ByteSeq::from_slice(&private_key, 0, private_key.len())) { + break; + } + } - (private_key.to_public_array(), public_key.to_public_array()) -} + // obtain the corresponding public key + let scalar = P256Scalar::from_byte_seq_be(&private_key); + let public_key_point = p256_point_mul_base(scalar).unwrap(); + let public_key = BytesP256ElemLenHacspec::from_seq(&public_key_point.0.to_byte_seq_be()); + (private_key.to_public_array(), public_key.to_public_array()) + } } #[cfg(test)] diff --git a/crypto/edhoc-crypto-psa/src/lib.rs b/crypto/edhoc-crypto-psa/src/lib.rs index c5c8df94..2c54d925 100644 --- a/crypto/edhoc-crypto-psa/src/lib.rs +++ b/crypto/edhoc-crypto-psa/src/lib.rs @@ -25,219 +25,219 @@ pub extern "C" fn mbedtls_hardware_poll( pub struct Crypto; impl CryptoTrait for Crypto { + fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + let hash_alg = Hash::Sha256; + let mut hash: [u8; SHA256_DIGEST_LEN] = [0; SHA256_DIGEST_LEN]; + psa_crypto::init().unwrap(); + hash_compute(hash_alg, &message[..message_len], &mut hash).unwrap(); -fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { - let hash_alg = Hash::Sha256; - let mut hash: [u8; SHA256_DIGEST_LEN] = [0; SHA256_DIGEST_LEN]; - psa_crypto::init().unwrap(); - hash_compute(hash_alg, &message[..message_len], &mut hash).unwrap(); - - hash -} - -// FIXME: Together with hkdf_extract, and the hmac_sha256 helper, this could be a provided -// function. -fn hkdf_expand( - prk: &BytesHashLen, - info: &BytesMaxInfoBuffer, - info_len: usize, - length: usize, -) -> BytesMaxBuffer { - // Implementation of HKDF-Expand as per RFC5869 - - let mut output: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; - - let mut n = 0; - - // N = ceil(L/HashLen) - if length % SHA256_DIGEST_LEN == 0 { - n = length / SHA256_DIGEST_LEN; - } else { - n = length / SHA256_DIGEST_LEN + 1; + hash } - let mut message: [u8; MAX_INFO_LEN + SHA256_DIGEST_LEN + 1] = - [0; MAX_INFO_LEN + SHA256_DIGEST_LEN + 1]; - message[..info_len].copy_from_slice(&info[..info_len]); - message[info_len] = 0x01; - let mut t_i = hmac_sha256(&message[..info_len + 1], prk); - output[..SHA256_DIGEST_LEN].copy_from_slice(&t_i); - - for i in 2..n { - message[..SHA256_DIGEST_LEN].copy_from_slice(&t_i); - message[SHA256_DIGEST_LEN..SHA256_DIGEST_LEN + info_len].copy_from_slice(&info[..info_len]); - message[SHA256_DIGEST_LEN + info_len] = i as u8; - t_i = hmac_sha256(&message[..SHA256_DIGEST_LEN + info_len + 1], prk); - output[i * SHA256_DIGEST_LEN..(i + 1) * SHA256_DIGEST_LEN].copy_from_slice(&t_i); - } + // FIXME: Together with hkdf_extract, and the hmac_sha256 helper, this could be a provided + // function. + fn hkdf_expand( + prk: &BytesHashLen, + info: &BytesMaxInfoBuffer, + info_len: usize, + length: usize, + ) -> BytesMaxBuffer { + // Implementation of HKDF-Expand as per RFC5869 + + let mut output: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; + + let mut n = 0; + + // N = ceil(L/HashLen) + if length % SHA256_DIGEST_LEN == 0 { + n = length / SHA256_DIGEST_LEN; + } else { + n = length / SHA256_DIGEST_LEN + 1; + } - output[length..].fill(0x00); + let mut message: [u8; MAX_INFO_LEN + SHA256_DIGEST_LEN + 1] = + [0; MAX_INFO_LEN + SHA256_DIGEST_LEN + 1]; + message[..info_len].copy_from_slice(&info[..info_len]); + message[info_len] = 0x01; + let mut t_i = hmac_sha256(&message[..info_len + 1], prk); + output[..SHA256_DIGEST_LEN].copy_from_slice(&t_i); + + for i in 2..n { + message[..SHA256_DIGEST_LEN].copy_from_slice(&t_i); + message[SHA256_DIGEST_LEN..SHA256_DIGEST_LEN + info_len] + .copy_from_slice(&info[..info_len]); + message[SHA256_DIGEST_LEN + info_len] = i as u8; + t_i = hmac_sha256(&message[..SHA256_DIGEST_LEN + info_len + 1], prk); + output[i * SHA256_DIGEST_LEN..(i + 1) * SHA256_DIGEST_LEN].copy_from_slice(&t_i); + } - output -} + output[length..].fill(0x00); -fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { - // Implementation of HKDF-Extract as per RFC 5869 + output + } - // TODO generalize if salt is not provided - let output = hmac_sha256(ikm, salt); + fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { + // Implementation of HKDF-Extract as per RFC 5869 - output -} + // TODO generalize if salt is not provided + let output = hmac_sha256(ikm, salt); -fn aes_ccm_encrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &BytesEncStructureLen, - plaintext: &BufferPlaintext3, -) -> BufferCiphertext3 { - psa_crypto::init().unwrap(); - - let alg = Aead::AeadWithShortenedTag { - aead_alg: AeadWithDefaultLengthTag::Ccm, - tag_length: 8, - }; - let mut usage_flags: UsageFlags = Default::default(); - usage_flags.set_encrypt(); - - let attributes = Attributes { - key_type: Type::Aes, - bits: 128, - lifetime: Lifetime::Volatile, - policy: Policy { - usage_flags, - permitted_algorithms: alg.into(), - }, - }; - let my_key = key_management::import(attributes, None, &key[..]).unwrap(); - let mut output_buffer: BufferCiphertext3 = BufferCiphertext3::new(); - - aead::encrypt( - my_key, - alg, - iv, - ad, - &plaintext.content[..plaintext.len], - &mut output_buffer.content, - ) - .unwrap(); - - output_buffer.len = plaintext.len + AES_CCM_TAG_LEN; - output_buffer -} + output + } -fn aes_ccm_decrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &BytesEncStructureLen, - ciphertext: &BufferCiphertext3, -) -> Result { - psa_crypto::init().unwrap(); - - let alg = Aead::AeadWithShortenedTag { - aead_alg: AeadWithDefaultLengthTag::Ccm, - tag_length: 8, - }; - let mut usage_flags: UsageFlags = Default::default(); - usage_flags.set_decrypt(); - - let attributes = Attributes { - key_type: Type::Aes, - bits: 128, - lifetime: Lifetime::Volatile, - policy: Policy { - usage_flags, - permitted_algorithms: alg.into(), - }, - }; - let my_key = key_management::import(attributes, None, &key[..]).unwrap(); - let mut output_buffer: BufferPlaintext3 = BufferPlaintext3::new(); - - match aead::decrypt( - my_key, - alg, - iv, - ad, - &ciphertext.content[..ciphertext.len], - &mut output_buffer.content, - ) { - Ok(_) => { - output_buffer.len = ciphertext.len - AES_CCM_TAG_LEN; - Ok(output_buffer) - } - Err(_) => Err(EDHOCError::MacVerificationFailed), + fn aes_ccm_encrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + plaintext: &BufferPlaintext3, + ) -> BufferCiphertext3 { + psa_crypto::init().unwrap(); + + let alg = Aead::AeadWithShortenedTag { + aead_alg: AeadWithDefaultLengthTag::Ccm, + tag_length: 8, + }; + let mut usage_flags: UsageFlags = Default::default(); + usage_flags.set_encrypt(); + + let attributes = Attributes { + key_type: Type::Aes, + bits: 128, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags, + permitted_algorithms: alg.into(), + }, + }; + let my_key = key_management::import(attributes, None, &key[..]).unwrap(); + let mut output_buffer: BufferCiphertext3 = BufferCiphertext3::new(); + + aead::encrypt( + my_key, + alg, + iv, + ad, + &plaintext.content[..plaintext.len], + &mut output_buffer.content, + ) + .unwrap(); + + output_buffer.len = plaintext.len + AES_CCM_TAG_LEN; + output_buffer } -} -fn p256_ecdh( - private_key: &BytesP256ElemLen, - public_key: &BytesP256ElemLen, -) -> BytesP256ElemLen { - let mut peer_public_key: [u8; 33] = [0; 33]; - peer_public_key[0] = 0x02; // sign does not matter for ECDH operation - peer_public_key[1..33].copy_from_slice(&public_key[..]); - - let alg = RawKeyAgreement::Ecdh; - let mut usage_flags: UsageFlags = Default::default(); - usage_flags.set_derive(); - let attributes = Attributes { - key_type: Type::EccKeyPair { - curve_family: EccFamily::SecpR1, - }, - bits: 256, - lifetime: Lifetime::Volatile, - policy: Policy { - usage_flags, - permitted_algorithms: KeyAgreement::Raw(alg).into(), - }, - }; - - psa_crypto::init().unwrap(); - let my_key = key_management::import(attributes, None, private_key).unwrap(); - let mut output_buffer: [u8; P256_ELEM_LEN] = [0; P256_ELEM_LEN]; - - key_agreement::raw_key_agreement(alg, my_key, &peer_public_key, &mut output_buffer).unwrap(); - - output_buffer -} + fn aes_ccm_decrypt_tag_8( + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &BytesEncStructureLen, + ciphertext: &BufferCiphertext3, + ) -> Result { + psa_crypto::init().unwrap(); + + let alg = Aead::AeadWithShortenedTag { + aead_alg: AeadWithDefaultLengthTag::Ccm, + tag_length: 8, + }; + let mut usage_flags: UsageFlags = Default::default(); + usage_flags.set_decrypt(); + + let attributes = Attributes { + key_type: Type::Aes, + bits: 128, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags, + permitted_algorithms: alg.into(), + }, + }; + let my_key = key_management::import(attributes, None, &key[..]).unwrap(); + let mut output_buffer: BufferPlaintext3 = BufferPlaintext3::new(); + + match aead::decrypt( + my_key, + alg, + iv, + ad, + &ciphertext.content[..ciphertext.len], + &mut output_buffer.content, + ) { + Ok(_) => { + output_buffer.len = ciphertext.len - AES_CCM_TAG_LEN; + Ok(output_buffer) + } + Err(_) => Err(EDHOCError::MacVerificationFailed), + } + } -fn get_random_byte() -> u8 { - psa_crypto::init().unwrap(); - let mut buffer = [0u8; 1]; - generate_random(&mut buffer); // TODO: check return value - buffer[0] -} + fn p256_ecdh( + private_key: &BytesP256ElemLen, + public_key: &BytesP256ElemLen, + ) -> BytesP256ElemLen { + let mut peer_public_key: [u8; 33] = [0; 33]; + peer_public_key[0] = 0x02; // sign does not matter for ECDH operation + peer_public_key[1..33].copy_from_slice(&public_key[..]); + + let alg = RawKeyAgreement::Ecdh; + let mut usage_flags: UsageFlags = Default::default(); + usage_flags.set_derive(); + let attributes = Attributes { + key_type: Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + }, + bits: 256, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags, + permitted_algorithms: KeyAgreement::Raw(alg).into(), + }, + }; + + psa_crypto::init().unwrap(); + let my_key = key_management::import(attributes, None, private_key).unwrap(); + let mut output_buffer: [u8; P256_ELEM_LEN] = [0; P256_ELEM_LEN]; + + key_agreement::raw_key_agreement(alg, my_key, &peer_public_key, &mut output_buffer) + .unwrap(); + + output_buffer + } -fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { - let alg = RawKeyAgreement::Ecdh; - let mut usage_flags: UsageFlags = UsageFlags::default(); - usage_flags.set_export(); - usage_flags.set_derive(); - let attributes = Attributes { - key_type: Type::EccKeyPair { - curve_family: EccFamily::SecpR1, - }, - bits: 256, - lifetime: Lifetime::Volatile, - policy: Policy { - usage_flags, - permitted_algorithms: KeyAgreement::Raw(alg).into(), - }, - }; - - psa_crypto::init().unwrap(); - - let key_id = key_management::generate(attributes, None).unwrap(); - let mut private_key: [u8; P256_ELEM_LEN] = [0; P256_ELEM_LEN]; - key_management::export(key_id, &mut private_key).unwrap(); - - let mut public_key: [u8; P256_ELEM_LEN * 2 + 1] = [0; P256_ELEM_LEN * 2 + 1]; // allocate buffer for: sign, x, and y coordinates - key_management::export_public(key_id, &mut public_key).unwrap(); - let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // return only the x coordinate - - (private_key, public_key) -} + fn get_random_byte() -> u8 { + psa_crypto::init().unwrap(); + let mut buffer = [0u8; 1]; + generate_random(&mut buffer); // TODO: check return value + buffer[0] + } + fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { + let alg = RawKeyAgreement::Ecdh; + let mut usage_flags: UsageFlags = UsageFlags::default(); + usage_flags.set_export(); + usage_flags.set_derive(); + let attributes = Attributes { + key_type: Type::EccKeyPair { + curve_family: EccFamily::SecpR1, + }, + bits: 256, + lifetime: Lifetime::Volatile, + policy: Policy { + usage_flags, + permitted_algorithms: KeyAgreement::Raw(alg).into(), + }, + }; + + psa_crypto::init().unwrap(); + + let key_id = key_management::generate(attributes, None).unwrap(); + let mut private_key: [u8; P256_ELEM_LEN] = [0; P256_ELEM_LEN]; + key_management::export(key_id, &mut private_key).unwrap(); + + let mut public_key: [u8; P256_ELEM_LEN * 2 + 1] = [0; P256_ELEM_LEN * 2 + 1]; // allocate buffer for: sign, x, and y coordinates + key_management::export_public(key_id, &mut public_key).unwrap(); + let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // return only the x coordinate + + (private_key, public_key) + } } fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLen { From 717abb11b57bf91020efa41b8c643c9d426e968e Mon Sep 17 00:00:00 2001 From: chrysn Date: Sun, 8 Oct 2023 10:51:13 +0200 Subject: [PATCH 3/8] refactor: Use explicit imports now that they're few --- lib/src/edhoc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index 8d6209f5..eacb4f52 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -1,7 +1,7 @@ #![no_std] use edhoc_consts::*; -use edhoc_crypto::*; +use edhoc_crypto::{Crypto, CryptoTrait}; use edhoc_ead::*; pub fn edhoc_exporter( From e26e51317da082c99c84f276ca6bf06a4688d3b5 Mon Sep 17 00:00:00 2001 From: chrysn Date: Sun, 8 Oct 2023 20:36:48 +0200 Subject: [PATCH 4/8] fix!: Make edhoc.rs generic over crypto implementation This is likely not a final version, as it is terribly verbose. The verbosity would be mitigated if the functions were methods of their states, as then, it would be concentrated atop the impl blocks. It is also incomplete in that it merely shifts the cfg-switched Crypto implementation from being referenced in edhdoc.rs to being referenced in lib.rs, instead of making the latter generic as well. --- lib/Cargo.toml | 1 + lib/src/edhoc.rs | 166 ++++++++++++++++++++++++----------------------- lib/src/lib.rs | 20 +++--- 3 files changed, 95 insertions(+), 92 deletions(-) diff --git a/lib/Cargo.toml b/lib/Cargo.toml index d782b7e6..3514bbbc 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -12,6 +12,7 @@ hex = { version = "0.4.3", default-features = false } hacspec-lib = { version = "0.1.0-beta.1", default-features = false, optional = true } edhoc-crypto = { path = "../crypto", default-features = false } +edhoc-crypto-trait = { path = "../crypto/edhoc-crypto-trait" } edhoc-consts = { path = "../consts" } edhoc-ead = { path = "../ead", default-features = false } panic-semihosting = { version = "0.6.0", features = ["exit"], optional = true } diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index eacb4f52..ebda651c 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -1,10 +1,10 @@ #![no_std] use edhoc_consts::*; -use edhoc_crypto::{Crypto, CryptoTrait}; +use edhoc_crypto_trait::Crypto as CryptoTrait; use edhoc_ead::*; -pub fn edhoc_exporter( +pub fn edhoc_exporter( state: State, label: u8, context: &BytesMaxContextBuffer, @@ -28,14 +28,14 @@ pub fn edhoc_exporter( let mut error = EDHOCError::UnknownError; if current_state == EDHOCState::Completed { - output = edhoc_kdf(&prk_exporter, label, context, context_len, length); + output = edhoc_kdf::(&prk_exporter, label, context, context_len, length); Ok((state, output)) } else { Err(EDHOCError::WrongState) } } -pub fn edhoc_key_update( +pub fn edhoc_key_update( mut state: State, context: &BytesMaxContextBuffer, context_len: usize, @@ -58,11 +58,11 @@ pub fn edhoc_key_update( if current_state == EDHOCState::Completed { // new PRK_out - prk_new_buf = edhoc_kdf(&prk_out, 11u8, context, context_len, SHA256_DIGEST_LEN); + prk_new_buf = edhoc_kdf::(&prk_out, 11u8, context, context_len, SHA256_DIGEST_LEN); prk_out[..SHA256_DIGEST_LEN].copy_from_slice(&prk_new_buf[..SHA256_DIGEST_LEN]); // new PRK_exporter - prk_new_buf = edhoc_kdf( + prk_new_buf = edhoc_kdf::( &prk_out, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -90,7 +90,7 @@ pub fn edhoc_key_update( } } -pub fn r_process_message_1( +pub fn r_process_message_1( mut state: State, message_1: &BufferMessage1, ) -> Result { @@ -170,7 +170,7 @@ pub fn r_process_message_1( } } -pub fn r_prepare_message_2( +pub fn r_prepare_message_2( mut state: State, id_cred_r: &BytesIdCred, cred_r: &[u8], @@ -197,15 +197,15 @@ pub fn r_prepare_message_2( if current_state == EDHOCState::ProcessedMessage1 { // compute TH_2 - let th_2 = compute_th_2(&g_y, &h_message_1); + let th_2 = compute_th_2::(&g_y, &h_message_1); // compute prk_3e2m - let prk_2e = compute_prk_2e(&y, &g_x, &th_2); - let salt_3e2m = compute_salt_3e2m(&prk_2e, &th_2); - prk_3e2m = compute_prk_3e2m(&salt_3e2m, r, &g_x); + let prk_2e = compute_prk_2e::(&y, &g_x, &th_2); + let salt_3e2m = compute_salt_3e2m::(&prk_2e, &th_2); + prk_3e2m = compute_prk_3e2m::(&salt_3e2m, r, &g_x); // compute MAC_2 - let mac_2 = compute_mac_2(&prk_3e2m, id_cred_r, cred_r, &th_2); + let mac_2 = compute_mac_2::(&prk_3e2m, id_cred_r, cred_r, &th_2); let ead_2 = r_prepare_ead_2(); @@ -214,13 +214,13 @@ pub fn r_prepare_message_2( // step is actually from processing of message_3 // but we do it here to avoid storing plaintext_2 in State - th_3 = compute_th_3(&th_2, &plaintext_2, cred_r); + th_3 = compute_th_3::(&th_2, &plaintext_2, cred_r); let mut ct: BufferCiphertext2 = BufferCiphertext2::new(); ct.len = plaintext_2.len; ct.content[..ct.len].copy_from_slice(&plaintext_2.content[..ct.len]); - let (ciphertext_2, ciphertext_2_len) = encrypt_decrypt_ciphertext_2(&prk_2e, &th_2, &ct); + let (ciphertext_2, ciphertext_2_len) = encrypt_decrypt_ciphertext_2::(&prk_2e, &th_2, &ct); ct.content[..ct.len].copy_from_slice(&ciphertext_2[..ct.len]); @@ -252,7 +252,7 @@ pub fn r_prepare_message_2( } // FIXME fetch ID_CRED_I and CRED_I based on kid -pub fn r_process_message_3( +pub fn r_process_message_3( mut state: State, message_3: &BufferMessage3, id_cred_i_expected: &BytesIdCred, @@ -275,7 +275,7 @@ pub fn r_process_message_3( let mut error = EDHOCError::UnknownError; if current_state == EDHOCState::WaitMessage3 { - let plaintext_3 = decrypt_message_3(&prk_3e2m, &th_3, message_3); + let plaintext_3 = decrypt_message_3::(&prk_3e2m, &th_3, message_3); if plaintext_3.is_ok() { let plaintext_3 = plaintext_3.unwrap(); @@ -294,31 +294,31 @@ pub fn r_process_message_3( // compare the kid received with the kid expected in id_cred_i if kid == id_cred_i_expected[id_cred_i_expected.len() - 1] { // compute salt_4e3m - let salt_4e3m = compute_salt_4e3m(&prk_3e2m, &th_3); + let salt_4e3m = compute_salt_4e3m::(&prk_3e2m, &th_3); // TODO compute prk_4e3m - prk_4e3m = compute_prk_4e3m(&salt_4e3m, &y, g_i); + prk_4e3m = compute_prk_4e3m::(&salt_4e3m, &y, g_i); // compute mac_3 let expected_mac_3 = - compute_mac_3(&prk_4e3m, &th_3, id_cred_i_expected, cred_i_expected); + compute_mac_3::(&prk_4e3m, &th_3, id_cred_i_expected, cred_i_expected); // verify mac_3 if mac_3 == expected_mac_3 { error = EDHOCError::Success; - let th_4 = compute_th_4(&th_3, &plaintext_3, cred_i_expected); + let th_4 = compute_th_4::(&th_3, &plaintext_3, cred_i_expected); let mut th_4_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_4_buf[..th_4.len()].copy_from_slice(&th_4[..]); // compute prk_out // PRK_out = EDHOC-KDF( PRK_4e3m, 7, TH_4, hash_length ) let prk_out_buf = - edhoc_kdf(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); + edhoc_kdf::(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); prk_out[..SHA256_DIGEST_LEN] .copy_from_slice(&prk_out_buf[..SHA256_DIGEST_LEN]); // compute prk_exporter from prk_out // PRK_exporter = EDHOC-KDF( PRK_out, 10, h'', hash_length ) - let prk_exporter_buf = edhoc_kdf( + let prk_exporter_buf = edhoc_kdf::( &prk_out, 10u8, &[0x00u8; MAX_KDF_CONTEXT_LEN], @@ -369,7 +369,7 @@ pub fn r_process_message_3( } } -pub fn i_prepare_message_1( +pub fn i_prepare_message_1( mut state: State, x: BytesP256ElemLen, g_x: BytesP256ElemLen, @@ -440,7 +440,7 @@ pub fn i_prepare_message_1( } // returns c_r -pub fn i_process_message_2( +pub fn i_process_message_2( mut state: State, message_2: &BufferMessage2, id_cred_r_expected: &BytesIdCred, @@ -471,13 +471,13 @@ pub fn i_process_message_2( if res.is_ok() { let (g_y, ciphertext_2) = res.unwrap(); - let th_2 = compute_th_2(&g_y, &h_message_1); + let th_2 = compute_th_2::(&g_y, &h_message_1); // compute prk_2e - let prk_2e = compute_prk_2e(&x, &g_y, &th_2); + let prk_2e = compute_prk_2e::(&x, &g_y, &th_2); let (plaintext_2, plaintext_2_len) = - encrypt_decrypt_ciphertext_2(&prk_2e, &th_2, &ciphertext_2); + encrypt_decrypt_ciphertext_2::(&prk_2e, &th_2, &ciphertext_2); // decode plaintext_2 let plaintext_2_decoded = decode_plaintext_2(&plaintext_2, plaintext_2_len); @@ -494,12 +494,12 @@ pub fn i_process_message_2( }; if ead_success { // verify mac_2 - let salt_3e2m = compute_salt_3e2m(&prk_2e, &th_2); + let salt_3e2m = compute_salt_3e2m::(&prk_2e, &th_2); - prk_3e2m = compute_prk_3e2m(&salt_3e2m, &x, g_r); + prk_3e2m = compute_prk_3e2m::(&salt_3e2m, &x, g_r); let expected_mac_2 = - compute_mac_2(&prk_3e2m, id_cred_r_expected, cred_r_expected, &th_2); + compute_mac_2::(&prk_3e2m, id_cred_r_expected, cred_r_expected, &th_2); if mac_2 == expected_mac_2 { if kid == id_cred_r_expected[id_cred_r_expected.len() - 1] { @@ -509,12 +509,12 @@ pub fn i_process_message_2( pt2.content[..plaintext_2_len] .copy_from_slice(&plaintext_2[..plaintext_2_len]); pt2.len = plaintext_2_len; - th_3 = compute_th_3(&th_2, &pt2, cred_r_expected); + th_3 = compute_th_3::(&th_2, &pt2, cred_r_expected); // message 3 processing - let salt_4e3m = compute_salt_4e3m(&prk_3e2m, &th_3); + let salt_4e3m = compute_salt_4e3m::(&prk_3e2m, &th_3); - prk_4e3m = compute_prk_4e3m(&salt_4e3m, i, &g_y); + prk_4e3m = compute_prk_4e3m::(&salt_4e3m, i, &g_y); error = EDHOCError::Success; current_state = EDHOCState::ProcessedMessage2; @@ -557,7 +557,7 @@ pub fn i_process_message_2( } } -pub fn i_prepare_message_3( +pub fn i_prepare_message_3( mut state: State, id_cred_i: &BytesIdCred, cred_i: &[u8], @@ -579,26 +579,26 @@ pub fn i_prepare_message_3( let mut message_3: BufferMessage3 = BufferMessage3::new(); if current_state == EDHOCState::ProcessedMessage2 { - let mac_3 = compute_mac_3(&prk_4e3m, &th_3, id_cred_i, cred_i); + let mac_3 = compute_mac_3::(&prk_4e3m, &th_3, id_cred_i, cred_i); let ead_3 = i_prepare_ead_3(); let plaintext_3 = encode_plaintext_3(id_cred_i, &mac_3, &ead_3); - message_3 = encrypt_message_3(&prk_3e2m, &th_3, &plaintext_3); + message_3 = encrypt_message_3::(&prk_3e2m, &th_3, &plaintext_3); - let th_4 = compute_th_4(&th_3, &plaintext_3, cred_i); + let th_4 = compute_th_4::(&th_3, &plaintext_3, cred_i); let mut th_4_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_4_buf[..th_4.len()].copy_from_slice(&th_4[..]); // compute prk_out // PRK_out = EDHOC-KDF( PRK_4e3m, 7, TH_4, hash_length ) - let prk_out_buf = edhoc_kdf(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); + let prk_out_buf = edhoc_kdf::(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); prk_out[..SHA256_DIGEST_LEN].copy_from_slice(&prk_out_buf[..SHA256_DIGEST_LEN]); // compute prk_exporter from prk_out // PRK_exporter = EDHOC-KDF( PRK_out, 10, h'', hash_length ) - let prk_exporter_buf = edhoc_kdf( + let prk_exporter_buf = edhoc_kdf::( &prk_out, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -992,7 +992,7 @@ fn encode_message_2(g_y: &BytesP256ElemLen, ciphertext_2: &BufferCiphertext2) -> output } -fn compute_th_2(g_y: &BytesP256ElemLen, h_message_1: &BytesHashLen) -> BytesHashLen { +fn compute_th_2(g_y: &BytesP256ElemLen, h_message_1: &BytesHashLen) -> BytesHashLen { let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; message[0] = CBOR_BYTE_STRING; message[1] = P256_ELEM_LEN as u8; @@ -1009,7 +1009,7 @@ fn compute_th_2(g_y: &BytesP256ElemLen, h_message_1: &BytesHashLen) -> BytesHash th_2 } -fn compute_th_3( +fn compute_th_3( th_2: &BytesHashLen, plaintext_2: &BufferPlaintext2, cred_r: &[u8], @@ -1029,7 +1029,7 @@ fn compute_th_3( output } -fn compute_th_4( +fn compute_th_4( th_3: &BytesHashLen, plaintext_3: &BufferPlaintext3, cred_i: &[u8], @@ -1049,7 +1049,7 @@ fn compute_th_4( output } -fn edhoc_kdf( +fn edhoc_kdf( prk: &BytesHashLen, label: u8, context: &BytesMaxContextBuffer, @@ -1175,7 +1175,7 @@ fn encode_enc_structure(th_3: &BytesHashLen) -> BytesEncStructureLen { enc_structure } -fn compute_k_3_iv_3( +fn compute_k_3_iv_3( prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, ) -> (BytesCcmKeyLen, BytesCcmIvLen) { @@ -1183,19 +1183,19 @@ fn compute_k_3_iv_3( let mut k_3: BytesCcmKeyLen = [0x00; AES_CCM_KEY_LEN]; let mut th_3_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_3_buf[..th_3.len()].copy_from_slice(&th_3[..]); - let k_3_buf = edhoc_kdf(prk_3e2m, 3u8, &th_3_buf, th_3.len(), AES_CCM_KEY_LEN); + let k_3_buf = edhoc_kdf::(prk_3e2m, 3u8, &th_3_buf, th_3.len(), AES_CCM_KEY_LEN); k_3[..].copy_from_slice(&k_3_buf[..AES_CCM_KEY_LEN]); // IV_3 = EDHOC-KDF( PRK_3e2m, 4, TH_3, iv_length ) let mut iv_3: BytesCcmIvLen = [0x00; AES_CCM_IV_LEN]; - let iv_3_buf = edhoc_kdf(prk_3e2m, 4u8, &th_3_buf, th_3.len(), AES_CCM_IV_LEN); + let iv_3_buf = edhoc_kdf::(prk_3e2m, 4u8, &th_3_buf, th_3.len(), AES_CCM_IV_LEN); iv_3[..].copy_from_slice(&iv_3_buf[..AES_CCM_IV_LEN]); (k_3, iv_3) } // calculates ciphertext_3 wrapped in a cbor byte string -fn encrypt_message_3( +fn encrypt_message_3( prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, plaintext_3: &BufferPlaintext3, @@ -1206,7 +1206,7 @@ fn encrypt_message_3( let enc_structure = encode_enc_structure(th_3); - let (k_3, iv_3) = compute_k_3_iv_3(prk_3e2m, th_3); + let (k_3, iv_3) = compute_k_3_iv_3::(prk_3e2m, th_3); let ciphertext_3 = Crypto::aes_ccm_encrypt_tag_8(&k_3, &iv_3, &enc_structure, plaintext_3); @@ -1215,7 +1215,7 @@ fn encrypt_message_3( output } -fn decrypt_message_3( +fn decrypt_message_3( prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, message_3: &BufferMessage3, @@ -1230,7 +1230,7 @@ fn decrypt_message_3( ciphertext_3.len = len; ciphertext_3.content[..len].copy_from_slice(&message_3.content[1..1 + len]); - let (k_3, iv_3) = compute_k_3_iv_3(prk_3e2m, th_3); + let (k_3, iv_3) = compute_k_3_iv_3::(prk_3e2m, th_3); let enc_structure = encode_enc_structure(th_3); @@ -1272,7 +1272,7 @@ fn encode_kdf_context( (output, output_len) } -fn compute_mac_3( +fn compute_mac_3( prk_4e3m: &BytesHashLen, th_3: &BytesHashLen, id_cred_i: &BytesIdCred, @@ -1282,7 +1282,7 @@ fn compute_mac_3( let (context, context_len) = encode_kdf_context(id_cred_i, th_3, cred_i); // compute mac_3 - let output_buf = edhoc_kdf( + let output_buf = edhoc_kdf::( prk_4e3m, 6u8, // registered label for "MAC_3" &context, @@ -1295,7 +1295,7 @@ fn compute_mac_3( output } -fn compute_mac_2( +fn compute_mac_2( prk_3e2m: &BytesHashLen, id_cred_r: &BytesIdCred, cred_r: &[u8], @@ -1307,7 +1307,7 @@ fn compute_mac_2( // MAC_2 = EDHOC-KDF( PRK_3e2m, 2, context_2, mac_length_2 ) let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2]; mac_2[..].copy_from_slice( - &edhoc_kdf(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2)[..MAC_LENGTH_2], + &edhoc_kdf::(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2)[..MAC_LENGTH_2], ); mac_2 @@ -1386,7 +1386,7 @@ fn encode_plaintext_2( plaintext_2 } -fn encrypt_decrypt_ciphertext_2( +fn encrypt_decrypt_ciphertext_2( prk_2e: &BytesHashLen, th_2: &BytesHashLen, ciphertext_2: &BufferCiphertext2, @@ -1396,7 +1396,7 @@ fn encrypt_decrypt_ciphertext_2( th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); // KEYSTREAM_2 = EDHOC-KDF( PRK_2e, 0, TH_2, plaintext_length ) - let keystream_2 = edhoc_kdf( + let keystream_2 = edhoc_kdf::( prk_2e, 0u8, &th_2_context, @@ -1413,17 +1413,17 @@ fn encrypt_decrypt_ciphertext_2( (plaintext_2, ciphertext_2.len) } -fn compute_salt_4e3m(prk_3e2m: &BytesHashLen, th_3: &BytesHashLen) -> BytesHashLen { +fn compute_salt_4e3m(prk_3e2m: &BytesHashLen, th_3: &BytesHashLen) -> BytesHashLen { let mut th_3_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_3_context[..th_3.len()].copy_from_slice(&th_3[..]); - let salt_4e3m_buf = edhoc_kdf(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); + let salt_4e3m_buf = edhoc_kdf::(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); let mut salt_4e3m: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; salt_4e3m[..].copy_from_slice(&salt_4e3m_buf[..SHA256_DIGEST_LEN]); salt_4e3m } -fn compute_prk_4e3m( +fn compute_prk_4e3m( salt_4e3m: &BytesHashLen, i: &BytesP256ElemLen, g_y: &BytesP256ElemLen, @@ -1435,11 +1435,11 @@ fn compute_prk_4e3m( prk_4e3m } -fn compute_salt_3e2m(prk_2e: &BytesHashLen, th_2: &BytesHashLen) -> BytesHashLen { +fn compute_salt_3e2m(prk_2e: &BytesHashLen, th_2: &BytesHashLen) -> BytesHashLen { let mut th_2_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); - let salt_3e2m_buf = edhoc_kdf( + let salt_3e2m_buf = edhoc_kdf::( prk_2e, 1u8, &th_2_context, @@ -1453,7 +1453,7 @@ fn compute_salt_3e2m(prk_2e: &BytesHashLen, th_2: &BytesHashLen) -> BytesHashLen salt_3e2m } -fn compute_prk_3e2m( +fn compute_prk_3e2m( salt_3e2m: &BytesHashLen, x: &BytesP256ElemLen, g_r: &BytesP256ElemLen, @@ -1465,7 +1465,7 @@ fn compute_prk_3e2m( prk_3e2m } -fn compute_prk_2e( +fn compute_prk_2e( x: &BytesP256ElemLen, g_y: &BytesP256ElemLen, th_2: &BytesHashLen, @@ -1482,6 +1482,8 @@ fn compute_prk_2e( mod tests { use super::*; use hexlit::hex; + + use edhoc_crypto::Crypto; // test vectors (TV) // message_1 (first_time) @@ -1728,7 +1730,7 @@ mod tests { #[test] fn test_compute_th_2() { - let th_2 = compute_th_2(&G_Y_TV, &H_MESSAGE_1_TV); + let th_2 = compute_th_2::(&G_Y_TV, &H_MESSAGE_1_TV); assert_eq!(th_2, TH_2_TV); } @@ -1736,7 +1738,7 @@ mod tests { fn test_compute_th_3() { let plaintext_2_tv = BufferPlaintext2::from_hex(PLAINTEXT_2_TV); - let th_3 = compute_th_3(&TH_2_TV, &plaintext_2_tv, &CRED_R_TV); + let th_3 = compute_th_3::(&TH_2_TV, &plaintext_2_tv, &CRED_R_TV); assert_eq!(th_3, TH_3_TV); } @@ -1744,7 +1746,7 @@ mod tests { fn test_compute_th_4() { let plaintext_3_tv = BufferPlaintext3::from_hex(PLAINTEXT_3_TV); - let th_4 = compute_th_4(&TH_3_TV, &plaintext_3_tv, &CRED_I_TV); + let th_4 = compute_th_4::(&TH_3_TV, &plaintext_3_tv, &CRED_I_TV); assert_eq!(th_4, TH_4_TV); } @@ -1754,7 +1756,7 @@ mod tests { th_2_context_tv[..TH_2_TV.len()].copy_from_slice(&TH_2_TV[..]); const LEN_TV: usize = PLAINTEXT_2_LEN_TV; - let output = edhoc_kdf(&PRK_2E_TV, 0u8, &th_2_context_tv, SHA256_DIGEST_LEN, LEN_TV); + let output = edhoc_kdf::(&PRK_2E_TV, 0u8, &th_2_context_tv, SHA256_DIGEST_LEN, LEN_TV); for i in 0..KEYSTREAM_2_TV.len() { assert_eq!(KEYSTREAM_2_TV[i], output[i]); } @@ -1763,7 +1765,7 @@ mod tests { context_info_mac_2[..CONTEXT_INFO_MAC_2_TV.len()] .copy_from_slice(&CONTEXT_INFO_MAC_2_TV[..]); - let output_2 = edhoc_kdf( + let output_2 = edhoc_kdf::( &PRK_3E2M_TV, 2u8, &context_info_mac_2, @@ -1781,7 +1783,7 @@ mod tests { let plaintext_3_tv = BufferPlaintext3::from_hex(PLAINTEXT_3_TV); let message_3_tv = BufferMessage3::from_hex(MESSAGE_3_TV); - let message_3 = encrypt_message_3(&PRK_3E2M_TV, &TH_3_TV, &plaintext_3_tv); + let message_3 = encrypt_message_3::(&PRK_3E2M_TV, &TH_3_TV, &plaintext_3_tv); assert_eq!(message_3, message_3_tv); } @@ -1790,20 +1792,20 @@ mod tests { let plaintext_3_tv = BufferPlaintext3::from_hex(PLAINTEXT_3_TV); let message_3_tv = BufferMessage3::from_hex(MESSAGE_3_TV); - let plaintext_3 = decrypt_message_3(&PRK_3E2M_TV, &TH_3_TV, &message_3_tv); + let plaintext_3 = decrypt_message_3::(&PRK_3E2M_TV, &TH_3_TV, &message_3_tv); assert!(plaintext_3.is_ok()); assert_eq!(plaintext_3.unwrap(), plaintext_3_tv); } #[test] fn test_compute_mac_3() { - let mac_3 = compute_mac_3(&PRK_4E3M_TV, &TH_3_TV, &ID_CRED_I_TV, &CRED_I_TV); + let mac_3 = compute_mac_3::(&PRK_4E3M_TV, &TH_3_TV, &ID_CRED_I_TV, &CRED_I_TV); assert_eq!(mac_3, MAC_3_TV); } #[test] fn test_compute_and_verify_mac_2() { - let rcvd_mac_2 = compute_mac_2(&PRK_3E2M_TV, &ID_CRED_R_TV, &CRED_R_TV, &TH_2_TV); + let rcvd_mac_2 = compute_mac_2::(&PRK_3E2M_TV, &ID_CRED_R_TV, &CRED_R_TV, &TH_2_TV); assert_eq!(rcvd_mac_2, MAC_2_TV); } @@ -1856,7 +1858,7 @@ mod tests { let ciphertext_2_tv = BufferPlaintext2::from_hex(CIPHERTEXT_2_TV); // test decryption let (plaintext_2, plaintext_2_len) = - encrypt_decrypt_ciphertext_2(&PRK_2E_TV, &TH_2_TV, &ciphertext_2_tv); + encrypt_decrypt_ciphertext_2::(&PRK_2E_TV, &TH_2_TV, &ciphertext_2_tv); assert_eq!(plaintext_2_len, PLAINTEXT_2_LEN_TV); for i in 0..PLAINTEXT_2_LEN_TV { @@ -1869,7 +1871,7 @@ mod tests { // test encryption let (ciphertext_2, ciphertext_2_len) = - encrypt_decrypt_ciphertext_2(&PRK_2E_TV, &TH_2_TV, &plaintext_2_tmp); + encrypt_decrypt_ciphertext_2::(&PRK_2E_TV, &TH_2_TV, &plaintext_2_tmp); assert_eq!(ciphertext_2_len, CIPHERTEXT_2_LEN_TV); for i in 0..CIPHERTEXT_2_LEN_TV { @@ -1879,19 +1881,19 @@ mod tests { #[test] fn test_compute_prk_4e3m() { - let prk_4e3m = compute_prk_4e3m(&SALT_4E3M_TV, &SK_I_TV, &G_Y_TV); + let prk_4e3m = compute_prk_4e3m::(&SALT_4E3M_TV, &SK_I_TV, &G_Y_TV); assert_eq!(prk_4e3m, PRK_4E3M_TV); } #[test] fn test_compute_prk_3e2m() { - let prk_3e2m = compute_prk_3e2m(&SALT_3E2M_TV, &X_TV, &G_R_TV); + let prk_3e2m = compute_prk_3e2m::(&SALT_3E2M_TV, &X_TV, &G_R_TV); assert_eq!(prk_3e2m, PRK_3E2M_TV); } #[test] fn test_compute_prk_2e() { - let prk_2e = compute_prk_2e(&X_TV, &G_Y_TV, &TH_2_TV); + let prk_2e = compute_prk_2e::(&X_TV, &G_Y_TV, &TH_2_TV); assert_eq!(prk_2e, PRK_2E_TV); } @@ -2003,7 +2005,7 @@ mod tests { let mut th_4_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_4_context[..TH_4_TV.len()].copy_from_slice(&TH_4_TV[..]); - let prk_out_buf = edhoc_kdf( + let prk_out_buf = edhoc_kdf::( &PRK_4E3M_TV, 7u8, &th_4_context, @@ -2018,7 +2020,7 @@ mod tests { #[test] fn test_compute_prk_exporter() { let mut prk_exporter: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; - let prk_exporter_buf = edhoc_kdf( + let prk_exporter_buf = edhoc_kdf::( &PRK_OUT_TV, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -2032,7 +2034,7 @@ mod tests { #[test] fn test_compute_oscore_master_secret_salt() { - let oscore_master_secret_buf = edhoc_kdf( + let oscore_master_secret_buf = edhoc_kdf::( &PRK_EXPORTER_TV, 0u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -2044,7 +2046,7 @@ mod tests { &OSCORE_MASTER_SECRET_TV[..] ); - let oscore_master_salt_buf = edhoc_kdf( + let oscore_master_salt_buf = edhoc_kdf::( &PRK_EXPORTER_TV, 1u8, &[0x00; MAX_KDF_CONTEXT_LEN], diff --git a/lib/src/lib.rs b/lib/src/lib.rs index c5806ab4..f285c7c4 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -87,7 +87,7 @@ impl<'a> EdhocResponderState<'a> { self: &mut EdhocResponderState<'a>, message_1: &BufferMessage1, ) -> Result<(), EDHOCError> { - let state = r_process_message_1(self.state, message_1)?; + let state = r_process_message_1::(self.state, message_1)?; self.state = state; Ok(()) @@ -99,7 +99,7 @@ impl<'a> EdhocResponderState<'a> { ) -> Result { let (y, g_y) = Crypto::p256_generate_key_pair(); - match r_prepare_message_2( + match r_prepare_message_2::( self.state, &self .id_cred_r @@ -123,7 +123,7 @@ impl<'a> EdhocResponderState<'a> { self: &mut EdhocResponderState<'a>, message_3: &BufferMessage3, ) -> Result<[u8; SHA256_DIGEST_LEN], EDHOCError> { - match r_process_message_3( + match r_process_message_3::( self.state, message_3, &self @@ -150,7 +150,7 @@ impl<'a> EdhocResponderState<'a> { let mut context_buf: BytesMaxContextBuffer = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_exporter(self.state, label, &context_buf, context.len(), length) { + match edhoc_exporter::(self.state, label, &context_buf, context.len(), length) { Ok((state, output)) => { self.state = state; Ok(output) @@ -166,7 +166,7 @@ impl<'a> EdhocResponderState<'a> { let mut context_buf = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_key_update(self.state, &context_buf, context.len()) { + match edhoc_key_update::(self.state, &context_buf, context.len()) { Ok((state, prk_out_new)) => { self.state = state; Ok(prk_out_new) @@ -226,7 +226,7 @@ impl<'a> EdhocInitiatorState<'a> { ) -> Result { let (x, g_x) = Crypto::p256_generate_key_pair(); - match i_prepare_message_1(self.state, x, g_x, c_i) { + match i_prepare_message_1::(self.state, x, g_x, c_i) { Ok((state, message_1)) => { self.state = state; Ok(message_1) @@ -239,7 +239,7 @@ impl<'a> EdhocInitiatorState<'a> { self: &mut EdhocInitiatorState<'a>, message_2: &BufferMessage2, ) -> Result { - match i_process_message_2( + match i_process_message_2::( self.state, message_2, &self @@ -263,7 +263,7 @@ impl<'a> EdhocInitiatorState<'a> { pub fn prepare_message_3( self: &mut EdhocInitiatorState<'a>, ) -> Result<(BufferMessage3, [u8; SHA256_DIGEST_LEN]), EDHOCError> { - match i_prepare_message_3( + match i_prepare_message_3::( self.state, &self .id_cred_i @@ -288,7 +288,7 @@ impl<'a> EdhocInitiatorState<'a> { let mut context_buf: BytesMaxContextBuffer = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_exporter(self.state, label, &context_buf, context.len(), length) { + match edhoc_exporter::(self.state, label, &context_buf, context.len(), length) { Ok((state, output)) => { self.state = state; Ok(output) @@ -304,7 +304,7 @@ impl<'a> EdhocInitiatorState<'a> { let mut context_buf = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_key_update(self.state, &context_buf, context.len()) { + match edhoc_key_update::(self.state, &context_buf, context.len()) { Ok((state, prk_out_new)) => { self.state = state; Ok(prk_out_new) From 2685ffdf61308e5dd9b11a8754ac1093262dd52a Mon Sep 17 00:00:00 2001 From: chrysn Date: Sun, 8 Oct 2023 20:40:53 +0200 Subject: [PATCH 5/8] chore: cargo fmt This is deferred from the previous commit to maintain its "minimality" --- lib/src/edhoc.rs | 55 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index ebda651c..9d94a873 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -220,7 +220,8 @@ pub fn r_prepare_message_2( ct.len = plaintext_2.len; ct.content[..ct.len].copy_from_slice(&plaintext_2.content[..ct.len]); - let (ciphertext_2, ciphertext_2_len) = encrypt_decrypt_ciphertext_2::(&prk_2e, &th_2, &ct); + let (ciphertext_2, ciphertext_2_len) = + encrypt_decrypt_ciphertext_2::(&prk_2e, &th_2, &ct); ct.content[..ct.len].copy_from_slice(&ciphertext_2[..ct.len]); @@ -299,8 +300,12 @@ pub fn r_process_message_3( prk_4e3m = compute_prk_4e3m::(&salt_4e3m, &y, g_i); // compute mac_3 - let expected_mac_3 = - compute_mac_3::(&prk_4e3m, &th_3, id_cred_i_expected, cred_i_expected); + let expected_mac_3 = compute_mac_3::( + &prk_4e3m, + &th_3, + id_cred_i_expected, + cred_i_expected, + ); // verify mac_3 if mac_3 == expected_mac_3 { @@ -311,8 +316,13 @@ pub fn r_process_message_3( th_4_buf[..th_4.len()].copy_from_slice(&th_4[..]); // compute prk_out // PRK_out = EDHOC-KDF( PRK_4e3m, 7, TH_4, hash_length ) - let prk_out_buf = - edhoc_kdf::(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); + let prk_out_buf = edhoc_kdf::( + &prk_4e3m, + 7u8, + &th_4_buf, + th_4.len(), + SHA256_DIGEST_LEN, + ); prk_out[..SHA256_DIGEST_LEN] .copy_from_slice(&prk_out_buf[..SHA256_DIGEST_LEN]); @@ -498,8 +508,12 @@ pub fn i_process_message_2( prk_3e2m = compute_prk_3e2m::(&salt_3e2m, &x, g_r); - let expected_mac_2 = - compute_mac_2::(&prk_3e2m, id_cred_r_expected, cred_r_expected, &th_2); + let expected_mac_2 = compute_mac_2::( + &prk_3e2m, + id_cred_r_expected, + cred_r_expected, + &th_2, + ); if mac_2 == expected_mac_2 { if kid == id_cred_r_expected[id_cred_r_expected.len() - 1] { @@ -593,7 +607,8 @@ pub fn i_prepare_message_3( // compute prk_out // PRK_out = EDHOC-KDF( PRK_4e3m, 7, TH_4, hash_length ) - let prk_out_buf = edhoc_kdf::(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); + let prk_out_buf = + edhoc_kdf::(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); prk_out[..SHA256_DIGEST_LEN].copy_from_slice(&prk_out_buf[..SHA256_DIGEST_LEN]); // compute prk_exporter from prk_out @@ -992,7 +1007,10 @@ fn encode_message_2(g_y: &BytesP256ElemLen, ciphertext_2: &BufferCiphertext2) -> output } -fn compute_th_2(g_y: &BytesP256ElemLen, h_message_1: &BytesHashLen) -> BytesHashLen { +fn compute_th_2( + g_y: &BytesP256ElemLen, + h_message_1: &BytesHashLen, +) -> BytesHashLen { let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; message[0] = CBOR_BYTE_STRING; message[1] = P256_ELEM_LEN as u8; @@ -1307,7 +1325,8 @@ fn compute_mac_2( // MAC_2 = EDHOC-KDF( PRK_3e2m, 2, context_2, mac_length_2 ) let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2]; mac_2[..].copy_from_slice( - &edhoc_kdf::(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2)[..MAC_LENGTH_2], + &edhoc_kdf::(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2) + [..MAC_LENGTH_2], ); mac_2 @@ -1413,10 +1432,14 @@ fn encrypt_decrypt_ciphertext_2( (plaintext_2, ciphertext_2.len) } -fn compute_salt_4e3m(prk_3e2m: &BytesHashLen, th_3: &BytesHashLen) -> BytesHashLen { +fn compute_salt_4e3m( + prk_3e2m: &BytesHashLen, + th_3: &BytesHashLen, +) -> BytesHashLen { let mut th_3_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_3_context[..th_3.len()].copy_from_slice(&th_3[..]); - let salt_4e3m_buf = edhoc_kdf::(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); + let salt_4e3m_buf = + edhoc_kdf::(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); let mut salt_4e3m: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; salt_4e3m[..].copy_from_slice(&salt_4e3m_buf[..SHA256_DIGEST_LEN]); @@ -1435,7 +1458,10 @@ fn compute_prk_4e3m( prk_4e3m } -fn compute_salt_3e2m(prk_2e: &BytesHashLen, th_2: &BytesHashLen) -> BytesHashLen { +fn compute_salt_3e2m( + prk_2e: &BytesHashLen, + th_2: &BytesHashLen, +) -> BytesHashLen { let mut th_2_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); @@ -1756,7 +1782,8 @@ mod tests { th_2_context_tv[..TH_2_TV.len()].copy_from_slice(&TH_2_TV[..]); const LEN_TV: usize = PLAINTEXT_2_LEN_TV; - let output = edhoc_kdf::(&PRK_2E_TV, 0u8, &th_2_context_tv, SHA256_DIGEST_LEN, LEN_TV); + let output = + edhoc_kdf::(&PRK_2E_TV, 0u8, &th_2_context_tv, SHA256_DIGEST_LEN, LEN_TV); for i in 0..KEYSTREAM_2_TV.len() { assert_eq!(KEYSTREAM_2_TV[i], output[i]); } From 8d278a71b68ca2615e01ebfe19ddb9598ed02fce Mon Sep 17 00:00:00 2001 From: chrysn Date: Tue, 10 Oct 2023 20:22:21 +0200 Subject: [PATCH 6/8] refactor: Shuffle sequence of functions to separate crypto dependent from crypto independent --- lib/src/edhoc.rs | 368 +++++++++++++++++++++++------------------------ 1 file changed, 184 insertions(+), 184 deletions(-) diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index 9d94a873..5ca68cc7 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -1103,96 +1103,6 @@ fn edhoc_kdf( output } -fn decode_plaintext_3( - plaintext_3: &BufferPlaintext3, -) -> Result<(u8, BytesMac3, Option), EDHOCError> { - let mut ead_3 = None::; - let mut error = EDHOCError::UnknownError; - let mut kid: u8 = 0xff; - let mut mac_3: BytesMac3 = [0x00; MAC_LENGTH_3]; - - // check ID_CRED_I and MAC_3 - if (is_cbor_neg_int_1byte(plaintext_3.content[0]) || is_cbor_uint_1byte(plaintext_3.content[0])) - && (is_cbor_bstr_1byte_prefix(plaintext_3.content[1])) - { - kid = plaintext_3.content[0usize]; - // skip the CBOR magic byte as we know how long the MAC is - mac_3[..].copy_from_slice(&plaintext_3.content[2..2 + MAC_LENGTH_3]); - - // if there is still more to parse, the rest will be the EAD_3 - if plaintext_3.len > (2 + MAC_LENGTH_3) { - // NOTE: since the current implementation only supports one EAD handler, - // we assume only one EAD item - let ead_res = parse_ead(plaintext_3, 2 + MAC_LENGTH_3); - if ead_res.is_ok() { - ead_3 = ead_res.unwrap(); - error = EDHOCError::Success; - } else { - error = ead_res.unwrap_err(); - } - } else if plaintext_3.len == (2 + MAC_LENGTH_3) { - error = EDHOCError::Success; - } else { - error = EDHOCError::ParsingError; - } - } else { - error = EDHOCError::ParsingError; - } - - match error { - EDHOCError::Success => Ok((kid, mac_3, ead_3)), - _ => Err(error), - } -} - -fn encode_plaintext_3( - id_cred_i: &BytesIdCred, - mac_3: &BytesMac3, - ead_3: &Option, -) -> BufferPlaintext3 { - let mut plaintext_3: BufferPlaintext3 = BufferPlaintext3::new(); - - // plaintext: P = ( ? PAD, ID_CRED_I / bstr / int, Signature_or_MAC_3, ? EAD_3 ) - plaintext_3.content[0] = id_cred_i[id_cred_i.len() - 1]; // hack: take the last byte of ID_CRED_I as KID - plaintext_3.content[1] = CBOR_MAJOR_BYTE_STRING | MAC_LENGTH_3 as u8; - plaintext_3.content[2..2 + mac_3.len()].copy_from_slice(&mac_3[..]); - plaintext_3.len = 2 + mac_3.len(); - - if let Some(ead_3) = ead_3 { - let ead_3 = encode_ead_item(ead_3); - plaintext_3.content[plaintext_3.len..plaintext_3.len + ead_3.len] - .copy_from_slice(&ead_3.content[..ead_3.len]); - plaintext_3.len += ead_3.len; - } - - plaintext_3 -} - -fn encode_enc_structure(th_3: &BytesHashLen) -> BytesEncStructureLen { - let mut encrypt0: Bytes8 = [0x00; 8]; - encrypt0[0] = 0x45u8; // 'E' - encrypt0[1] = 0x6eu8; // 'n' - encrypt0[2] = 0x63u8; // 'c' - encrypt0[3] = 0x72u8; // 'r' - encrypt0[4] = 0x79u8; // 'y' - encrypt0[5] = 0x70u8; // 'p' - encrypt0[6] = 0x74u8; // 't' - encrypt0[7] = 0x30u8; // '0' - - let mut enc_structure: BytesEncStructureLen = [0x00; ENC_STRUCTURE_LEN]; - - // encode Enc_structure from draft-ietf-cose-rfc8152bis Section 5.3 - enc_structure[0] = CBOR_MAJOR_ARRAY | 3 as u8; // 3 is the fixed number of elements in the array - enc_structure[1] = CBOR_MAJOR_TEXT_STRING | encrypt0.len() as u8; - enc_structure[2..2 + encrypt0.len()].copy_from_slice(&encrypt0[..]); - enc_structure[encrypt0.len() + 2] = CBOR_MAJOR_BYTE_STRING | 0x00 as u8; // 0 for zero-length byte string - enc_structure[encrypt0.len() + 3] = CBOR_BYTE_STRING; // byte string greater than 24 - enc_structure[encrypt0.len() + 4] = SHA256_DIGEST_LEN as u8; - enc_structure[encrypt0.len() + 5..encrypt0.len() + 5 + th_3.len()].copy_from_slice(&th_3[..]); - - enc_structure -} - fn compute_k_3_iv_3( prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, @@ -1269,27 +1179,6 @@ fn decrypt_message_3( } } -// output must hold id_cred.len() + cred.len() -fn encode_kdf_context( - id_cred: &BytesIdCred, - th: &BytesHashLen, - cred: &[u8], -) -> (BytesMaxContextBuffer, usize) { - // encode context in line - // assumes ID_CRED_R and CRED_R are already CBOR-encoded - let mut output: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; - output[..id_cred.len()].copy_from_slice(&id_cred[..]); - output[id_cred.len()] = CBOR_BYTE_STRING; - output[id_cred.len() + 1] = SHA256_DIGEST_LEN as u8; - output[id_cred.len() + 2..id_cred.len() + 2 + th.len()].copy_from_slice(&th[..]); - output[id_cred.len() + 2 + th.len()..id_cred.len() + 2 + th.len() + cred.len()] - .copy_from_slice(&cred); - - let output_len = (id_cred.len() + 2 + SHA256_DIGEST_LEN + cred.len()) as usize; - - (output, output_len) -} - fn compute_mac_3( prk_4e3m: &BytesHashLen, th_3: &BytesHashLen, @@ -1332,79 +1221,6 @@ fn compute_mac_2( mac_2 } -fn decode_plaintext_2( - plaintext_2: &BytesMaxBuffer, - plaintext_2_len: usize, -) -> Result<(u8, u8, BytesMac2, Option), EDHOCError> { - let mut error = EDHOCError::UnknownError; - let mut ead_2 = None::; - let mut c_r: u8 = 0xff; - let mut id_cred_r: u8 = 0xff; - let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2]; - - // check CBOR sequence types for c_r, id_cred_r, and mac_2 - if (is_cbor_neg_int_1byte(plaintext_2[0]) || is_cbor_uint_1byte(plaintext_2[0])) - && (is_cbor_neg_int_1byte(plaintext_2[1]) || is_cbor_uint_1byte(plaintext_2[1])) - && (is_cbor_bstr_1byte_prefix(plaintext_2[2])) - // TODO: check mac length as well - { - c_r = plaintext_2[0]; - id_cred_r = plaintext_2[1]; - // skip cbor byte string byte as we know how long the string is - mac_2[..].copy_from_slice(&plaintext_2[3..3 + MAC_LENGTH_2]); - - // if there is still more to parse, the rest will be the EAD_2 - if plaintext_2_len > (3 + MAC_LENGTH_2) { - // NOTE: since the current implementation only supports one EAD handler, - // we assume only one EAD item - let ead_res = parse_ead( - &plaintext_2[..plaintext_2_len].try_into().expect("too long"), - 3 + MAC_LENGTH_2, - ); - if ead_res.is_ok() { - ead_2 = ead_res.unwrap(); - error = EDHOCError::Success; - } else { - error = ead_res.unwrap_err(); - } - } else if plaintext_2_len == (3 + MAC_LENGTH_2) { - error = EDHOCError::Success; - } else { - error = EDHOCError::ParsingError; - } - } else { - error = EDHOCError::ParsingError; - } - - match error { - EDHOCError::Success => Ok((c_r, id_cred_r, mac_2, ead_2)), - _ => Err(error), - } -} - -fn encode_plaintext_2( - c_r: u8, - id_cred_r: &BytesIdCred, - mac_2: &BytesMac2, - ead_2: &Option, -) -> BufferPlaintext2 { - let mut plaintext_2: BufferPlaintext2 = BufferPlaintext2::new(); - plaintext_2.content[0] = c_r; - plaintext_2.content[1] = id_cred_r[id_cred_r.len() - 1]; - plaintext_2.content[2] = CBOR_MAJOR_BYTE_STRING | MAC_LENGTH_2 as u8; - plaintext_2.content[3..3 + mac_2.len()].copy_from_slice(&mac_2[..]); - plaintext_2.len = 3 + mac_2.len(); - - if let Some(ead_2) = ead_2 { - let ead_2 = encode_ead_item(ead_2); - plaintext_2.content[plaintext_2.len..plaintext_2.len + ead_2.len] - .copy_from_slice(&ead_2.content[..ead_2.len]); - plaintext_2.len += ead_2.len; - } - - plaintext_2 -} - fn encrypt_decrypt_ciphertext_2( prk_2e: &BytesHashLen, th_2: &BytesHashLen, @@ -1504,6 +1320,190 @@ fn compute_prk_2e( prk_2e } +fn decode_plaintext_3( + plaintext_3: &BufferPlaintext3, +) -> Result<(u8, BytesMac3, Option), EDHOCError> { + let mut ead_3 = None::; + let mut error = EDHOCError::UnknownError; + let mut kid: u8 = 0xff; + let mut mac_3: BytesMac3 = [0x00; MAC_LENGTH_3]; + + // check ID_CRED_I and MAC_3 + if (is_cbor_neg_int_1byte(plaintext_3.content[0]) || is_cbor_uint_1byte(plaintext_3.content[0])) + && (is_cbor_bstr_1byte_prefix(plaintext_3.content[1])) + { + kid = plaintext_3.content[0usize]; + // skip the CBOR magic byte as we know how long the MAC is + mac_3[..].copy_from_slice(&plaintext_3.content[2..2 + MAC_LENGTH_3]); + + // if there is still more to parse, the rest will be the EAD_3 + if plaintext_3.len > (2 + MAC_LENGTH_3) { + // NOTE: since the current implementation only supports one EAD handler, + // we assume only one EAD item + let ead_res = parse_ead(plaintext_3, 2 + MAC_LENGTH_3); + if ead_res.is_ok() { + ead_3 = ead_res.unwrap(); + error = EDHOCError::Success; + } else { + error = ead_res.unwrap_err(); + } + } else if plaintext_3.len == (2 + MAC_LENGTH_3) { + error = EDHOCError::Success; + } else { + error = EDHOCError::ParsingError; + } + } else { + error = EDHOCError::ParsingError; + } + + match error { + EDHOCError::Success => Ok((kid, mac_3, ead_3)), + _ => Err(error), + } +} + +fn encode_plaintext_3( + id_cred_i: &BytesIdCred, + mac_3: &BytesMac3, + ead_3: &Option, +) -> BufferPlaintext3 { + let mut plaintext_3: BufferPlaintext3 = BufferPlaintext3::new(); + + // plaintext: P = ( ? PAD, ID_CRED_I / bstr / int, Signature_or_MAC_3, ? EAD_3 ) + plaintext_3.content[0] = id_cred_i[id_cred_i.len() - 1]; // hack: take the last byte of ID_CRED_I as KID + plaintext_3.content[1] = CBOR_MAJOR_BYTE_STRING | MAC_LENGTH_3 as u8; + plaintext_3.content[2..2 + mac_3.len()].copy_from_slice(&mac_3[..]); + plaintext_3.len = 2 + mac_3.len(); + + if let Some(ead_3) = ead_3 { + let ead_3 = encode_ead_item(ead_3); + plaintext_3.content[plaintext_3.len..plaintext_3.len + ead_3.len] + .copy_from_slice(&ead_3.content[..ead_3.len]); + plaintext_3.len += ead_3.len; + } + + plaintext_3 +} + +fn encode_enc_structure(th_3: &BytesHashLen) -> BytesEncStructureLen { + let mut encrypt0: Bytes8 = [0x00; 8]; + encrypt0[0] = 0x45u8; // 'E' + encrypt0[1] = 0x6eu8; // 'n' + encrypt0[2] = 0x63u8; // 'c' + encrypt0[3] = 0x72u8; // 'r' + encrypt0[4] = 0x79u8; // 'y' + encrypt0[5] = 0x70u8; // 'p' + encrypt0[6] = 0x74u8; // 't' + encrypt0[7] = 0x30u8; // '0' + + let mut enc_structure: BytesEncStructureLen = [0x00; ENC_STRUCTURE_LEN]; + + // encode Enc_structure from draft-ietf-cose-rfc8152bis Section 5.3 + enc_structure[0] = CBOR_MAJOR_ARRAY | 3 as u8; // 3 is the fixed number of elements in the array + enc_structure[1] = CBOR_MAJOR_TEXT_STRING | encrypt0.len() as u8; + enc_structure[2..2 + encrypt0.len()].copy_from_slice(&encrypt0[..]); + enc_structure[encrypt0.len() + 2] = CBOR_MAJOR_BYTE_STRING | 0x00 as u8; // 0 for zero-length byte string + enc_structure[encrypt0.len() + 3] = CBOR_BYTE_STRING; // byte string greater than 24 + enc_structure[encrypt0.len() + 4] = SHA256_DIGEST_LEN as u8; + enc_structure[encrypt0.len() + 5..encrypt0.len() + 5 + th_3.len()].copy_from_slice(&th_3[..]); + + enc_structure +} + +// output must hold id_cred.len() + cred.len() +fn encode_kdf_context( + id_cred: &BytesIdCred, + th: &BytesHashLen, + cred: &[u8], +) -> (BytesMaxContextBuffer, usize) { + // encode context in line + // assumes ID_CRED_R and CRED_R are already CBOR-encoded + let mut output: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; + output[..id_cred.len()].copy_from_slice(&id_cred[..]); + output[id_cred.len()] = CBOR_BYTE_STRING; + output[id_cred.len() + 1] = SHA256_DIGEST_LEN as u8; + output[id_cred.len() + 2..id_cred.len() + 2 + th.len()].copy_from_slice(&th[..]); + output[id_cred.len() + 2 + th.len()..id_cred.len() + 2 + th.len() + cred.len()] + .copy_from_slice(&cred); + + let output_len = (id_cred.len() + 2 + SHA256_DIGEST_LEN + cred.len()) as usize; + + (output, output_len) +} + +fn decode_plaintext_2( + plaintext_2: &BytesMaxBuffer, + plaintext_2_len: usize, +) -> Result<(u8, u8, BytesMac2, Option), EDHOCError> { + let mut error = EDHOCError::UnknownError; + let mut ead_2 = None::; + let mut c_r: u8 = 0xff; + let mut id_cred_r: u8 = 0xff; + let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2]; + + // check CBOR sequence types for c_r, id_cred_r, and mac_2 + if (is_cbor_neg_int_1byte(plaintext_2[0]) || is_cbor_uint_1byte(plaintext_2[0])) + && (is_cbor_neg_int_1byte(plaintext_2[1]) || is_cbor_uint_1byte(plaintext_2[1])) + && (is_cbor_bstr_1byte_prefix(plaintext_2[2])) + // TODO: check mac length as well + { + c_r = plaintext_2[0]; + id_cred_r = plaintext_2[1]; + // skip cbor byte string byte as we know how long the string is + mac_2[..].copy_from_slice(&plaintext_2[3..3 + MAC_LENGTH_2]); + + // if there is still more to parse, the rest will be the EAD_2 + if plaintext_2_len > (3 + MAC_LENGTH_2) { + // NOTE: since the current implementation only supports one EAD handler, + // we assume only one EAD item + let ead_res = parse_ead( + &plaintext_2[..plaintext_2_len].try_into().expect("too long"), + 3 + MAC_LENGTH_2, + ); + if ead_res.is_ok() { + ead_2 = ead_res.unwrap(); + error = EDHOCError::Success; + } else { + error = ead_res.unwrap_err(); + } + } else if plaintext_2_len == (3 + MAC_LENGTH_2) { + error = EDHOCError::Success; + } else { + error = EDHOCError::ParsingError; + } + } else { + error = EDHOCError::ParsingError; + } + + match error { + EDHOCError::Success => Ok((c_r, id_cred_r, mac_2, ead_2)), + _ => Err(error), + } +} + +fn encode_plaintext_2( + c_r: u8, + id_cred_r: &BytesIdCred, + mac_2: &BytesMac2, + ead_2: &Option, +) -> BufferPlaintext2 { + let mut plaintext_2: BufferPlaintext2 = BufferPlaintext2::new(); + plaintext_2.content[0] = c_r; + plaintext_2.content[1] = id_cred_r[id_cred_r.len() - 1]; + plaintext_2.content[2] = CBOR_MAJOR_BYTE_STRING | MAC_LENGTH_2 as u8; + plaintext_2.content[3..3 + mac_2.len()].copy_from_slice(&mac_2[..]); + plaintext_2.len = 3 + mac_2.len(); + + if let Some(ead_2) = ead_2 { + let ead_2 = encode_ead_item(ead_2); + plaintext_2.content[plaintext_2.len..plaintext_2.len + ead_2.len] + .copy_from_slice(&ead_2.content[..ead_2.len]); + plaintext_2.len += ead_2.len; + } + + plaintext_2 +} + #[cfg(test)] mod tests { use super::*; From 84e9d2467fee42cb89f8c0fd859a65a409cc76b0 Mon Sep 17 00:00:00 2001 From: chrysn Date: Tue, 10 Oct 2023 20:59:24 +0200 Subject: [PATCH 7/8] refactor!: Pass crypto implementation around as an argument This commit is not formatted to increase its readability. --- .../edhoc-crypto-cryptocell310-sys/src/lib.rs | 12 +- crypto/edhoc-crypto-hacspec/src/lib.rs | 20 +- crypto/edhoc-crypto-psa/src/lib.rs | 16 +- crypto/edhoc-crypto-trait/src/lib.rs | 18 +- crypto/src/lib.rs | 15 ++ examples/edhoc-rs-no_std/src/main.rs | 10 +- lib/src/c_wrapper.rs | 4 +- lib/src/edhoc.rs | 215 ++++++++++-------- lib/src/lib.rs | 34 +-- 9 files changed, 209 insertions(+), 135 deletions(-) diff --git a/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs b/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs index 9b09803c..460ea8fc 100644 --- a/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs +++ b/crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs @@ -23,7 +23,7 @@ fn convert_array(input: &[u32]) -> [u8; SHA256_DIGEST_LEN] { pub struct Crypto; impl CryptoTrait for Crypto { - fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + fn sha256_digest(&mut self, message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; unsafe { @@ -39,6 +39,7 @@ impl CryptoTrait for Crypto { } fn hkdf_expand( + &mut self, prk: &BytesHashLen, info: &BytesMaxInfoBuffer, info_len: usize, @@ -63,7 +64,7 @@ impl CryptoTrait for Crypto { buffer } - fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { + fn hkdf_extract(&mut self, salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { // Implementation of HKDF-Extract as per RFC 5869 // TODO generalize if salt is not provided @@ -73,6 +74,7 @@ impl CryptoTrait for Crypto { } fn aes_ccm_encrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -110,6 +112,7 @@ impl CryptoTrait for Crypto { } fn aes_ccm_decrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -148,6 +151,7 @@ impl CryptoTrait for Crypto { } fn p256_ecdh( + &mut self, private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen, ) -> BytesP256ElemLen { @@ -200,7 +204,7 @@ impl CryptoTrait for Crypto { output } - fn get_random_byte() -> u8 { + fn get_random_byte(&mut self) -> u8 { let mut rnd_context = CRYS_RND_State_t::default(); let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); unsafe { @@ -221,7 +225,7 @@ impl CryptoTrait for Crypto { buffer[0] } - fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { + fn p256_generate_key_pair(&mut self) -> (BytesP256ElemLen, BytesP256ElemLen) { let mut rnd_context = CRYS_RND_State_t::default(); let mut rnd_work_buffer = CRYS_RND_WorkBuff_t::default(); unsafe { diff --git a/crypto/edhoc-crypto-hacspec/src/lib.rs b/crypto/edhoc-crypto-hacspec/src/lib.rs index f35b9372..a7a46ea9 100644 --- a/crypto/edhoc-crypto-hacspec/src/lib.rs +++ b/crypto/edhoc-crypto-hacspec/src/lib.rs @@ -75,7 +75,7 @@ type BufferPlaintext3Hacspec = EdhocMessageBufferHacspec; pub struct Crypto; impl CryptoTrait for Crypto { - fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + fn sha256_digest(&mut self, message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { let message: BytesMaxBufferHacspec = BytesMaxBufferHacspec::from_public_slice(message); let output = @@ -85,6 +85,7 @@ impl CryptoTrait for Crypto { } fn hkdf_expand( + &mut self, prk: &BytesHashLen, info: &BytesMaxInfoBuffer, info_len: usize, @@ -107,7 +108,7 @@ impl CryptoTrait for Crypto { output.to_public_array() } - fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { + fn hkdf_extract(&mut self, salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { let output = BytesHashLenHacspec::from_seq(&extract( &ByteSeq::from_slice(&BytesHashLenHacspec::from_public_slice(salt), 0, salt.len()), &ByteSeq::from_slice( @@ -120,6 +121,7 @@ impl CryptoTrait for Crypto { } fn aes_ccm_encrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -143,6 +145,7 @@ impl CryptoTrait for Crypto { } fn aes_ccm_decrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -168,6 +171,7 @@ impl CryptoTrait for Crypto { } fn p256_ecdh( + &mut self, private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen, ) -> BytesP256ElemLen { @@ -189,12 +193,12 @@ impl CryptoTrait for Crypto { } #[cfg(not(feature = "hacspec-pure"))] - fn get_random_byte() -> u8 { + fn get_random_byte(&mut self) -> u8 { rand::thread_rng().gen::() } #[cfg(not(feature = "hacspec-pure"))] - fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { + fn p256_generate_key_pair(&mut self) -> (BytesP256ElemLen, BytesP256ElemLen) { // generate a private key let mut private_key = BytesP256ElemLenHacspec::new(); loop { @@ -221,14 +225,14 @@ mod tests { #[test] fn test_p256_keys() { - let (x, g_x) = Crypto::p256_generate_key_pair(); + let (x, g_x) = Crypto.p256_generate_key_pair(); assert_eq!(x.len(), 32); assert_eq!(g_x.len(), 32); - let (y, g_y) = p256_generate_key_pair(); + let (y, g_y) = Crypto.p256_generate_key_pair(); - let g_xy = p256_ecdh(&x, &g_y); - let g_yx = p256_ecdh(&y, &g_x); + let g_xy = Crypto.p256_ecdh(&x, &g_y); + let g_yx = Crypto.p256_ecdh(&y, &g_x); assert_eq!(g_xy, g_yx); } diff --git a/crypto/edhoc-crypto-psa/src/lib.rs b/crypto/edhoc-crypto-psa/src/lib.rs index 2c54d925..a8ed7cb6 100644 --- a/crypto/edhoc-crypto-psa/src/lib.rs +++ b/crypto/edhoc-crypto-psa/src/lib.rs @@ -25,7 +25,7 @@ pub extern "C" fn mbedtls_hardware_poll( pub struct Crypto; impl CryptoTrait for Crypto { - fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + fn sha256_digest(&mut self, message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { let hash_alg = Hash::Sha256; let mut hash: [u8; SHA256_DIGEST_LEN] = [0; SHA256_DIGEST_LEN]; psa_crypto::init().unwrap(); @@ -37,6 +37,7 @@ impl CryptoTrait for Crypto { // FIXME: Together with hkdf_extract, and the hmac_sha256 helper, this could be a provided // function. fn hkdf_expand( + &mut self, prk: &BytesHashLen, info: &BytesMaxInfoBuffer, info_len: usize, @@ -76,7 +77,7 @@ impl CryptoTrait for Crypto { output } - fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { + fn hkdf_extract(&mut self, salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { // Implementation of HKDF-Extract as per RFC 5869 // TODO generalize if salt is not provided @@ -86,6 +87,7 @@ impl CryptoTrait for Crypto { } fn aes_ccm_encrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -127,6 +129,7 @@ impl CryptoTrait for Crypto { } fn aes_ccm_decrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, @@ -170,6 +173,7 @@ impl CryptoTrait for Crypto { } fn p256_ecdh( + &mut self, private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen, ) -> BytesP256ElemLen { @@ -202,14 +206,14 @@ impl CryptoTrait for Crypto { output_buffer } - fn get_random_byte() -> u8 { + fn get_random_byte(&mut self) -> u8 { psa_crypto::init().unwrap(); let mut buffer = [0u8; 1]; generate_random(&mut buffer); // TODO: check return value buffer[0] } - fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen) { + fn p256_generate_key_pair(&mut self) -> (BytesP256ElemLen, BytesP256ElemLen) { let alg = RawKeyAgreement::Ecdh; let mut usage_flags: UsageFlags = UsageFlags::default(); usage_flags.set_export(); @@ -264,7 +268,7 @@ fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLen { s2[64..64 + message.len()].copy_from_slice(message); // (4) apply H to the stream generated in step (3) - let ih = Crypto::sha256_digest(&s2, 64 + message.len()); + let ih = Crypto.sha256_digest(&s2, 64 + message.len()); // (5) XOR (bitwise exclusive-OR) the B byte string computed in // step (1) with opad @@ -278,7 +282,7 @@ fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLen { // (7) apply H to the stream generated in step (6) and output // the result - let oh = Crypto::sha256_digest(&s5, 3 * SHA256_DIGEST_LEN); + let oh = Crypto.sha256_digest(&s5, 3 * SHA256_DIGEST_LEN); oh } diff --git a/crypto/edhoc-crypto-trait/src/lib.rs b/crypto/edhoc-crypto-trait/src/lib.rs index 9863b7be..a3030c4c 100644 --- a/crypto/edhoc-crypto-trait/src/lib.rs +++ b/crypto/edhoc-crypto-trait/src/lib.rs @@ -4,28 +4,34 @@ use edhoc_consts::*; pub trait Crypto { - fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen; + fn sha256_digest(&mut self, message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen; fn hkdf_expand( + &mut self, prk: &BytesHashLen, info: &BytesMaxInfoBuffer, info_len: usize, length: usize, ) -> BytesMaxBuffer; - fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen; + fn hkdf_extract(&mut self, salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen; fn aes_ccm_encrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, plaintext: &BufferPlaintext3, ) -> BufferCiphertext3; fn aes_ccm_decrypt_tag_8( + &mut self, key: &BytesCcmKeyLen, iv: &BytesCcmIvLen, ad: &BytesEncStructureLen, ciphertext: &BufferCiphertext3, ) -> Result; - fn p256_ecdh(private_key: &BytesP256ElemLen, public_key: &BytesP256ElemLen) - -> BytesP256ElemLen; - fn get_random_byte() -> u8; - fn p256_generate_key_pair() -> (BytesP256ElemLen, BytesP256ElemLen); + fn p256_ecdh( + &mut self, + private_key: &BytesP256ElemLen, + public_key: &BytesP256ElemLen, + ) -> BytesP256ElemLen; + fn get_random_byte(&mut self) -> u8; + fn p256_generate_key_pair(&mut self) -> (BytesP256ElemLen, BytesP256ElemLen); } diff --git a/crypto/src/lib.rs b/crypto/src/lib.rs index 2ab28510..09e0f6b6 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -12,6 +12,11 @@ pub use edhoc_crypto_trait::Crypto as CryptoTrait; #[cfg(feature = "hacspec")] pub type Crypto = edhoc_crypto_hacspec::Crypto; +#[cfg(feature = "hacspec")] +pub const fn default_crypto() -> Crypto { + edhoc_crypto_hacspec::Crypto +} + // FIXME: Does not work with crypto-as-trait yet #[cfg(feature = "cc2538")] pub use edhoc_crypto_cc2538::*; @@ -19,9 +24,19 @@ pub use edhoc_crypto_cc2538::*; #[cfg(any(feature = "psa", feature = "psa-rust",))] pub type Crypto = edhoc_crypto_psa::Crypto; +#[cfg(any(feature = "psa", feature = "psa-rust",))] +pub const fn default_crypto() -> Crypto { + edhoc_crypto_psa::Crypto +} + #[cfg(any(feature = "cryptocell310", feature = "cryptocell310-rust"))] pub type Crypto = edhoc_crypto_cryptocell310::Crypto; +#[cfg(any(feature = "cryptocell310", feature = "cryptocell310-rust"))] +pub const fn default_crypto() -> Crypto { + edhoc_crypto_cryptocell310::Crypto +} + /// See test_implements_crypto #[allow(dead_code)] fn test_helper() {} diff --git a/examples/edhoc-rs-no_std/src/main.rs b/examples/edhoc-rs-no_std/src/main.rs index d6be5370..a6d02734 100644 --- a/examples/edhoc-rs-no_std/src/main.rs +++ b/examples/edhoc-rs-no_std/src/main.rs @@ -13,7 +13,7 @@ use panic_semihosting as _; #[cfg(feature = "rtt")] use rtt_target::{rprintln as println, rtt_init_print}; -use edhoc_crypto::{Crypto, CryptoTrait}; +use edhoc_crypto::{default_crypto, CryptoTrait}; use edhoc_rs::*; extern crate alloc; @@ -81,11 +81,11 @@ fn main() -> ! { println!("Test test_new_initiator passed."); fn test_p256_keys() { - let (x, g_x) = Crypto::p256_generate_key_pair(); - let (y, g_y) = Crypto::p256_generate_key_pair(); + let (x, g_x) = default_crypto().p256_generate_key_pair(); + let (y, g_y) = default_crypto().p256_generate_key_pair(); - let g_xy = Crypto::p256_ecdh(&x, &g_y); - let g_yx = Crypto::p256_ecdh(&y, &g_x); + let g_xy = default_crypto().p256_ecdh(&x, &g_y); + let g_yx = default_crypto().p256_ecdh(&y, &g_x); assert_eq!(g_xy, g_yx); } diff --git a/lib/src/c_wrapper.rs b/lib/src/c_wrapper.rs index c394c7f1..a6a7be0f 100644 --- a/lib/src/c_wrapper.rs +++ b/lib/src/c_wrapper.rs @@ -3,7 +3,7 @@ use core::{slice, str}; use edhoc_consts::*; use hexlit::hex; -use edhoc_crypto::{Crypto, CryptoTrait}; +use edhoc_crypto::{default_crypto, CryptoTrait}; // Panic handler for cortex-m targets #[cfg(any(feature = "crypto-cryptocell310", feature = "crypto-psa-baremetal"))] @@ -12,7 +12,7 @@ use panic_semihosting as _; // This function is mainly used to test the C wrapper #[no_mangle] pub extern "C" fn p256_generate_key_pair_from_c(out_private_key: *mut u8, out_public_key: *mut u8) { - let (private_key, public_key) = Crypto::p256_generate_key_pair(); + let (private_key, public_key) = default_crypto().p256_generate_key_pair(); unsafe { // copy the arrays to the pointers received from C diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index 5ca68cc7..e5f31ddb 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -6,6 +6,7 @@ use edhoc_ead::*; pub fn edhoc_exporter( state: State, + crypto: &mut Crypto, label: u8, context: &BytesMaxContextBuffer, context_len: usize, @@ -28,7 +29,7 @@ pub fn edhoc_exporter( let mut error = EDHOCError::UnknownError; if current_state == EDHOCState::Completed { - output = edhoc_kdf::(&prk_exporter, label, context, context_len, length); + output = crypto.edhoc_kdf(&prk_exporter, label, context, context_len, length); Ok((state, output)) } else { Err(EDHOCError::WrongState) @@ -37,6 +38,7 @@ pub fn edhoc_exporter( pub fn edhoc_key_update( mut state: State, + crypto: &mut Crypto, context: &BytesMaxContextBuffer, context_len: usize, ) -> Result<(State, BytesHashLen), EDHOCError> { @@ -58,11 +60,11 @@ pub fn edhoc_key_update( if current_state == EDHOCState::Completed { // new PRK_out - prk_new_buf = edhoc_kdf::(&prk_out, 11u8, context, context_len, SHA256_DIGEST_LEN); + prk_new_buf = crypto.edhoc_kdf(&prk_out, 11u8, context, context_len, SHA256_DIGEST_LEN); prk_out[..SHA256_DIGEST_LEN].copy_from_slice(&prk_new_buf[..SHA256_DIGEST_LEN]); // new PRK_exporter - prk_new_buf = edhoc_kdf::( + prk_new_buf = crypto.edhoc_kdf( &prk_out, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -92,6 +94,7 @@ pub fn edhoc_key_update( pub fn r_process_message_1( mut state: State, + crypto: &mut Crypto, message_1: &BufferMessage1, ) -> Result { let State( @@ -131,7 +134,7 @@ pub fn r_process_message_1( let mut message_1_buf: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; message_1_buf[..message_1.len] .copy_from_slice(&message_1.content[..message_1.len]); - h_message_1 = Crypto::sha256_digest(&message_1_buf, message_1.len); + h_message_1 = crypto.sha256_digest(&message_1_buf, message_1.len); error = EDHOCError::Success; current_state = EDHOCState::ProcessedMessage1; @@ -172,6 +175,7 @@ pub fn r_process_message_1( pub fn r_prepare_message_2( mut state: State, + crypto: &mut Crypto, id_cred_r: &BytesIdCred, cred_r: &[u8], r: &BytesP256ElemLen, // R's static private DH key @@ -197,15 +201,15 @@ pub fn r_prepare_message_2( if current_state == EDHOCState::ProcessedMessage1 { // compute TH_2 - let th_2 = compute_th_2::(&g_y, &h_message_1); + let th_2 = crypto.compute_th_2(&g_y, &h_message_1); // compute prk_3e2m - let prk_2e = compute_prk_2e::(&y, &g_x, &th_2); - let salt_3e2m = compute_salt_3e2m::(&prk_2e, &th_2); - prk_3e2m = compute_prk_3e2m::(&salt_3e2m, r, &g_x); + let prk_2e = crypto.compute_prk_2e(&y, &g_x, &th_2); + let salt_3e2m = crypto.compute_salt_3e2m(&prk_2e, &th_2); + prk_3e2m = crypto.compute_prk_3e2m(&salt_3e2m, r, &g_x); // compute MAC_2 - let mac_2 = compute_mac_2::(&prk_3e2m, id_cred_r, cred_r, &th_2); + let mac_2 = crypto.compute_mac_2(&prk_3e2m, id_cred_r, cred_r, &th_2); let ead_2 = r_prepare_ead_2(); @@ -214,14 +218,14 @@ pub fn r_prepare_message_2( // step is actually from processing of message_3 // but we do it here to avoid storing plaintext_2 in State - th_3 = compute_th_3::(&th_2, &plaintext_2, cred_r); + th_3 = crypto.compute_th_3(&th_2, &plaintext_2, cred_r); let mut ct: BufferCiphertext2 = BufferCiphertext2::new(); ct.len = plaintext_2.len; ct.content[..ct.len].copy_from_slice(&plaintext_2.content[..ct.len]); let (ciphertext_2, ciphertext_2_len) = - encrypt_decrypt_ciphertext_2::(&prk_2e, &th_2, &ct); + crypto.encrypt_decrypt_ciphertext_2(&prk_2e, &th_2, &ct); ct.content[..ct.len].copy_from_slice(&ciphertext_2[..ct.len]); @@ -255,6 +259,7 @@ pub fn r_prepare_message_2( // FIXME fetch ID_CRED_I and CRED_I based on kid pub fn r_process_message_3( mut state: State, + crypto: &mut Crypto, message_3: &BufferMessage3, id_cred_i_expected: &BytesIdCred, cred_i_expected: &[u8], @@ -276,7 +281,7 @@ pub fn r_process_message_3( let mut error = EDHOCError::UnknownError; if current_state == EDHOCState::WaitMessage3 { - let plaintext_3 = decrypt_message_3::(&prk_3e2m, &th_3, message_3); + let plaintext_3 = crypto.decrypt_message_3(&prk_3e2m, &th_3, message_3); if plaintext_3.is_ok() { let plaintext_3 = plaintext_3.unwrap(); @@ -295,12 +300,12 @@ pub fn r_process_message_3( // compare the kid received with the kid expected in id_cred_i if kid == id_cred_i_expected[id_cred_i_expected.len() - 1] { // compute salt_4e3m - let salt_4e3m = compute_salt_4e3m::(&prk_3e2m, &th_3); + let salt_4e3m = crypto.compute_salt_4e3m(&prk_3e2m, &th_3); // TODO compute prk_4e3m - prk_4e3m = compute_prk_4e3m::(&salt_4e3m, &y, g_i); + prk_4e3m = crypto.compute_prk_4e3m(&salt_4e3m, &y, g_i); // compute mac_3 - let expected_mac_3 = compute_mac_3::( + let expected_mac_3 = crypto.compute_mac_3( &prk_4e3m, &th_3, id_cred_i_expected, @@ -310,13 +315,13 @@ pub fn r_process_message_3( // verify mac_3 if mac_3 == expected_mac_3 { error = EDHOCError::Success; - let th_4 = compute_th_4::(&th_3, &plaintext_3, cred_i_expected); + let th_4 = crypto.compute_th_4(&th_3, &plaintext_3, cred_i_expected); let mut th_4_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_4_buf[..th_4.len()].copy_from_slice(&th_4[..]); // compute prk_out // PRK_out = EDHOC-KDF( PRK_4e3m, 7, TH_4, hash_length ) - let prk_out_buf = edhoc_kdf::( + let prk_out_buf = crypto.edhoc_kdf( &prk_4e3m, 7u8, &th_4_buf, @@ -328,7 +333,7 @@ pub fn r_process_message_3( // compute prk_exporter from prk_out // PRK_exporter = EDHOC-KDF( PRK_out, 10, h'', hash_length ) - let prk_exporter_buf = edhoc_kdf::( + let prk_exporter_buf = crypto.edhoc_kdf( &prk_out, 10u8, &[0x00u8; MAX_KDF_CONTEXT_LEN], @@ -381,6 +386,7 @@ pub fn r_process_message_3( pub fn i_prepare_message_1( mut state: State, + crypto: &mut Crypto, x: BytesP256ElemLen, g_x: BytesP256ElemLen, c_i: u8, @@ -423,7 +429,7 @@ pub fn i_prepare_message_1( message_1_buf[..message_1.len].copy_from_slice(&message_1.content[..message_1.len]); // hash message_1 here to avoid saving the whole message in the state - h_message_1 = Crypto::sha256_digest(&message_1_buf, message_1.len); + h_message_1 = crypto.sha256_digest(&message_1_buf, message_1.len); error = EDHOCError::Success; current_state = EDHOCState::WaitMessage2; @@ -452,6 +458,7 @@ pub fn i_prepare_message_1( // returns c_r pub fn i_process_message_2( mut state: State, + crypto: &mut Crypto, message_2: &BufferMessage2, id_cred_r_expected: &BytesIdCred, cred_r_expected: &[u8], @@ -481,13 +488,13 @@ pub fn i_process_message_2( if res.is_ok() { let (g_y, ciphertext_2) = res.unwrap(); - let th_2 = compute_th_2::(&g_y, &h_message_1); + let th_2 = crypto.compute_th_2(&g_y, &h_message_1); // compute prk_2e - let prk_2e = compute_prk_2e::(&x, &g_y, &th_2); + let prk_2e = crypto.compute_prk_2e(&x, &g_y, &th_2); let (plaintext_2, plaintext_2_len) = - encrypt_decrypt_ciphertext_2::(&prk_2e, &th_2, &ciphertext_2); + crypto.encrypt_decrypt_ciphertext_2(&prk_2e, &th_2, &ciphertext_2); // decode plaintext_2 let plaintext_2_decoded = decode_plaintext_2(&plaintext_2, plaintext_2_len); @@ -504,11 +511,11 @@ pub fn i_process_message_2( }; if ead_success { // verify mac_2 - let salt_3e2m = compute_salt_3e2m::(&prk_2e, &th_2); + let salt_3e2m = crypto.compute_salt_3e2m(&prk_2e, &th_2); - prk_3e2m = compute_prk_3e2m::(&salt_3e2m, &x, g_r); + prk_3e2m = crypto.compute_prk_3e2m(&salt_3e2m, &x, g_r); - let expected_mac_2 = compute_mac_2::( + let expected_mac_2 = crypto.compute_mac_2( &prk_3e2m, id_cred_r_expected, cred_r_expected, @@ -523,12 +530,12 @@ pub fn i_process_message_2( pt2.content[..plaintext_2_len] .copy_from_slice(&plaintext_2[..plaintext_2_len]); pt2.len = plaintext_2_len; - th_3 = compute_th_3::(&th_2, &pt2, cred_r_expected); + th_3 = crypto.compute_th_3(&th_2, &pt2, cred_r_expected); // message 3 processing - let salt_4e3m = compute_salt_4e3m::(&prk_3e2m, &th_3); + let salt_4e3m = crypto.compute_salt_4e3m(&prk_3e2m, &th_3); - prk_4e3m = compute_prk_4e3m::(&salt_4e3m, i, &g_y); + prk_4e3m = crypto.compute_prk_4e3m(&salt_4e3m, i, &g_y); error = EDHOCError::Success; current_state = EDHOCState::ProcessedMessage2; @@ -573,6 +580,7 @@ pub fn i_process_message_2( pub fn i_prepare_message_3( mut state: State, + crypto: &mut Crypto, id_cred_i: &BytesIdCred, cred_i: &[u8], ) -> Result<(State, BufferMessage3, BytesHashLen), EDHOCError> { @@ -593,14 +601,14 @@ pub fn i_prepare_message_3( let mut message_3: BufferMessage3 = BufferMessage3::new(); if current_state == EDHOCState::ProcessedMessage2 { - let mac_3 = compute_mac_3::(&prk_4e3m, &th_3, id_cred_i, cred_i); + let mac_3 = crypto.compute_mac_3(&prk_4e3m, &th_3, id_cred_i, cred_i); let ead_3 = i_prepare_ead_3(); let plaintext_3 = encode_plaintext_3(id_cred_i, &mac_3, &ead_3); - message_3 = encrypt_message_3::(&prk_3e2m, &th_3, &plaintext_3); + message_3 = crypto.encrypt_message_3(&prk_3e2m, &th_3, &plaintext_3); - let th_4 = compute_th_4::(&th_3, &plaintext_3, cred_i); + let th_4 = crypto.compute_th_4(&th_3, &plaintext_3, cred_i); let mut th_4_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_4_buf[..th_4.len()].copy_from_slice(&th_4[..]); @@ -608,12 +616,12 @@ pub fn i_prepare_message_3( // compute prk_out // PRK_out = EDHOC-KDF( PRK_4e3m, 7, TH_4, hash_length ) let prk_out_buf = - edhoc_kdf::(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); + crypto.edhoc_kdf(&prk_4e3m, 7u8, &th_4_buf, th_4.len(), SHA256_DIGEST_LEN); prk_out[..SHA256_DIGEST_LEN].copy_from_slice(&prk_out_buf[..SHA256_DIGEST_LEN]); // compute prk_exporter from prk_out // PRK_exporter = EDHOC-KDF( PRK_out, 10, h'', hash_length ) - let prk_exporter_buf = edhoc_kdf::( + let prk_exporter_buf = crypto.edhoc_kdf( &prk_out, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -1007,7 +1015,18 @@ fn encode_message_2(g_y: &BytesP256ElemLen, ciphertext_2: &BufferCiphertext2) -> output } -fn compute_th_2( +// All these functions that are generally pure functions without any state they handle are +// expressed as an extension to the Crypto trait, because this gives the easiest invocation +// semantics -- any code outside them can just call `crypto.compute_th_2()`, code inside calls +// `self.some_function()`. +// +// It's easier to write because it allows the Crypto generics to sit on the trait instead of being +// repeated for each function. (Other than that, they could all just as well be called +// `computed_th_2(crypto, ...)` etc). +trait CryptoExt: CryptoTrait { + +fn compute_th_2( + &mut self, g_y: &BytesP256ElemLen, h_message_1: &BytesHashLen, ) -> BytesHashLen { @@ -1022,12 +1041,13 @@ fn compute_th_2( let len = 4 + P256_ELEM_LEN + SHA256_DIGEST_LEN; - let th_2 = Crypto::sha256_digest(&message, len); + let th_2 = self.sha256_digest(&message, len); th_2 } -fn compute_th_3( +fn compute_th_3( + &mut self, th_2: &BytesHashLen, plaintext_2: &BufferPlaintext2, cred_r: &[u8], @@ -1042,12 +1062,13 @@ fn compute_th_3( message[2 + th_2.len() + plaintext_2.len..2 + th_2.len() + plaintext_2.len + cred_r.len()] .copy_from_slice(cred_r); - let output = Crypto::sha256_digest(&message, th_2.len() + 2 + plaintext_2.len + cred_r.len()); + let output = self.sha256_digest(&message, th_2.len() + 2 + plaintext_2.len + cred_r.len()); output } -fn compute_th_4( +fn compute_th_4( + &mut self, th_3: &BytesHashLen, plaintext_3: &BufferPlaintext3, cred_i: &[u8], @@ -1062,12 +1083,13 @@ fn compute_th_4( message[2 + th_3.len() + plaintext_3.len..2 + th_3.len() + plaintext_3.len + cred_i.len()] .copy_from_slice(cred_i); - let output = Crypto::sha256_digest(&message, th_3.len() + 2 + plaintext_3.len + cred_i.len()); + let output = self.sha256_digest(&message, th_3.len() + 2 + plaintext_3.len + cred_i.len()); output } -fn edhoc_kdf( +fn edhoc_kdf( + &mut self, prk: &BytesHashLen, label: u8, context: &BytesMaxContextBuffer, @@ -1098,12 +1120,13 @@ fn edhoc_kdf( info_len = info_len + 2; } - let output = Crypto::hkdf_expand(prk, &info, info_len, length); + let output = self.hkdf_expand(prk, &info, info_len, length); output } -fn compute_k_3_iv_3( +fn compute_k_3_iv_3( + &mut self, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, ) -> (BytesCcmKeyLen, BytesCcmIvLen) { @@ -1111,19 +1134,20 @@ fn compute_k_3_iv_3( let mut k_3: BytesCcmKeyLen = [0x00; AES_CCM_KEY_LEN]; let mut th_3_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_3_buf[..th_3.len()].copy_from_slice(&th_3[..]); - let k_3_buf = edhoc_kdf::(prk_3e2m, 3u8, &th_3_buf, th_3.len(), AES_CCM_KEY_LEN); + let k_3_buf = self.edhoc_kdf(prk_3e2m, 3u8, &th_3_buf, th_3.len(), AES_CCM_KEY_LEN); k_3[..].copy_from_slice(&k_3_buf[..AES_CCM_KEY_LEN]); // IV_3 = EDHOC-KDF( PRK_3e2m, 4, TH_3, iv_length ) let mut iv_3: BytesCcmIvLen = [0x00; AES_CCM_IV_LEN]; - let iv_3_buf = edhoc_kdf::(prk_3e2m, 4u8, &th_3_buf, th_3.len(), AES_CCM_IV_LEN); + let iv_3_buf = self.edhoc_kdf(prk_3e2m, 4u8, &th_3_buf, th_3.len(), AES_CCM_IV_LEN); iv_3[..].copy_from_slice(&iv_3_buf[..AES_CCM_IV_LEN]); (k_3, iv_3) } // calculates ciphertext_3 wrapped in a cbor byte string -fn encrypt_message_3( +fn encrypt_message_3( + &mut self, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, plaintext_3: &BufferPlaintext3, @@ -1134,16 +1158,17 @@ fn encrypt_message_3( let enc_structure = encode_enc_structure(th_3); - let (k_3, iv_3) = compute_k_3_iv_3::(prk_3e2m, th_3); + let (k_3, iv_3) = self.compute_k_3_iv_3(prk_3e2m, th_3); - let ciphertext_3 = Crypto::aes_ccm_encrypt_tag_8(&k_3, &iv_3, &enc_structure, plaintext_3); + let ciphertext_3 = self.aes_ccm_encrypt_tag_8(&k_3, &iv_3, &enc_structure, plaintext_3); output.content[1..output.len].copy_from_slice(&ciphertext_3.content[..ciphertext_3.len]); output } -fn decrypt_message_3( +fn decrypt_message_3( + &mut self, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, message_3: &BufferMessage3, @@ -1158,11 +1183,11 @@ fn decrypt_message_3( ciphertext_3.len = len; ciphertext_3.content[..len].copy_from_slice(&message_3.content[1..1 + len]); - let (k_3, iv_3) = compute_k_3_iv_3::(prk_3e2m, th_3); + let (k_3, iv_3) = self.compute_k_3_iv_3(prk_3e2m, th_3); let enc_structure = encode_enc_structure(th_3); - let p3 = Crypto::aes_ccm_decrypt_tag_8(&k_3, &iv_3, &enc_structure, &ciphertext_3); + let p3 = self.aes_ccm_decrypt_tag_8(&k_3, &iv_3, &enc_structure, &ciphertext_3); if p3.is_ok() { error = EDHOCError::Success; @@ -1179,7 +1204,8 @@ fn decrypt_message_3( } } -fn compute_mac_3( +fn compute_mac_3( + &mut self, prk_4e3m: &BytesHashLen, th_3: &BytesHashLen, id_cred_i: &BytesIdCred, @@ -1189,7 +1215,7 @@ fn compute_mac_3( let (context, context_len) = encode_kdf_context(id_cred_i, th_3, cred_i); // compute mac_3 - let output_buf = edhoc_kdf::( + let output_buf = self.edhoc_kdf( prk_4e3m, 6u8, // registered label for "MAC_3" &context, @@ -1202,7 +1228,8 @@ fn compute_mac_3( output } -fn compute_mac_2( +fn compute_mac_2( + &mut self, prk_3e2m: &BytesHashLen, id_cred_r: &BytesIdCred, cred_r: &[u8], @@ -1214,14 +1241,15 @@ fn compute_mac_2( // MAC_2 = EDHOC-KDF( PRK_3e2m, 2, context_2, mac_length_2 ) let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2]; mac_2[..].copy_from_slice( - &edhoc_kdf::(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2) + &self.edhoc_kdf(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2) [..MAC_LENGTH_2], ); mac_2 } -fn encrypt_decrypt_ciphertext_2( +fn encrypt_decrypt_ciphertext_2( + &mut self, prk_2e: &BytesHashLen, th_2: &BytesHashLen, ciphertext_2: &BufferCiphertext2, @@ -1231,7 +1259,7 @@ fn encrypt_decrypt_ciphertext_2( th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); // KEYSTREAM_2 = EDHOC-KDF( PRK_2e, 0, TH_2, plaintext_length ) - let keystream_2 = edhoc_kdf::( + let keystream_2 = self.edhoc_kdf( prk_2e, 0u8, &th_2_context, @@ -1248,40 +1276,43 @@ fn encrypt_decrypt_ciphertext_2( (plaintext_2, ciphertext_2.len) } -fn compute_salt_4e3m( +fn compute_salt_4e3m( + &mut self, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, ) -> BytesHashLen { let mut th_3_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_3_context[..th_3.len()].copy_from_slice(&th_3[..]); let salt_4e3m_buf = - edhoc_kdf::(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); + self.edhoc_kdf(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); let mut salt_4e3m: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; salt_4e3m[..].copy_from_slice(&salt_4e3m_buf[..SHA256_DIGEST_LEN]); salt_4e3m } -fn compute_prk_4e3m( +fn compute_prk_4e3m( + &mut self, salt_4e3m: &BytesHashLen, i: &BytesP256ElemLen, g_y: &BytesP256ElemLen, ) -> BytesHashLen { // compute g_rx from static R's public key and private ephemeral key - let g_iy = Crypto::p256_ecdh(i, g_y); - let prk_4e3m = Crypto::hkdf_extract(salt_4e3m, &g_iy); + let g_iy = self.p256_ecdh(i, g_y); + let prk_4e3m = self.hkdf_extract(salt_4e3m, &g_iy); prk_4e3m } -fn compute_salt_3e2m( +fn compute_salt_3e2m( + &mut self, prk_2e: &BytesHashLen, th_2: &BytesHashLen, ) -> BytesHashLen { let mut th_2_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); - let salt_3e2m_buf = edhoc_kdf::( + let salt_3e2m_buf = self.edhoc_kdf( prk_2e, 1u8, &th_2_context, @@ -1295,31 +1326,37 @@ fn compute_salt_3e2m( salt_3e2m } -fn compute_prk_3e2m( +fn compute_prk_3e2m( + &mut self, salt_3e2m: &BytesHashLen, x: &BytesP256ElemLen, g_r: &BytesP256ElemLen, ) -> BytesHashLen { // compute g_rx from static R's public key and private ephemeral key - let g_rx = Crypto::p256_ecdh(x, g_r); - let prk_3e2m = Crypto::hkdf_extract(salt_3e2m, &g_rx); + let g_rx = self.p256_ecdh(x, g_r); + let prk_3e2m = self.hkdf_extract(salt_3e2m, &g_rx); prk_3e2m } -fn compute_prk_2e( +fn compute_prk_2e( + &mut self, x: &BytesP256ElemLen, g_y: &BytesP256ElemLen, th_2: &BytesHashLen, ) -> BytesHashLen { // compute the shared secret - let g_xy = Crypto::p256_ecdh(x, g_y); + let g_xy = self.p256_ecdh(x, g_y); // compute prk_2e as PRK_2e = HMAC-SHA-256( salt, G_XY ) - let prk_2e = Crypto::hkdf_extract(th_2, &g_xy); + let prk_2e = self.hkdf_extract(th_2, &g_xy); prk_2e } +} + +impl CryptoExt for Crypto {} + fn decode_plaintext_3( plaintext_3: &BufferPlaintext3, ) -> Result<(u8, BytesMac3, Option), EDHOCError> { @@ -1509,7 +1546,7 @@ mod tests { use super::*; use hexlit::hex; - use edhoc_crypto::Crypto; + use edhoc_crypto::default_crypto; // test vectors (TV) // message_1 (first_time) @@ -1618,7 +1655,7 @@ mod tests { #[test] fn test_ecdh() { - let g_xy = Crypto::p256_ecdh(&X_TV, &G_Y_TV); + let g_xy = default_crypto().p256_ecdh(&X_TV, &G_Y_TV); assert_eq!(g_xy, G_XY_TV); } @@ -1756,7 +1793,7 @@ mod tests { #[test] fn test_compute_th_2() { - let th_2 = compute_th_2::(&G_Y_TV, &H_MESSAGE_1_TV); + let th_2 = default_crypto().compute_th_2(&G_Y_TV, &H_MESSAGE_1_TV); assert_eq!(th_2, TH_2_TV); } @@ -1764,7 +1801,7 @@ mod tests { fn test_compute_th_3() { let plaintext_2_tv = BufferPlaintext2::from_hex(PLAINTEXT_2_TV); - let th_3 = compute_th_3::(&TH_2_TV, &plaintext_2_tv, &CRED_R_TV); + let th_3 = default_crypto().compute_th_3(&TH_2_TV, &plaintext_2_tv, &CRED_R_TV); assert_eq!(th_3, TH_3_TV); } @@ -1772,7 +1809,7 @@ mod tests { fn test_compute_th_4() { let plaintext_3_tv = BufferPlaintext3::from_hex(PLAINTEXT_3_TV); - let th_4 = compute_th_4::(&TH_3_TV, &plaintext_3_tv, &CRED_I_TV); + let th_4 = default_crypto().compute_th_4(&TH_3_TV, &plaintext_3_tv, &CRED_I_TV); assert_eq!(th_4, TH_4_TV); } @@ -1783,7 +1820,7 @@ mod tests { const LEN_TV: usize = PLAINTEXT_2_LEN_TV; let output = - edhoc_kdf::(&PRK_2E_TV, 0u8, &th_2_context_tv, SHA256_DIGEST_LEN, LEN_TV); + default_crypto().edhoc_kdf(&PRK_2E_TV, 0u8, &th_2_context_tv, SHA256_DIGEST_LEN, LEN_TV); for i in 0..KEYSTREAM_2_TV.len() { assert_eq!(KEYSTREAM_2_TV[i], output[i]); } @@ -1792,7 +1829,7 @@ mod tests { context_info_mac_2[..CONTEXT_INFO_MAC_2_TV.len()] .copy_from_slice(&CONTEXT_INFO_MAC_2_TV[..]); - let output_2 = edhoc_kdf::( + let output_2 = default_crypto().edhoc_kdf( &PRK_3E2M_TV, 2u8, &context_info_mac_2, @@ -1810,7 +1847,7 @@ mod tests { let plaintext_3_tv = BufferPlaintext3::from_hex(PLAINTEXT_3_TV); let message_3_tv = BufferMessage3::from_hex(MESSAGE_3_TV); - let message_3 = encrypt_message_3::(&PRK_3E2M_TV, &TH_3_TV, &plaintext_3_tv); + let message_3 = default_crypto().encrypt_message_3(&PRK_3E2M_TV, &TH_3_TV, &plaintext_3_tv); assert_eq!(message_3, message_3_tv); } @@ -1819,20 +1856,20 @@ mod tests { let plaintext_3_tv = BufferPlaintext3::from_hex(PLAINTEXT_3_TV); let message_3_tv = BufferMessage3::from_hex(MESSAGE_3_TV); - let plaintext_3 = decrypt_message_3::(&PRK_3E2M_TV, &TH_3_TV, &message_3_tv); + let plaintext_3 = default_crypto().decrypt_message_3(&PRK_3E2M_TV, &TH_3_TV, &message_3_tv); assert!(plaintext_3.is_ok()); assert_eq!(plaintext_3.unwrap(), plaintext_3_tv); } #[test] fn test_compute_mac_3() { - let mac_3 = compute_mac_3::(&PRK_4E3M_TV, &TH_3_TV, &ID_CRED_I_TV, &CRED_I_TV); + let mac_3 = default_crypto().compute_mac_3(&PRK_4E3M_TV, &TH_3_TV, &ID_CRED_I_TV, &CRED_I_TV); assert_eq!(mac_3, MAC_3_TV); } #[test] fn test_compute_and_verify_mac_2() { - let rcvd_mac_2 = compute_mac_2::(&PRK_3E2M_TV, &ID_CRED_R_TV, &CRED_R_TV, &TH_2_TV); + let rcvd_mac_2 = default_crypto().compute_mac_2(&PRK_3E2M_TV, &ID_CRED_R_TV, &CRED_R_TV, &TH_2_TV); assert_eq!(rcvd_mac_2, MAC_2_TV); } @@ -1885,7 +1922,7 @@ mod tests { let ciphertext_2_tv = BufferPlaintext2::from_hex(CIPHERTEXT_2_TV); // test decryption let (plaintext_2, plaintext_2_len) = - encrypt_decrypt_ciphertext_2::(&PRK_2E_TV, &TH_2_TV, &ciphertext_2_tv); + default_crypto().encrypt_decrypt_ciphertext_2(&PRK_2E_TV, &TH_2_TV, &ciphertext_2_tv); assert_eq!(plaintext_2_len, PLAINTEXT_2_LEN_TV); for i in 0..PLAINTEXT_2_LEN_TV { @@ -1898,7 +1935,7 @@ mod tests { // test encryption let (ciphertext_2, ciphertext_2_len) = - encrypt_decrypt_ciphertext_2::(&PRK_2E_TV, &TH_2_TV, &plaintext_2_tmp); + default_crypto().encrypt_decrypt_ciphertext_2(&PRK_2E_TV, &TH_2_TV, &plaintext_2_tmp); assert_eq!(ciphertext_2_len, CIPHERTEXT_2_LEN_TV); for i in 0..CIPHERTEXT_2_LEN_TV { @@ -1908,19 +1945,19 @@ mod tests { #[test] fn test_compute_prk_4e3m() { - let prk_4e3m = compute_prk_4e3m::(&SALT_4E3M_TV, &SK_I_TV, &G_Y_TV); + let prk_4e3m = default_crypto().compute_prk_4e3m(&SALT_4E3M_TV, &SK_I_TV, &G_Y_TV); assert_eq!(prk_4e3m, PRK_4E3M_TV); } #[test] fn test_compute_prk_3e2m() { - let prk_3e2m = compute_prk_3e2m::(&SALT_3E2M_TV, &X_TV, &G_R_TV); + let prk_3e2m = default_crypto().compute_prk_3e2m(&SALT_3E2M_TV, &X_TV, &G_R_TV); assert_eq!(prk_3e2m, PRK_3E2M_TV); } #[test] fn test_compute_prk_2e() { - let prk_2e = compute_prk_2e::(&X_TV, &G_Y_TV, &TH_2_TV); + let prk_2e = default_crypto().compute_prk_2e(&X_TV, &G_Y_TV, &TH_2_TV); assert_eq!(prk_2e, PRK_2E_TV); } @@ -2032,7 +2069,7 @@ mod tests { let mut th_4_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; th_4_context[..TH_4_TV.len()].copy_from_slice(&TH_4_TV[..]); - let prk_out_buf = edhoc_kdf::( + let prk_out_buf = default_crypto().edhoc_kdf( &PRK_4E3M_TV, 7u8, &th_4_context, @@ -2047,7 +2084,7 @@ mod tests { #[test] fn test_compute_prk_exporter() { let mut prk_exporter: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; - let prk_exporter_buf = edhoc_kdf::( + let prk_exporter_buf = default_crypto().edhoc_kdf( &PRK_OUT_TV, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -2061,7 +2098,7 @@ mod tests { #[test] fn test_compute_oscore_master_secret_salt() { - let oscore_master_secret_buf = edhoc_kdf::( + let oscore_master_secret_buf = default_crypto().edhoc_kdf( &PRK_EXPORTER_TV, 0u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -2073,7 +2110,7 @@ mod tests { &OSCORE_MASTER_SECRET_TV[..] ); - let oscore_master_salt_buf = edhoc_kdf::( + let oscore_master_salt_buf = default_crypto().edhoc_kdf( &PRK_EXPORTER_TV, 1u8, &[0x00; MAX_KDF_CONTEXT_LEN], diff --git a/lib/src/lib.rs b/lib/src/lib.rs index f285c7c4..3938d7e6 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -1,7 +1,7 @@ #![cfg_attr(not(test), no_std)] pub use { - edhoc_consts::State as EdhocState, edhoc_consts::*, edhoc_crypto::Crypto, + edhoc_consts::State as EdhocState, edhoc_consts::*, edhoc_crypto::default_crypto, edhoc_crypto::CryptoTrait, EdhocInitiatorState as EdhocInitiator, EdhocResponderState as EdhocResponder, }; @@ -87,7 +87,7 @@ impl<'a> EdhocResponderState<'a> { self: &mut EdhocResponderState<'a>, message_1: &BufferMessage1, ) -> Result<(), EDHOCError> { - let state = r_process_message_1::(self.state, message_1)?; + let state = r_process_message_1(self.state, &mut default_crypto(), message_1)?; self.state = state; Ok(()) @@ -97,10 +97,11 @@ impl<'a> EdhocResponderState<'a> { self: &mut EdhocResponderState<'a>, c_r: u8, ) -> Result { - let (y, g_y) = Crypto::p256_generate_key_pair(); + let (y, g_y) = default_crypto().p256_generate_key_pair(); - match r_prepare_message_2::( + match r_prepare_message_2( self.state, + &mut default_crypto(), &self .id_cred_r .try_into() @@ -123,8 +124,9 @@ impl<'a> EdhocResponderState<'a> { self: &mut EdhocResponderState<'a>, message_3: &BufferMessage3, ) -> Result<[u8; SHA256_DIGEST_LEN], EDHOCError> { - match r_process_message_3::( + match r_process_message_3( self.state, + &mut default_crypto(), message_3, &self .id_cred_i @@ -150,7 +152,7 @@ impl<'a> EdhocResponderState<'a> { let mut context_buf: BytesMaxContextBuffer = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_exporter::(self.state, label, &context_buf, context.len(), length) { + match edhoc_exporter(self.state, &mut default_crypto(), label, &context_buf, context.len(), length) { Ok((state, output)) => { self.state = state; Ok(output) @@ -166,7 +168,7 @@ impl<'a> EdhocResponderState<'a> { let mut context_buf = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_key_update::(self.state, &context_buf, context.len()) { + match edhoc_key_update(self.state, &mut default_crypto(), &context_buf, context.len()) { Ok((state, prk_out_new)) => { self.state = state; Ok(prk_out_new) @@ -224,9 +226,9 @@ impl<'a> EdhocInitiatorState<'a> { self: &mut EdhocInitiatorState<'a>, c_i: u8, ) -> Result { - let (x, g_x) = Crypto::p256_generate_key_pair(); + let (x, g_x) = default_crypto().p256_generate_key_pair(); - match i_prepare_message_1::(self.state, x, g_x, c_i) { + match i_prepare_message_1(self.state, &mut default_crypto(), x, g_x, c_i) { Ok((state, message_1)) => { self.state = state; Ok(message_1) @@ -239,8 +241,9 @@ impl<'a> EdhocInitiatorState<'a> { self: &mut EdhocInitiatorState<'a>, message_2: &BufferMessage2, ) -> Result { - match i_process_message_2::( + match i_process_message_2( self.state, + &mut default_crypto(), message_2, &self .id_cred_r @@ -263,8 +266,9 @@ impl<'a> EdhocInitiatorState<'a> { pub fn prepare_message_3( self: &mut EdhocInitiatorState<'a>, ) -> Result<(BufferMessage3, [u8; SHA256_DIGEST_LEN]), EDHOCError> { - match i_prepare_message_3::( + match i_prepare_message_3( self.state, + &mut default_crypto(), &self .id_cred_i .try_into() @@ -288,7 +292,7 @@ impl<'a> EdhocInitiatorState<'a> { let mut context_buf: BytesMaxContextBuffer = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_exporter::(self.state, label, &context_buf, context.len(), length) { + match edhoc_exporter(self.state, &mut default_crypto(), label, &context_buf, context.len(), length) { Ok((state, output)) => { self.state = state; Ok(output) @@ -304,7 +308,7 @@ impl<'a> EdhocInitiatorState<'a> { let mut context_buf = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_key_update::(self.state, &context_buf, context.len()) { + match edhoc_key_update(self.state, &mut default_crypto(), &context_buf, context.len()) { Ok((state, prk_out_new)) => { self.state = state; Ok(prk_out_new) @@ -328,9 +332,9 @@ pub fn generate_connection_identifier_cbor() -> u8 { /// generates an identifier that can be serialized as a single CBOR integer, i.e. -24 <= x <= 23 pub fn generate_connection_identifier() -> i8 { - let mut conn_id = Crypto::get_random_byte() as i8; + let mut conn_id = default_crypto().get_random_byte() as i8; while conn_id < -24 || conn_id > 23 { - conn_id = Crypto::get_random_byte() as i8; + conn_id = default_crypto().get_random_byte() as i8; } conn_id } From 3e9b45d02de82cad1aa173f6cef1181be2e6f732 Mon Sep 17 00:00:00 2001 From: chrysn Date: Tue, 10 Oct 2023 21:00:33 +0200 Subject: [PATCH 8/8] chore: cargo fmt This mostly changes the indentation of functions that moved from pure function to provided impls of a trait. --- lib/src/edhoc.rs | 584 +++++++++++++++++++++++------------------------ lib/src/lib.rs | 32 ++- 2 files changed, 314 insertions(+), 302 deletions(-) diff --git a/lib/src/edhoc.rs b/lib/src/edhoc.rs index e5f31ddb..3c8d3ecf 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -515,12 +515,8 @@ pub fn i_process_message_2( prk_3e2m = crypto.compute_prk_3e2m(&salt_3e2m, &x, g_r); - let expected_mac_2 = crypto.compute_mac_2( - &prk_3e2m, - id_cred_r_expected, - cred_r_expected, - &th_2, - ); + let expected_mac_2 = + crypto.compute_mac_2(&prk_3e2m, id_cred_r_expected, cred_r_expected, &th_2); if mac_2 == expected_mac_2 { if kid == id_cred_r_expected[id_cred_r_expected.len() - 1] { @@ -1024,335 +1020,320 @@ fn encode_message_2(g_y: &BytesP256ElemLen, ciphertext_2: &BufferCiphertext2) -> // repeated for each function. (Other than that, they could all just as well be called // `computed_th_2(crypto, ...)` etc). trait CryptoExt: CryptoTrait { + fn compute_th_2(&mut self, g_y: &BytesP256ElemLen, h_message_1: &BytesHashLen) -> BytesHashLen { + let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; + message[0] = CBOR_BYTE_STRING; + message[1] = P256_ELEM_LEN as u8; + message[2..2 + P256_ELEM_LEN].copy_from_slice(g_y); + message[2 + P256_ELEM_LEN] = CBOR_BYTE_STRING; + message[3 + P256_ELEM_LEN] = SHA256_DIGEST_LEN as u8; + message[4 + P256_ELEM_LEN..4 + P256_ELEM_LEN + SHA256_DIGEST_LEN] + .copy_from_slice(&h_message_1[..]); + + let len = 4 + P256_ELEM_LEN + SHA256_DIGEST_LEN; + + let th_2 = self.sha256_digest(&message, len); + + th_2 + } + + fn compute_th_3( + &mut self, + th_2: &BytesHashLen, + plaintext_2: &BufferPlaintext2, + cred_r: &[u8], + ) -> BytesHashLen { + let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; + + message[0] = CBOR_BYTE_STRING; + message[1] = th_2.len() as u8; + message[2..2 + th_2.len()].copy_from_slice(&th_2[..]); + message[2 + th_2.len()..2 + th_2.len() + plaintext_2.len] + .copy_from_slice(&plaintext_2.content[..plaintext_2.len]); + message[2 + th_2.len() + plaintext_2.len..2 + th_2.len() + plaintext_2.len + cred_r.len()] + .copy_from_slice(cred_r); + + let output = self.sha256_digest(&message, th_2.len() + 2 + plaintext_2.len + cred_r.len()); + + output + } + + fn compute_th_4( + &mut self, + th_3: &BytesHashLen, + plaintext_3: &BufferPlaintext3, + cred_i: &[u8], + ) -> BytesHashLen { + let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; + + message[0] = CBOR_BYTE_STRING; + message[1] = th_3.len() as u8; + message[2..2 + th_3.len()].copy_from_slice(&th_3[..]); + message[2 + th_3.len()..2 + th_3.len() + plaintext_3.len] + .copy_from_slice(&plaintext_3.content[..plaintext_3.len]); + message[2 + th_3.len() + plaintext_3.len..2 + th_3.len() + plaintext_3.len + cred_i.len()] + .copy_from_slice(cred_i); + + let output = self.sha256_digest(&message, th_3.len() + 2 + plaintext_3.len + cred_i.len()); + + output + } + + fn edhoc_kdf( + &mut self, + prk: &BytesHashLen, + label: u8, + context: &BytesMaxContextBuffer, + context_len: usize, + length: usize, + ) -> BytesMaxBuffer { + let mut info: BytesMaxInfoBuffer = [0x00; MAX_INFO_LEN]; + let mut info_len = 0; + + // construct info with inline cbor encoding + info[0] = label; + if context_len < 24 { + info[1] = context_len as u8 | CBOR_MAJOR_BYTE_STRING; + info[2..2 + context_len].copy_from_slice(&context[..context_len]); + info_len = 2 + context_len; + } else { + info[1] = CBOR_BYTE_STRING; + info[2] = context_len as u8; + info[3..3 + context_len].copy_from_slice(&context[..context_len]); + info_len = 3 + context_len; + } + if length < 24 { + info[info_len] = length as u8; + info_len = info_len + 1; + } else { + info[info_len] = CBOR_UINT_1BYTE; + info[info_len + 1] = length as u8; + info_len = info_len + 2; + } -fn compute_th_2( - &mut self, - g_y: &BytesP256ElemLen, - h_message_1: &BytesHashLen, -) -> BytesHashLen { - let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; - message[0] = CBOR_BYTE_STRING; - message[1] = P256_ELEM_LEN as u8; - message[2..2 + P256_ELEM_LEN].copy_from_slice(g_y); - message[2 + P256_ELEM_LEN] = CBOR_BYTE_STRING; - message[3 + P256_ELEM_LEN] = SHA256_DIGEST_LEN as u8; - message[4 + P256_ELEM_LEN..4 + P256_ELEM_LEN + SHA256_DIGEST_LEN] - .copy_from_slice(&h_message_1[..]); - - let len = 4 + P256_ELEM_LEN + SHA256_DIGEST_LEN; - - let th_2 = self.sha256_digest(&message, len); - - th_2 -} + let output = self.hkdf_expand(prk, &info, info_len, length); -fn compute_th_3( - &mut self, - th_2: &BytesHashLen, - plaintext_2: &BufferPlaintext2, - cred_r: &[u8], -) -> BytesHashLen { - let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; + output + } - message[0] = CBOR_BYTE_STRING; - message[1] = th_2.len() as u8; - message[2..2 + th_2.len()].copy_from_slice(&th_2[..]); - message[2 + th_2.len()..2 + th_2.len() + plaintext_2.len] - .copy_from_slice(&plaintext_2.content[..plaintext_2.len]); - message[2 + th_2.len() + plaintext_2.len..2 + th_2.len() + plaintext_2.len + cred_r.len()] - .copy_from_slice(cred_r); + fn compute_k_3_iv_3( + &mut self, + prk_3e2m: &BytesHashLen, + th_3: &BytesHashLen, + ) -> (BytesCcmKeyLen, BytesCcmIvLen) { + // K_3 = EDHOC-KDF( PRK_3e2m, 3, TH_3, key_length ) + let mut k_3: BytesCcmKeyLen = [0x00; AES_CCM_KEY_LEN]; + let mut th_3_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; + th_3_buf[..th_3.len()].copy_from_slice(&th_3[..]); + let k_3_buf = self.edhoc_kdf(prk_3e2m, 3u8, &th_3_buf, th_3.len(), AES_CCM_KEY_LEN); + k_3[..].copy_from_slice(&k_3_buf[..AES_CCM_KEY_LEN]); - let output = self.sha256_digest(&message, th_2.len() + 2 + plaintext_2.len + cred_r.len()); + // IV_3 = EDHOC-KDF( PRK_3e2m, 4, TH_3, iv_length ) + let mut iv_3: BytesCcmIvLen = [0x00; AES_CCM_IV_LEN]; + let iv_3_buf = self.edhoc_kdf(prk_3e2m, 4u8, &th_3_buf, th_3.len(), AES_CCM_IV_LEN); + iv_3[..].copy_from_slice(&iv_3_buf[..AES_CCM_IV_LEN]); - output -} + (k_3, iv_3) + } -fn compute_th_4( - &mut self, - th_3: &BytesHashLen, - plaintext_3: &BufferPlaintext3, - cred_i: &[u8], -) -> BytesHashLen { - let mut message: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; + // calculates ciphertext_3 wrapped in a cbor byte string + fn encrypt_message_3( + &mut self, + prk_3e2m: &BytesHashLen, + th_3: &BytesHashLen, + plaintext_3: &BufferPlaintext3, + ) -> BufferMessage3 { + let mut output: BufferMessage3 = BufferMessage3::new(); + output.len = 1 + plaintext_3.len + AES_CCM_TAG_LEN; + output.content[0] = CBOR_MAJOR_BYTE_STRING | (plaintext_3.len + AES_CCM_TAG_LEN) as u8; // FIXME if plaintext_3.len + AES_CCM_TAG_LEN > 23, then should use CBOR_BYTE_STRING - message[0] = CBOR_BYTE_STRING; - message[1] = th_3.len() as u8; - message[2..2 + th_3.len()].copy_from_slice(&th_3[..]); - message[2 + th_3.len()..2 + th_3.len() + plaintext_3.len] - .copy_from_slice(&plaintext_3.content[..plaintext_3.len]); - message[2 + th_3.len() + plaintext_3.len..2 + th_3.len() + plaintext_3.len + cred_i.len()] - .copy_from_slice(cred_i); + let enc_structure = encode_enc_structure(th_3); - let output = self.sha256_digest(&message, th_3.len() + 2 + plaintext_3.len + cred_i.len()); + let (k_3, iv_3) = self.compute_k_3_iv_3(prk_3e2m, th_3); - output -} + let ciphertext_3 = self.aes_ccm_encrypt_tag_8(&k_3, &iv_3, &enc_structure, plaintext_3); -fn edhoc_kdf( - &mut self, - prk: &BytesHashLen, - label: u8, - context: &BytesMaxContextBuffer, - context_len: usize, - length: usize, -) -> BytesMaxBuffer { - let mut info: BytesMaxInfoBuffer = [0x00; MAX_INFO_LEN]; - let mut info_len = 0; - - // construct info with inline cbor encoding - info[0] = label; - if context_len < 24 { - info[1] = context_len as u8 | CBOR_MAJOR_BYTE_STRING; - info[2..2 + context_len].copy_from_slice(&context[..context_len]); - info_len = 2 + context_len; - } else { - info[1] = CBOR_BYTE_STRING; - info[2] = context_len as u8; - info[3..3 + context_len].copy_from_slice(&context[..context_len]); - info_len = 3 + context_len; - } - if length < 24 { - info[info_len] = length as u8; - info_len = info_len + 1; - } else { - info[info_len] = CBOR_UINT_1BYTE; - info[info_len + 1] = length as u8; - info_len = info_len + 2; + output.content[1..output.len].copy_from_slice(&ciphertext_3.content[..ciphertext_3.len]); + + output } - let output = self.hkdf_expand(prk, &info, info_len, length); + fn decrypt_message_3( + &mut self, + prk_3e2m: &BytesHashLen, + th_3: &BytesHashLen, + message_3: &BufferMessage3, + ) -> Result { + let mut error = EDHOCError::UnknownError; + let mut plaintext_3: BufferPlaintext3 = BufferPlaintext3::new(); - output -} + // decode message_3 + let len = (message_3.content[0usize] ^ CBOR_MAJOR_BYTE_STRING) as usize; -fn compute_k_3_iv_3( - &mut self, - prk_3e2m: &BytesHashLen, - th_3: &BytesHashLen, -) -> (BytesCcmKeyLen, BytesCcmIvLen) { - // K_3 = EDHOC-KDF( PRK_3e2m, 3, TH_3, key_length ) - let mut k_3: BytesCcmKeyLen = [0x00; AES_CCM_KEY_LEN]; - let mut th_3_buf: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; - th_3_buf[..th_3.len()].copy_from_slice(&th_3[..]); - let k_3_buf = self.edhoc_kdf(prk_3e2m, 3u8, &th_3_buf, th_3.len(), AES_CCM_KEY_LEN); - k_3[..].copy_from_slice(&k_3_buf[..AES_CCM_KEY_LEN]); - - // IV_3 = EDHOC-KDF( PRK_3e2m, 4, TH_3, iv_length ) - let mut iv_3: BytesCcmIvLen = [0x00; AES_CCM_IV_LEN]; - let iv_3_buf = self.edhoc_kdf(prk_3e2m, 4u8, &th_3_buf, th_3.len(), AES_CCM_IV_LEN); - iv_3[..].copy_from_slice(&iv_3_buf[..AES_CCM_IV_LEN]); - - (k_3, iv_3) -} + let mut ciphertext_3: BufferCiphertext3 = BufferCiphertext3::new(); + ciphertext_3.len = len; + ciphertext_3.content[..len].copy_from_slice(&message_3.content[1..1 + len]); -// calculates ciphertext_3 wrapped in a cbor byte string -fn encrypt_message_3( - &mut self, - prk_3e2m: &BytesHashLen, - th_3: &BytesHashLen, - plaintext_3: &BufferPlaintext3, -) -> BufferMessage3 { - let mut output: BufferMessage3 = BufferMessage3::new(); - output.len = 1 + plaintext_3.len + AES_CCM_TAG_LEN; - output.content[0] = CBOR_MAJOR_BYTE_STRING | (plaintext_3.len + AES_CCM_TAG_LEN) as u8; // FIXME if plaintext_3.len + AES_CCM_TAG_LEN > 23, then should use CBOR_BYTE_STRING + let (k_3, iv_3) = self.compute_k_3_iv_3(prk_3e2m, th_3); - let enc_structure = encode_enc_structure(th_3); + let enc_structure = encode_enc_structure(th_3); - let (k_3, iv_3) = self.compute_k_3_iv_3(prk_3e2m, th_3); + let p3 = self.aes_ccm_decrypt_tag_8(&k_3, &iv_3, &enc_structure, &ciphertext_3); - let ciphertext_3 = self.aes_ccm_encrypt_tag_8(&k_3, &iv_3, &enc_structure, plaintext_3); + if p3.is_ok() { + error = EDHOCError::Success; + let p3 = p3.unwrap(); + plaintext_3.content[..p3.len].copy_from_slice(&p3.content[..p3.len]); + plaintext_3.len = p3.len; + } else { + error = p3.unwrap_err(); + } - output.content[1..output.len].copy_from_slice(&ciphertext_3.content[..ciphertext_3.len]); + match error { + EDHOCError::Success => Ok(plaintext_3), + _ => Err(error), + } + } - output -} + fn compute_mac_3( + &mut self, + prk_4e3m: &BytesHashLen, + th_3: &BytesHashLen, + id_cred_i: &BytesIdCred, + cred_i: &[u8], + ) -> BytesMac3 { + // MAC_3 = EDHOC-KDF( PRK_4e3m, 6, context_3, mac_length_3 ) + let (context, context_len) = encode_kdf_context(id_cred_i, th_3, cred_i); -fn decrypt_message_3( - &mut self, - prk_3e2m: &BytesHashLen, - th_3: &BytesHashLen, - message_3: &BufferMessage3, -) -> Result { - let mut error = EDHOCError::UnknownError; - let mut plaintext_3: BufferPlaintext3 = BufferPlaintext3::new(); + // compute mac_3 + let output_buf = self.edhoc_kdf( + prk_4e3m, + 6u8, // registered label for "MAC_3" + &context, + context_len, + MAC_LENGTH_3, + ); - // decode message_3 - let len = (message_3.content[0usize] ^ CBOR_MAJOR_BYTE_STRING) as usize; + let mut output: BytesMac3 = [0x00; MAC_LENGTH_3]; + output[..MAC_LENGTH_3].copy_from_slice(&output_buf[..MAC_LENGTH_3]); + output + } - let mut ciphertext_3: BufferCiphertext3 = BufferCiphertext3::new(); - ciphertext_3.len = len; - ciphertext_3.content[..len].copy_from_slice(&message_3.content[1..1 + len]); + fn compute_mac_2( + &mut self, + prk_3e2m: &BytesHashLen, + id_cred_r: &BytesIdCred, + cred_r: &[u8], + th_2: &BytesHashLen, + ) -> BytesMac2 { + // compute MAC_2 + let (context, context_len) = encode_kdf_context(id_cred_r, th_2, cred_r); - let (k_3, iv_3) = self.compute_k_3_iv_3(prk_3e2m, th_3); + // MAC_2 = EDHOC-KDF( PRK_3e2m, 2, context_2, mac_length_2 ) + let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2]; + mac_2[..].copy_from_slice( + &self.edhoc_kdf(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2)[..MAC_LENGTH_2], + ); - let enc_structure = encode_enc_structure(th_3); + mac_2 + } - let p3 = self.aes_ccm_decrypt_tag_8(&k_3, &iv_3, &enc_structure, &ciphertext_3); + fn encrypt_decrypt_ciphertext_2( + &mut self, + prk_2e: &BytesHashLen, + th_2: &BytesHashLen, + ciphertext_2: &BufferCiphertext2, + ) -> (BytesMaxBuffer, usize) { + // convert the transcript hash th_2 to BytesMaxContextBuffer type + let mut th_2_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; + th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); - if p3.is_ok() { - error = EDHOCError::Success; - let p3 = p3.unwrap(); - plaintext_3.content[..p3.len].copy_from_slice(&p3.content[..p3.len]); - plaintext_3.len = p3.len; - } else { - error = p3.unwrap_err(); - } + // KEYSTREAM_2 = EDHOC-KDF( PRK_2e, 0, TH_2, plaintext_length ) + let keystream_2 = self.edhoc_kdf( + prk_2e, + 0u8, + &th_2_context, + SHA256_DIGEST_LEN, + ciphertext_2.len, + ); - match error { - EDHOCError::Success => Ok(plaintext_3), - _ => Err(error), + let mut plaintext_2: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; + // decrypt/encrypt ciphertext_2 + for i in 0..ciphertext_2.len { + plaintext_2[i] = ciphertext_2.content[i] ^ keystream_2[i]; + } + + (plaintext_2, ciphertext_2.len) } -} -fn compute_mac_3( - &mut self, - prk_4e3m: &BytesHashLen, - th_3: &BytesHashLen, - id_cred_i: &BytesIdCred, - cred_i: &[u8], -) -> BytesMac3 { - // MAC_3 = EDHOC-KDF( PRK_4e3m, 6, context_3, mac_length_3 ) - let (context, context_len) = encode_kdf_context(id_cred_i, th_3, cred_i); + fn compute_salt_4e3m(&mut self, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen) -> BytesHashLen { + let mut th_3_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; + th_3_context[..th_3.len()].copy_from_slice(&th_3[..]); + let salt_4e3m_buf = + self.edhoc_kdf(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); + let mut salt_4e3m: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; + salt_4e3m[..].copy_from_slice(&salt_4e3m_buf[..SHA256_DIGEST_LEN]); - // compute mac_3 - let output_buf = self.edhoc_kdf( - prk_4e3m, - 6u8, // registered label for "MAC_3" - &context, - context_len, - MAC_LENGTH_3, - ); - - let mut output: BytesMac3 = [0x00; MAC_LENGTH_3]; - output[..MAC_LENGTH_3].copy_from_slice(&output_buf[..MAC_LENGTH_3]); - output -} + salt_4e3m + } -fn compute_mac_2( - &mut self, - prk_3e2m: &BytesHashLen, - id_cred_r: &BytesIdCred, - cred_r: &[u8], - th_2: &BytesHashLen, -) -> BytesMac2 { - // compute MAC_2 - let (context, context_len) = encode_kdf_context(id_cred_r, th_2, cred_r); + fn compute_prk_4e3m( + &mut self, + salt_4e3m: &BytesHashLen, + i: &BytesP256ElemLen, + g_y: &BytesP256ElemLen, + ) -> BytesHashLen { + // compute g_rx from static R's public key and private ephemeral key + let g_iy = self.p256_ecdh(i, g_y); + let prk_4e3m = self.hkdf_extract(salt_4e3m, &g_iy); - // MAC_2 = EDHOC-KDF( PRK_3e2m, 2, context_2, mac_length_2 ) - let mut mac_2: BytesMac2 = [0x00; MAC_LENGTH_2]; - mac_2[..].copy_from_slice( - &self.edhoc_kdf(prk_3e2m, 2 as u8, &context, context_len, MAC_LENGTH_2) - [..MAC_LENGTH_2], - ); + prk_4e3m + } - mac_2 -} + fn compute_salt_3e2m(&mut self, prk_2e: &BytesHashLen, th_2: &BytesHashLen) -> BytesHashLen { + let mut th_2_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; + th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); -fn encrypt_decrypt_ciphertext_2( - &mut self, - prk_2e: &BytesHashLen, - th_2: &BytesHashLen, - ciphertext_2: &BufferCiphertext2, -) -> (BytesMaxBuffer, usize) { - // convert the transcript hash th_2 to BytesMaxContextBuffer type - let mut th_2_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; - th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); - - // KEYSTREAM_2 = EDHOC-KDF( PRK_2e, 0, TH_2, plaintext_length ) - let keystream_2 = self.edhoc_kdf( - prk_2e, - 0u8, - &th_2_context, - SHA256_DIGEST_LEN, - ciphertext_2.len, - ); - - let mut plaintext_2: BytesMaxBuffer = [0x00; MAX_BUFFER_LEN]; - // decrypt/encrypt ciphertext_2 - for i in 0..ciphertext_2.len { - plaintext_2[i] = ciphertext_2.content[i] ^ keystream_2[i]; - } - - (plaintext_2, ciphertext_2.len) -} + let salt_3e2m_buf = self.edhoc_kdf( + prk_2e, + 1u8, + &th_2_context, + SHA256_DIGEST_LEN, + SHA256_DIGEST_LEN, + ); -fn compute_salt_4e3m( - &mut self, - prk_3e2m: &BytesHashLen, - th_3: &BytesHashLen, -) -> BytesHashLen { - let mut th_3_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; - th_3_context[..th_3.len()].copy_from_slice(&th_3[..]); - let salt_4e3m_buf = - self.edhoc_kdf(prk_3e2m, 5u8, &th_3_context, th_3.len(), SHA256_DIGEST_LEN); - let mut salt_4e3m: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; - salt_4e3m[..].copy_from_slice(&salt_4e3m_buf[..SHA256_DIGEST_LEN]); - - salt_4e3m -} + let mut salt_3e2m: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; + salt_3e2m[..].copy_from_slice(&salt_3e2m_buf[..SHA256_DIGEST_LEN]); -fn compute_prk_4e3m( - &mut self, - salt_4e3m: &BytesHashLen, - i: &BytesP256ElemLen, - g_y: &BytesP256ElemLen, -) -> BytesHashLen { - // compute g_rx from static R's public key and private ephemeral key - let g_iy = self.p256_ecdh(i, g_y); - let prk_4e3m = self.hkdf_extract(salt_4e3m, &g_iy); - - prk_4e3m -} + salt_3e2m + } -fn compute_salt_3e2m( - &mut self, - prk_2e: &BytesHashLen, - th_2: &BytesHashLen, -) -> BytesHashLen { - let mut th_2_context: BytesMaxContextBuffer = [0x00; MAX_KDF_CONTEXT_LEN]; - th_2_context[..th_2.len()].copy_from_slice(&th_2[..]); - - let salt_3e2m_buf = self.edhoc_kdf( - prk_2e, - 1u8, - &th_2_context, - SHA256_DIGEST_LEN, - SHA256_DIGEST_LEN, - ); - - let mut salt_3e2m: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; - salt_3e2m[..].copy_from_slice(&salt_3e2m_buf[..SHA256_DIGEST_LEN]); - - salt_3e2m -} + fn compute_prk_3e2m( + &mut self, + salt_3e2m: &BytesHashLen, + x: &BytesP256ElemLen, + g_r: &BytesP256ElemLen, + ) -> BytesHashLen { + // compute g_rx from static R's public key and private ephemeral key + let g_rx = self.p256_ecdh(x, g_r); + let prk_3e2m = self.hkdf_extract(salt_3e2m, &g_rx); -fn compute_prk_3e2m( - &mut self, - salt_3e2m: &BytesHashLen, - x: &BytesP256ElemLen, - g_r: &BytesP256ElemLen, -) -> BytesHashLen { - // compute g_rx from static R's public key and private ephemeral key - let g_rx = self.p256_ecdh(x, g_r); - let prk_3e2m = self.hkdf_extract(salt_3e2m, &g_rx); - - prk_3e2m -} + prk_3e2m + } -fn compute_prk_2e( - &mut self, - x: &BytesP256ElemLen, - g_y: &BytesP256ElemLen, - th_2: &BytesHashLen, -) -> BytesHashLen { - // compute the shared secret - let g_xy = self.p256_ecdh(x, g_y); - // compute prk_2e as PRK_2e = HMAC-SHA-256( salt, G_XY ) - let prk_2e = self.hkdf_extract(th_2, &g_xy); - - prk_2e -} + fn compute_prk_2e( + &mut self, + x: &BytesP256ElemLen, + g_y: &BytesP256ElemLen, + th_2: &BytesHashLen, + ) -> BytesHashLen { + // compute the shared secret + let g_xy = self.p256_ecdh(x, g_y); + // compute prk_2e as PRK_2e = HMAC-SHA-256( salt, G_XY ) + let prk_2e = self.hkdf_extract(th_2, &g_xy); + prk_2e + } } impl CryptoExt for Crypto {} @@ -1819,8 +1800,13 @@ mod tests { th_2_context_tv[..TH_2_TV.len()].copy_from_slice(&TH_2_TV[..]); const LEN_TV: usize = PLAINTEXT_2_LEN_TV; - let output = - default_crypto().edhoc_kdf(&PRK_2E_TV, 0u8, &th_2_context_tv, SHA256_DIGEST_LEN, LEN_TV); + let output = default_crypto().edhoc_kdf( + &PRK_2E_TV, + 0u8, + &th_2_context_tv, + SHA256_DIGEST_LEN, + LEN_TV, + ); for i in 0..KEYSTREAM_2_TV.len() { assert_eq!(KEYSTREAM_2_TV[i], output[i]); } @@ -1863,13 +1849,15 @@ mod tests { #[test] fn test_compute_mac_3() { - let mac_3 = default_crypto().compute_mac_3(&PRK_4E3M_TV, &TH_3_TV, &ID_CRED_I_TV, &CRED_I_TV); + let mac_3 = + default_crypto().compute_mac_3(&PRK_4E3M_TV, &TH_3_TV, &ID_CRED_I_TV, &CRED_I_TV); assert_eq!(mac_3, MAC_3_TV); } #[test] fn test_compute_and_verify_mac_2() { - let rcvd_mac_2 = default_crypto().compute_mac_2(&PRK_3E2M_TV, &ID_CRED_R_TV, &CRED_R_TV, &TH_2_TV); + let rcvd_mac_2 = + default_crypto().compute_mac_2(&PRK_3E2M_TV, &ID_CRED_R_TV, &CRED_R_TV, &TH_2_TV); assert_eq!(rcvd_mac_2, MAC_2_TV); } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 3938d7e6..70a29208 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -152,7 +152,14 @@ impl<'a> EdhocResponderState<'a> { let mut context_buf: BytesMaxContextBuffer = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_exporter(self.state, &mut default_crypto(), label, &context_buf, context.len(), length) { + match edhoc_exporter( + self.state, + &mut default_crypto(), + label, + &context_buf, + context.len(), + length, + ) { Ok((state, output)) => { self.state = state; Ok(output) @@ -168,7 +175,12 @@ impl<'a> EdhocResponderState<'a> { let mut context_buf = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_key_update(self.state, &mut default_crypto(), &context_buf, context.len()) { + match edhoc_key_update( + self.state, + &mut default_crypto(), + &context_buf, + context.len(), + ) { Ok((state, prk_out_new)) => { self.state = state; Ok(prk_out_new) @@ -292,7 +304,14 @@ impl<'a> EdhocInitiatorState<'a> { let mut context_buf: BytesMaxContextBuffer = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_exporter(self.state, &mut default_crypto(), label, &context_buf, context.len(), length) { + match edhoc_exporter( + self.state, + &mut default_crypto(), + label, + &context_buf, + context.len(), + length, + ) { Ok((state, output)) => { self.state = state; Ok(output) @@ -308,7 +327,12 @@ impl<'a> EdhocInitiatorState<'a> { let mut context_buf = [0x00u8; MAX_KDF_CONTEXT_LEN]; context_buf[..context.len()].copy_from_slice(context); - match edhoc_key_update(self.state, &mut default_crypto(), &context_buf, context.len()) { + match edhoc_key_update( + self.state, + &mut default_crypto(), + &context_buf, + context.len(), + ) { Ok((state, prk_out_new)) => { self.state = state; Ok(prk_out_new)