4 * SHA1 Secure Hash Algorithm.
6 * Derived from cryptoapi implementation, adapted for in-place
7 * scatterlist interface. Originally based on the public domain
8 * implementation written by Steve Reid.
10 * Copyright (c) Alan Smithee.
11 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
12 * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
14 * This program is free software; you can redistribute it and/or modify it
15 * under the terms of the GNU General Public License as published by the Free
16 * Software Foundation; either version 2 of the License, or (at your option)
20 #include <linux/init.h>
21 #include <linux/module.h>
23 #include <linux/crypto.h>
24 #include <asm/scatterlist.h>
25 #include <asm/byteorder.h>
27 #define SHA1_DIGEST_SIZE 20
28 #define SHA1_HMAC_BLOCK_SIZE 64
30 static inline u32
rol(u32 value
, u32 bits
)
32 return (((value
) << (bits
)) | ((value
) >> (32 - (bits
))));
35 /* blk0() and blk() perform the initial expand. */
36 /* I got the idea of expanding during the round function from SSLeay */
37 # define blk0(i) block32[i]
39 #define blk(i) (block32[i&15] = rol(block32[(i+13)&15]^block32[(i+8)&15] \
40 ^block32[(i+2)&15]^block32[i&15],1))
42 /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
43 #define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5); \
45 #define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5); \
47 #define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
48 #define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5); \
50 #define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
58 /* Hash a single 512-bit block. This is the core of the algorithm. */
59 static void sha1_transform(u32
*state
, const u8
*in
)
64 /* convert/copy data to workspace */
65 for (a
= 0; a
< sizeof(block32
)/sizeof(u32
); a
++)
66 block32
[a
] = be32_to_cpu (((const u32
*)in
)[a
]);
68 /* Copy context->state[] to working vars */
75 /* 4 rounds of 20 operations each. Loop unrolled. */
76 R0(a
,b
,c
,d
,e
, 0); R0(e
,a
,b
,c
,d
, 1); R0(d
,e
,a
,b
,c
, 2); R0(c
,d
,e
,a
,b
, 3);
77 R0(b
,c
,d
,e
,a
, 4); R0(a
,b
,c
,d
,e
, 5); R0(e
,a
,b
,c
,d
, 6); R0(d
,e
,a
,b
,c
, 7);
78 R0(c
,d
,e
,a
,b
, 8); R0(b
,c
,d
,e
,a
, 9); R0(a
,b
,c
,d
,e
,10); R0(e
,a
,b
,c
,d
,11);
79 R0(d
,e
,a
,b
,c
,12); R0(c
,d
,e
,a
,b
,13); R0(b
,c
,d
,e
,a
,14); R0(a
,b
,c
,d
,e
,15);
80 R1(e
,a
,b
,c
,d
,16); R1(d
,e
,a
,b
,c
,17); R1(c
,d
,e
,a
,b
,18); R1(b
,c
,d
,e
,a
,19);
81 R2(a
,b
,c
,d
,e
,20); R2(e
,a
,b
,c
,d
,21); R2(d
,e
,a
,b
,c
,22); R2(c
,d
,e
,a
,b
,23);
82 R2(b
,c
,d
,e
,a
,24); R2(a
,b
,c
,d
,e
,25); R2(e
,a
,b
,c
,d
,26); R2(d
,e
,a
,b
,c
,27);
83 R2(c
,d
,e
,a
,b
,28); R2(b
,c
,d
,e
,a
,29); R2(a
,b
,c
,d
,e
,30); R2(e
,a
,b
,c
,d
,31);
84 R2(d
,e
,a
,b
,c
,32); R2(c
,d
,e
,a
,b
,33); R2(b
,c
,d
,e
,a
,34); R2(a
,b
,c
,d
,e
,35);
85 R2(e
,a
,b
,c
,d
,36); R2(d
,e
,a
,b
,c
,37); R2(c
,d
,e
,a
,b
,38); R2(b
,c
,d
,e
,a
,39);
86 R3(a
,b
,c
,d
,e
,40); R3(e
,a
,b
,c
,d
,41); R3(d
,e
,a
,b
,c
,42); R3(c
,d
,e
,a
,b
,43);
87 R3(b
,c
,d
,e
,a
,44); R3(a
,b
,c
,d
,e
,45); R3(e
,a
,b
,c
,d
,46); R3(d
,e
,a
,b
,c
,47);
88 R3(c
,d
,e
,a
,b
,48); R3(b
,c
,d
,e
,a
,49); R3(a
,b
,c
,d
,e
,50); R3(e
,a
,b
,c
,d
,51);
89 R3(d
,e
,a
,b
,c
,52); R3(c
,d
,e
,a
,b
,53); R3(b
,c
,d
,e
,a
,54); R3(a
,b
,c
,d
,e
,55);
90 R3(e
,a
,b
,c
,d
,56); R3(d
,e
,a
,b
,c
,57); R3(c
,d
,e
,a
,b
,58); R3(b
,c
,d
,e
,a
,59);
91 R4(a
,b
,c
,d
,e
,60); R4(e
,a
,b
,c
,d
,61); R4(d
,e
,a
,b
,c
,62); R4(c
,d
,e
,a
,b
,63);
92 R4(b
,c
,d
,e
,a
,64); R4(a
,b
,c
,d
,e
,65); R4(e
,a
,b
,c
,d
,66); R4(d
,e
,a
,b
,c
,67);
93 R4(c
,d
,e
,a
,b
,68); R4(b
,c
,d
,e
,a
,69); R4(a
,b
,c
,d
,e
,70); R4(e
,a
,b
,c
,d
,71);
94 R4(d
,e
,a
,b
,c
,72); R4(c
,d
,e
,a
,b
,73); R4(b
,c
,d
,e
,a
,74); R4(a
,b
,c
,d
,e
,75);
95 R4(e
,a
,b
,c
,d
,76); R4(d
,e
,a
,b
,c
,77); R4(c
,d
,e
,a
,b
,78); R4(b
,c
,d
,e
,a
,79);
96 /* Add the working vars back into context.state[] */
103 a
= b
= c
= d
= e
= 0;
104 memset (block32
, 0x00, sizeof block32
);
107 static void sha1_init(void *ctx
)
109 struct sha1_ctx
*sctx
= ctx
;
110 static const struct sha1_ctx initstate
= {
112 { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
119 static void sha1_update(void *ctx
, const u8
*data
, unsigned int len
)
121 struct sha1_ctx
*sctx
= ctx
;
124 j
= (sctx
->count
>> 3) & 0x3f;
125 sctx
->count
+= len
<< 3;
127 if ((j
+ len
) > 63) {
128 memcpy(&sctx
->buffer
[j
], data
, (i
= 64-j
));
129 sha1_transform(sctx
->state
, sctx
->buffer
);
130 for ( ; i
+ 63 < len
; i
+= 64) {
131 sha1_transform(sctx
->state
, &data
[i
]);
136 memcpy(&sctx
->buffer
[j
], &data
[i
], len
- i
);
140 /* Add padding and return the message digest. */
141 static void sha1_final(void* ctx
, u8
*out
)
143 struct sha1_ctx
*sctx
= ctx
;
144 u32 i
, j
, index
, padlen
;
147 static const u8 padding
[64] = { 0x80, };
150 bits
[7] = 0xff & t
; t
>>=8;
151 bits
[6] = 0xff & t
; t
>>=8;
152 bits
[5] = 0xff & t
; t
>>=8;
153 bits
[4] = 0xff & t
; t
>>=8;
154 bits
[3] = 0xff & t
; t
>>=8;
155 bits
[2] = 0xff & t
; t
>>=8;
156 bits
[1] = 0xff & t
; t
>>=8;
159 /* Pad out to 56 mod 64 */
160 index
= (sctx
->count
>> 3) & 0x3f;
161 padlen
= (index
< 56) ? (56 - index
) : ((64+56) - index
);
162 sha1_update(sctx
, padding
, padlen
);
165 sha1_update(sctx
, bits
, sizeof bits
);
167 /* Store state in digest */
168 for (i
= j
= 0; i
< 5; i
++, j
+= 4) {
169 u32 t2
= sctx
->state
[i
];
170 out
[j
+3] = t2
& 0xff; t2
>>=8;
171 out
[j
+2] = t2
& 0xff; t2
>>=8;
172 out
[j
+1] = t2
& 0xff; t2
>>=8;
177 memset(sctx
, 0, sizeof *sctx
);
180 static struct crypto_alg alg
= {
182 .cra_flags
= CRYPTO_ALG_TYPE_DIGEST
,
183 .cra_blocksize
= SHA1_HMAC_BLOCK_SIZE
,
184 .cra_ctxsize
= sizeof(struct sha1_ctx
),
185 .cra_module
= THIS_MODULE
,
186 .cra_list
= LIST_HEAD_INIT(alg
.cra_list
),
187 .cra_u
= { .digest
= {
188 .dia_digestsize
= SHA1_DIGEST_SIZE
,
189 .dia_init
= sha1_init
,
190 .dia_update
= sha1_update
,
191 .dia_final
= sha1_final
} }
194 static int __init
init(void)
196 return crypto_register_alg(&alg
);
199 static void __exit
fini(void)
201 crypto_unregister_alg(&alg
);
207 MODULE_LICENSE("GPL");
208 MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");