Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core functions for the lake-authz draft #110

Merged
merged 25 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
65f28a7
feat[zeroconf]: encode ead_1
geonnave Oct 4, 2023
c90481e
wip: build ENC_ID
geonnave Oct 5, 2023
c3fcfa6
feat: build ENC_ID
geonnave Oct 5, 2023
e1bb540
feat: add test vector playground
geonnave Oct 9, 2023
0eaf146
wip: fixing ead_1 preparation
geonnave Oct 10, 2023
54d4e5e
fix: build_enc_id generates correct result
geonnave Oct 11, 2023
54813d8
fix: i_prepare_ead_1 pass tests
geonnave Oct 11, 2023
0b25c8d
feat: build voucher_request and test with TV
geonnave Oct 11, 2023
3a182c5
feat: parse voucher request, encode voucher input
geonnave Oct 12, 2023
10ed108
feat: compute mac and encode voucher
geonnave Oct 12, 2023
f365e06
feat: build voucher request
geonnave Oct 12, 2023
f680b8c
feat: prepare ead_2
geonnave Oct 12, 2023
9b6daa6
feat: process ead 2 at U
geonnave Oct 12, 2023
abac7db
feat: make opaque state optional
geonnave Oct 13, 2023
7d33db3
feat: add tests for stateful (default) operation of V
geonnave Oct 13, 2023
9930ec6
refactor: move cbor helpers to consts crate
geonnave Oct 13, 2023
65f73d0
feat: make main crate tests pass
geonnave Oct 13, 2023
c846dfe
refactor: make sure .unwraps are safe
geonnave Oct 24, 2023
439c326
refactor: validate sizes on parsing
geonnave Oct 24, 2023
774c8ca
refactor: use constants instead of magic numbers
geonnave Oct 25, 2023
e994bf2
fix: voucher has MAC_LENGTH bytes
geonnave Oct 25, 2023
125df8d
refactor: use smaller arrays for voucher
geonnave Oct 25, 2023
dce19eb
fix: adjust iv length according to draft
geonnave Oct 26, 2023
bb20772
refactor: move encoding of info to helpers module
geonnave Oct 26, 2023
d07c5ee
chore: remove outdated comment
geonnave Nov 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 98 additions & 5 deletions consts/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
#![no_std]

pub use consts::*;
pub use helpers::*;
pub use structs::*;

