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

POLYVAL universal hash function for AES-GCM(-SIV) #13

Merged
merged 4 commits into from
Aug 26, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
27 changes: 17 additions & 10 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,38 @@ matrix:
rust: 1.21.0
script: cd hmac && cargo test --verbose
- rust: 1.27.0
script: cargo test --verbose --all
script: cargo test --verbose --all --exclude=polyval
- rust: stable
script: cargo test --verbose --all
script: cargo test --verbose --all --exclude=polyval
- rust: nightly
script: cargo test --verbose --all
script: cargo test --verbose --all --exclude=polyval

- env: TARGET=i686-unknown-linux-gnu
rust: stable
- env: TARGET=powerpc-unknown-linux-gnu
rust: stable
- env: TARGET=powerpc64-unknown-linux-gnu
rust: stable

# tests if crates truly can be built without std
- env: TARGET=thumbv7em-none-eabi
rust: nightly
script: xargo build --verbose --target $TARGET
install:
- cargo install xargo || true
- rustup target install armv7-unknown-linux-gnueabihf
- rustup component add rust-src
rust: stable
install: rustup target install $TARGET
script:
- cargo build --verbose --all --exclude=polyval --tests

# polyval presently needs either RUSTFLAGS or non-default features
- name: "Rust: 1.32.0 (polyval)"
rust: 1.32.0
script: ./test_polyval.sh
- name: "Rust: stable (polyval)"
rust: stable
script: ./test_polyval.sh

install:
- cargo install cross || true

script:
- cross test --verbose --all --target $TARGET
- cross test --verbose --all --exclude=polyval --target $TARGET

cache: cargo
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ members = [
"daa",
"hmac",
"pmac",
"poly1305"
"poly1305",
"polyval",
]
5 changes: 3 additions & 2 deletions poly1305/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "poly1305"
version = "0.2.0"
authors = ["RustCrypto Developers"]
license = "MIT/Apache-2.0"
license = "MIT OR Apache-2.0"
description = "The Poly1305 universal hash function and message authentication code"
documentation = "https://docs.rs/poly1305"
repository = "https://github.com/RustCrypto/MACs"
Expand All @@ -12,11 +12,12 @@ readme = "README.md"

[dependencies]
byteorder = { version = "1", default-features = false }
crypto-mac = "0.7"
subtle = { version = "2", default-features = false }
zeroize = { version = "0.9", optional = true, default-features = false }

[dev-dependencies]
crypto-mac = { version = "0.7", features = ["dev"] }

[badges]
maintenance = { status = "experimental" }
travis-ci = { repository = "RustCrypto/hashes" }
12 changes: 11 additions & 1 deletion poly1305/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
[![crate][crate-image]][crate-link]
[![Docs][docs-image]][docs-link]
![Apache2/MIT licensed][license-image]
![Rust Version][rustc-image]
![MSRV][rustc-image]
![Maintenance Status: Experimental][maintenance-image]
[![Build Status][build-image]][build-link]

[Poly1305][1] is a [universal hash function][2] which, when combined with a cipher,
Expand All @@ -14,6 +15,14 @@ In practice, Poly1305 is primarily combined with ciphers from the

[Documentation][docs-link]

## Security Warning

No security audits of this crate have ever been performed, and it has not been
thoroughly assessed to ensure its operation is constant-time on common CPU
architectures.

USE AT YOUR OWN RISK!

## License

Licensed under either of:
Expand All @@ -37,6 +46,7 @@ dual licensed as above, without any additional terms or conditions.
[docs-link]: https://docs.rs/poly1305/
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.27+-blue.svg
[maintenance-image]: https://img.shields.io/badge/maintenance-experimental-blue.svg
[build-image]: https://travis-ci.org/RustCrypto/MACs.svg?branch=master
[build-link]: https://travis-ci.org/RustCrypto/MACs

Expand Down
7 changes: 3 additions & 4 deletions poly1305/benches/poly1305.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crypto_mac::generic_array::{
GenericArray,
};
use crypto_mac::MacResult;
use poly1305::Poly1305;
use poly1305::{Poly1305, Block};
use std::convert::TryInto;

bench!(Poly1305Mac);
Expand Down Expand Up @@ -42,8 +42,7 @@ impl Mac for Poly1305Mac {
}

fn result(self) -> MacResult<Self::OutputSize> {
let mut mac = GenericArray::default();
mac.copy_from_slice(&self.0.result());
MacResult::new(mac)
let tag: Block = self.0.result().into();
MacResult::new(tag.into())
}
}
52 changes: 41 additions & 11 deletions poly1305/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,28 @@

// TODO: replace with `u32::{from_le_bytes, to_le_bytes}` in libcore (1.32+)
extern crate byteorder;
extern crate crypto_mac;
pub extern crate subtle;

#[cfg(feature = "zeroize")]
extern crate zeroize;

use byteorder::{ByteOrder, LE};
use core::cmp::min;
use crypto_mac::generic_array::{typenum::U16, GenericArray};
use crypto_mac::MacResult;
use subtle::{Choice, ConstantTimeEq};
#[cfg(feature = "zeroize")]
use zeroize::Zeroize;

/// Size of a Poly1305 key
pub const KEY_SIZE: usize = 32;

/// Poly1305 keys (32-bytes)
pub type Key = [u8; KEY_SIZE];

/// Size of the blocks Poly1305 acts upon
pub const BLOCK_SIZE: usize = 16;

/// Poly1305 authentication tags
pub type Tag = MacResult<U16>;
/// Poly1305 blocks (16-bytes)
pub type Block = [u8; BLOCK_SIZE];

