From 95ddb6dc865ee8c6e2d8d1fc60847ee547383b0a Mon Sep 17 00:00:00 2001 From: chrysn Date: Sun, 5 Nov 2023 01:24:22 +0100 Subject: [PATCH] refactor!: Move crypto operations into a trait. --- Cargo.toml | 1 + crypto/Cargo.toml | 2 + .../edhoc-crypto-cryptocell310-sys/Cargo.toml | 1 + .../edhoc-crypto-cryptocell310-sys/src/lib.rs | 476 +++++++++--------- crypto/edhoc-crypto-hacspec/Cargo.toml | 1 + crypto/edhoc-crypto-hacspec/src/lib.rs | 238 ++++----- crypto/edhoc-crypto-psa/Cargo.toml | 1 + crypto/edhoc-crypto-psa/src/lib.rs | 466 ++++++++--------- crypto/edhoc-crypto-trait/Cargo.toml | 7 + crypto/edhoc-crypto-trait/src/lib.rs | 37 ++ crypto/src/lib.rs | 42 +- ead/edhoc-ead-zeroconf/src/lib.rs | 12 +- examples/edhoc-rs-no_std/Cargo.toml | 1 + examples/edhoc-rs-no_std/src/main.rs | 9 +- lib/Cargo.toml | 1 + lib/src/c_wrapper.rs | 4 +- lib/src/edhoc.rs | 255 +++++++--- lib/src/lib.rs | 65 ++- 18 files changed, 951 insertions(+), 668 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 5c51e383..ddbcc76e 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,183 +20,273 @@ fn convert_array(input: &[u32]) -> [u8; SHA256_DIGEST_LEN] { output } -pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { - let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; +pub struct Crypto; - unsafe { - CRYS_HASH( - CRYS_HASH_OperationMode_t_CRYS_HASH_SHA256_mode, - message.clone().as_mut_ptr(), - message_len, - buffer.as_mut_ptr(), - ); - } +impl CryptoTrait for Crypto { + fn sha256_digest(&mut self, message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + let mut buffer: [u32; 64 / 4] = [0x00; 64 / 4]; - convert_array(&buffer[0..SHA256_DIGEST_LEN / 4]) -} + unsafe { + CRYS_HASH( + CRYS_HASH_OperationMode_t_CRYS_HASH_SHA256_mode, + message.clone().as_mut_ptr(), + message_len, + buffer.as_mut_ptr(), + ); + } -pub 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, - ); + convert_array(&buffer[0..SHA256_DIGEST_LEN / 4]) } - buffer -} + fn hkdf_expand( + &mut self, + 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, + ); + } -pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { - // Implementation of HKDF-Extract as per RFC 5869 + buffer + } - // TODO generalize if salt is not provided - let output = hmac_sha256(&mut ikm.clone()[..], *salt); + fn hkdf_extract(&mut self, 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(&mut ikm.clone()[..], *salt); -pub fn aes_ccm_encrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &[u8], - 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(); - let mut aesccm_ad = [0x00u8; ENC_STRUCTURE_LEN]; - - aesccm_key[0..AES_CCM_KEY_LEN].copy_from_slice(&key[..]); - aesccm_ad[0..ad.len()].copy_from_slice(&ad[..]); - - 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, - aesccm_ad.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 + } - output -} + fn aes_ccm_encrypt_tag_8( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + 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(); + let mut aesccm_ad = [0x00u8; ENC_STRUCTURE_LEN]; + + aesccm_key[0..AES_CCM_KEY_LEN].copy_from_slice(&key[..]); + aesccm_ad[0..ad.len()].copy_from_slice(&ad[..]); + + 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, + aesccm_ad.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 + } + + fn aes_ccm_decrypt_tag_8( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + 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.as_ptr() as *mut _, + 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), + } + } + } -pub 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(); + fn p256_ecdh( + &mut self, + 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(), + ); + } - aesccm_key[0..AES_CCM_KEY_LEN].copy_from_slice(&key[..]); + let mut private_key_cc310: CRYS_ECPKI_UserPrivKey_t = Default::default(); - let mut err = EDHOCError::MacVerificationFailed; + unsafe { + CRYS_ECPKI_BuildPrivKey( + domain, + private_key.clone().as_mut_ptr(), + P256_ELEM_LEN as u32, + &mut private_key_cc310, + ); + } - 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), + unsafe { + CRYS_ECDH_SVDP_DH( + &mut public_key_cc310, + &mut private_key_cc310, + output.as_mut_ptr(), + &mut output_len, + &mut tmp, + ); } + + output } -} -pub 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; + 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 { + 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] + } - let mut tmp: CRYS_ECDH_TempData_t = Default::default(); + 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 { + 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, + ); + } - 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: [u8; P256_ELEM_LEN] = [0x0; P256_ELEM_LEN]; + let mut key_size: u32 = P256_ELEM_LEN.try_into().unwrap(); - let mut public_key_cc310: CRYS_ECPKI_UserPublKey_t = Default::default(); + unsafe { + CRYS_ECPKI_ExportPrivKey(crys_private_key, private_key.as_mut_ptr(), &mut key_size); + } - let mut domain = - unsafe { CRYS_ECPKI_GetEcDomain(CRYS_ECPKI_DomainID_t_CRYS_ECPKI_DomainID_secp256r1) }; + // let private_key = BytesP256ElemLen::from_public_slice(&private_key[..]); - 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: [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 mut private_key_cc310: CRYS_ECPKI_UserPrivKey_t = Default::default(); + unsafe { + CRYS_ECPKI_ExportPublKey( + crys_public_key, + compressed_flag, + public_key.as_mut_ptr(), + &mut key_size, + ); + } - unsafe { - CRYS_ECPKI_BuildPrivKey( - domain, - private_key.clone().as_mut_ptr(), - P256_ELEM_LEN as u32, - &mut private_key_cc310, - ); - } + let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // discard sign byte - unsafe { - CRYS_ECDH_SVDP_DH( - &mut public_key_cc310, - &mut private_key_cc310, - output.as_mut_ptr(), - &mut output_len, - &mut tmp, - ); + (private_key, public_key) } - - output } fn hmac_sha256(message: &mut [u8], mut key: [u8; SHA256_DIGEST_LEN]) -> BytesHashLen { @@ -213,85 +305,3 @@ fn hmac_sha256(message: &mut [u8], mut key: [u8; SHA256_DIGEST_LEN]) -> BytesHas convert_array(&buffer[..SHA256_DIGEST_LEN / 4]) } - -pub 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] -} - -pub 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, - ); - } - - 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_ExportPrivKey(crys_private_key, private_key.as_mut_ptr(), &mut key_size); - } - - // let private_key = BytesP256ElemLen::from_public_slice(&private_key[..]); - - 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; - - unsafe { - CRYS_ECPKI_ExportPublKey( - crys_public_key, - compressed_flag, - public_key.as_mut_ptr(), - &mut key_size, - ); - } - - let public_key: [u8; P256_ELEM_LEN] = public_key[1..33].try_into().unwrap(); // discard sign byte - - (private_key, public_key) -} 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 c81adcac..46c4c487 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,139 +72,147 @@ type BufferPlaintext3Hacspec = EdhocMessageBufferHacspec; // Public functions -pub fn sha256_digest(message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { - let message: BytesMaxBufferHacspec = BytesMaxBufferHacspec::from_public_slice(message); +pub struct Crypto; - let output = - BytesHashLenHacspec::from_seq(&hash(&ByteSeq::from_slice(&message, 0, message_len))); +impl CryptoTrait for Crypto { + fn sha256_digest(&mut self, message: &BytesMaxBuffer, message_len: usize) -> BytesHashLen { + let message: BytesMaxBufferHacspec = BytesMaxBufferHacspec::from_public_slice(message); - output.to_public_array() -} + let output = + BytesHashLenHacspec::from_seq(&hash(&ByteSeq::from_slice(&message, 0, message_len))); + + output.to_public_array() + } + + fn hkdf_expand( + &mut self, + 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() + } -pub 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(&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( - &BytesMaxInfoBufferHacspec::from_public_slice(info), + &BytesP256ElemLenHacspec::from_public_slice(ikm), 0, - info_len, + ikm.len(), ), - length, - ) - .unwrap(), - ); - output.to_public_array() -} - -pub 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() + } -pub fn aes_ccm_encrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &[u8], - plaintext: &BufferPlaintext3, -) -> BufferCiphertext3 { - let plaintext = BufferPlaintext3Hacspec::from_public_buffer(plaintext); - - let output = BufferCiphertext3Hacspec::from_seq(&encrypt_ccm( - ByteSeq::from_public_slice(ad), - 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( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + plaintext: &BufferPlaintext3, + ) -> BufferCiphertext3 { + let plaintext = BufferPlaintext3Hacspec::from_public_buffer(plaintext); + + let output = BufferCiphertext3Hacspec::from_seq(&encrypt_ccm( + ByteSeq::from_public_slice(ad), + 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() + } -pub 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), + fn aes_ccm_decrypt_tag_8( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + 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), + } } -} -pub 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 p256_ecdh( + &mut self, + 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); - 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 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)), + ); - // we only care about the x coordinate - let (x, _y) = p256_point_mul(scalar, point).unwrap(); + // we only care about the x coordinate + let (x, _y) = p256_point_mul(scalar, point).unwrap(); - let secret = BytesP256ElemLenHacspec::from_seq(&x.to_byte_seq_be()); + let secret = BytesP256ElemLenHacspec::from_seq(&x.to_byte_seq_be()); - secret.to_public_array() -} + secret.to_public_array() + } -#[cfg(not(feature = "hacspec-pure"))] -pub fn get_random_byte() -> u8 { - rand::thread_rng().gen::() -} + #[cfg(not(feature = "hacspec-pure"))] + fn get_random_byte(&mut self) -> u8 { + rand::thread_rng().gen::() + } -#[cfg(not(feature = "hacspec-pure"))] -pub 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::()); + #[cfg(not(feature = "hacspec-pure"))] + fn p256_generate_key_pair(&mut self) -> (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; + } } - if p256_validate_private_key(&ByteSeq::from_slice(&private_key, 0, private_key.len())) { - break; - } - } - // 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()); + // 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()) + (private_key.to_public_array(), public_key.to_public_array()) + } } #[cfg(test)] 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 66a9956d..8161d2df 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,257 +22,269 @@ pub extern "C" fn mbedtls_hardware_poll( 0i32 } -pub 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(); +pub struct Crypto; - hash -} +impl CryptoTrait for Crypto { + 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(); + hash_compute(hash_alg, &message[..message_len], &mut hash).unwrap(); -pub fn hkdf_expand( - prk: &BytesHashLen, - info: &BytesMaxInfoBuffer, - info_len: usize, - length: usize, -) -> BytesMaxBuffer { - // Implementation of HKDF-Expand as per RFC5869 + hash + } - let mut output: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; + fn hkdf_expand( + &mut self, + prk: &BytesHashLen, + info: &BytesMaxInfoBuffer, + info_len: usize, + length: usize, + ) -> BytesMaxBuffer { + // Implementation of HKDF-Expand as per RFC5869 - let mut n = 0; + let mut output: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; - // N = ceil(L/HashLen) - if length % SHA256_DIGEST_LEN == 0 { - n = length / SHA256_DIGEST_LEN; - } else { - n = length / SHA256_DIGEST_LEN + 1; - } + let mut n = 0; - 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); - } + // N = ceil(L/HashLen) + if length % SHA256_DIGEST_LEN == 0 { + n = length / SHA256_DIGEST_LEN; + } else { + n = length / SHA256_DIGEST_LEN + 1; + } + + 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 = self.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 = self.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[length..].fill(0x00); + output[length..].fill(0x00); - output -} + output + } -pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen { - // Implementation of HKDF-Extract as per RFC 5869 + 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 - let output = hmac_sha256(ikm, salt); + // TODO generalize if salt is not provided + let output = self.hmac_sha256(ikm, salt); - output -} + output + } -pub fn aes_ccm_encrypt_tag_8( - key: &BytesCcmKeyLen, - iv: &BytesCcmIvLen, - ad: &[u8], - 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 aes_ccm_encrypt_tag_8( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + 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 + } -pub 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) + fn aes_ccm_decrypt_tag_8( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + 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), } - Err(_) => Err(EDHOCError::MacVerificationFailed), } -} -pub 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_ecdh( + &mut self, + 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 + } -pub fn hmac_sha256(message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLen { - // implementation of HMAC as per RFC2104 + 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] + } - const IPAD: [u8; 64] = [0x36; 64]; - const OPAD: [u8; 64] = [0x5C; 64]; + fn p256_generate_key_pair(&mut self) -> (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) + } +} - // (1) append zeros to the end of K to create a B byte string - // (e.g., if K is of length 20 bytes and B=64, then K will be - // appended with 44 zero bytes 0x00) - let mut b: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; - b[0..SHA256_DIGEST_LEN].copy_from_slice(&key[..]); +impl Crypto { + pub fn hmac_sha256(&mut self, message: &[u8], key: &[u8; SHA256_DIGEST_LEN]) -> BytesHashLen { + // implementation of HMAC as per RFC2104 - // (2) XOR (bitwise exclusive-OR) the B byte string computed in step - // (1) with ipad - let mut s2: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; - for i in 0..64 { - s2[i] = b[i] ^ IPAD[i]; - } + const IPAD: [u8; 64] = [0x36; 64]; + const OPAD: [u8; 64] = [0x5C; 64]; - // (3) append the stream of data 'text' to the B byte string resulting - // from step (2) - s2[64..64 + message.len()].copy_from_slice(message); + // (1) append zeros to the end of K to create a B byte string + // (e.g., if K is of length 20 bytes and B=64, then K will be + // appended with 44 zero bytes 0x00) + let mut b: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; + b[0..SHA256_DIGEST_LEN].copy_from_slice(&key[..]); - // (4) apply H to the stream generated in step (3) - let ih = sha256_digest(&s2, 64 + message.len()); + // (2) XOR (bitwise exclusive-OR) the B byte string computed in step + // (1) with ipad + let mut s2: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; + for i in 0..64 { + s2[i] = b[i] ^ IPAD[i]; + } - // (5) XOR (bitwise exclusive-OR) the B byte string computed in - // step (1) with opad - let mut s5: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; - for i in 0..64 { - s5[i] = b[i] ^ OPAD[i]; - } - // (6) append the H result from step (4) to the B byte string - // resulting from step (5) - s5[64..64 + SHA256_DIGEST_LEN].copy_from_slice(&ih); + // (3) append the stream of data 'text' to the B byte string resulting + // from step (2) + s2[64..64 + message.len()].copy_from_slice(message); - // (7) apply H to the stream generated in step (6) and output - // the result - let oh = sha256_digest(&s5, 3 * SHA256_DIGEST_LEN); + // (4) apply H to the stream generated in step (3) + let ih = crypto.sha256_digest(&s2, 64 + message.len()); - oh -} + // (5) XOR (bitwise exclusive-OR) the B byte string computed in + // step (1) with opad + let mut s5: [u8; MAX_BUFFER_LEN] = [0; MAX_BUFFER_LEN]; + for i in 0..64 { + s5[i] = b[i] ^ OPAD[i]; + } + // (6) append the H result from step (4) to the B byte string + // resulting from step (5) + s5[64..64 + SHA256_DIGEST_LEN].copy_from_slice(&ih); -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] -} + // (7) apply H to the stream generated in step (6) and output + // the result + let oh = crypto.sha256_digest(&s5, 3 * SHA256_DIGEST_LEN); -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) + oh + } } #[cfg(test)] @@ -293,10 +307,10 @@ mod tests { 0xd0, 0xe6, 0x55, 0xa3, ]; - let result_1 = hmac_sha256(&MESSAGE_1, &KEY); + let result_1 = Crypto.hmac_sha256(&MESSAGE_1, &KEY); assert_eq!(result_1, RESULT_1_TV); - let result_2 = hmac_sha256(&MESSAGE_2, &KEY); + let result_2 = Crypto.hmac_sha256(&MESSAGE_2, &KEY); assert_eq!(result_2, RESULT_2_TV); } } 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..8e716954 --- /dev/null +++ b/crypto/edhoc-crypto-trait/src/lib.rs @@ -0,0 +1,37 @@ +//! Cryptography trait back-end for the edhoc-crypto crate +#![no_std] + +use edhoc_consts::*; + +pub trait Crypto { + 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(&mut self, salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen; + fn aes_ccm_encrypt_tag_8( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + plaintext: &BufferPlaintext3, + ) -> BufferCiphertext3; + fn aes_ccm_decrypt_tag_8( + &mut self, + key: &BytesCcmKeyLen, + iv: &BytesCcmIvLen, + ad: &[u8], + ciphertext: &BufferCiphertext3, + ) -> Result; + 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 5c300559..09e0f6b6 100644 --- a/crypto/src/lib.rs +++ b/crypto/src/lib.rs @@ -1,13 +1,49 @@ +//! 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 type Crypto = edhoc_crypto_hacspec::Crypto; + #[cfg(feature = "hacspec")] -pub use edhoc_crypto_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::*; #[cfg(any(feature = "psa", feature = "psa-rust",))] -pub use edhoc_crypto_psa::*; +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 use edhoc_crypto_cryptocell310::*; +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() {} + +/// 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/ead/edhoc-ead-zeroconf/src/lib.rs b/ead/edhoc-ead-zeroconf/src/lib.rs index 2ce56be4..c4d8ca29 100644 --- a/ead/edhoc-ead-zeroconf/src/lib.rs +++ b/ead/edhoc-ead-zeroconf/src/lib.rs @@ -1,7 +1,7 @@ #![no_std] use edhoc_consts::*; -use edhoc_crypto::*; +use edhoc_crypto::{default_crypto, CryptoTrait}; // ---- initiator side (device) @@ -165,15 +165,15 @@ fn build_enc_id(prk: &BytesHashLen, id_u: &EdhocMessageBuffer, ss: u8) -> EdhocM let enc_structure = encode_enc_structure(ss); // ENC_ID = 'ciphertext' of COSE_Encrypt0 - aes_ccm_encrypt_tag_8(&k_1, &iv_1, &enc_structure[..], &plaintext) + default_crypto().aes_ccm_encrypt_tag_8(&k_1, &iv_1, &enc_structure[..], &plaintext) } fn compute_prk(a: &BytesP256ElemLen, g_b: &BytesP256ElemLen) -> BytesHashLen { // NOTE: salt should be h'' (the zero-length byte string), but crypto backends are hardcoded to salts of size SHA256_DIGEST_LEN (32). // nevertheless, using a salt of HashLen zeros works as well (see RFC 5869, Section 2.2). let salt: BytesHashLen = [0u8; SHA256_DIGEST_LEN]; - let g_ab = p256_ecdh(a, g_b); - hkdf_extract(&salt, &g_ab) + let g_ab = default_crypto().p256_ecdh(a, g_b); + default_crypto().hkdf_extract(&salt, &g_ab) } fn compute_k_1_iv_1(prk: &BytesHashLen) -> (BytesCcmKeyLen, BytesCcmIvLen) { @@ -236,7 +236,7 @@ fn edhoc_kdf_expand( length: usize, ) -> BytesMaxBuffer { let (info, info_len) = encode_info(label, context, context_len, length); - let output = hkdf_expand(prk, &info, info_len, length); + let output = default_crypto().hkdf_expand(prk, &info, info_len, length); output } @@ -544,7 +544,7 @@ fn handle_voucher_request( // compute hash 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]); - let h_message_1 = sha256_digest(&message_1_buf, message_1.len); + let h_message_1 = default_crypto().sha256_digest(&message_1_buf, message_1.len); let prk = compute_prk(w, g_x); 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 bf91226c..8720458d 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::{default_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) = default_crypto().p256_generate_key_pair(); + let (y, g_y) = default_crypto().p256_generate_key_pair(); - let g_xy = p256_ecdh(&x, &g_y); - let g_yx = 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/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/c_wrapper.rs b/lib/src/c_wrapper.rs index 297d44b6..4214c79e 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::{default_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) = 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 4bceb381..43026e7f 100644 --- a/lib/src/edhoc.rs +++ b/lib/src/edhoc.rs @@ -1,11 +1,12 @@ #![no_std] use edhoc_consts::*; -use edhoc_crypto::*; +use edhoc_crypto_trait::Crypto as CryptoTrait; use edhoc_ead::*; pub fn edhoc_exporter( state: State, + crypto: &mut impl CryptoTrait, 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 = edhoc_kdf(crypto, &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 impl CryptoTrait, context: &BytesMaxContextBuffer, context_len: usize, ) -> Result<(State, BytesHashLen), EDHOCError> { @@ -58,11 +60,19 @@ 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( + crypto, + &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( + crypto, &prk_out, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -92,6 +102,7 @@ pub fn edhoc_key_update( pub fn r_process_message_1( mut state: State, + crypto: &mut impl CryptoTrait, message_1: &BufferMessage1, ) -> Result { let State( @@ -131,7 +142,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; @@ -172,6 +183,7 @@ pub fn r_process_message_1( pub fn r_prepare_message_2( mut state: State, + crypto: &mut impl CryptoTrait, cred_r: &[u8], r: &BytesP256ElemLen, // R's static private DH key y: BytesP256ElemLen, @@ -196,15 +208,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(crypto, &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(crypto, &y, &g_x, &th_2); + let salt_3e2m = compute_salt_3e2m(crypto, &prk_2e, &th_2); + prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, r, &g_x); // compute MAC_2 - let mac_2 = compute_mac_2(&prk_3e2m, &get_id_cred(cred_r), cred_r, &th_2); + let mac_2 = compute_mac_2(crypto, &prk_3e2m, &get_id_cred(cred_r), cred_r, &th_2); let ead_2 = r_prepare_ead_2(); @@ -221,13 +233,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 = compute_th_3(crypto, &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(crypto, &prk_2e, &th_2, &ct); ct.content[..ct.len].copy_from_slice(&ciphertext_2[..ct.len]); @@ -261,6 +274,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 impl CryptoTrait, message_3: &BufferMessage3, cred_i_expected: &[u8], ) -> Result<(State, BytesHashLen), EDHOCError> { @@ -280,7 +294,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(crypto, &prk_3e2m, &th_3, message_3); if plaintext_3.is_ok() { let plaintext_3 = plaintext_3.unwrap(); @@ -301,12 +315,13 @@ pub fn r_process_message_3( // compare the kid received with the kid expected in id_cred_i if kid == kid_i { // compute salt_4e3m - let salt_4e3m = compute_salt_4e3m(&prk_3e2m, &th_3); + let salt_4e3m = compute_salt_4e3m(crypto, &prk_3e2m, &th_3); // TODO compute prk_4e3m - prk_4e3m = compute_prk_4e3m(&salt_4e3m, &y, &g_i); + prk_4e3m = compute_prk_4e3m(crypto, &salt_4e3m, &y, &g_i); // compute mac_3 let expected_mac_3 = compute_mac_3( + crypto, &prk_4e3m, &th_3, &get_id_cred(cred_i_expected), @@ -316,20 +331,27 @@ 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 = compute_th_4(crypto, &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); + let prk_out_buf = edhoc_kdf( + crypto, + &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( + crypto, &prk_out, 10u8, &[0x00u8; MAX_KDF_CONTEXT_LEN], @@ -382,6 +404,7 @@ pub fn r_process_message_3( pub fn i_prepare_message_1( mut state: State, + crypto: &mut impl CryptoTrait, x: BytesP256ElemLen, g_x: BytesP256ElemLen, c_i: u8, @@ -424,7 +447,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; @@ -453,6 +476,7 @@ pub fn i_prepare_message_1( // returns c_r pub fn i_process_message_2( mut state: State, + crypto: &mut impl CryptoTrait, message_2: &BufferMessage2, cred_r_expected: Option<&[u8]>, i: &BytesP256ElemLen, // I's static private DH key @@ -482,13 +506,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(crypto, &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(crypto, &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(crypto, &prk_2e, &th_2, &ciphertext_2); // decode plaintext_2 let plaintext_2_decoded = decode_plaintext_2(&plaintext_2, plaintext_2_len); @@ -574,11 +598,12 @@ pub fn i_process_message_2( if ead_res.is_ok() { // verify mac_2 - let salt_3e2m = compute_salt_3e2m(&prk_2e, &th_2); + let salt_3e2m = compute_salt_3e2m(crypto, &prk_2e, &th_2); - prk_3e2m = compute_prk_3e2m(&salt_3e2m, &x, &g_r); + prk_3e2m = compute_prk_3e2m(crypto, &salt_3e2m, &x, &g_r); let expected_mac_2 = compute_mac_2( + crypto, &prk_3e2m, &get_id_cred(valid_cred_r), &valid_cred_r, @@ -592,12 +617,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, &valid_cred_r); + th_3 = compute_th_3(crypto, &th_2, &pt2, &valid_cred_r); // message 3 processing - let salt_4e3m = compute_salt_4e3m(&prk_3e2m, &th_3); + let salt_4e3m = compute_salt_4e3m(crypto, &prk_3e2m, &th_3); - prk_4e3m = compute_prk_4e3m(&salt_4e3m, i, &g_y); + prk_4e3m = compute_prk_4e3m(crypto, &salt_4e3m, i, &g_y); error = EDHOCError::Success; current_state = EDHOCState::ProcessedMessage2; @@ -641,6 +666,7 @@ pub fn i_process_message_2( pub fn i_prepare_message_3( mut state: State, + crypto: &mut impl CryptoTrait, id_cred_i: &BytesIdCred, cred_i: &[u8], ) -> Result<(State, BufferMessage3, BytesHashLen), EDHOCError> { @@ -661,26 +687,34 @@ 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(crypto, &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(crypto, &prk_3e2m, &th_3, &plaintext_3); - let th_4 = compute_th_4(&th_3, &plaintext_3, cred_i); + let th_4 = compute_th_4(crypto, &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( + crypto, + &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( + crypto, &prk_out, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -858,7 +892,11 @@ 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( + crypto: &mut impl CryptoTrait, + 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; @@ -870,12 +908,13 @@ 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 } fn compute_th_3( + crypto: &mut impl CryptoTrait, th_2: &BytesHashLen, plaintext_2: &BufferPlaintext2, cred_r: &[u8], @@ -890,12 +929,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 = 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 } fn compute_th_4( + crypto: &mut impl CryptoTrait, th_3: &BytesHashLen, plaintext_3: &BufferPlaintext3, cred_i: &[u8], @@ -910,13 +950,14 @@ 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 } // TODO: consider moving this to a new 'edhoc crypto primitives' module fn edhoc_kdf( + crypto: &mut impl CryptoTrait, prk: &BytesHashLen, label: u8, context: &BytesMaxContextBuffer, @@ -924,7 +965,7 @@ fn edhoc_kdf( length: usize, ) -> BytesMaxBuffer { let (info, info_len) = encode_info(label, context, context_len, length); - let output = hkdf_expand(prk, &info, info_len, length); + let output = crypto.hkdf_expand(prk, &info, info_len, length); output } @@ -1019,6 +1060,7 @@ fn encode_enc_structure(th_3: &BytesHashLen) -> BytesEncStructureLen { } fn compute_k_3_iv_3( + crypto: &mut impl CryptoTrait, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, ) -> (BytesCcmKeyLen, BytesCcmIvLen) { @@ -1026,12 +1068,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( + crypto, + 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(crypto, 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) @@ -1039,6 +1088,7 @@ fn compute_k_3_iv_3( // calculates ciphertext_3 wrapped in a cbor byte string fn encrypt_message_3( + crypto: &mut impl CryptoTrait, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, plaintext_3: &BufferPlaintext3, @@ -1049,9 +1099,9 @@ 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(crypto, 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]); @@ -1059,6 +1109,7 @@ fn encrypt_message_3( } fn decrypt_message_3( + crypto: &mut impl CryptoTrait, prk_3e2m: &BytesHashLen, th_3: &BytesHashLen, message_3: &BufferMessage3, @@ -1073,11 +1124,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) = compute_k_3_iv_3(crypto, prk_3e2m, th_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; @@ -1116,6 +1167,7 @@ fn encode_kdf_context( } fn compute_mac_3( + crypto: &mut impl CryptoTrait, prk_4e3m: &BytesHashLen, th_3: &BytesHashLen, id_cred_i: &BytesIdCred, @@ -1126,6 +1178,7 @@ fn compute_mac_3( // compute mac_3 let output_buf = edhoc_kdf( + crypto, prk_4e3m, 6u8, // registered label for "MAC_3" &context, @@ -1139,6 +1192,7 @@ fn compute_mac_3( } fn compute_mac_2( + crypto: &mut impl CryptoTrait, prk_3e2m: &BytesHashLen, id_cred_r: &BytesIdCred, cred_r: &[u8], @@ -1150,7 +1204,14 @@ 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( + crypto, + prk_3e2m, + 2 as u8, + &context, + context_len, + MAC_LENGTH_2, + )[..MAC_LENGTH_2], ); mac_2 @@ -1260,6 +1321,7 @@ fn encode_plaintext_2( } fn encrypt_decrypt_ciphertext_2( + crypto: &mut impl CryptoTrait, prk_2e: &BytesHashLen, th_2: &BytesHashLen, ciphertext_2: &BufferCiphertext2, @@ -1270,6 +1332,7 @@ fn encrypt_decrypt_ciphertext_2( // KEYSTREAM_2 = EDHOC-KDF( PRK_2e, 0, TH_2, plaintext_length ) let keystream_2 = edhoc_kdf( + crypto, prk_2e, 0u8, &th_2_context, @@ -1286,10 +1349,21 @@ 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( + crypto: &mut impl CryptoTrait, + 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( + crypto, + 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]); @@ -1297,22 +1371,28 @@ fn compute_salt_4e3m(prk_3e2m: &BytesHashLen, th_3: &BytesHashLen) -> BytesHashL } fn compute_prk_4e3m( + crypto: &mut impl CryptoTrait, 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 = 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 } -fn compute_salt_3e2m(prk_2e: &BytesHashLen, th_2: &BytesHashLen) -> BytesHashLen { +fn compute_salt_3e2m( + crypto: &mut impl CryptoTrait, + 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( + crypto, prk_2e, 1u8, &th_2_context, @@ -1327,26 +1407,28 @@ fn compute_salt_3e2m(prk_2e: &BytesHashLen, th_2: &BytesHashLen) -> BytesHashLen } fn compute_prk_3e2m( + crypto: &mut impl CryptoTrait, 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 = 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 } fn compute_prk_2e( + crypto: &mut impl CryptoTrait, x: &BytesP256ElemLen, g_y: &BytesP256ElemLen, 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 } @@ -1354,6 +1436,7 @@ fn compute_prk_2e( #[cfg(test)] mod tests { use super::*; + use edhoc_crypto::default_crypto; use hexlit::hex; // test vectors (TV) @@ -1463,7 +1546,7 @@ mod tests { #[test] fn test_ecdh() { - let g_xy = 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); } @@ -1601,7 +1684,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(&mut default_crypto(), &G_Y_TV, &H_MESSAGE_1_TV); assert_eq!(th_2, TH_2_TV); } @@ -1609,7 +1692,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(&mut default_crypto(), &TH_2_TV, &plaintext_2_tv, &CRED_R_TV); assert_eq!(th_3, TH_3_TV); } @@ -1617,7 +1700,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(&mut default_crypto(), &TH_3_TV, &plaintext_3_tv, &CRED_I_TV); assert_eq!(th_4, TH_4_TV); } @@ -1627,7 +1710,14 @@ 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( + &mut default_crypto(), + &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]); } @@ -1637,6 +1727,7 @@ mod tests { .copy_from_slice(&CONTEXT_INFO_MAC_2_TV[..]); let output_2 = edhoc_kdf( + &mut default_crypto(), &PRK_3E2M_TV, 2u8, &context_info_mac_2, @@ -1654,7 +1745,12 @@ 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( + &mut default_crypto(), + &PRK_3E2M_TV, + &TH_3_TV, + &plaintext_3_tv, + ); assert_eq!(message_3, message_3_tv); } @@ -1663,20 +1759,33 @@ 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(&mut default_crypto(), &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( + &mut default_crypto(), + &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( + &mut default_crypto(), + &PRK_3E2M_TV, + &ID_CRED_R_TV, + &CRED_R_TV, + &TH_2_TV, + ); assert_eq!(rcvd_mac_2, MAC_2_TV); } @@ -1737,8 +1846,12 @@ mod tests { let plaintext_2_tv = BufferPlaintext2::from_hex(PLAINTEXT_2_TV); 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); + let (plaintext_2, plaintext_2_len) = encrypt_decrypt_ciphertext_2( + &mut default_crypto(), + &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 { @@ -1750,8 +1863,12 @@ mod tests { plaintext_2_tmp.content[..plaintext_2_len].copy_from_slice(&plaintext_2[..plaintext_2_len]); // test encryption - let (ciphertext_2, ciphertext_2_len) = - encrypt_decrypt_ciphertext_2(&PRK_2E_TV, &TH_2_TV, &plaintext_2_tmp); + let (ciphertext_2, ciphertext_2_len) = encrypt_decrypt_ciphertext_2( + &mut default_crypto(), + &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 { @@ -1761,19 +1878,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(&mut default_crypto(), &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(&mut default_crypto(), &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(&mut default_crypto(), &X_TV, &G_Y_TV, &TH_2_TV); assert_eq!(prk_2e, PRK_2E_TV); } @@ -1886,6 +2003,7 @@ mod tests { th_4_context[..TH_4_TV.len()].copy_from_slice(&TH_4_TV[..]); let prk_out_buf = edhoc_kdf( + &mut default_crypto(), &PRK_4E3M_TV, 7u8, &th_4_context, @@ -1901,6 +2019,7 @@ mod tests { fn test_compute_prk_exporter() { let mut prk_exporter: BytesHashLen = [0x00; SHA256_DIGEST_LEN]; let prk_exporter_buf = edhoc_kdf( + &mut default_crypto(), &PRK_OUT_TV, 10u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -1915,6 +2034,7 @@ mod tests { #[test] fn test_compute_oscore_master_secret_salt() { let oscore_master_secret_buf = edhoc_kdf( + &mut default_crypto(), &PRK_EXPORTER_TV, 0u8, &[0x00; MAX_KDF_CONTEXT_LEN], @@ -1927,6 +2047,7 @@ mod tests { ); let oscore_master_salt_buf = edhoc_kdf( + &mut default_crypto(), &PRK_EXPORTER_TV, 1u8, &[0x00; MAX_KDF_CONTEXT_LEN], diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 1368bf4d..bc8d9037 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -2,8 +2,9 @@ #![allow(warnings)] 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::default_crypto, + edhoc_crypto_trait::Crypto as CryptoTrait, EdhocInitiatorState as EdhocInitiator, + EdhocResponderState as EdhocResponder, }; #[cfg(any(feature = "ead-none", feature = "ead-zeroconf"))] @@ -67,7 +68,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(()) @@ -77,10 +78,11 @@ 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) = default_crypto().p256_generate_key_pair(); match r_prepare_message_2( self.state, + &mut default_crypto(), &self.cred_r, self.r.try_into().expect("Wrong length of private key"), y, @@ -99,7 +101,12 @@ impl<'a> EdhocResponderState<'a> { self: &mut EdhocResponderState<'a>, message_3: &BufferMessage3, ) -> Result<[u8; SHA256_DIGEST_LEN], EDHOCError> { - match r_process_message_3(self.state, message_3, self.cred_i.unwrap()) { + match r_process_message_3( + self.state, + &mut default_crypto(), + message_3, + self.cred_i.unwrap(), + ) { Ok((state, prk_out)) => { self.state = state; Ok(prk_out) @@ -117,7 +124,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, 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) @@ -133,7 +147,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, &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) @@ -177,9 +196,9 @@ 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) = 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) @@ -194,6 +213,7 @@ impl<'a> EdhocInitiatorState<'a> { ) -> Result { match i_process_message_2( self.state, + &mut default_crypto(), message_2, self.cred_r, self.i @@ -211,7 +231,12 @@ 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(self.state, &get_id_cred(self.cred_i), self.cred_i) { + match i_prepare_message_3( + self.state, + &mut default_crypto(), + &get_id_cred(self.cred_i), + self.cred_i, + ) { Ok((state, message_3, prk_out)) => { self.state = state; Ok((message_3, prk_out)) @@ -229,7 +254,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, 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) @@ -245,7 +277,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, &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) @@ -269,9 +306,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 = default_crypto().get_random_byte() as i8; while conn_id < -24 || conn_id > 23 { - conn_id = edhoc_crypto::get_random_byte() as i8; + conn_id = default_crypto().get_random_byte() as i8; } conn_id }