xref: /openbmc/linux/crypto/sha1_generic.c (revision ad5d27899fdbe7a66e57fdf1af883dbd7ff88dac)
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