Skip to content

Commit

Permalink
poly1305/polyval: Switch from MacResult to built-in Tag types
Browse files Browse the repository at this point in the history
Eliminates the dependency on `crypto-mac` by using a built-in `Tag` type
which impl's `subtle::ConstantTimeEq`.

Ideally this would probably get extracted into some other trait, e.g.
`UniversalHash`, but for now just use concrete types per crate.
  • Loading branch information
tarcieri committed Aug 26, 2019
1 parent fe2a616 commit 89f6277
Show file tree
Hide file tree
Showing 15 changed files with 163 additions and 66 deletions.
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());
}
3 changes: 2 additions & 1 deletion polyval/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ categories = ["cryptography", "no-std"]

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

[dev-dependencies]
crypto-mac = { version = "0.7", features = ["dev"] }
Expand All @@ -25,6 +25,7 @@ hex-literal = "0.1"
insecure-soft = ["byteorder"]

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

[package.metadata.docs.rs]
Expand Down
10 changes: 10 additions & 0 deletions polyval/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
[![Docs][docs-image]][docs-link]
![Apache2/MIT licensed][license-image]
![Rust Version][rustc-image]
![Maintenance Status: Experimental][maintenance-image]
[![Build Status][build-image]][build-link]

[POLYVAL][1] ([RFC 8452][2]) is a [universal hash function][3] which operates
Expand All @@ -16,6 +17,14 @@ closely related to [GHASH][6] and therefore can also be used to implement

[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 @@ -39,6 +48,7 @@ dual licensed as above, without any additional terms or conditions.
[docs-link]: https://docs.rs/polyval/
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.32+-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
5 changes: 3 additions & 2 deletions polyval/benches/polyval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,15 @@ impl Mac for PolyvalMac {
}

fn result(self) -> MacResult<Self::OutputSize> {
self.poly.result()
let tag: Block = self.poly.result().into();
MacResult::new(tag.into())
}
}

impl PolyvalMac {
/// Input the current internal buffer into POLYVAL
fn block(&mut self) {
let elem = self.buffer;
self.poly.input(elem)
self.poly.input_block(elem)
}
}
2 changes: 1 addition & 1 deletion polyval/src/field/backend/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub(crate) use self::pclmulqdq::M128i;
pub(crate) use self::soft::U64x2 as M128i;

/// Trait representing the arithmetic operations we expect on the XMM registers
pub trait Xmm:
pub trait Backend:
BitXor<Output = Self> + Clmul + Copy + From<Block> + Into<Block> + From<u128>
{
/// Swap the hi and low 64-bit halves of the register
Expand Down
4 changes: 2 additions & 2 deletions polyval/src/field/backend/pclmulqdq.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use core::arch::x86::*;
#[cfg(target_arch = "x86_64")]
use core::arch::x86_64::*;

use super::Xmm;
use super::Backend;
use core::ops::BitXor;
use field::clmul::{self, Clmul};
use Block;
Expand Down Expand Up @@ -60,7 +60,7 @@ impl Clmul for M128i {
}
}

impl Xmm for M128i {
impl Backend for M128i {
fn shuffle(self) -> Self {
M128i(unsafe { shufpd1(self.0) })
}
Expand Down
4 changes: 2 additions & 2 deletions polyval/src/field/backend/soft.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// TODO(tarcieri): performance-oriented constant-time implementation
// See: <https://bearssl.org/gitweb/?p=BearSSL;a=blob;f=src/hash/ghash_ctmul64.c>

use super::Xmm;
use super::Backend;
use byteorder::{ByteOrder, LE};
use core::ops::BitXor;
use field::clmul::{self, Clmul};
Expand Down Expand Up @@ -86,7 +86,7 @@ impl Clmul for U64x2 {
}
}

impl Xmm for U64x2 {
impl Backend for U64x2 {
fn shuffle(self) -> Self {
U64x2([self.0[1], self.0[0]])
}
Expand Down
Loading

0 comments on commit 89f6277

Please sign in to comment.