ascon: Key type alias; cache key in Ascon state (#42)

- Adds a type alias for Ascon keys (16-byte)
- Stores key internally in `struct Ascon` so it doesn't need to be
  passed separately to `Ascon::finalize`.
This commit is contained in:
Tony Arcieri 2023-02-25 19:00:09 -07:00 committed by GitHub
parent 8773f6a963
commit 37bc658306
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 26 additions and 41 deletions

22
Cargo.lock generated
View File

@ -5,25 +5,3 @@ version = 3
[[package]]
name = "ascon"
version = "0.2.0-pre"
[[package]]
name = "cpufeatures"
version = "0.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
dependencies = [
"libc",
]
[[package]]
name = "keccak"
version = "0.1.3"
dependencies = [
"cpufeatures",
]
[[package]]
name = "libc"
version = "0.2.137"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"

View File

@ -1,6 +1,6 @@
//! Authenticated Encryption with Associated Data.
use crate::{Ascon, KEY_LEN, RATE, S_SIZE};
use crate::{Ascon, Key, KEY_SIZE, RATE, S_SIZE};
use alloc::{vec, vec::Vec};
/// Ascon(a,b) `b`-parameter.
@ -23,7 +23,7 @@ pub enum DecryptFail {
}
/// AEAD encryption.
pub fn encrypt(key: &[u8], iv: &[u8], message: &[u8], aad: &[u8]) -> (Vec<u8>, Tag) {
pub fn encrypt(key: &Key, iv: &[u8], message: &[u8], aad: &[u8]) -> (Vec<u8>, Tag) {
let s = aad.len() / RATE + 1;
let t = message.len() / RATE + 1;
let l = message.len() % RATE;
@ -70,20 +70,20 @@ pub fn encrypt(key: &[u8], iv: &[u8], message: &[u8], aad: &[u8]) -> (Vec<u8>, T
// tag
let mut tag = Tag::default();
tag.copy_from_slice(&ss.finalize(key)[S_SIZE - KEY_LEN..]);
tag.copy_from_slice(&ss.finalize()[S_SIZE - KEY_SIZE..]);
(output, tag)
}
/// AEAD decryption.
pub fn decrypt(
key: &[u8],
key: &Key,
iv: &[u8],
ciphertext: &[u8],
aad: &[u8],
tag: &[u8],
) -> Result<Vec<u8>, DecryptFail> {
if tag.len() != KEY_LEN {
if tag.len() != KEY_SIZE {
Err(DecryptFail::TagLengthError)?
};
@ -128,9 +128,9 @@ pub fn decrypt(
ss.state[l] ^= 0x80;
// finalization
let expected_tag = ss.finalize(key);
let expected_tag = ss.finalize();
if ct_eq(&expected_tag[S_SIZE - KEY_LEN..], tag) {
if ct_eq(&expected_tag[S_SIZE - KEY_SIZE..], tag) {
Ok(mm[..ciphertext.len()].into())
} else {
Err(DecryptFail::AuthenticationFail)

View File

@ -22,8 +22,8 @@ pub mod aead;
use core::convert::TryInto;
/// Key length.
const KEY_LEN: usize = 16;
/// Size of an Ascon key in bytes.
const KEY_SIZE: usize = 16;
/// State size in bits.
const S_BITS: usize = 320;
@ -34,24 +34,31 @@ const S_SIZE: usize = S_BITS / 8;
/// Rate: Sᵣ.
const RATE: usize = 128 / 8;
/// Ascon permutation key.
pub type Key = [u8; KEY_SIZE];
/// Ascon permutation state.
type State = [u8; S_SIZE];
/// Ascon(a,b) permutation.
pub struct Ascon<const A: usize = 12, const B: usize = 8> {
state: [u8; S_SIZE],
key: Key,
state: State,
}
impl<const A: usize, const B: usize> Ascon<A, B> {
/// Initialize Ascon permutation.
// TODO(tarcieri): validate length of key and nonce
pub fn new(key: &[u8], nonce: &[u8]) -> Self {
pub fn new(key: &Key, nonce: &[u8]) -> Self {
let mut state = [0; S_SIZE];
state[0] = KEY_LEN as u8 * 8;
state[0] = KEY_SIZE as u8 * 8;
state[1] = RATE as u8 * 8;
state[2] = A as u8;
state[3] = B as u8;
let mut pos = S_SIZE - 2 * KEY_LEN;
let mut pos = S_SIZE - 2 * KEY_SIZE;
state[pos..pos + key.len()].copy_from_slice(key);
pos += KEY_LEN;
pos += KEY_SIZE;
state[pos..pos + nonce.len()].copy_from_slice(nonce);
permutation(&mut state, 12 - A, A);
@ -60,7 +67,7 @@ impl<const A: usize, const B: usize> Ascon<A, B> {
state[pos + i] ^= b;
}
Self { state }
Self { key: *key, state }
}
/// Perform Ascon permutation on internal state.
@ -71,17 +78,17 @@ impl<const A: usize, const B: usize> Ascon<A, B> {
/// Finalize Ascon permutation.
#[inline(always)]
#[must_use]
pub fn finalize(self, key: &[u8]) -> [u8; S_SIZE] {
pub fn finalize(self) -> [u8; S_SIZE] {
let mut s = self.state;
for (i, &b) in key.iter().enumerate() {
for (i, &b) in self.key.iter().enumerate() {
s[RATE + i] ^= b;
}
permutation(&mut s, 12 - A, A);
for (i, &b) in key.iter().enumerate() {
s[S_SIZE - KEY_LEN + i] ^= b;
for (i, &b) in self.key.iter().enumerate() {
s[S_SIZE - KEY_SIZE + i] ^= b;
}
s