2 * Poly1305 authenticator algorithm, RFC7539
4 * Copyright (C) 2015 Martin Willi
6 * Based on public domain code by Andrew Moon and Daniel J. Bernstein.
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
14 #include <linux/byteorder.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <asm/unaligned.h>
19 #include <linux/crypto.h>
20 #include <crypto/algapi.h>
21 #include <crypto/hash.h>
22 #include <crypto/poly1305.h>
24 static struct shash_alg poly1305_alg;
26 struct poly1305_desc_ctx {
28 crypto_onetimeauth_poly1305_state s;
31 static int poly1305_init(struct shash_desc *desc)
33 struct poly1305_desc_ctx *state = (void *) desc->ctx;
35 state->key_done = false;
39 static int poly1305_update(struct shash_desc *desc,
40 const u8 *src, unsigned len)
42 struct poly1305_desc_ctx *state = (void *) desc->ctx;
44 if (!state->key_done) {
45 BUG_ON(len != crypto_onetimeauth_poly1305_KEYBYTES);
47 state->key_done = true;
48 return crypto_onetimeauth_poly1305_init(&state->s, src);
51 return crypto_onetimeauth_poly1305_update(&state->s, src, len);
54 static int poly1305_final(struct shash_desc *desc, u8 *out)
56 struct poly1305_desc_ctx *state = (void *) desc->ctx;
58 return crypto_onetimeauth_poly1305_final(&state->s, out);
61 static void *poly1305_alloc_tfm(void)
63 struct crypto_shash *tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
68 tfm->base.alg = &poly1305_alg.base;
69 tfm->descsize = sizeof(struct poly1305_desc_ctx);
73 static struct shash_alg poly1305_alg = {
74 .digestsize = crypto_onetimeauth_poly1305_BYTES,
75 .init = poly1305_init,
76 .update = poly1305_update,
77 .final = poly1305_final,
78 .descsize = sizeof(struct poly1305_desc_ctx),
80 .base.cra_name = "poly1305",
81 .base.alloc_tfm = poly1305_alloc_tfm,
84 __attribute__((constructor(110)))
85 static int poly1305_mod_init(void)
87 return crypto_register_shash(&poly1305_alg);