mod consts {
use super::structs::*;

pub const MAX_MESSAGE_SIZE_LEN: usize = 64;
pub const MAX_EAD_SIZE_LEN: usize = 64;
// TODO: find a way to configure the buffer size
// need 128 to handle EAD fields, and 192 for the EAD_1 voucher
pub const MAX_MESSAGE_SIZE_LEN: usize = 128 + 64;
pub type EADMessageBuffer = EdhocMessageBuffer; // TODO: make it of size MAX_EAD_SIZE_LEN
pub const EAD_ZEROCONF_LABEL: u8 = 0x1; // NOTE: in lake-authz-draft-02 it is still TBD1

pub const ID_CRED_LEN: usize = 4;
pub const SUITES_LEN: usize = 9;
Expand All @@ -20,14 +21,17 @@ mod consts {
pub const AES_CCM_KEY_LEN: usize = 16;
pub const AES_CCM_IV_LEN: usize = 13;
pub const AES_CCM_TAG_LEN: usize = 8;
pub const MAC_LENGTH_2: usize = 8;
pub const MAC_LENGTH: usize = 8; // used for EAD Zeroconf
pub const MAC_LENGTH_2: usize = MAC_LENGTH;
pub const MAC_LENGTH_3: usize = MAC_LENGTH_2;
pub const ENCODED_VOUCHER_LEN: usize = 1 + MAC_LENGTH; // 1 byte for the length of the bstr-encoded voucher

// maximum supported length of connection identifier for R
pub const MAX_KDF_CONTEXT_LEN: usize = 150;
pub const MAX_KDF_LABEL_LEN: usize = 15; // for "KEYSTREAM_2"
pub const MAX_BUFFER_LEN: usize = 220;
pub const CBOR_BYTE_STRING: u8 = 0x58u8;
pub const CBOR_TEXT_STRING: u8 = 0x78u8;
pub const CBOR_UINT_1BYTE: u8 = 0x18u8;
pub const CBOR_NEG_INT_1BYTE_START: u8 = 0x20u8;
pub const CBOR_NEG_INT_1BYTE_END: u8 = 0x37u8;
Expand All @@ -47,6 +51,12 @@ mod consts {

pub const EDHOC_SUITES: BytesSuites = [0, 1, 2, 3, 4, 5, 6, 24, 25]; // all but private cipher suites
pub const EDHOC_SUPPORTED_SUITES: BytesSupportedSuites = [0x2u8];

pub const MAX_EAD_SIZE_LEN: usize = 64;
pub const EAD_ZEROCONF_LABEL: u8 = 0x1; // NOTE: in lake-authz-draft-02 it is still TBD1
pub const EAD_ZEROCONF_INFO_K_1_LABEL: u8 = 0x0;
pub const EAD_ZEROCONF_INFO_IV_1_LABEL: u8 = 0x1;
pub const EAD_ZEROCONF_ENC_STRUCTURE_LEN: usize = 2 + 8 + 3;
}

mod structs {
Expand Down Expand Up @@ -76,6 +86,9 @@ mod structs {
pub type BytesMaxLabelBuffeer = [u8; MAX_KDF_LABEL_LEN];
pub type BytesEncStructureLen = [u8; ENC_STRUCTURE_LEN];

pub type BytesMac = [u8; MAC_LENGTH];
pub type BytesEncodedVoucher = [u8; ENCODED_VOUCHER_LEN];

#[repr(C)]
#[derive(Default, PartialEq, Copy, Clone, Debug)]
pub enum EDHOCState {
Expand Down Expand Up @@ -118,7 +131,7 @@ mod structs {
);

#[repr(C)]
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, Copy, Clone)]
pub struct EdhocMessageBuffer {
pub content: [u8; MAX_MESSAGE_SIZE_LEN],
pub len: usize,
Expand Down Expand Up @@ -189,3 +202,83 @@ mod structs {
}
}
}

mod helpers {
use super::consts::*;
use super::structs::*;

/// Check for: an unsigned integer encoded as a single byte
#[inline(always)]
pub fn is_cbor_uint_1byte(byte: u8) -> bool {
return byte >= CBOR_UINT_1BYTE_START && byte <= CBOR_UINT_1BYTE_END;
}

/// Check for: an unsigned integer encoded as two bytes
#[inline(always)]
pub fn is_cbor_uint_2bytes(byte: u8) -> bool {
return byte == CBOR_UINT_1BYTE;
}

/// Check for: a negative integer encoded as a single byte
#[inline(always)]
pub fn is_cbor_neg_int_1byte(byte: u8) -> bool {
return byte >= CBOR_NEG_INT_1BYTE_START && byte <= CBOR_NEG_INT_1BYTE_END;
}

/// Check for: a bstr denoted by a single byte which encodes both type and content length
#[inline(always)]
pub fn is_cbor_bstr_1byte_prefix(byte: u8) -> bool {
return byte >= CBOR_MAJOR_BYTE_STRING && byte <= CBOR_MAJOR_BYTE_STRING_MAX;
}

/// Check for: a bstr denoted by two bytes, one for type the other for content length
#[inline(always)]
pub fn is_cbor_bstr_2bytes_prefix(byte: u8) -> bool {
return byte == CBOR_BYTE_STRING;
}

/// Check for: a tstr denoted by two bytes, one for type the other for content length
#[inline(always)]
pub fn is_cbor_tstr_2bytes_prefix(byte: u8) -> bool {
return byte == CBOR_TEXT_STRING;
}

/// Check for: an array denoted by a single byte which encodes both type and content length
#[inline(always)]
pub fn is_cbor_array_1byte_prefix(byte: u8) -> bool {
return byte >= CBOR_MAJOR_ARRAY && byte <= CBOR_MAJOR_ARRAY_MAX;
}

pub fn encode_info(
label: u8,
context: &BytesMaxContextBuffer,
context_len: usize,
length: usize,
) -> (BytesMaxInfoBuffer, usize) {
let mut info: BytesMaxInfoBuffer = [0x00; MAX_INFO_LEN];

// construct info with inline cbor encoding
info[0] = label;
let mut info_len = 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]);
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]);
3 + context_len
};

