2015-06-01 13:43:58 +02:00
/*
* Poly1305 authenticator algorithm , RFC7539
*
* Copyright ( C ) 2015 Martin Willi
*
* Based on public domain code by Andrew Moon and Daniel J . Bernstein .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*/
# include <crypto/algapi.h>
# include <crypto/internal/hash.h>
2019-11-08 13:22:19 +01:00
# include <crypto/internal/poly1305.h>
2015-06-01 13:43:58 +02:00
# include <linux/crypto.h>
# include <linux/kernel.h>
# include <linux/module.h>
2016-11-07 20:47:09 +01:00
# include <asm/unaligned.h>
2015-06-01 13:43:58 +02:00
2019-11-08 13:22:22 +01:00
static int crypto_poly1305_init ( struct shash_desc * desc )
2015-06-01 13:43:58 +02:00
{
struct poly1305_desc_ctx * dctx = shash_desc_ctx ( desc ) ;
2018-11-16 17:26:28 -08:00
poly1305_core_init ( & dctx - > h ) ;
2015-06-01 13:43:58 +02:00
dctx - > buflen = 0 ;
2019-11-08 13:22:20 +01:00
dctx - > rset = 0 ;
2015-06-16 11:34:16 +02:00
dctx - > sset = false ;
2015-06-01 13:43:58 +02:00
return 0 ;
}
2019-11-08 13:22:19 +01:00
static void poly1305_blocks ( struct poly1305_desc_ctx * dctx , const u8 * src ,
unsigned int srclen )
2018-11-16 17:26:28 -08:00
{
unsigned int datalen ;
if ( unlikely ( ! dctx - > sset ) ) {
datalen = crypto_poly1305_setdesckey ( dctx , src , srclen ) ;
src + = srclen - datalen ;
srclen = datalen ;
}
2019-11-08 13:22:20 +01:00
poly1305_core_blocks ( & dctx - > h , dctx - > r , src ,
2019-11-08 13:22:19 +01:00
srclen / POLY1305_BLOCK_SIZE , 1 ) ;
2015-06-01 13:43:58 +02:00
}
2019-11-08 13:22:22 +01:00
static int crypto_poly1305_update ( struct shash_desc * desc ,
const u8 * src , unsigned int srclen )
2015-06-01 13:43:58 +02:00
{
struct poly1305_desc_ctx * dctx = shash_desc_ctx ( desc ) ;
unsigned int bytes ;
if ( unlikely ( dctx - > buflen ) ) {
bytes = min ( srclen , POLY1305_BLOCK_SIZE - dctx - > buflen ) ;
memcpy ( dctx - > buf + dctx - > buflen , src , bytes ) ;
src + = bytes ;
srclen - = bytes ;
dctx - > buflen + = bytes ;
if ( dctx - > buflen = = POLY1305_BLOCK_SIZE ) {
2015-06-16 11:34:16 +02:00
poly1305_blocks ( dctx , dctx - > buf ,
2019-11-08 13:22:19 +01:00
POLY1305_BLOCK_SIZE ) ;
2015-06-01 13:43:58 +02:00
dctx - > buflen = 0 ;
}
}
if ( likely ( srclen > = POLY1305_BLOCK_SIZE ) ) {
2019-11-08 13:22:19 +01:00
poly1305_blocks ( dctx , src , srclen ) ;
2018-11-16 17:26:28 -08:00
src + = srclen - ( srclen % POLY1305_BLOCK_SIZE ) ;
srclen % = POLY1305_BLOCK_SIZE ;
2015-06-01 13:43:58 +02:00
}
if ( unlikely ( srclen ) ) {
dctx - > buflen = srclen ;
memcpy ( dctx - > buf , src , srclen ) ;
}
return 0 ;
}
2019-11-08 13:22:22 +01:00
static int crypto_poly1305_final ( struct shash_desc * desc , u8 * dst )
2018-11-16 17:26:28 -08:00
{
struct poly1305_desc_ctx * dctx = shash_desc_ctx ( desc ) ;
if ( unlikely ( ! dctx - > sset ) )
return - ENOKEY ;
2019-11-08 13:22:21 +01:00
poly1305_final_generic ( dctx , dst ) ;
2015-06-01 13:43:58 +02:00
return 0 ;
}
static struct shash_alg poly1305_alg = {
. digestsize = POLY1305_DIGEST_SIZE ,
2015-07-16 19:14:05 +02:00
. init = crypto_poly1305_init ,
. update = crypto_poly1305_update ,
. final = crypto_poly1305_final ,
2015-06-01 13:43:58 +02:00
. descsize = sizeof ( struct poly1305_desc_ctx ) ,
. base = {
. cra_name = " poly1305 " ,
. cra_driver_name = " poly1305-generic " ,
. cra_priority = 100 ,
. cra_blocksize = POLY1305_BLOCK_SIZE ,
. cra_module = THIS_MODULE ,
} ,
} ;
static int __init poly1305_mod_init ( void )
{
return crypto_register_shash ( & poly1305_alg ) ;
}
static void __exit poly1305_mod_exit ( void )
{
crypto_unregister_shash ( & poly1305_alg ) ;
}
2019-04-11 21:57:42 -07:00
subsys_initcall ( poly1305_mod_init ) ;
2015-06-01 13:43:58 +02:00
module_exit ( poly1305_mod_exit ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_AUTHOR ( " Martin Willi <martin@strongswan.org> " ) ;
MODULE_DESCRIPTION ( " Poly1305 authenticator " ) ;
MODULE_ALIAS_CRYPTO ( " poly1305 " ) ;
MODULE_ALIAS_CRYPTO ( " poly1305-generic " ) ;