1*ad5d2789SSebastian Siewior /* 2*ad5d2789SSebastian Siewior * Cryptographic API. 3*ad5d2789SSebastian Siewior * 4*ad5d2789SSebastian Siewior * SHA1 Secure Hash Algorithm. 5*ad5d2789SSebastian Siewior * 6*ad5d2789SSebastian Siewior * Derived from cryptoapi implementation, adapted for in-place 7*ad5d2789SSebastian Siewior * scatterlist interface. 8*ad5d2789SSebastian Siewior * 9*ad5d2789SSebastian Siewior * Copyright (c) Alan Smithee. 10*ad5d2789SSebastian Siewior * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> 11*ad5d2789SSebastian Siewior * Copyright (c) Jean-Francois Dive <jef@linuxbe.org> 12*ad5d2789SSebastian Siewior * 13*ad5d2789SSebastian Siewior * This program is free software; you can redistribute it and/or modify it 14*ad5d2789SSebastian Siewior * under the terms of the GNU General Public License as published by the Free 15*ad5d2789SSebastian Siewior * Software Foundation; either version 2 of the License, or (at your option) 16*ad5d2789SSebastian Siewior * any later version. 17*ad5d2789SSebastian Siewior * 18*ad5d2789SSebastian Siewior */ 19*ad5d2789SSebastian Siewior #include <linux/init.h> 20*ad5d2789SSebastian Siewior #include <linux/module.h> 21*ad5d2789SSebastian Siewior #include <linux/mm.h> 22*ad5d2789SSebastian Siewior #include <linux/crypto.h> 23*ad5d2789SSebastian Siewior #include <linux/cryptohash.h> 24*ad5d2789SSebastian Siewior #include <linux/types.h> 25*ad5d2789SSebastian Siewior #include <asm/scatterlist.h> 26*ad5d2789SSebastian Siewior #include <asm/byteorder.h> 27*ad5d2789SSebastian Siewior 28*ad5d2789SSebastian Siewior #define SHA1_DIGEST_SIZE 20 29*ad5d2789SSebastian Siewior #define SHA1_HMAC_BLOCK_SIZE 64 30*ad5d2789SSebastian Siewior 31*ad5d2789SSebastian Siewior struct sha1_ctx { 32*ad5d2789SSebastian Siewior u64 count; 33*ad5d2789SSebastian Siewior u32 state[5]; 34*ad5d2789SSebastian Siewior u8 buffer[64]; 35*ad5d2789SSebastian Siewior }; 36*ad5d2789SSebastian Siewior 37*ad5d2789SSebastian Siewior static void sha1_init(struct crypto_tfm *tfm) 38*ad5d2789SSebastian Siewior { 39*ad5d2789SSebastian Siewior struct sha1_ctx *sctx = crypto_tfm_ctx(tfm); 40*ad5d2789SSebastian Siewior static const struct sha1_ctx initstate = { 41*ad5d2789SSebastian Siewior 0, 42*ad5d2789SSebastian Siewior { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }, 43*ad5d2789SSebastian Siewior { 0, } 44*ad5d2789SSebastian Siewior }; 45*ad5d2789SSebastian Siewior 46*ad5d2789SSebastian Siewior *sctx = initstate; 47*ad5d2789SSebastian Siewior } 48*ad5d2789SSebastian Siewior 49*ad5d2789SSebastian Siewior static void sha1_update(struct crypto_tfm *tfm, const u8 *data, 50*ad5d2789SSebastian Siewior unsigned int len) 51*ad5d2789SSebastian Siewior { 52*ad5d2789SSebastian Siewior struct sha1_ctx *sctx = crypto_tfm_ctx(tfm); 53*ad5d2789SSebastian Siewior unsigned int partial, done; 54*ad5d2789SSebastian Siewior const u8 *src; 55*ad5d2789SSebastian Siewior 56*ad5d2789SSebastian Siewior partial = sctx->count & 0x3f; 57*ad5d2789SSebastian Siewior sctx->count += len; 58*ad5d2789SSebastian Siewior done = 0; 59*ad5d2789SSebastian Siewior src = data; 60*ad5d2789SSebastian Siewior 61*ad5d2789SSebastian Siewior if ((partial + len) > 63) { 62*ad5d2789SSebastian Siewior u32 temp[SHA_WORKSPACE_WORDS]; 63*ad5d2789SSebastian Siewior 64*ad5d2789SSebastian Siewior if (partial) { 65*ad5d2789SSebastian Siewior done = -partial; 66*ad5d2789SSebastian Siewior memcpy(sctx->buffer + partial, data, done + 64); 67*ad5d2789SSebastian Siewior src = sctx->buffer; 68*ad5d2789SSebastian Siewior } 69*ad5d2789SSebastian Siewior 70*ad5d2789SSebastian Siewior do { 71*ad5d2789SSebastian Siewior sha_transform(sctx->state, src, temp); 72*ad5d2789SSebastian Siewior done += 64; 73*ad5d2789SSebastian Siewior src = data + done; 74*ad5d2789SSebastian Siewior } while (done + 63 < len); 75*ad5d2789SSebastian Siewior 76*ad5d2789SSebastian Siewior memset(temp, 0, sizeof(temp)); 77*ad5d2789SSebastian Siewior partial = 0; 78*ad5d2789SSebastian Siewior } 79*ad5d2789SSebastian Siewior memcpy(sctx->buffer + partial, src, len - done); 80*ad5d2789SSebastian Siewior } 81*ad5d2789SSebastian Siewior 82*ad5d2789SSebastian Siewior 83*ad5d2789SSebastian Siewior /* Add padding and return the message digest. */ 84*ad5d2789SSebastian Siewior static void sha1_final(struct crypto_tfm *tfm, u8 *out) 85*ad5d2789SSebastian Siewior { 86*ad5d2789SSebastian Siewior struct sha1_ctx *sctx = crypto_tfm_ctx(tfm); 87*ad5d2789SSebastian Siewior __be32 *dst = (__be32 *)out; 88*ad5d2789SSebastian Siewior u32 i, index, padlen; 89*ad5d2789SSebastian Siewior __be64 bits; 90*ad5d2789SSebastian Siewior static const u8 padding[64] = { 0x80, }; 91*ad5d2789SSebastian Siewior 92*ad5d2789SSebastian Siewior bits = cpu_to_be64(sctx->count << 3); 93*ad5d2789SSebastian Siewior 94*ad5d2789SSebastian Siewior /* Pad out to 56 mod 64 */ 95*ad5d2789SSebastian Siewior index = sctx->count & 0x3f; 96*ad5d2789SSebastian Siewior padlen = (index < 56) ? (56 - index) : ((64+56) - index); 97*ad5d2789SSebastian Siewior sha1_update(tfm, padding, padlen); 98*ad5d2789SSebastian Siewior 99*ad5d2789SSebastian Siewior /* Append length */ 100*ad5d2789SSebastian Siewior sha1_update(tfm, (const u8 *)&bits, sizeof(bits)); 101*ad5d2789SSebastian Siewior 102*ad5d2789SSebastian Siewior /* Store state in digest */ 103*ad5d2789SSebastian Siewior for (i = 0; i < 5; i++) 104*ad5d2789SSebastian Siewior dst[i] = cpu_to_be32(sctx->state[i]); 105*ad5d2789SSebastian Siewior 106*ad5d2789SSebastian Siewior /* Wipe context */ 107*ad5d2789SSebastian Siewior memset(sctx, 0, sizeof *sctx); 108*ad5d2789SSebastian Siewior } 109*ad5d2789SSebastian Siewior 110*ad5d2789SSebastian Siewior static struct crypto_alg alg = { 111*ad5d2789SSebastian Siewior .cra_name = "sha1", 112*ad5d2789SSebastian Siewior .cra_driver_name= "sha1-generic", 113*ad5d2789SSebastian Siewior .cra_flags = CRYPTO_ALG_TYPE_DIGEST, 114*ad5d2789SSebastian Siewior .cra_blocksize = SHA1_HMAC_BLOCK_SIZE, 115*ad5d2789SSebastian Siewior .cra_ctxsize = sizeof(struct sha1_ctx), 116*ad5d2789SSebastian Siewior .cra_module = THIS_MODULE, 117*ad5d2789SSebastian Siewior .cra_alignmask = 3, 118*ad5d2789SSebastian Siewior .cra_list = LIST_HEAD_INIT(alg.cra_list), 119*ad5d2789SSebastian Siewior .cra_u = { .digest = { 120*ad5d2789SSebastian Siewior .dia_digestsize = SHA1_DIGEST_SIZE, 121*ad5d2789SSebastian Siewior .dia_init = sha1_init, 122*ad5d2789SSebastian Siewior .dia_update = sha1_update, 123*ad5d2789SSebastian Siewior .dia_final = sha1_final } } 124*ad5d2789SSebastian Siewior }; 125*ad5d2789SSebastian Siewior 126*ad5d2789SSebastian Siewior static int __init init(void) 127*ad5d2789SSebastian Siewior { 128*ad5d2789SSebastian Siewior return crypto_register_alg(&alg); 129*ad5d2789SSebastian Siewior } 130*ad5d2789SSebastian Siewior 131*ad5d2789SSebastian Siewior static void __exit fini(void) 132*ad5d2789SSebastian Siewior { 133*ad5d2789SSebastian Siewior crypto_unregister_alg(&alg); 134*ad5d2789SSebastian Siewior } 135*ad5d2789SSebastian Siewior 136*ad5d2789SSebastian Siewior module_init(init); 137*ad5d2789SSebastian Siewior module_exit(fini); 138*ad5d2789SSebastian Siewior 139*ad5d2789SSebastian Siewior MODULE_LICENSE("GPL"); 140*ad5d2789SSebastian Siewior MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm"); 141*ad5d2789SSebastian Siewior 142*ad5d2789SSebastian Siewior MODULE_ALIAS("sha1"); 143