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 <asm/unaligned.h>
11 #include <crypto/internal/poly1305.h>
13 typedef __uint128_t u128
;
15 void poly1305_core_setkey(struct poly1305_core_key
*key
, const u8 raw_key
[16])
19 /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
20 t0
= get_unaligned_le64(&raw_key
[0]);
21 t1
= get_unaligned_le64(&raw_key
[8]);
23 key
->key
.r64
[0] = t0
& 0xffc0fffffffULL
;
24 key
->key
.r64
[1] = ((t0
>> 44) | (t1
<< 20)) & 0xfffffc0ffffULL
;
25 key
->key
.r64
[2] = ((t1
>> 24)) & 0x00ffffffc0fULL
;
28 key
->precomputed_s
.r64
[0] = key
->key
.r64
[1] * 20;
29 key
->precomputed_s
.r64
[1] = key
->key
.r64
[2] * 20;
31 EXPORT_SYMBOL(poly1305_core_setkey
);
33 void poly1305_core_blocks(struct poly1305_state
*state
,
34 const struct poly1305_core_key
*key
, const void *src
,
35 unsigned int nblocks
, u32 hibit
)
37 const u8
*input
= src
;
48 hibit64
= ((u64
)hibit
) << 40;
58 s1
= key
->precomputed_s
.r64
[0];
59 s2
= key
->precomputed_s
.r64
[1];
65 t0
= get_unaligned_le64(&input
[0]);
66 t1
= get_unaligned_le64(&input
[8]);
68 h0
+= t0
& 0xfffffffffffULL
;
69 h1
+= ((t0
>> 44) | (t1
<< 20)) & 0xfffffffffffULL
;
70 h2
+= (((t1
>> 24)) & 0x3ffffffffffULL
) | hibit64
;
89 /* (partial) h %= p */
91 h0
= (u64
)d0
& 0xfffffffffffULL
;
94 h1
= (u64
)d1
& 0xfffffffffffULL
;
97 h2
= (u64
)d2
& 0x3ffffffffffULL
;
100 h0
= h0
& 0xfffffffffffULL
;
103 input
+= POLY1305_BLOCK_SIZE
;
110 EXPORT_SYMBOL(poly1305_core_blocks
);
112 void poly1305_core_emit(const struct poly1305_state
*state
, const u32 nonce
[4],
126 h1
&= 0xfffffffffffULL
;
129 h2
&= 0x3ffffffffffULL
;
132 h0
&= 0xfffffffffffULL
;
135 h1
&= 0xfffffffffffULL
;
138 h2
&= 0x3ffffffffffULL
;
141 h0
&= 0xfffffffffffULL
;
147 g0
&= 0xfffffffffffULL
;
150 g1
&= 0xfffffffffffULL
;
151 g2
= h2
+ c
- (1ULL << 42);
153 /* select h if h < p, or h + -p if h >= p */
154 c
= (g2
>> ((sizeof(u64
) * 8) - 1)) - 1;
164 /* h = (h + nonce) */
165 t0
= ((u64
)nonce
[1] << 32) | nonce
[0];
166 t1
= ((u64
)nonce
[3] << 32) | nonce
[2];
168 h0
+= t0
& 0xfffffffffffULL
;
170 h0
&= 0xfffffffffffULL
;
171 h1
+= (((t0
>> 44) | (t1
<< 20)) & 0xfffffffffffULL
) + c
;
173 h1
&= 0xfffffffffffULL
;
174 h2
+= (((t1
>> 24)) & 0x3ffffffffffULL
) + c
;
175 h2
&= 0x3ffffffffffULL
;
178 /* mac = h % (2^128) */
179 h0
= h0
| (h1
<< 44);
180 h1
= (h1
>> 20) | (h2
<< 24);
182 put_unaligned_le64(h0
, &mac
[0]);
183 put_unaligned_le64(h1
, &mac
[8]);
185 EXPORT_SYMBOL(poly1305_core_emit
);