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