2005-04-17 02:20:36 +04:00
/*
* Cryptographic API .
*
* SHA1 Secure Hash Algorithm .
*
* Derived from cryptoapi implementation , adapted for in - place
* scatterlist interface .
*
* Copyright ( c ) Alan Smithee .
* Copyright ( c ) Andrew McDonald < andrew @ mcdonald . org . uk >
* Copyright ( c ) Jean - Francois Dive < jef @ linuxbe . org >
*
* 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 <linux/init.h>
# include <linux/module.h>
# include <linux/mm.h>
# include <linux/crypto.h>
# include <linux/cryptohash.h>
2005-10-30 13:25:15 +03:00
# include <linux/types.h>
2005-04-17 02:20:36 +04:00
# include <asm/scatterlist.h>
# include <asm/byteorder.h>
# define SHA1_DIGEST_SIZE 20
# define SHA1_HMAC_BLOCK_SIZE 64
struct sha1_ctx {
u64 count ;
u32 state [ 5 ] ;
u8 buffer [ 64 ] ;
} ;
2006-05-16 16:09:29 +04:00
static void sha1_init ( struct crypto_tfm * tfm )
2005-04-17 02:20:36 +04:00
{
2006-05-16 16:09:29 +04:00
struct sha1_ctx * sctx = crypto_tfm_ctx ( tfm ) ;
2005-04-17 02:20:36 +04:00
static const struct sha1_ctx initstate = {
0 ,
{ 0x67452301 , 0xEFCDAB89 , 0x98BADCFE , 0x10325476 , 0xC3D2E1F0 } ,
{ 0 , }
} ;
* sctx = initstate ;
}
2006-05-16 16:09:29 +04:00
static void sha1_update ( struct crypto_tfm * tfm , const u8 * data ,
unsigned int len )
2005-04-17 02:20:36 +04:00
{
2006-05-16 16:09:29 +04:00
struct sha1_ctx * sctx = crypto_tfm_ctx ( tfm ) ;
2005-11-13 02:59:54 +03:00
unsigned int partial , done ;
2005-11-13 02:47:20 +03:00
const u8 * src ;
2005-04-17 02:20:36 +04:00
2005-11-13 03:17:33 +03:00
partial = sctx - > count & 0x3f ;
sctx - > count + = len ;
2005-11-13 02:59:54 +03:00
done = 0 ;
2005-11-13 02:47:20 +03:00
src = data ;
2005-04-17 02:20:36 +04:00
2005-11-13 02:59:54 +03:00
if ( ( partial + len ) > 63 ) {
2005-11-13 02:47:20 +03:00
u32 temp [ SHA_WORKSPACE_WORDS ] ;
2005-11-13 02:59:54 +03:00
if ( partial ) {
2005-12-21 14:01:58 +03:00
done = - partial ;
memcpy ( sctx - > buffer + partial , data , done + 64 ) ;
2005-11-13 02:47:20 +03:00
src = sctx - > buffer ;
2005-04-17 02:20:36 +04:00
}
2005-11-13 02:47:20 +03:00
do {
sha_transform ( sctx - > state , src , temp ) ;
2005-11-13 02:59:54 +03:00
done + = 64 ;
src = data + done ;
} while ( done + 63 < len ) ;
2005-11-13 02:47:20 +03:00
memset ( temp , 0 , sizeof ( temp ) ) ;
2005-11-13 02:59:54 +03:00
partial = 0 ;
2005-04-17 02:20:36 +04:00
}
2005-11-13 02:59:54 +03:00
memcpy ( sctx - > buffer + partial , src , len - done ) ;
2005-04-17 02:20:36 +04:00
}
/* Add padding and return the message digest. */
2006-05-16 16:09:29 +04:00
static void sha1_final ( struct crypto_tfm * tfm , u8 * out )
2005-04-17 02:20:36 +04:00
{
2006-05-16 16:09:29 +04:00
struct sha1_ctx * sctx = crypto_tfm_ctx ( tfm ) ;
2005-10-30 13:25:15 +03:00
__be32 * dst = ( __be32 * ) out ;
u32 i , index , padlen ;
__be64 bits ;
2005-04-17 02:20:36 +04:00
static const u8 padding [ 64 ] = { 0x80 , } ;
2005-11-13 03:17:33 +03:00
bits = cpu_to_be64 ( sctx - > count < < 3 ) ;
2005-04-17 02:20:36 +04:00
/* Pad out to 56 mod 64 */
2005-11-13 03:17:33 +03:00
index = sctx - > count & 0x3f ;
2005-04-17 02:20:36 +04:00
padlen = ( index < 56 ) ? ( 56 - index ) : ( ( 64 + 56 ) - index ) ;
2006-05-16 16:09:29 +04:00
sha1_update ( tfm , padding , padlen ) ;
2005-04-17 02:20:36 +04:00
/* Append length */
2006-05-16 16:09:29 +04:00
sha1_update ( tfm , ( const u8 * ) & bits , sizeof ( bits ) ) ;
2005-04-17 02:20:36 +04:00
/* Store state in digest */
2005-10-30 13:25:15 +03:00
for ( i = 0 ; i < 5 ; i + + )
dst [ i ] = cpu_to_be32 ( sctx - > state [ i ] ) ;
2005-04-17 02:20:36 +04:00
/* Wipe context */
memset ( sctx , 0 , sizeof * sctx ) ;
}
static struct crypto_alg alg = {
. cra_name = " sha1 " ,
2006-07-09 02:59:38 +04:00
. cra_driver_name = " sha1-generic " ,
2005-04-17 02:20:36 +04:00
. cra_flags = CRYPTO_ALG_TYPE_DIGEST ,
. cra_blocksize = SHA1_HMAC_BLOCK_SIZE ,
. cra_ctxsize = sizeof ( struct sha1_ctx ) ,
. cra_module = THIS_MODULE ,
2006-04-10 02:42:35 +04:00
. cra_alignmask = 3 ,
2005-04-17 02:20:36 +04:00
. cra_list = LIST_HEAD_INIT ( alg . cra_list ) ,
. cra_u = { . digest = {
. dia_digestsize = SHA1_DIGEST_SIZE ,
. dia_init = sha1_init ,
. dia_update = sha1_update ,
. dia_final = sha1_final } }
} ;
static int __init init ( void )
{
return crypto_register_alg ( & alg ) ;
}
static void __exit fini ( void )
{
crypto_unregister_alg ( & alg ) ;
}
module_init ( init ) ;
module_exit ( fini ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " SHA1 Secure Hash Algorithm " ) ;
2006-07-09 02:59:38 +04:00
MODULE_ALIAS ( " sha1-generic " ) ;