Skip to content

Commit

Permalink
Merge pull request miscreant#164 from miscreant/rust/upgrade-aesni
Browse files Browse the repository at this point in the history
rust: Upgrade aesni crate to 0.3; use block-modes crate
  • Loading branch information
tarcieri authored Mar 19, 2018
2 parents 908a293 + da2d7e7 commit fe280ca
Show file tree
Hide file tree
Showing 18 changed files with 443 additions and 462 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ matrix:
- language: rust
rust: nightly
before_script: cd rust
env:
- RUSTFLAGS=-Ctarget-feature=+aes
- language: rust
rust: nightly
before_script: cd rust/tests/ffi
env:
- CC=clang
- LDFLAGS=-rtlib=compiler-rt
- RUSTFLAGS=-Ctarget-feature=+aes
script:
- make
- ./ffi_test
Expand Down
25 changes: 20 additions & 5 deletions rust/Cargo.lock

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

5 changes: 2 additions & 3 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,13 @@ keywords = ["cryptography", "encryption", "security", "streaming"]
crate-type = ["rlib", "staticlib"]

[dependencies]
aesni = "0.2"
aesni = "0.3"
crypto-mac = "0.6"
block-cipher-trait = "0.5"
block-modes = "0.1"
byteorder = { version = "1.2", default-features = false }
clear_on_drop = { version = "0.2", features = ["nightly"] }
cmac = "0.1"
dbl = "0.1"
generic-array = "0.9"
pmac = "0.1"
ring = { version = "0.11", optional = true }
subtle = { version = "0.3", default-features = false }
Expand Down
25 changes: 17 additions & 8 deletions rust/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,28 @@ For more information, see the [toplevel README.md].

## Requirements

This library presently requires the following:
miscreant.rs presently requires the following:

* **x86_64** CPU architecture
* Rust **nightly** compiler

This library implements the AES cipher using the [aesni] crate, which
uses the [Intel AES-NI] CPU instructions to provide a fast, constant-time
hardware-based implementation. No software-only implementation of AES is
provided. Additionally it includes Intel assembly language implementations of
certain secret-dependent functions which have verified constant-time operation.
This is because it depends on the `aesni` crate which uses the `core::arch` API
for (soon-to-be) stable access to CPU intrinsics, namely the [Intel AES-NI] CPU
instructions which provide a hardware implementation of AES.

Supporting stable Rust will require upstream changes in the [aesni] crate,
which is nightly-only due to its use of inline assembly.
To access these features, you will need both a relatively recent
Rust nightly and to pass the following as RUSTFLAGS:

```
RUSTFLAGS=-C target-feature=+aes
```

You can configure your `~/.cargo/config` to always pass these flags:

```toml
[build]
rustflags = ["-C", "target-feature=+aes"]
```

[aesni]: https://github.com/RustCrypto/block-ciphers
[Intel AES-NI]: https://software.intel.com/en-us/blogs/2012/01/11/aes-ni-in-laymens-terms
Expand Down
32 changes: 22 additions & 10 deletions rust/src/aead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,16 @@
//! and authenticity.

use aesni::{Aes128, Aes256};
use aesni::block_cipher_trait::BlockCipher;
use aesni::block_cipher_trait::generic_array::{ArrayLength, GenericArray};
use aesni::block_cipher_trait::generic_array::typenum::{U16, U32, U64};
use cmac::Cmac;
use core::marker::PhantomData;
use crypto_mac::Mac;
use ctr::{Aes128Ctr, Aes256Ctr, Ctr};
#[cfg(feature = "std")]
use ctr::IV_SIZE;
use error::Error;
use generic_array::ArrayLength;
use generic_array::typenum::{U16, U32, U64};
use pmac::Pmac;
use siv::Siv;

Expand Down Expand Up @@ -96,26 +97,36 @@ pub trait Algorithm {
}

