Skip to content

Commit 2bbb4fd

Browse files
authored
Merge pull request #16 from RustCrypto/poly1305/fixups-for-salsa20-aead
poly1305: Fixups based on ChaCha20Poly1305 experience
2 parents 9be6338 + 98cf577 commit 2bbb4fd

File tree

3 files changed

+75
-22
lines changed

3 files changed

+75
-22
lines changed

Diff for: poly1305/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ readme = "README.md"
1212

1313
[dependencies]
1414
byteorder = { version = "1", default-features = false }
15+
crypto-mac = "0.7"
1516
zeroize = { version = "0.9", optional = true, default-features = false }
1617

1718
[dev-dependencies]

Diff for: poly1305/src/lib.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818

1919
// TODO: replace with `u32::{from_le_bytes, to_le_bytes}` in libcore (1.32+)
2020
extern crate byteorder;
21+
extern crate crypto_mac;
2122

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

2526
use byteorder::{ByteOrder, LE};
2627
use core::cmp::min;
28+
use crypto_mac::generic_array::{typenum::U16, GenericArray};
29+
use crypto_mac::MacResult;
2730
#[cfg(feature = "zeroize")]
2831
use zeroize::Zeroize;
2932

@@ -33,6 +36,9 @@ pub const KEY_SIZE: usize = 32;
3336
/// Size of the blocks Poly1305 acts upon
3437
pub const BLOCK_SIZE: usize = 16;
3538

39+
/// Poly1305 authentication tags
40+
pub type Tag = MacResult<U16>;
41+
3642
/// The Poly1305 universal hash function.
3743
///
3844
/// Note that Poly1305 is not a traditional MAC and is single-use only
@@ -109,14 +115,33 @@ impl Poly1305 {
109115
self.leftover = m.len();
110116
}
111117

118+
/// Input data into Poly1305, first padding it to Poly1305's block size
119+
/// ala the `pad16()` function described in RFC 8439 section 2.8.1:
120+
/// <https://tools.ietf.org/html/rfc8439#section-2.8.1>
121+
///
122+
/// This is primarily useful for implementing Salsa20 family authenticated
123+
/// encryption constructions.
124+
pub fn input_padded(&mut self, data: &[u8]) {
125+
self.input(data);
126+
127+
// Pad associated data with `\0` if it's unaligned with the block size
128+
let unaligned_len = data.len() % BLOCK_SIZE;
129+
130+
if unaligned_len != 0 {
131+
let pad = [0u8; BLOCK_SIZE];
132+
let pad_len = BLOCK_SIZE - unaligned_len;
133+
self.input(&pad[..pad_len]);
134+
}
135+
}
136+
112137
/// Process input messages in a chained manner
113138
pub fn chain(mut self, data: &[u8]) -> Self {
114139
self.input(data);
115140
self
116141
}
117142

