/src/CMake/Utilities/cmlibrhash/librhash/sha1.c
Line | Count | Source |
1 | | /* sha1.c - an implementation of Secure Hash Algorithm 1 (SHA1) |
2 | | * based on RFC 3174. |
3 | | * |
4 | | * Copyright (c) 2008, Aleksey Kravchenko <rhash.admin@gmail.com> |
5 | | * |
6 | | * Permission to use, copy, modify, and/or distribute this software for any |
7 | | * purpose with or without fee is hereby granted. |
8 | | * |
9 | | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH |
10 | | * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY |
11 | | * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, |
12 | | * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM |
13 | | * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE |
14 | | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
15 | | * PERFORMANCE OF THIS SOFTWARE. |
16 | | */ |
17 | | |
18 | | #include <string.h> |
19 | | #include "byte_order.h" |
20 | | #include "sha1.h" |
21 | | |
22 | | /** |
23 | | * Initialize context before calculating hash. |
24 | | * |
25 | | * @param ctx context to initialize |
26 | | */ |
27 | | void rhash_sha1_init(sha1_ctx* ctx) |
28 | 0 | { |
29 | 0 | ctx->length = 0; |
30 | | |
31 | | /* initialize algorithm state */ |
32 | 0 | ctx->hash[0] = 0x67452301; |
33 | 0 | ctx->hash[1] = 0xefcdab89; |
34 | 0 | ctx->hash[2] = 0x98badcfe; |
35 | 0 | ctx->hash[3] = 0x10325476; |
36 | 0 | ctx->hash[4] = 0xc3d2e1f0; |
37 | 0 | } |
38 | | |
39 | | /* constants for SHA1 rounds */ |
40 | | static const uint32_t K0 = 0x5a827999; |
41 | | static const uint32_t K1 = 0x6ed9eba1; |
42 | | static const uint32_t K2 = 0x8f1bbcdc; |
43 | | static const uint32_t K3 = 0xca62c1d6; |
44 | | |
45 | | /* round functions for SHA1 */ |
46 | 0 | #define CHO(X,Y,Z) (((X)&(Y))|((~(X))&(Z))) |
47 | 0 | #define PAR(X,Y,Z) ((X)^(Y)^(Z)) |
48 | 0 | #define MAJ(X,Y,Z) (((X)&(Y))|((X)&(Z))|((Y)&(Z))) |
49 | | |
50 | 0 | #define ROUND_0(a,b,c,d,e, FF, k, w) e += FF(b, c, d )+ROTL32(a,5)+k+w |
51 | 0 | #define ROUND_1(a,b,c,d,e, FF, k, w) e += FF(b,ROTL32(c,30), d )+ROTL32(a,5)+k+w |
52 | 0 | #define ROUND_2(a,b,c,d,e, FF, k, w) e += FF(b,ROTL32(c,30),ROTL32(d,30))+ROTL32(a,5)+k+w |
53 | 0 | #define ROUND(a,b,c,d,e, FF, k, w) e = ROTL32(e,30)+FF(b,ROTL32(c,30),ROTL32(d,30))+ROTL32(a,5)+k+w |
54 | | |
55 | | |
56 | | /** |
57 | | * The core transformation. Process a 512-bit block. |
58 | | * The function has been taken from RFC 3174 with little changes. |
59 | | * |
60 | | * @param hash algorithm state |
61 | | * @param block the message block to process |
62 | | */ |
63 | | static void rhash_sha1_process_block(unsigned* hash, const unsigned* block) |
64 | 0 | { |
65 | 0 | uint32_t W[80]; /* Word sequence */ |
66 | 0 | uint32_t A, B, C, D, E; /* Word buffers */ |
67 | | |
68 | |
|
69 | 0 | A = hash[0]; |
70 | 0 | B = hash[1]; |
71 | 0 | C = hash[2]; |
72 | 0 | D = hash[3]; |
73 | 0 | E = hash[4]; |
74 | | |
75 | | /* 0..19 */ |
76 | 0 | W[ 0] = be2me_32(block[ 0]); |
77 | 0 | ROUND_0(A,B,C,D,E, CHO, K0, W[ 0]); |
78 | 0 | W[ 1] = be2me_32(block[ 1]); |
79 | 0 | ROUND_1(E,A,B,C,D, CHO, K0, W[ 1]); |
80 | 0 | W[ 2] = be2me_32(block[ 2]); |
81 | 0 | ROUND_2(D,E,A,B,C, CHO, K0, W[ 2]); |
82 | 0 | W[ 3] = be2me_32(block[ 3]); |
83 | 0 | ROUND(C,D,E,A,B, CHO, K0, W[ 3]); |
84 | 0 | W[ 4] = be2me_32(block[ 4]); |
85 | 0 | ROUND(B,C,D,E,A, CHO, K0, W[ 4]); |
86 | |
|
87 | 0 | W[ 5] = be2me_32(block[ 5]); |
88 | 0 | ROUND(A,B,C,D,E, CHO, K0, W[ 5]); |
89 | 0 | W[ 6] = be2me_32(block[ 6]); |
90 | 0 | ROUND(E,A,B,C,D, CHO, K0, W[ 6]); |
91 | 0 | W[ 7] = be2me_32(block[ 7]); |
92 | 0 | ROUND(D,E,A,B,C, CHO, K0, W[ 7]); |
93 | 0 | W[ 8] = be2me_32(block[ 8]); |
94 | 0 | ROUND(C,D,E,A,B, CHO, K0, W[ 8]); |
95 | 0 | W[ 9] = be2me_32(block[ 9]); |
96 | 0 | ROUND(B,C,D,E,A, CHO, K0, W[ 9]); |
97 | |
|
98 | 0 | W[10] = be2me_32(block[10]); |
99 | 0 | ROUND(A,B,C,D,E, CHO, K0, W[10]); |
100 | 0 | W[11] = be2me_32(block[11]); |
101 | 0 | ROUND(E,A,B,C,D, CHO, K0, W[11]); |
102 | 0 | W[12] = be2me_32(block[12]); |
103 | 0 | ROUND(D,E,A,B,C, CHO, K0, W[12]); |
104 | 0 | W[13] = be2me_32(block[13]); |
105 | 0 | ROUND(C,D,E,A,B, CHO, K0, W[13]); |
106 | 0 | W[14] = be2me_32(block[14]); |
107 | 0 | ROUND(B,C,D,E,A, CHO, K0, W[14]); |
108 | |
|
109 | 0 | W[15] = be2me_32(block[15]); |
110 | 0 | ROUND(A,B,C,D,E, CHO, K0, W[15]); |
111 | 0 | W[16] = ROTL32(W[13] ^ W[ 8] ^ W[ 2] ^ W[ 0], 1); |
112 | 0 | ROUND(E,A,B,C,D, CHO, K0, W[16]); |
113 | 0 | W[17] = ROTL32(W[14] ^ W[ 9] ^ W[ 3] ^ W[ 1], 1); |
114 | 0 | ROUND(D,E,A,B,C, CHO, K0, W[17]); |
115 | 0 | W[18] = ROTL32(W[15] ^ W[10] ^ W[ 4] ^ W[ 2], 1); |
116 | 0 | ROUND(C,D,E,A,B, CHO, K0, W[18]); |
117 | 0 | W[19] = ROTL32(W[16] ^ W[11] ^ W[ 5] ^ W[ 3], 1); |
118 | 0 | ROUND(B,C,D,E,A, CHO, K0, W[19]); |
119 | | /* 20..39 */ |
120 | 0 | W[20] = ROTL32(W[17] ^ W[12] ^ W[ 6] ^ W[ 4], 1); |
121 | 0 | ROUND(A,B,C,D,E, PAR, K1, W[20]); |
122 | 0 | W[21] = ROTL32(W[18] ^ W[13] ^ W[ 7] ^ W[ 5], 1); |
123 | 0 | ROUND(E,A,B,C,D, PAR, K1, W[21]); |
124 | 0 | W[22] = ROTL32(W[19] ^ W[14] ^ W[ 8] ^ W[ 6], 1); |
125 | 0 | ROUND(D,E,A,B,C, PAR, K1, W[22]); |
126 | 0 | W[23] = ROTL32(W[20] ^ W[15] ^ W[ 9] ^ W[ 7], 1); |
127 | 0 | ROUND(C,D,E,A,B, PAR, K1, W[23]); |
128 | 0 | W[24] = ROTL32(W[21] ^ W[16] ^ W[10] ^ W[ 8], 1); |
129 | 0 | ROUND(B,C,D,E,A, PAR, K1, W[24]); |
130 | |
|
131 | 0 | W[25] = ROTL32(W[22] ^ W[17] ^ W[11] ^ W[ 9], 1); |
132 | 0 | ROUND(A,B,C,D,E, PAR, K1, W[25]); |
133 | 0 | W[26] = ROTL32(W[23] ^ W[18] ^ W[12] ^ W[10], 1); |
134 | 0 | ROUND(E,A,B,C,D, PAR, K1, W[26]); |
135 | 0 | W[27] = ROTL32(W[24] ^ W[19] ^ W[13] ^ W[11], 1); |
136 | 0 | ROUND(D,E,A,B,C, PAR, K1, W[27]); |
137 | 0 | W[28] = ROTL32(W[25] ^ W[20] ^ W[14] ^ W[12], 1); |
138 | 0 | ROUND(C,D,E,A,B, PAR, K1, W[28]); |
139 | 0 | W[29] = ROTL32(W[26] ^ W[21] ^ W[15] ^ W[13], 1); |
140 | 0 | ROUND(B,C,D,E,A, PAR, K1, W[29]); |
141 | |
|
142 | 0 | W[30] = ROTL32(W[27] ^ W[22] ^ W[16] ^ W[14], 1); |
143 | 0 | ROUND(A,B,C,D,E, PAR, K1, W[30]); |
144 | 0 | W[31] = ROTL32(W[28] ^ W[23] ^ W[17] ^ W[15], 1); |
145 | 0 | ROUND(E,A,B,C,D, PAR, K1, W[31]); |
146 | 0 | W[32] = ROTL32(W[29] ^ W[24] ^ W[18] ^ W[16], 1); |
147 | 0 | ROUND(D,E,A,B,C, PAR, K1, W[32]); |
148 | 0 | W[33] = ROTL32(W[30] ^ W[25] ^ W[19] ^ W[17], 1); |
149 | 0 | ROUND(C,D,E,A,B, PAR, K1, W[33]); |
150 | 0 | W[34] = ROTL32(W[31] ^ W[26] ^ W[20] ^ W[18], 1); |
151 | 0 | ROUND(B,C,D,E,A, PAR, K1, W[34]); |
152 | |
|
153 | 0 | W[35] = ROTL32(W[32] ^ W[27] ^ W[21] ^ W[19], 1); |
154 | 0 | ROUND(A,B,C,D,E, PAR, K1, W[35]); |
155 | 0 | W[36] = ROTL32(W[33] ^ W[28] ^ W[22] ^ W[20], 1); |
156 | 0 | ROUND(E,A,B,C,D, PAR, K1, W[36]); |
157 | 0 | W[37] = ROTL32(W[34] ^ W[29] ^ W[23] ^ W[21], 1); |
158 | 0 | ROUND(D,E,A,B,C, PAR, K1, W[37]); |
159 | 0 | W[38] = ROTL32(W[35] ^ W[30] ^ W[24] ^ W[22], 1); |
160 | 0 | ROUND(C,D,E,A,B, PAR, K1, W[38]); |
161 | 0 | W[39] = ROTL32(W[36] ^ W[31] ^ W[25] ^ W[23], 1); |
162 | 0 | ROUND(B,C,D,E,A, PAR, K1, W[39]); |
163 | | /* 40..59 */ |
164 | 0 | W[40] = ROTL32(W[37] ^ W[32] ^ W[26] ^ W[24], 1); |
165 | 0 | ROUND(A,B,C,D,E, MAJ, K2, W[40]); |
166 | 0 | W[41] = ROTL32(W[38] ^ W[33] ^ W[27] ^ W[25], 1); |
167 | 0 | ROUND(E,A,B,C,D, MAJ, K2, W[41]); |
168 | 0 | W[42] = ROTL32(W[39] ^ W[34] ^ W[28] ^ W[26], 1); |
169 | 0 | ROUND(D,E,A,B,C, MAJ, K2, W[42]); |
170 | 0 | W[43] = ROTL32(W[40] ^ W[35] ^ W[29] ^ W[27], 1); |
171 | 0 | ROUND(C,D,E,A,B, MAJ, K2, W[43]); |
172 | 0 | W[44] = ROTL32(W[41] ^ W[36] ^ W[30] ^ W[28], 1); |
173 | 0 | ROUND(B,C,D,E,A, MAJ, K2, W[44]); |
174 | |
|
175 | 0 | W[45] = ROTL32(W[42] ^ W[37] ^ W[31] ^ W[29], 1); |
176 | 0 | ROUND(A,B,C,D,E, MAJ, K2, W[45]); |
177 | 0 | W[46] = ROTL32(W[43] ^ W[38] ^ W[32] ^ W[30], 1); |
178 | 0 | ROUND(E,A,B,C,D, MAJ, K2, W[46]); |
179 | 0 | W[47] = ROTL32(W[44] ^ W[39] ^ W[33] ^ W[31], 1); |
180 | 0 | ROUND(D,E,A,B,C, MAJ, K2, W[47]); |
181 | 0 | W[48] = ROTL32(W[45] ^ W[40] ^ W[34] ^ W[32], 1); |
182 | 0 | ROUND(C,D,E,A,B, MAJ, K2, W[48]); |
183 | 0 | W[49] = ROTL32(W[46] ^ W[41] ^ W[35] ^ W[33], 1); |
184 | 0 | ROUND(B,C,D,E,A, MAJ, K2, W[49]); |
185 | |
|
186 | 0 | W[50] = ROTL32(W[47] ^ W[42] ^ W[36] ^ W[34], 1); |
187 | 0 | ROUND(A,B,C,D,E, MAJ, K2, W[50]); |
188 | 0 | W[51] = ROTL32(W[48] ^ W[43] ^ W[37] ^ W[35], 1); |
189 | 0 | ROUND(E,A,B,C,D, MAJ, K2, W[51]); |
190 | 0 | W[52] = ROTL32(W[49] ^ W[44] ^ W[38] ^ W[36], 1); |
191 | 0 | ROUND(D,E,A,B,C, MAJ, K2, W[52]); |
192 | 0 | W[53] = ROTL32(W[50] ^ W[45] ^ W[39] ^ W[37], 1); |
193 | 0 | ROUND(C,D,E,A,B, MAJ, K2, W[53]); |
194 | 0 | W[54] = ROTL32(W[51] ^ W[46] ^ W[40] ^ W[38], 1); |
195 | 0 | ROUND(B,C,D,E,A, MAJ, K2, W[54]); |
196 | |
|
197 | 0 | W[55] = ROTL32(W[52] ^ W[47] ^ W[41] ^ W[39], 1); |
198 | 0 | ROUND(A,B,C,D,E, MAJ, K2, W[55]); |
199 | 0 | W[56] = ROTL32(W[53] ^ W[48] ^ W[42] ^ W[40], 1); |
200 | 0 | ROUND(E,A,B,C,D, MAJ, K2, W[56]); |
201 | 0 | W[57] = ROTL32(W[54] ^ W[49] ^ W[43] ^ W[41], 1); |
202 | 0 | ROUND(D,E,A,B,C, MAJ, K2, W[57]); |
203 | 0 | W[58] = ROTL32(W[55] ^ W[50] ^ W[44] ^ W[42], 1); |
204 | 0 | ROUND(C,D,E,A,B, MAJ, K2, W[58]); |
205 | 0 | W[59] = ROTL32(W[56] ^ W[51] ^ W[45] ^ W[43], 1); |
206 | 0 | ROUND(B,C,D,E,A, MAJ, K2, W[59]); |
207 | | /* 60..79 */ |
208 | 0 | W[60] = ROTL32(W[57] ^ W[52] ^ W[46] ^ W[44], 1); |
209 | 0 | ROUND(A,B,C,D,E, PAR, K3, W[60]); |
210 | 0 | W[61] = ROTL32(W[58] ^ W[53] ^ W[47] ^ W[45], 1); |
211 | 0 | ROUND(E,A,B,C,D, PAR, K3, W[61]); |
212 | 0 | W[62] = ROTL32(W[59] ^ W[54] ^ W[48] ^ W[46], 1); |
213 | 0 | ROUND(D,E,A,B,C, PAR, K3, W[62]); |
214 | 0 | W[63] = ROTL32(W[60] ^ W[55] ^ W[49] ^ W[47], 1); |
215 | 0 | ROUND(C,D,E,A,B, PAR, K3, W[63]); |
216 | 0 | W[64] = ROTL32(W[61] ^ W[56] ^ W[50] ^ W[48], 1); |
217 | 0 | ROUND(B,C,D,E,A, PAR, K3, W[64]); |
218 | |
|
219 | 0 | W[65] = ROTL32(W[62] ^ W[57] ^ W[51] ^ W[49], 1); |
220 | 0 | ROUND(A,B,C,D,E, PAR, K3, W[65]); |
221 | 0 | W[66] = ROTL32(W[63] ^ W[58] ^ W[52] ^ W[50], 1); |
222 | 0 | ROUND(E,A,B,C,D, PAR, K3, W[66]); |
223 | 0 | W[67] = ROTL32(W[64] ^ W[59] ^ W[53] ^ W[51], 1); |
224 | 0 | ROUND(D,E,A,B,C, PAR, K3, W[67]); |
225 | 0 | W[68] = ROTL32(W[65] ^ W[60] ^ W[54] ^ W[52], 1); |
226 | 0 | ROUND(C,D,E,A,B, PAR, K3, W[68]); |
227 | 0 | W[69] = ROTL32(W[66] ^ W[61] ^ W[55] ^ W[53], 1); |
228 | 0 | ROUND(B,C,D,E,A, PAR, K3, W[69]); |
229 | |
|
230 | 0 | W[70] = ROTL32(W[67] ^ W[62] ^ W[56] ^ W[54], 1); |
231 | 0 | ROUND(A,B,C,D,E, PAR, K3, W[70]); |
232 | 0 | W[71] = ROTL32(W[68] ^ W[63] ^ W[57] ^ W[55], 1); |
233 | 0 | ROUND(E,A,B,C,D, PAR, K3, W[71]); |
234 | 0 | W[72] = ROTL32(W[69] ^ W[64] ^ W[58] ^ W[56], 1); |
235 | 0 | ROUND(D,E,A,B,C, PAR, K3, W[72]); |
236 | 0 | W[73] = ROTL32(W[70] ^ W[65] ^ W[59] ^ W[57], 1); |
237 | 0 | ROUND(C,D,E,A,B, PAR, K3, W[73]); |
238 | 0 | W[74] = ROTL32(W[71] ^ W[66] ^ W[60] ^ W[58], 1); |
239 | 0 | ROUND(B,C,D,E,A, PAR, K3, W[74]); |
240 | |
|
241 | 0 | W[75] = ROTL32(W[72] ^ W[67] ^ W[61] ^ W[59], 1); |
242 | 0 | ROUND(A,B,C,D,E, PAR, K3, W[75]); |
243 | 0 | W[76] = ROTL32(W[73] ^ W[68] ^ W[62] ^ W[60], 1); |
244 | 0 | ROUND(E,A,B,C,D, PAR, K3, W[76]); |
245 | 0 | W[77] = ROTL32(W[74] ^ W[69] ^ W[63] ^ W[61], 1); |
246 | 0 | ROUND(D,E,A,B,C, PAR, K3, W[77]); |
247 | 0 | W[78] = ROTL32(W[75] ^ W[70] ^ W[64] ^ W[62], 1); |
248 | 0 | ROUND(C,D,E,A,B, PAR, K3, W[78]); |
249 | 0 | W[79] = ROTL32(W[76] ^ W[71] ^ W[65] ^ W[63], 1); |
250 | 0 | ROUND(B,C,D,E,A, PAR, K3, W[79]); |
251 | | |
252 | |
|
253 | 0 | hash[0] += A; |
254 | 0 | hash[1] += B; |
255 | 0 | hash[2] += ROTL32(C,30); |
256 | 0 | hash[3] += ROTL32(D,30); |
257 | 0 | hash[4] += ROTL32(E,30); |
258 | 0 | } |
259 | | |
260 | | /** |
261 | | * Calculate message hash. |
262 | | * Can be called repeatedly with chunks of the message to be hashed. |
263 | | * |
264 | | * @param ctx the algorithm context containing current hashing state |
265 | | * @param msg message chunk |
266 | | * @param size length of the message chunk |
267 | | */ |
268 | | void rhash_sha1_update(sha1_ctx* ctx, const unsigned char* msg, size_t size) |
269 | 0 | { |
270 | 0 | unsigned index = (unsigned)ctx->length & 63; |
271 | 0 | ctx->length += size; |
272 | | |
273 | | /* fill partial block */ |
274 | 0 | if (index) { |
275 | 0 | unsigned left = sha1_block_size - index; |
276 | 0 | memcpy(ctx->message + index, msg, (size < left ? size : left)); |
277 | 0 | if (size < left) return; |
278 | | |
279 | | /* process partial block */ |
280 | 0 | rhash_sha1_process_block(ctx->hash, (unsigned*)ctx->message); |
281 | 0 | msg += left; |
282 | 0 | size -= left; |
283 | 0 | } |
284 | 0 | while (size >= sha1_block_size) { |
285 | 0 | unsigned* aligned_message_block; |
286 | 0 | if (IS_ALIGNED_32(msg)) { |
287 | | /* the most common case is processing of an already aligned message |
288 | | without copying it */ |
289 | 0 | aligned_message_block = (unsigned*)msg; |
290 | 0 | } else { |
291 | 0 | memcpy(ctx->message, msg, sha1_block_size); |
292 | 0 | aligned_message_block = (unsigned*)ctx->message; |
293 | 0 | } |
294 | |
|
295 | 0 | rhash_sha1_process_block(ctx->hash, aligned_message_block); |
296 | 0 | msg += sha1_block_size; |
297 | 0 | size -= sha1_block_size; |
298 | 0 | } |
299 | 0 | if (size) { |
300 | | /* save leftovers */ |
301 | 0 | memcpy(ctx->message, msg, size); |
302 | 0 | } |
303 | 0 | } |
304 | | |
305 | | /** |
306 | | * Store calculated hash into the given array. |
307 | | * |
308 | | * @param ctx the algorithm context containing current hashing state |
309 | | * @param result calculated hash in binary form |
310 | | */ |
311 | | void rhash_sha1_final(sha1_ctx* ctx, unsigned char* result) |
312 | 0 | { |
313 | 0 | unsigned index = (unsigned)ctx->length & 63; |
314 | 0 | unsigned* msg32 = (unsigned*)ctx->message; |
315 | | |
316 | | /* pad message and run for last block */ |
317 | 0 | ctx->message[index++] = 0x80; |
318 | 0 | while ((index & 3) != 0) { |
319 | 0 | ctx->message[index++] = 0; |
320 | 0 | } |
321 | 0 | index >>= 2; |
322 | | |
323 | | /* if no room left in the message to store 64-bit message length */ |
324 | 0 | if (index > 14) { |
325 | | /* then fill the rest with zeros and process it */ |
326 | 0 | while (index < 16) { |
327 | 0 | msg32[index++] = 0; |
328 | 0 | } |
329 | 0 | rhash_sha1_process_block(ctx->hash, msg32); |
330 | 0 | index = 0; |
331 | 0 | } |
332 | 0 | while (index < 14) { |
333 | 0 | msg32[index++] = 0; |
334 | 0 | } |
335 | 0 | msg32[14] = be2me_32( (unsigned)(ctx->length >> 29) ); |
336 | 0 | msg32[15] = be2me_32( (unsigned)(ctx->length << 3) ); |
337 | 0 | rhash_sha1_process_block(ctx->hash, msg32); |
338 | |
|
339 | 0 | if (result) be32_copy(result, 0, &ctx->hash, sha1_hash_size); |
340 | 0 | } |