info_len = if length < 24 {
info[info_len] = length as u8;
info_len + 1
} else {
info[info_len] = CBOR_UINT_1BYTE;
info[info_len + 1] = length as u8;
info_len + 2
};

(info, info_len)
}
}
6 changes: 4 additions & 2 deletions crypto/edhoc-crypto-cryptocell310-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,16 @@ pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen
pub fn aes_ccm_encrypt_tag_8(
key: &BytesCcmKeyLen,
iv: &BytesCcmIvLen,
ad: &BytesEncStructureLen,
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(
Expand All @@ -86,7 +88,7 @@ pub fn aes_ccm_encrypt_tag_8(
CRYS_AESCCM_KeySize_t_CRYS_AES_Key128BitSize,
iv.clone().as_mut_ptr(),
iv.len() as u8,
ad.clone().as_mut_ptr(),
aesccm_ad.as_mut_ptr(),
ad.len() as u32,
plaintext.content.clone().as_mut_ptr(),
plaintext.len as u32,
Expand Down
8 changes: 2 additions & 6 deletions crypto/edhoc-crypto-hacspec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,17 +117,13 @@ pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen
pub fn aes_ccm_encrypt_tag_8(
key: &BytesCcmKeyLen,
iv: &BytesCcmIvLen,
ad: &BytesEncStructureLen,
ad: &[u8],
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_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()),
Expand Down
2 changes: 1 addition & 1 deletion crypto/edhoc-crypto-psa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn hkdf_extract(salt: &BytesHashLen, ikm: &BytesP256ElemLen) -> BytesHashLen
pub fn aes_ccm_encrypt_tag_8(
key: &BytesCcmKeyLen,
iv: &BytesCcmIvLen,
ad: &BytesEncStructureLen,
ad: &[u8],
plaintext: &BufferPlaintext3,
) -> BufferCiphertext3 {
psa_crypto::init().unwrap();
Expand Down
17 changes: 12 additions & 5 deletions ead/edhoc-ead-none/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,19 @@

use edhoc_consts::*;

// TODO: the function signatures should not be necessarily the same as the zeroconf version
// find a way to be generic on this part.

// initiator side
pub fn i_prepare_ead_1() -> Option<EADItem> {
pub fn i_prepare_ead_1(_x: &BytesP256ElemLen, _ss: u8) -> Option<EADItem> {
None
}

pub fn i_process_ead_2(ead_2: EADItem) -> Result<(), ()> {
pub fn i_process_ead_2(
_ead_2: EADItem,
_cred_v_u8: &[u8],
_h_message_1: &BytesHashLen,
) -> Result<(), ()> {
Ok(())
}

Expand All @@ -16,14 +23,14 @@ pub fn i_prepare_ead_3() -> Option<EADItem> {
}

// responder side
pub fn r_process_ead_1(ead_1: EADItem) -> Result<(), ()> {
pub fn r_process_ead_1(_ead_1: &EADItem, _message_1: &BufferMessage1) -> Result<(), ()> {
Ok(())
}

pub fn r_prepare_ead_2() -> Option<EADItem> {
pub fn r_prepare_ead_2(_voucher_response: &Option<EdhocMessageBuffer>) -> Option<EADItem> {
None
}

pub fn r_process_ead_3(ead_3: EADItem) -> Result<(), ()> {
pub fn r_process_ead_3(_ead_3: EADItem) -> Result<(), ()> {
Ok(())
}
7 changes: 7 additions & 0 deletions ead/edhoc-ead-zeroconf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,10 @@ description = "EDHOC EAD zeroconf (draf-lake-authz)"

[dependencies]
edhoc-consts = { path = "../../consts" }
edhoc-crypto = { path = "../../crypto", default-features = false }
hacspec-lib = { version = "0.1.0-beta.1", default-features = false, optional = true }
hexlit = "0.5.3"

[features]
crypto-psa = [ "edhoc-crypto/psa" ]
crypto-hacspec = ["hacspec-lib/std", "edhoc-crypto/hacspec" ]
Loading