Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/lib/crypto/poly1305.c
29267 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Poly1305 authenticator algorithm, RFC7539
4
*
5
* Copyright (C) 2015 Martin Willi
6
*
7
* Based on public domain code by Andrew Moon and Daniel J. Bernstein.
8
*/
9
10
#include <crypto/internal/poly1305.h>
11
#include <linux/export.h>
12
#include <linux/kernel.h>
13
#include <linux/module.h>
14
#include <linux/string.h>
15
#include <linux/unaligned.h>
16
17
#ifdef CONFIG_CRYPTO_LIB_POLY1305_ARCH
18
#include "poly1305.h" /* $(SRCARCH)/poly1305.h */
19
#else
20
#define poly1305_block_init poly1305_block_init_generic
21
#define poly1305_blocks poly1305_blocks_generic
22
#define poly1305_emit poly1305_emit_generic
23
#endif
24
25
void poly1305_init(struct poly1305_desc_ctx *desc,
26
const u8 key[POLY1305_KEY_SIZE])
27
{
28
desc->s[0] = get_unaligned_le32(key + 16);
29
desc->s[1] = get_unaligned_le32(key + 20);
30
desc->s[2] = get_unaligned_le32(key + 24);
31
desc->s[3] = get_unaligned_le32(key + 28);
32
desc->buflen = 0;
33
poly1305_block_init(&desc->state, key);
34
}
35
EXPORT_SYMBOL(poly1305_init);
36
37
void poly1305_update(struct poly1305_desc_ctx *desc,
38
const u8 *src, unsigned int nbytes)
39
{
40
if (desc->buflen + nbytes >= POLY1305_BLOCK_SIZE) {
41
unsigned int bulk_len;
42
43
if (desc->buflen) {
44
unsigned int l = POLY1305_BLOCK_SIZE - desc->buflen;
45
46
memcpy(&desc->buf[desc->buflen], src, l);
47
src += l;
48
nbytes -= l;
49
50
poly1305_blocks(&desc->state, desc->buf,
51
POLY1305_BLOCK_SIZE, 1);
52
desc->buflen = 0;
53
}
54
55
bulk_len = round_down(nbytes, POLY1305_BLOCK_SIZE);
56
nbytes %= POLY1305_BLOCK_SIZE;
57
58
if (bulk_len) {
59
poly1305_blocks(&desc->state, src, bulk_len, 1);
60
src += bulk_len;
61
}
62
}
63
if (nbytes) {
64
memcpy(&desc->buf[desc->buflen], src, nbytes);
65
desc->buflen += nbytes;
66
}
67
}
68
EXPORT_SYMBOL(poly1305_update);
69
70
void poly1305_final(struct poly1305_desc_ctx *desc, u8 *dst)
71
{
72
if (unlikely(desc->buflen)) {
73
desc->buf[desc->buflen++] = 1;
74
memset(desc->buf + desc->buflen, 0,
75
POLY1305_BLOCK_SIZE - desc->buflen);
76
poly1305_blocks(&desc->state, desc->buf, POLY1305_BLOCK_SIZE,
77
0);
78
}
79
80
poly1305_emit(&desc->state.h, dst, desc->s);
81
*desc = (struct poly1305_desc_ctx){};
82
}
83
EXPORT_SYMBOL(poly1305_final);
84
85
#ifdef poly1305_mod_init_arch
86
static int __init poly1305_mod_init(void)
87
{
88
poly1305_mod_init_arch();
89
return 0;
90
}
91
subsys_initcall(poly1305_mod_init);
92
93
static void __exit poly1305_mod_exit(void)
94
{
95
}
96
module_exit(poly1305_mod_exit);
97
#endif
98
99
MODULE_LICENSE("GPL");
100
MODULE_DESCRIPTION("Poly1305 authenticator algorithm, RFC7539");
101
102