2 * Copyright (C) 2013 Gregor Pintar <grpintar@gmail.com>
4 * Permission is granted to deal in this work without any restriction,
5 * including unlimited rights to use, publicly perform, publish,
6 * reproduce, relicence, modify, merge, and/or distribute in any form,
7 * for any purpose, with or without fee, and by any means.
9 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind,
10 * to the utmost extent permitted by applicable law. In no event
11 * shall a licensor, author or contributor be held liable for any
12 * issues arising in any way out of dealing in the work.
21 #include <kripto/cast.h>
22 #include <kripto/loadstore.h>
23 #include <kripto/rotate.h>
24 #include <kripto/memwipe.h>
25 #include <kripto/hash.h>
26 #include <kripto/desc/hash.h>
27 #include <kripto/object/hash.h>
29 #include <kripto/hash/sha1.h>
33 struct kripto_hash_object obj
;
41 #define F0(X, Y, Z) (Z ^ (X & (Y ^ Z)))
42 #define F1(X, Y, Z) (X ^ Y ^ Z)
43 #define F2(X, Y, Z) ((X & Y) | (Z & (X | Y)))
45 #define G0(A, B, C, D, E, W) \
47 E += ROL32(A, 5) + F0(B, C, D) + W + 0x5A827999; \
51 #define G1(A, B, C, D, E, W) \
53 E += ROL32(A, 5) + F1(B, C, D) + W + 0x6ED9EBA1; \
57 #define G2(A, B, C, D, E, W) \
59 E += ROL32(A, 5) + F2(B, C, D) + W + 0x8F1BBCDC; \
63 #define G3(A, B, C, D, E, W) \
65 E += ROL32(A, 5) + F1(B, C, D) + W + 0xCA62C1D6; \
69 static kripto_hash
*sha1_recreate
78 s
->len
= s
->o
= s
->i
= 0;
89 static void sha1_process(kripto_hash
*s
, const uint8_t *data
)
100 w
[1] = LOAD32B(data
+ 4);
101 w
[2] = LOAD32B(data
+ 8);
102 w
[3] = LOAD32B(data
+ 12);
103 w
[4] = LOAD32B(data
+ 16);
104 w
[5] = LOAD32B(data
+ 20);
105 w
[6] = LOAD32B(data
+ 24);
106 w
[7] = LOAD32B(data
+ 28);
107 w
[8] = LOAD32B(data
+ 32);
108 w
[9] = LOAD32B(data
+ 36);
109 w
[10] = LOAD32B(data
+ 40);
110 w
[11] = LOAD32B(data
+ 44);
111 w
[12] = LOAD32B(data
+ 48);
112 w
[13] = LOAD32B(data
+ 52);
113 w
[14] = LOAD32B(data
+ 56);
114 w
[15] = LOAD32B(data
+ 60);
116 for(i
= 16; i
< 80; i
++)
117 w
[i
] = ROL32(w
[i
- 3] ^ w
[i
- 8] ^ w
[i
- 14] ^ w
[i
- 16], 1);
121 G0(a
, b
, c
, d
, e
, w
[i
++]);
122 G0(e
, a
, b
, c
, d
, w
[i
++]);
123 G0(d
, e
, a
, b
, c
, w
[i
++]);
124 G0(c
, d
, e
, a
, b
, w
[i
++]);
125 G0(b
, c
, d
, e
, a
, w
[i
++]);
130 G1(a
, b
, c
, d
, e
, w
[i
++]);
131 G1(e
, a
, b
, c
, d
, w
[i
++]);
132 G1(d
, e
, a
, b
, c
, w
[i
++]);
133 G1(c
, d
, e
, a
, b
, w
[i
++]);
134 G1(b
, c
, d
, e
, a
, w
[i
++]);
139 G2(a
, b
, c
, d
, e
, w
[i
++]);
140 G2(e
, a
, b
, c
, d
, w
[i
++]);
141 G2(d
, e
, a
, b
, c
, w
[i
++]);
142 G2(c
, d
, e
, a
, b
, w
[i
++]);
143 G2(b
, c
, d
, e
, a
, w
[i
++]);
148 G3(a
, b
, c
, d
, e
, w
[i
++]);
149 G3(e
, a
, b
, c
, d
, w
[i
++]);
150 G3(d
, e
, a
, b
, c
, w
[i
++]);
151 G3(c
, d
, e
, a
, b
, w
[i
++]);
152 G3(b
, c
, d
, e
, a
, w
[i
++]);
155 kripto_memwipe(w
, 320);
164 static void sha1_input
174 assert(s
->len
>= len
<< 3);
176 for(i
= 0; i
< len
; i
++)
178 s
->buf
[s
->i
++] = CU8(in
)[i
];
182 sha1_process(s
, s
->buf
);
188 static void sha1_finish(kripto_hash
*s
)
190 s
->buf
[s
->i
++] = 0x80; /* pad */
192 if(s
->i
> 56) /* not enough space for length */
194 while(s
->i
< 64) s
->buf
[s
->i
++] = 0;
195 sha1_process(s
, s
->buf
);
198 while(s
->i
< 56) s
->buf
[s
->i
++] = 0;
202 STORE64B(s
->len
, s
->buf
+ 56);
204 sha1_process(s
, s
->buf
);
210 static void sha1_output(kripto_hash
*s
, void *out
, size_t len
)
214 if(!s
->o
) sha1_finish(s
);
217 for(i
= 0; i
< len
; s
->i
++, i
++)
218 U8(out
)[i
] = s
->h
[s
->i
>> 2] >> (24 - ((s
->i
& 3) << 3));
221 static kripto_hash
*sha1_create(unsigned int r
, size_t len
)
225 s
= malloc(sizeof(kripto_hash
));
228 s
->obj
.desc
= kripto_hash_sha1
;
230 (void)sha1_recreate(s
, r
, len
);
235 static void sha1_destroy(kripto_hash
*s
)
237 kripto_memwipe(s
, sizeof(kripto_hash
));
252 (void)sha1_recreate(&s
, r
, out_len
);
253 sha1_input(&s
, in
, in_len
);
254 sha1_output(&s
, out
, out_len
);
256 kripto_memwipe(&s
, sizeof(kripto_hash
));
261 static const kripto_hash_desc sha1
=
273 const kripto_hash_desc
*const kripto_hash_sha1
= &sha1
;