Skip to content

Commit

Permalink
Merge pull request #13 from RustCrypto/polyval
Browse files Browse the repository at this point in the history
POLYVAL universal hash function for AES-GCM(-SIV)
  • Loading branch information
tarcieri committed Aug 26, 2019
2 parents 37adacf + 89f6277 commit bd1bcf5
Show file tree
Hide file tree
Showing 21 changed files with 1,117 additions and 37 deletions.
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

0 comments on commit bd1bcf5

Please sign in to comment.