Skip to content

Commit

Permalink
cleanup and message limits
Browse files Browse the repository at this point in the history
  • Loading branch information
franziskuskiefer committed Apr 21, 2021
1 parent 7613455 commit 7b6ee1c
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 26 deletions.
41 changes: 33 additions & 8 deletions src/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ pub(crate) trait AeadTrait: Debug + Sync {
aad: &[u8],
cipher_txt: &[u8],
) -> Result<Vec<u8>, Error>;
fn get_key_length(&self) -> usize;
fn get_nonce_length(&self) -> usize;
fn key_length(&self) -> usize;
fn nonce_length(&self) -> usize;
}

#[derive(Debug)]
Expand Down Expand Up @@ -111,7 +111,7 @@ impl<'de> Deserialize<'de> for Aead {
}
}

fn get_aead_object(mode: Mode) -> Box<dyn AeadTrait> {
fn aead_object(mode: Mode) -> Box<dyn AeadTrait> {
match mode {
Mode::AesGcm128 => Box::new(AesGcm128::new()),
Mode::AesGcm256 => Box::new(AesGcm256::new()),
Expand All @@ -121,18 +121,30 @@ fn get_aead_object(mode: Mode) -> Box<dyn AeadTrait> {
}

impl Aead {
/// Create a new Aead with the given `mode`.
pub fn new(mode: Mode) -> Self {
Self {
mode,
aead: get_aead_object(mode),
aead: aead_object(mode),
}
}
pub fn get_nk(&self) -> usize {
self.aead.get_key_length()

/// Get the key length of the used scheme.
pub fn nk(&self) -> usize {
self.aead.key_length()
}
pub fn get_nn(&self) -> usize {
self.aead.get_nonce_length()

/// Get the nonce length of the used scheme.
pub fn nn(&self) -> usize {
self.aead.nonce_length()
}

/// Encrypt the given `plain_txt` with the `aad`, `key`, and `nonce`. All
/// values are passed in as byte slices.
///
/// The function returns a `Result`.
/// A byte vector with the cipher text and tag concatenated if successful.
/// Or an `Error` if any of the parameters are invalid.
pub fn seal(
&self,
key: &[u8],
Expand All @@ -142,6 +154,13 @@ impl Aead {
) -> Result<Vec<u8>, Error> {
self.aead.seal(key, nonce, aad, plain_txt)
}

/// Decrypt a given `cipher_txt` with the `aad`, `key`, and `nonce`. All
/// values are passed in as byte slices.
///
/// The function returns a `Result`.
/// A byte vector with the plaintext.
/// Or an `Error` if any of the parameters are invalid or the opening fails.
pub fn open(
&self,
key: &[u8],
Expand All @@ -151,4 +170,10 @@ impl Aead {
) -> Result<Vec<u8>, Error> {
self.aead.open(key, nonce, aad, cipher_txt)
}

/// Get the message limit for this AEAD.
/// If the message limit is reached, the key must be rotated.
pub fn message_limit(&self) -> u32 {
(1 << self.nn()) - 1
}
}
4 changes: 2 additions & 2 deletions src/aead_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ macro_rules! implement_aead {
Err(_) => Err(Error::OpenError),
}
}
fn get_key_length(&self) -> usize {
fn key_length(&self) -> usize {
$key_length
}
fn get_nonce_length(&self) -> usize {
fn nonce_length(&self) -> usize {
12
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/kdf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl Kdf {
}
}

pub(crate) fn get_nh(&self) -> usize {
pub(crate) fn nh(&self) -> usize {
self.kdf.digest_length()
}

Expand Down
4 changes: 2 additions & 2 deletions src/kem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub enum Error {
}

// Map KEM to KDF according to spec.
fn get_kdf(mode: Mode) -> kdf::Mode {
fn kdf(mode: Mode) -> kdf::Mode {
match mode {
Mode::DhKemP256 => kdf::Mode::HkdfSha256,
Mode::DhKemP384 => kdf::Mode::HkdfSha384,
Expand Down Expand Up @@ -146,7 +146,7 @@ impl Kem {
pub(crate) fn new(mode: Mode) -> Self {
Self {
mode,
kem: kem_object(mode, get_kdf(mode)),
kem: kem_object(mode, kdf(mode)),
}
}

Expand Down
39 changes: 26 additions & 13 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ pub enum HpkeError {

/// An error in the crypto library occurred.
CryptoError,

/// The message limit for this AEAD, key, and nonce.
MessageLimitReached,
}

#[deprecated(
Expand Down Expand Up @@ -216,7 +219,7 @@ impl<'a> Context<'a> {
.hpke
.aead
.seal(&self.key, &self.compute_nonce(), aad, plain_txt)?;
self.increment_seq();
self.increment_seq()?;
Ok(ctxt)
}

Expand All @@ -238,7 +241,7 @@ impl<'a> Context<'a> {
.hpke
.aead
.open(&self.key, &self.compute_nonce(), aad, cipher_txt)?;
self.increment_seq();
self.increment_seq()?;
Ok(ptxt)
}

Expand All @@ -254,23 +257,33 @@ impl<'a> Context<'a> {
pub fn export(&self, exporter_context: &[u8], length: usize) -> Vec<u8> {
self.hpke.kdf.labeled_expand(
&self.exporter_secret,
&self.hpke.get_ciphersuite(),
&self.hpke.ciphersuite(),
"sec",
exporter_context,
length,
)
}

// TODO: not cool
/// def Context<ROLE>.ComputeNonce(seq):
/// seq_bytes = I2OSP(seq, Nn)
/// return xor(self.base_nonce, seq_bytes)
fn compute_nonce(&self) -> Vec<u8> {
let seq = self.sequence_number.to_be_bytes();
let mut enc_seq = vec![0u8; self.nonce.len() - seq.len()];
enc_seq.append(&mut seq.to_vec());
util::xor_bytes(&enc_seq, &self.nonce)
}

fn increment_seq(&mut self) {
/// def Context<ROLE>.IncrementSeq():
/// if self.seq >= (1 << (8*Nn)) - 1:
/// raise MessageLimitReached
/// self.seq += 1
fn increment_seq(&mut self) -> Result<(), HpkeError> {
if self.sequence_number >= self.hpke.aead.message_limit() {
return Err(HpkeError::MessageLimitReached);
}
self.sequence_number += 1;
Ok(())
}
}

Expand Down Expand Up @@ -318,9 +331,9 @@ impl Hpke {
kem_id,
kdf_id,
aead_id,
nk: aead.get_nk(),
nn: aead.get_nn(),
nh: kdf.get_nh(),
nk: aead.nk(),
nn: aead.nn(),
nh: kdf.nh(),
kem,
kdf,
aead,
Expand Down Expand Up @@ -518,7 +531,7 @@ impl Hpke {
}

#[inline]
fn get_ciphersuite(&self) -> Vec<u8> {
fn ciphersuite(&self) -> Vec<u8> {
util::concat(&[
b"HPKE",
&(self.kem_id as u16).to_be_bytes(),
Expand All @@ -528,7 +541,7 @@ impl Hpke {
}

#[inline]
fn get_key_schedule_context(&self, info: &[u8], psk_id: &[u8], suite_id: &[u8]) -> Vec<u8> {
fn key_schedule_context(&self, info: &[u8], psk_id: &[u8], suite_id: &[u8]) -> Vec<u8> {
let psk_id_hash = self
.kdf
.labeled_extract(&[0], suite_id, "psk_id_hash", psk_id);
Expand Down Expand Up @@ -577,8 +590,8 @@ impl Hpke {
psk_id: &[u8],
) -> Result<Context, HpkeError> {
self.verify_psk_inputs(psk, psk_id)?;
let suite_id = self.get_ciphersuite();
let key_schedule_context = self.get_key_schedule_context(info, psk_id, &suite_id);
let suite_id = self.ciphersuite();
let key_schedule_context = self.key_schedule_context(info, psk_id, &suite_id);
let secret = self
.kdf
.labeled_extract(shared_secret, &suite_id, "secret", psk);
Expand Down Expand Up @@ -608,7 +621,7 @@ impl Hpke {

/// 4. Cryptographic Dependencies
/// Randomized algorithm to generate a key pair `(skX, pkX)` for the KEM.
/// This is equivalent to `derive_key_pair(get_random_vector(sk.len()))`
/// This is equivalent to `derive_key_pair(random_vector(sk.len()))`
///
/// Returns an `HpkeKeyPair`.
pub fn generate_key_pair(&self) -> HpkeKeyPair {
Expand Down

0 comments on commit 7b6ee1c

Please sign in to comment.