/// The Poly1305 universal hash function.
///
Expand All @@ -51,18 +53,18 @@ pub struct Poly1305 {
h: [u32; 5],
pad: [u32; 4],
leftover: usize,
buffer: [u8; BLOCK_SIZE],
buffer: Block,
}

impl Poly1305 {
/// Initialize Poly1305 with the given key
pub fn new(key: &[u8; KEY_SIZE]) -> Poly1305 {
pub fn new(key: &Key) -> Poly1305 {
let mut poly = Poly1305 {
r: [0u32; 5],
h: [0u32; 5],
pad: [0u32; 4],
leftover: 0,
buffer: [0u8; BLOCK_SIZE],
buffer: Block::default(),
};

// r &= 0xffffffc0ffffffc0ffffffc0fffffff
Expand Down Expand Up @@ -128,7 +130,7 @@ impl Poly1305 {
let unaligned_len = data.len() % BLOCK_SIZE;

if unaligned_len != 0 {
let pad = [0u8; BLOCK_SIZE];
let pad = Block::default();
let pad_len = BLOCK_SIZE - unaligned_len;
self.input(&pad[..pad_len]);
}
Expand Down Expand Up @@ -233,13 +235,13 @@ impl Poly1305 {
f = u64::from(h3) + u64::from(self.pad[3]) + (f >> 32);
h3 = f as u32;

let mut tag = GenericArray::default();
let mut tag = Block::default();
LE::write_u32(&mut tag[0..4], h0);
LE::write_u32(&mut tag[4..8], h1);
LE::write_u32(&mut tag[8..12], h2);
LE::write_u32(&mut tag[12..16], h3);

MacResult::new(tag)
Tag::new(tag)
}

/// Compute a single block of Poly1305 using the internal buffer
Expand Down Expand Up @@ -344,3 +346,31 @@ impl Drop for Poly1305 {
self.buffer.zeroize();
}
}

/// Poly1305 authentication tags
pub struct Tag(Block);

impl Tag {
/// Create a new Poly1305 authentication tag
fn new(tag: Block) -> Self {
Tag(tag)
}
}

impl AsRef<Block> for Tag {
fn as_ref(&self) -> &Block {
&self.0
}
}

impl ConstantTimeEq for Tag {
fn ct_eq(&self, other: &Self) -> Choice {
self.0.ct_eq(other.0.as_ref())
}
}

impl From<Tag> for Block {
fn from(tag: Tag) -> Block {
tag.0
}
}
16 changes: 8 additions & 8 deletions poly1305/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn test_nacl_vector() {
];

let result1 = Poly1305::new(&key).chain(&msg).result();
assert_eq!(&expected[..], result1.code().as_slice());
assert_eq!(&expected[..], result1.as_ref());

let result2 = Poly1305::new(&key)
.chain(&msg[0..32])
Expand All @@ -45,7 +45,7 @@ fn test_nacl_vector() {
.chain(&msg[130..131])
.result();

assert_eq!(&expected[..], result2.code().as_slice());
assert_eq!(&expected[..], result2.as_ref());
}

#[test]
Expand All @@ -68,7 +68,7 @@ fn donna_self_test() {

let result = Poly1305::new(&wrap_key).chain(&wrap_msg).result();

assert_eq!(&wrap_mac[..], result.code().as_slice());
assert_eq!(&wrap_mac[..], result.as_ref());

let total_key = [
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff,
Expand All @@ -89,10 +89,10 @@ fn donna_self_test() {

let msg: Vec<u8> = repeat(i as u8).take(256).collect();
let tag = Poly1305::new(&key).chain(&msg[..i]).result();
tpoly.input(tag.code().as_slice());
tpoly.input(tag.as_ref());
}

assert_eq!(&total_mac[..], tpoly.result().code().as_slice());
assert_eq!(&total_mac[..], tpoly.result().as_ref());
}

#[test]
Expand All @@ -107,7 +107,7 @@ fn test_tls_vectors() {
];

let result1 = Poly1305::new(&key).chain(&msg1).result();
assert_eq!(&expected1[..], result1.code().as_slice());
assert_eq!(&expected1[..], result1.as_ref());

let msg2 = b"Hello world!";
let expected2 = [
Expand All @@ -116,7 +116,7 @@ fn test_tls_vectors() {
];

let result2 = Poly1305::new(&key).chain(&msg2[..]).result();
assert_eq!(&expected2[..], result2.code().as_slice());
assert_eq!(&expected2[..], result2.as_ref());
}

#[test]
Expand All @@ -139,5 +139,5 @@ fn padded_input() {

let mut poly = Poly1305::new(&key);
poly.input_padded(&msg);
assert_eq!(&expected[..], poly.result().code().as_slice());
assert_eq!(&expected[..], poly.result().as_ref());
}
32 changes: 32 additions & 0 deletions polyval/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "polyval"
version = "0.0.0"
authors = ["RustCrypto Developers"]
license = "MIT OR Apache-2.0"
description = """
POLYVAL is a GHASH-like universal hash over GF(2^128) useful for constructing
a Message Authentication Code (MAC)
"""
documentation = "https://docs.rs/polyval"
repository = "https://github.com/RustCrypto/MACs"
readme = "README.md"
keywords = ["aes-gcm-siv", "crypto", "universal-hashing"]
categories = ["cryptography", "no-std"]

[dependencies]
byteorder = { version = "1", optional = true, default-features = false }
subtle = { version = "2", default-features = false }

[dev-dependencies]
crypto-mac = { version = "0.7", features = ["dev"] }
hex-literal = "0.1"

[features]
insecure-soft = ["byteorder"]

[badges]
maintenance = { status = "experimental" }
travis-ci = { repository = "RustCrypto/hashes" }

[package.metadata.docs.rs]
all-features = true
Loading