1 /* 2 * Poly1305 authenticator algorithm, RFC7539 3 * 4 * Copyright (C) 2015 Martin Willi 5 * 6 * Based on public domain code by Andrew Moon and Daniel J. Bernstein. 7 * 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. 12 */ 13 14 #include <crypto/algapi.h> 15 #include <crypto/internal/hash.h> 16 #include <crypto/internal/poly1305.h> 17 #include <linux/crypto.h> 18 #include <linux/kernel.h> 19 #include <linux/module.h> 20 #include <asm/unaligned.h> 21 22 static int crypto_poly1305_init(struct shash_desc *desc) 23 { 24 struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); 25 26 poly1305_core_init(&dctx->h); 27 dctx->buflen = 0; 28 dctx->rset = 0; 29 dctx->sset = false; 30 31 return 0; 32 } 33 34 static void poly1305_blocks(struct poly1305_desc_ctx *dctx, const u8 *src, 35 unsigned int srclen) 36 { 37 unsigned int datalen; 38 39 if (unlikely(!dctx->sset)) { 40 datalen = crypto_poly1305_setdesckey(dctx, src, srclen); 41 src += srclen - datalen; 42 srclen = datalen; 43 } 44 45 poly1305_core_blocks(&dctx->h, dctx->r, src, 46 srclen / POLY1305_BLOCK_SIZE, 1); 47 } 48 49 static int crypto_poly1305_update(struct shash_desc *desc, 50 const u8 *src, unsigned int srclen) 51 { 52 struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); 53 unsigned int bytes; 54 55 if (unlikely(dctx->buflen)) { 56 bytes = min(srclen, POLY1305_BLOCK_SIZE - dctx->buflen); 57 memcpy(dctx->buf + dctx->buflen, src, bytes); 58 src += bytes; 59 srclen -= bytes; 60 dctx->buflen += bytes; 61 62 if (dctx->buflen == POLY1305_BLOCK_SIZE) { 63 poly1305_blocks(dctx, dctx->buf, 64 POLY1305_BLOCK_SIZE); 65 dctx->buflen = 0; 66 } 67 } 68 69 if (likely(srclen >= POLY1305_BLOCK_SIZE)) { 70 poly1305_blocks(dctx, src, srclen); 71 src += srclen - (srclen % POLY1305_BLOCK_SIZE); 72 srclen %= POLY1305_BLOCK_SIZE; 73 } 74 75 if (unlikely(srclen)) { 76 dctx->buflen = srclen; 77 memcpy(dctx->buf, src, srclen); 78 } 79 80 return 0; 81 } 82 83 static int crypto_poly1305_final(struct shash_desc *desc, u8 *dst) 84 { 85 struct poly1305_desc_ctx *dctx = shash_desc_ctx(desc); 86 87 if (unlikely(!dctx->sset)) 88 return -ENOKEY; 89 90 poly1305_final_generic(dctx, dst); 91 return 0; 92 } 93 94 static struct shash_alg poly1305_alg = { 95 .digestsize = POLY1305_DIGEST_SIZE, 96 .init = crypto_poly1305_init, 97 .update = crypto_poly1305_update, 98 .final = crypto_poly1305_final, 99 .descsize = sizeof(struct poly1305_desc_ctx), 100 .base = { 101 .cra_name = "poly1305", 102 .cra_driver_name = "poly1305-generic", 103 .cra_priority = 100, 104 .cra_blocksize = POLY1305_BLOCK_SIZE, 105 .cra_module = THIS_MODULE, 106 }, 107 }; 108 109 static int __init poly1305_mod_init(void) 110 { 111 return crypto_register_shash(&poly1305_alg); 112 } 113 114 static void __exit poly1305_mod_exit(void) 115 { 116 crypto_unregister_shash(&poly1305_alg); 117 } 118 119 subsys_initcall(poly1305_mod_init); 120 module_exit(poly1305_mod_exit); 121 122 MODULE_LICENSE("GPL"); 123 MODULE_AUTHOR("Martin Willi <martin@strongswan.org>"); 124 MODULE_DESCRIPTION("Poly1305 authenticator"); 125 MODULE_ALIAS_CRYPTO("poly1305"); 126 MODULE_ALIAS_CRYPTO("poly1305-generic"); 127