1 // SPDX-License-Identifier: GPL-2.0 OR MIT
3 * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
5 * This is based in part on Andrew Moon's poly1305-donna, which is in the
9 #include <linux/kernel.h>
10 #include <linux/unaligned.h>
11 #include <crypto/internal/poly1305.h>
13 void poly1305_core_setkey(struct poly1305_core_key
*key
,
14 const u8 raw_key
[POLY1305_BLOCK_SIZE
])
18 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
19 t0
= get_unaligned_le64(&raw_key
[0]);
20 t1
= get_unaligned_le64(&raw_key
[8]);
22 key
->key
.r64
[0] = t0
& 0xffc0fffffffULL
;
23 key
->key
.r64
[1] = ((t0
>> 44) | (t1
<< 20)) & 0xfffffc0ffffULL
;
24 key
->key
.r64
[2] = ((t1
>> 24)) & 0x00ffffffc0fULL
;
27 key
->precomputed_s
.r64
[0] = key
->key
.r64
[1] * 20;
28 key
->precomputed_s
.r64
[1] = key
->key
.r64
[2] * 20;
30 EXPORT_SYMBOL(poly1305_core_setkey
);
32 void poly1305_core_blocks(struct poly1305_state
*state
,
33 const struct poly1305_core_key
*key
, const void *src
,
34 unsigned int nblocks
, u32 hibit
)
36 const u8
*input
= src
;
47 hibit64
= ((u64
)hibit
) << 40;
57 s1
= key
->precomputed_s
.r64
[0];
58 s2
= key
->precomputed_s
.r64
[1];
64 t0
= get_unaligned_le64(&input
[0]);
65 t1
= get_unaligned_le64(&input
[8]);
67 h0
+= t0
& 0xfffffffffffULL
;
68 h1
+= ((t0
>> 44) | (t1
<< 20)) & 0xfffffffffffULL
;
69 h2
+= (((t1
>> 24)) & 0x3ffffffffffULL
) | hibit64
;
88 /* (partial) h %= p */
90 h0
= (u64
)d0
& 0xfffffffffffULL
;
93 h1
= (u64
)d1
& 0xfffffffffffULL
;
96 h2
= (u64
)d2
& 0x3ffffffffffULL
;
99 h0
= h0
& 0xfffffffffffULL
;
102 input
+= POLY1305_BLOCK_SIZE
;
109 EXPORT_SYMBOL(poly1305_core_blocks
);
111 void poly1305_core_emit(const struct poly1305_state
*state
, const u32 nonce
[4],
125 h1
&= 0xfffffffffffULL
;
128 h2
&= 0x3ffffffffffULL
;
131 h0
&= 0xfffffffffffULL
;
134 h1
&= 0xfffffffffffULL
;
137 h2
&= 0x3ffffffffffULL
;
140 h0
&= 0xfffffffffffULL
;
146 g0
&= 0xfffffffffffULL
;
149 g1
&= 0xfffffffffffULL
;
150 g2
= h2
+ c
- (1ULL << 42);
152 /* select h if h < p, or h + -p if h >= p */
153 c
= (g2
>> ((sizeof(u64
) * 8) - 1)) - 1;
163 /* h = (h + nonce) */
164 t0
= ((u64
)nonce
[1] << 32) | nonce
[0];
165 t1
= ((u64
)nonce
[3] << 32) | nonce
[2];
167 h0
+= t0
& 0xfffffffffffULL
;
169 h0
&= 0xfffffffffffULL
;
170 h1
+= (((t0
>> 44) | (t1
<< 20)) & 0xfffffffffffULL
) + c
;
172 h1
&= 0xfffffffffffULL
;
173 h2
+= (((t1
>> 24)) & 0x3ffffffffffULL
) + c
;
174 h2
&= 0x3ffffffffffULL
;
177 /* mac = h % (2^128) */
178 h0
= h0
| (h1
<< 44);
179 h1
= (h1
>> 20) | (h2
<< 24);
181 put_unaligned_le64(h0
, &mac
[0]);
182 put_unaligned_le64(h1
, &mac
[8]);
184 EXPORT_SYMBOL(poly1305_core_emit
);