hacspec_poly1305/
poly1305.rs1use std::convert::TryInto;
2
3use hacspec_lib::hacspec_helper::*;
7
8pub type PolyKey = [u8; 32];
10
11const BLOCKSIZE: usize = 16;
12
13pub type PolyBlock = [u8; 16];
15
16pub type Poly1305Tag = [u8; 16];
18
19pub type SubBlock = Vec<u8>;
21
22pub type BlockIndex = usize;
24
25#[nat_mod("03fffffffffffffffffffffffffffffffb", 17)]
29pub struct FieldElement {}
30
31pub type PolyState = (FieldElement, FieldElement, PolyKey); pub fn poly1305_encode_r(b: &PolyBlock) -> FieldElement {
35 let mut n = u128::from_le_bytes(*b);
36 n &= 0x0fff_fffc_0fff_fffc_0fff_fffc_0fff_ffffu128;
37 FieldElement::from_u128(n)
38}
39
40pub fn poly1305_encode_block(b: &PolyBlock) -> FieldElement {
41 let n = u128::from_le_bytes(*b);
42 let f = FieldElement::from_u128(n);
43 f + FieldElement::pow2(128)
44}
45
46pub fn poly1305_encode_last(pad_len: BlockIndex, b: &SubBlock) -> FieldElement {
49 let mut bytes = [0u8; 16];
50 bytes[0..b.len()].copy_from_slice(b);
51 let n = u128::from_le_bytes(bytes);
52 let f = FieldElement::from_u128(n);
53 f + FieldElement::pow2(8 * pad_len)
54}
55
56pub fn poly1305_init(k: PolyKey) -> PolyState {
57 let r = poly1305_encode_r(&k[0..16].try_into().unwrap());
58 (FieldElement::zero(), r, k)
59}
60
61pub fn poly1305_update_block(b: &PolyBlock, st: PolyState) -> PolyState {
62 let (acc, r, k) = st;
63 ((poly1305_encode_block(b) + acc) * r, r, k)
64}
65
66pub fn poly1305_update_blocks(m: &[u8], st: PolyState) -> PolyState {
67 let mut st = st;
68 for block in m.chunks_exact(BLOCKSIZE) {
69 st = poly1305_update_block(block.try_into().unwrap(), st);
70 }
71 st
72}
73
74pub fn poly1305_update_last(pad_len: usize, b: &SubBlock, st: PolyState) -> PolyState {
75 let mut st = st;
76 if !b.is_empty() {
77 let (acc, r, k) = st;
78 st = ((poly1305_encode_last(pad_len, b) + acc) * r, r, k);
79 }
80 st
81}
82
83pub fn poly1305_update(m: &[u8], st: PolyState) -> PolyState {
84 let st = poly1305_update_blocks(m, st);
85 let mchunks = m.chunks_exact(BLOCKSIZE);
86 let last = mchunks.remainder();
87 poly1305_update_last(last.len(), &last.to_vec(), st)
88}
89
90pub fn poly1305_finish(st: PolyState) -> Poly1305Tag {
91 let (acc, _, k) = st;
92 let n = u128::from_le_bytes(k[16..32].try_into().unwrap());
93 let aby = acc.to_le_bytes();
94 let a = u128::from_le_bytes(aby[0..16].try_into().unwrap());
96 a.wrapping_add(n).to_le_bytes()
97}
98
99pub fn poly1305(m: &[u8], key: PolyKey) -> Poly1305Tag {
100 let mut st = poly1305_init(key);
101 st = poly1305_update(m, st);
102 poly1305_finish(st)
103}