/// AEAD interface provider for AES-(PMAC-)SIV types
pub struct SivAlgorithm<C: Ctr, M: Mac<OutputSize = U16>, K: ArrayLength<u8>> {
siv: Siv<C, M>,
pub struct SivAlgorithm<B, C, M, K>
where
B: BlockCipher<BlockSize = U16>,
B::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
C: Ctr<B>,
M: Mac<OutputSize = U16>,
K: ArrayLength<u8>,
{
block_cipher: PhantomData<B>,
siv: Siv<B, C, M>,
key_size: PhantomData<K>,
}

/// AES-CMAC-SIV in AEAD mode with 256-bit key size (128-bit security)
pub type Aes128Siv = SivAlgorithm<Aes128Ctr, Cmac<Aes128>, U32>;
pub type Aes128Siv = SivAlgorithm<Aes128, Aes128Ctr, Cmac<Aes128>, U32>;

/// AES-CMAC-SIV in AEAD mode with 512-bit key size (256-bit security)
pub type Aes256Siv = SivAlgorithm<Aes256Ctr, Cmac<Aes256>, U64>;
pub type Aes256Siv = SivAlgorithm<Aes256, Aes256Ctr, Cmac<Aes256>, U64>;

/// AES-PMAC-SIV in AEAD mode with 256-bit key size (128-bit security)
pub type Aes128PmacSiv = SivAlgorithm<Aes128Ctr, Pmac<Aes128>, U32>;
pub type Aes128PmacSiv = SivAlgorithm<Aes128, Aes128Ctr, Pmac<Aes128>, U32>;

/// AES-PMAC-SIV in AEAD mode with 512-bit key size (256-bit security)
pub type Aes256PmacSiv = SivAlgorithm<Aes256Ctr, Pmac<Aes256>, U64>;
pub type Aes256PmacSiv = SivAlgorithm<Aes256, Aes256Ctr, Pmac<Aes256>, U64>;

impl<C, M, K> Algorithm for SivAlgorithm<C, M, K>
impl<B, C, M, K> Algorithm for SivAlgorithm<B, C, M, K>
where
C: Ctr,
B: BlockCipher<BlockSize = U16>,
B::ParBlocks: ArrayLength<GenericArray<u8, U16>>,
C: Ctr<B>,
M: Mac<OutputSize = U16>,
K: ArrayLength<u8>,
{
Expand All @@ -124,6 +135,7 @@ where

fn new(key: &[u8]) -> Self {
Self {
block_cipher: PhantomData,
siv: Siv::new(key),
key_size: PhantomData,
}
Expand Down
38 changes: 25 additions & 13 deletions rust/src/bench.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
extern crate ring;

use self::ring::aead;
use siv::{Aes128Siv, Aes128PmacSiv};
use siv::{Aes128PmacSiv, Aes128Siv};
use test::Bencher;

// WARNING: Do not ever actually use a key of all zeroes
Expand All @@ -22,7 +22,9 @@ fn bench_aes_siv_128_encrypt_128_bytes(b: &mut Bencher) {
let mut buffer = vec![0u8; 144];
b.bytes = 128;

b.iter(|| { siv.seal_in_place(&[NONCE], &mut buffer); });
b.iter(|| {
siv.seal_in_place(&[NONCE], &mut buffer);
});
}

#[bench]
Expand All @@ -33,7 +35,9 @@ fn bench_aes_siv_128_encrypt_1024_bytes(b: &mut Bencher) {
let mut buffer = vec![0u8; 1040];
b.bytes = 1024;

b.iter(|| { siv.seal_in_place(&[NONCE], &mut buffer); });
b.iter(|| {
siv.seal_in_place(&[NONCE], &mut buffer);
});
}

#[bench]
Expand All @@ -44,7 +48,9 @@ fn bench_aes_siv_128_encrypt_16384_bytes(b: &mut Bencher) {
let mut buffer = vec![0u8; 16400];
b.bytes = 16384;

b.iter(|| { siv.seal_in_place(&[NONCE], &mut buffer); });
b.iter(|| {
siv.seal_in_place(&[NONCE], &mut buffer);
});
}

//
Expand All @@ -59,7 +65,9 @@ fn bench_aes_pmac_siv_128_encrypt_128_bytes(b: &mut Bencher) {
let mut buffer = vec![0u8; 144];
b.bytes = 128;

b.iter(|| { siv.seal_in_place(&[NONCE], &mut buffer); });
b.iter(|| {
siv.seal_in_place(&[NONCE], &mut buffer);
});
}

#[bench]
Expand All @@ -70,7 +78,9 @@ fn bench_aes_pmac_siv_128_encrypt_1024_bytes(b: &mut Bencher) {
let mut buffer = vec![0u8; 1040];
b.bytes = 1024;

b.iter(|| { siv.seal_in_place(&[NONCE], &mut buffer); });
b.iter(|| {
siv.seal_in_place(&[NONCE], &mut buffer);
});
}

#[bench]
Expand All @@ -81,7 +91,9 @@ fn bench_aes_pmac_siv_128_encrypt_16384_bytes(b: &mut Bencher) {
let mut buffer = vec![0u8; 16400];
b.bytes = 16384;

b.iter(|| { siv.seal_in_place(&[NONCE], &mut buffer); });
b.iter(|| {
siv.seal_in_place(&[NONCE], &mut buffer);
});
}

//
Expand All @@ -90,8 +102,8 @@ fn bench_aes_pmac_siv_128_encrypt_16384_bytes(b: &mut Bencher) {

#[bench]
fn bench_aes_gcm_128_encrypt_128_bytes(b: &mut Bencher) {
let sealing_key = aead::SealingKey::new(&aead::AES_128_GCM, &KEY_128_BIT[..])
.expect("valid key");
let sealing_key =
aead::SealingKey::new(&aead::AES_128_GCM, &KEY_128_BIT[..]).expect("valid key");

// 128 bytes input + 16 bytes tag
let mut buffer = [0u8; 144];
Expand All @@ -110,8 +122,8 @@ fn bench_aes_gcm_128_encrypt_128_bytes(b: &mut Bencher) {

#[bench]
fn bench_aes_gcm_128_encrypt_1024_bytes(b: &mut Bencher) {
let sealing_key = aead::SealingKey::new(&aead::AES_128_GCM, &KEY_128_BIT[..])
.expect("valid key");
let sealing_key =
aead::SealingKey::new(&aead::AES_128_GCM, &KEY_128_BIT[..]).expect("valid key");

// 1024 bytes input + 16 bytes tag
let mut buffer = [0u8; 1040];
Expand All @@ -130,8 +142,8 @@ fn bench_aes_gcm_128_encrypt_1024_bytes(b: &mut Bencher) {

#[bench]
fn bench_aes_gcm_128_encrypt_16384_bytes(b: &mut Bencher) {
let sealing_key = aead::SealingKey::new(&aead::AES_128_GCM, &KEY_128_BIT[..])
.expect("valid key");
let sealing_key =
aead::SealingKey::new(&aead::AES_128_GCM, &KEY_128_BIT[..]).expect("valid key");

// 16384 bytes input + 16 bytes tag
let mut buffer = [0u8; 16400];
Expand Down
Loading

0 comments on commit fe280ca

Please sign in to comment.