118143
/// Get the hashed output
119-
pub fn result(mut self) -> [u8; BLOCK_SIZE] {
144+
pub fn result(mut self) -> Tag {
120145
if self.leftover > 0 {
121146
self.buffer[self.leftover] = 1;
122147

@@ -208,13 +233,13 @@ impl Poly1305 {
208233
f = u64::from(h3) + u64::from(self.pad[3]) + (f >> 32);
209234
h3 = f as u32;
210235

211-
let mut output = [0u8; BLOCK_SIZE];
212-
LE::write_u32(&mut output[0..4], h0);
213-
LE::write_u32(&mut output[4..8], h1);
214-
LE::write_u32(&mut output[8..12], h2);
215-
LE::write_u32(&mut output[12..16], h3);
236+
let mut tag = GenericArray::default();
237+
LE::write_u32(&mut tag[0..4], h0);
238+
LE::write_u32(&mut tag[4..8], h1);
239+
LE::write_u32(&mut tag[8..12], h2);
240+
LE::write_u32(&mut tag[12..16], h3);
216241

217-
output
242+
MacResult::new(tag)
218243
}
219244

220245
/// Compute a single block of Poly1305 using the internal buffer

Diff for: poly1305/tests/lib.rs

+42-15
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ fn test_nacl_vector() {
2828
0xd9,
2929
];
3030

31-
assert_eq!(&Poly1305::new(&key).chain(&msg).result(), &expected[..]);
31+
let result1 = Poly1305::new(&key).chain(&msg).result();
32+
assert_eq!(&expected[..], result1.code().as_slice());
3233

33-
let result = Poly1305::new(&key)
34+
let result2 = Poly1305::new(&key)
3435
.chain(&msg[0..32])
3536
.chain(&msg[32..96])
3637
.chain(&msg[96..112])
@@ -44,7 +45,7 @@ fn test_nacl_vector() {
4445
.chain(&msg[130..131])
4546
.result();
4647

47-
assert_eq!(&result, &expected[..]);
48+
assert_eq!(&expected[..], result2.code().as_slice());
4849
}
4950

5051
#[test]
@@ -65,10 +66,9 @@ fn donna_self_test() {
6566
0x00,
6667
];
6768

68-
assert_eq!(
69-
&Poly1305::new(&wrap_key).chain(&wrap_msg).result(),
70-
&wrap_mac[..]
71-
);
69+
let result = Poly1305::new(&wrap_key).chain(&wrap_msg).result();
70+
71+
assert_eq!(&wrap_mac[..], result.code().as_slice());
7272

7373
let total_key = [
7474
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xff,
@@ -88,29 +88,56 @@ fn donna_self_test() {
8888
key.copy_from_slice(&repeat(i as u8).take(KEY_SIZE).collect::<Vec<_>>());
8989

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

94-
assert_eq!(&tpoly.result(), &total_mac[..]);
95+
assert_eq!(&total_mac[..], tpoly.result().code().as_slice());
9596
}
9697

9798
#[test]
9899
fn test_tls_vectors() {
99100
// from http://tools.ietf.org/html/draft-agl-tls-chacha20poly1305-04
100101
let key = b"this is 32-byte key for Poly1305";
101-
let msg = [0u8; 32];
102-
let expected = [
102+
103+
let msg1 = [0u8; 32];
104+
let expected1 = [
103105
0x49, 0xec, 0x78, 0x09, 0x0e, 0x48, 0x1e, 0xc6, 0xc2, 0x6b, 0x33, 0xb9, 0x1c, 0xcc, 0x03,
104106
0x07,
105107
];
106108

107-
assert_eq!(&Poly1305::new(&key).chain(&msg).result(), &expected[..]);
109+
let result1 = Poly1305::new(&key).chain(&msg1).result();
110+
assert_eq!(&expected1[..], result1.code().as_slice());
108111

109-
let msg = b"Hello world!";
110-
let expected = [
112+
let msg2 = b"Hello world!";
113+
let expected2 = [
111114
0xa6, 0xf7, 0x45, 0x00, 0x8f, 0x81, 0xc9, 0x16, 0xa2, 0x0d, 0xcc, 0x74, 0xee, 0xf2, 0xb2,
112115
0xf0,
113116
];
114117

115-
assert_eq!(&Poly1305::new(&key).chain(&msg[..]).result(), &expected[..]);
118+
let result2 = Poly1305::new(&key).chain(&msg2[..]).result();
119+
assert_eq!(&expected2[..], result2.code().as_slice());
120+
}
121+
122+
#[test]
123+
fn padded_input() {
124+
// poly1305 key and AAD from <https://tools.ietf.org/html/rfc8439#section-2.8.2>
125+
let key = [
126+
0x7b, 0xac, 0x2b, 0x25, 0x2d, 0xb4, 0x47, 0xaf, 0x09, 0xb6, 0x7a, 0x55, 0xa4, 0xe9, 0x55,
127+
0x84, 0x0a, 0xe1, 0xd6, 0x73, 0x10, 0x75, 0xd9, 0xeb, 0x2a, 0x93, 0x75, 0x78, 0x3e, 0xd5,
128+
0x53, 0xff,
129+
];
130+
131+
let msg = [
132+
0x50, 0x51, 0x52, 0x53, 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
133+
];
134+
135+
let expected = [
136+
0xad, 0xa5, 0x6c, 0xaa, 0x48, 0xf, 0xe6, 0xf5, 0x6, 0x70, 0x39, 0x24, 0x4a, 0x3d, 0x76,
137+
0xba,
138+
];
139+
140+
let mut poly = Poly1305::new(&key);
141+
poly.input_padded(&msg);
142+
assert_eq!(&expected[..], poly.result().code().as_slice());
116143
}

0 commit comments

Comments
 (0)