Skip to content

Commit

Permalink
Let implementations choose the tag length (#192)
Browse files Browse the repository at this point in the history
  • Loading branch information
ia0 authored Jul 21, 2023
1 parent 4a6c551 commit b6bd5f3
Show file tree
Hide file tree
Showing 36 changed files with 206 additions and 120 deletions.
1 change: 1 addition & 0 deletions crates/api-desc/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Patch

- Add `crypto::gcm::tag_length()` function
- Use `*const u8` instead of `*mut u8` for opaque data

## 0.1.3
Expand Down
10 changes: 8 additions & 2 deletions crates/api-desc/src/crypto/gcm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ pub(crate) fn new() -> Item {
support: usize,
}
},
item! {
/// Returns the supported tag length.
///
/// The tag argument to [`encrypt()`] and [`decrypt()`] must be of that length.
fn tag_length "cgt" {} -> { len: usize }
},
item! {
/// Encrypts and authenticates a clear text with associated data given a key and IV.
fn encrypt "cge" {
Expand Down Expand Up @@ -69,7 +75,7 @@ pub(crate) fn new() -> Item {
/// The cipher text.
cipher: *mut u8,

/// The 16 bytes authentication tag.
/// The authentication tag (see [`super::tag_length()`]).
tag: *mut u8,
} -> {
/// Zero on success, bitwise complement of [`Error`](crate::crypto::Error)
Expand All @@ -92,7 +98,7 @@ pub(crate) fn new() -> Item {
/// The length of the additional authenticated data.
aad_len: usize,

/// The 16 bytes authentication tag.
/// The authentication tag (see [`super::tag_length()`]).
tag: *const u8,

/// The length of the cipher (and clear) text.
Expand Down
3 changes: 2 additions & 1 deletion crates/board/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Major

- Make the tag length configurable for `crypto::aead::Api`
- Change crypto API to mention `Keysize`, `BlockSize`, and `OutputSize`

### Minor
Expand Down Expand Up @@ -59,4 +60,4 @@

## 0.1.0

<!-- Increment to skip CHANGELOG.md test: 8 -->
<!-- Increment to skip CHANGELOG.md test: 9 -->
76 changes: 38 additions & 38 deletions crates/board/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ pub mod ecc;

/// Cryptography interface.
pub trait Api {
type Aes128Ccm: aead::Api<U16, U13, U4>;
type Aes256Gcm: aead::Api<U32, U12, U16>;
type Aes128Ccm: aead::Api<U16, U13, Tag = U4>;
type Aes256Gcm: aead::Api<U32, U12>;

type HmacSha256: Support<bool> + Hmac<KeySize = U64, OutputSize = U32>;
type HmacSha384: Support<bool> + Hmac<KeySize = U128, OutputSize = U48>;
Expand All @@ -45,12 +45,12 @@ pub trait Hmac: KeyInit + Update + FixedOutput + MacMarker {}
impl<T: Default + BlockSizeUser + Update + FixedOutputReset + HashMarker> Hash for T {}
impl<T: KeyInit + Update + FixedOutput + MacMarker> Hmac for T {}

pub struct UnsupportedHash<Block: ArrayLength<u8> + 'static, Output: ArrayLength<u8> + 'static> {
pub struct UnsupportedHash<Block: ArrayLength<u8>, Output: ArrayLength<u8>> {
_never: !,
_block: Block,
_output: Output,
}
pub struct UnsupportedHmac<Key: ArrayLength<u8> + 'static, Output: ArrayLength<u8> + 'static> {
pub struct UnsupportedHmac<Key: ArrayLength<u8>, Output: ArrayLength<u8>> {
_never: !,
_key: Key,
_output: Output,
Expand Down Expand Up @@ -79,11 +79,11 @@ macro_rules! software {
impl<T: Api> Api for UnsupportedCrypto<T> {
software! {
#[cfg(feature = "software-crypto-aes128-ccm")]
type Aes128Ccm = ccm::Ccm<aes::Aes128, U4, U13> | Unsupported;
type Aes128Ccm = ccm::Ccm<aes::Aes128, U4, U13> | aead::Unsupported<U4>;
}
software! {
#[cfg(feature = "software-crypto-aes256-gcm")]
type Aes256Gcm = aes_gcm::Aes256Gcm | Unsupported;
type Aes256Gcm = aes_gcm::Aes256Gcm | aead::Unsupported<U16>;
}

software! {
Expand Down Expand Up @@ -127,31 +127,31 @@ impl Api for Unsupported {

impl<B, O> BlockSizeUser for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
type BlockSize = B;
}

impl<B, O> OutputSizeUser for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
type OutputSize = O;
}

impl<B, O> HashMarker for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
}

impl<B, O> Default for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn default() -> Self {
unreachable!()
Expand All @@ -160,8 +160,8 @@ where

impl<B, O> Update for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn update(&mut self, _: &[u8]) {
unreachable!()
Expand All @@ -170,8 +170,8 @@ where

impl<B, O> FixedOutput for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn finalize_into(self, _: &mut Output<Self>) {
unreachable!()
Expand All @@ -180,8 +180,8 @@ where

impl<B, O> FixedOutputReset for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn finalize_into_reset(&mut self, _: &mut Output<Self>) {
unreachable!()
Expand All @@ -190,8 +190,8 @@ where

impl<B, O> Reset for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn reset(&mut self) {
unreachable!()
Expand All @@ -200,39 +200,39 @@ where

impl<B, O> Support<bool> for UnsupportedHash<B, O>
where
B: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
B: ArrayLength<u8>,
O: ArrayLength<u8>,
{
const SUPPORT: bool = false;
}

impl<K, O> KeySizeUser for UnsupportedHmac<K, O>
where
K: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
K: ArrayLength<u8>,
O: ArrayLength<u8>,
{
type KeySize = K;
}

impl<K, O> OutputSizeUser for UnsupportedHmac<K, O>
where
K: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
K: ArrayLength<u8>,
O: ArrayLength<u8>,
{
type OutputSize = O;
}

impl<K, O> MacMarker for UnsupportedHmac<K, O>
where
K: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
K: ArrayLength<u8>,
O: ArrayLength<u8>,
{
}

impl<K, O> KeyInit for UnsupportedHmac<K, O>
where
K: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
K: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn new(_: &Key<Self>) -> Self {
unreachable!()
Expand All @@ -241,8 +241,8 @@ where

impl<K, O> Update for UnsupportedHmac<K, O>
where
K: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
K: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn update(&mut self, _: &[u8]) {
unreachable!()
Expand All @@ -251,8 +251,8 @@ where

impl<K, O> FixedOutput for UnsupportedHmac<K, O>
where
K: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
K: ArrayLength<u8>,
O: ArrayLength<u8>,
{
fn finalize_into(self, _: &mut Output<Self>) {
unreachable!()
Expand All @@ -261,8 +261,8 @@ where

impl<K, O> Support<bool> for UnsupportedHmac<K, O>
where
K: ArrayLength<u8> + 'static,
O: ArrayLength<u8> + 'static,
K: ArrayLength<u8>,
O: ArrayLength<u8>,
{
const SUPPORT: bool = false;
}
Expand Down
45 changes: 28 additions & 17 deletions crates/board/src/crypto/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use generic_array::{ArrayLength, GenericArray};
#[cfg(feature = "internal-aead")]
pub use software::*;

use crate::{Error, Support, Unsupported};
use crate::{Error, Support};

#[derive(Copy, Clone)]
pub struct AeadSupport {
Expand All @@ -33,51 +33,61 @@ impl From<AeadSupport> for bool {
}

/// Elliptic-curve cryptography interface.
pub trait Api<Key, Iv, Tag>: Support<AeadSupport>
pub trait Api<Key, Iv>: Support<AeadSupport>
where
Key: ArrayLength<u8>,
Iv: ArrayLength<u8>,
Tag: ArrayLength<u8>,
{
/// The tag length.
type Tag: ArrayLength<u8>;

/// Encrypts and authenticates a clear text with associated data given a key and IV.
///
/// The clear- and cipher-texts must have the same length. If the clear text is omitted, then
/// the cipher text is encrypted in place.
fn encrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], clear: Option<&[u8]>, cipher: &mut [u8],
tag: &mut Array<Tag>,
tag: &mut Array<Self::Tag>,
) -> Result<(), Error>;

/// Decrypts and authenticates a cipher text with associated data given a key and IV.
///
/// The cipher- and clear-texts must have the same length. If the cipher text is omitted, then
/// the clear text is decrypted in place.
fn decrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], cipher: Option<&[u8]>, tag: &Array<Tag>,
clear: &mut [u8],
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], cipher: Option<&[u8]>,
tag: &Array<Self::Tag>, clear: &mut [u8],
) -> Result<(), Error>;
}

pub type Array<N> = GenericArray<u8, N>;

impl Support<AeadSupport> for Unsupported {
pub struct Unsupported<Tag: ArrayLength<u8>> {
_never: !,
_tag: Tag,
}

impl<Tag: ArrayLength<u8>> Support<AeadSupport> for Unsupported<Tag> {
const SUPPORT: AeadSupport = AeadSupport { no_copy: false, in_place_no_copy: false };
}

impl<Key, Iv, Tag> Api<Key, Iv, Tag> for Unsupported
impl<Key, Iv, Tag: ArrayLength<u8>> Api<Key, Iv> for Unsupported<Tag>
where
Key: ArrayLength<u8>,
Iv: ArrayLength<u8>,
Tag: ArrayLength<u8>,
{
type Tag = Tag;

fn encrypt(
_: &Array<Key>, _: &Array<Iv>, _: &[u8], _: Option<&[u8]>, _: &mut [u8], _: &mut Array<Tag>,
_: &Array<Key>, _: &Array<Iv>, _: &[u8], _: Option<&[u8]>, _: &mut [u8],
_: &mut Array<Self::Tag>,
) -> Result<(), Error> {
unreachable!()
}

fn decrypt(
_: &Array<Key>, _: &Array<Iv>, _: &[u8], _: Option<&[u8]>, _: &Array<Tag>, _: &mut [u8],
_: &Array<Key>, _: &Array<Iv>, _: &[u8], _: Option<&[u8]>, _: &Array<Self::Tag>,
_: &mut [u8],
) -> Result<(), Error> {
unreachable!()
}
Expand All @@ -94,18 +104,19 @@ mod software {
const SUPPORT: AeadSupport = AeadSupport { no_copy: false, in_place_no_copy: true };
}

impl<Key, Iv, Tag, T> Api<Key, Iv, Tag> for T
impl<Key, Iv, T> Api<Key, Iv> for T
where
T: KeyInit + AeadInPlace,
T: KeySizeUser<KeySize = Key>,
T: AeadCore<NonceSize = Iv, TagSize = Tag>,
T: AeadCore<NonceSize = Iv>,
Key: ArrayLength<u8>,
Iv: ArrayLength<u8>,
Tag: ArrayLength<u8>,
{
type Tag = T::TagSize;

fn encrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], clear: Option<&[u8]>, cipher: &mut [u8],
tag: &mut Array<Tag>,
tag: &mut Array<Self::Tag>,
) -> Result<(), Error> {
let aead = T::new(key);
if let Some(clear) = clear {
Expand All @@ -118,8 +129,8 @@ mod software {
}

fn decrypt(
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], cipher: Option<&[u8]>, tag: &Array<Tag>,
clear: &mut [u8],
key: &Array<Key>, iv: &Array<Iv>, aad: &[u8], cipher: Option<&[u8]>,
tag: &Array<Self::Tag>, clear: &mut [u8],
) -> Result<(), Error> {
let aead = T::new(key);
if let Some(cipher) = cipher {
Expand Down
6 changes: 5 additions & 1 deletion crates/prelude/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
# Changelog

## 0.2.1-git
## 0.3.0-git

### Major

- Make the AES256-GCM tag variable length

### Minor

Expand Down
2 changes: 1 addition & 1 deletion crates/prelude/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit b6bd5f3

Please sign in to comment.