/src/CMake/Utilities/cmlibrhash/librhash/sha256.c
Line | Count | Source |
1 | | /* sha256.c - an implementation of SHA-256/224 hash functions |
2 | | * based on FIPS 180-3 (Federal Information Processing Standart). |
3 | | * |
4 | | * Copyright (c) 2010, 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 "sha256.h" |
21 | | |
22 | | /* SHA-224 and SHA-256 constants for 64 rounds. These words represent |
23 | | * the first 32 bits of the fractional parts of the cube |
24 | | * roots of the first 64 prime numbers. */ |
25 | | static const unsigned rhash_k256[64] = { |
26 | | 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, |
27 | | 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, |
28 | | 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, |
29 | | 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, |
30 | | 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, |
31 | | 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, |
32 | | 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, |
33 | | 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, |
34 | | 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, |
35 | | 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, |
36 | | 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 |
37 | | }; |
38 | | |
39 | | /* The SHA256/224 functions defined by FIPS 180-3, 4.1.2 */ |
40 | | /* Optimized version of Ch(x,y,z)=((x & y) | (~x & z)) */ |
41 | 0 | #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) |
42 | | /* Optimized version of Maj(x,y,z)=((x & y) ^ (x & z) ^ (y & z)) */ |
43 | 0 | #define Maj(x,y,z) (((x) & (y)) ^ ((z) & ((x) ^ (y)))) |
44 | | |
45 | 0 | #define Sigma0(x) (ROTR32((x), 2) ^ ROTR32((x), 13) ^ ROTR32((x), 22)) |
46 | 0 | #define Sigma1(x) (ROTR32((x), 6) ^ ROTR32((x), 11) ^ ROTR32((x), 25)) |
47 | | #define sigma0(x) (ROTR32((x), 7) ^ ROTR32((x), 18) ^ ((x) >> 3)) |
48 | | #define sigma1(x) (ROTR32((x),17) ^ ROTR32((x), 19) ^ ((x) >> 10)) |
49 | | |
50 | | /* Recalculate element n-th of circular buffer W using formula |
51 | | * W[n] = sigma1(W[n - 2]) + W[n - 7] + sigma0(W[n - 15]) + W[n - 16]; */ |
52 | | #define RECALCULATE_W(W,n) (W[n] += \ |
53 | | (sigma1(W[(n - 2) & 15]) + W[(n - 7) & 15] + sigma0(W[(n - 15) & 15]))) |
54 | | |
55 | 0 | #define ROUND(a,b,c,d,e,f,g,h,k,data) { \ |
56 | 0 | unsigned T1 = h + Sigma1(e) + Ch(e,f,g) + k + (data); \ |
57 | 0 | d += T1, h = T1 + Sigma0(a) + Maj(a,b,c); } |
58 | | #define ROUND_1_16(a,b,c,d,e,f,g,h,n) \ |
59 | 0 | ROUND(a,b,c,d,e,f,g,h, rhash_k256[n], W[n] = be2me_32(block[n])) |
60 | | #define ROUND_17_64(a,b,c,d,e,f,g,h,n) \ |
61 | 0 | ROUND(a,b,c,d,e,f,g,h, k[n], RECALCULATE_W(W, n)) |
62 | | |
63 | | /** |
64 | | * Initialize context before calculating hash. |
65 | | * |
66 | | * @param ctx context to initialize |
67 | | */ |
68 | | void rhash_sha256_init(sha256_ctx* ctx) |
69 | 0 | { |
70 | | /* Initial values. These words were obtained by taking the first 32 |
71 | | * bits of the fractional parts of the square roots of the first |
72 | | * eight prime numbers. */ |
73 | 0 | static const unsigned SHA256_H0[8] = { |
74 | 0 | 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, |
75 | 0 | 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 |
76 | 0 | }; |
77 | 0 | memset(ctx->message, 0, sizeof(ctx->message)); |
78 | 0 | ctx->length = 0; |
79 | 0 | ctx->digest_length = sha256_hash_size; |
80 | | |
81 | | /* initialize algorithm state */ |
82 | 0 | memcpy(ctx->hash, SHA256_H0, sizeof(ctx->hash)); |
83 | 0 | } |
84 | | |
85 | | /** |
86 | | * Initialize context before calculating hash. |
87 | | * |
88 | | * @param ctx context to initialize |
89 | | */ |
90 | | void rhash_sha224_init(struct sha256_ctx* ctx) |
91 | 0 | { |
92 | | /* Initial values from FIPS 180-3. These words were obtained by taking |
93 | | * bits from 33th to 64th of the fractional parts of the square |
94 | | * roots of ninth through sixteenth prime numbers. */ |
95 | 0 | static const unsigned SHA224_H0[8] = { |
96 | 0 | 0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, |
97 | 0 | 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4 |
98 | 0 | }; |
99 | 0 | memset(ctx->message, 0, sizeof(ctx->message)); |
100 | 0 | ctx->length = 0; |
101 | 0 | ctx->digest_length = sha224_hash_size; |
102 | |
|
103 | 0 | memcpy(ctx->hash, SHA224_H0, sizeof(ctx->hash)); |
104 | 0 | } |
105 | | |
106 | | /** |
107 | | * The core transformation. Process a 512-bit block. |
108 | | * |
109 | | * @param hash algorithm state |
110 | | * @param block the message block to process |
111 | | */ |
112 | | static void rhash_sha256_process_block(unsigned hash[8], unsigned block[16]) |
113 | 0 | { |
114 | 0 | unsigned A, B, C, D, E, F, G, H; |
115 | 0 | unsigned W[16]; |
116 | 0 | const unsigned* k; |
117 | 0 | int i; |
118 | |
|
119 | 0 | A = hash[0], B = hash[1], C = hash[2], D = hash[3]; |
120 | 0 | E = hash[4], F = hash[5], G = hash[6], H = hash[7]; |
121 | | |
122 | | /* Compute SHA using alternate Method: FIPS 180-3 6.1.3 */ |
123 | 0 | ROUND_1_16(A, B, C, D, E, F, G, H, 0); |
124 | 0 | ROUND_1_16(H, A, B, C, D, E, F, G, 1); |
125 | 0 | ROUND_1_16(G, H, A, B, C, D, E, F, 2); |
126 | 0 | ROUND_1_16(F, G, H, A, B, C, D, E, 3); |
127 | 0 | ROUND_1_16(E, F, G, H, A, B, C, D, 4); |
128 | 0 | ROUND_1_16(D, E, F, G, H, A, B, C, 5); |
129 | 0 | ROUND_1_16(C, D, E, F, G, H, A, B, 6); |
130 | 0 | ROUND_1_16(B, C, D, E, F, G, H, A, 7); |
131 | 0 | ROUND_1_16(A, B, C, D, E, F, G, H, 8); |
132 | 0 | ROUND_1_16(H, A, B, C, D, E, F, G, 9); |
133 | 0 | ROUND_1_16(G, H, A, B, C, D, E, F, 10); |
134 | 0 | ROUND_1_16(F, G, H, A, B, C, D, E, 11); |
135 | 0 | ROUND_1_16(E, F, G, H, A, B, C, D, 12); |
136 | 0 | ROUND_1_16(D, E, F, G, H, A, B, C, 13); |
137 | 0 | ROUND_1_16(C, D, E, F, G, H, A, B, 14); |
138 | 0 | ROUND_1_16(B, C, D, E, F, G, H, A, 15); |
139 | |
|
140 | 0 | for (i = 16, k = &rhash_k256[16]; i < 64; i += 16, k += 16) { |
141 | 0 | ROUND_17_64(A, B, C, D, E, F, G, H, 0); |
142 | 0 | ROUND_17_64(H, A, B, C, D, E, F, G, 1); |
143 | 0 | ROUND_17_64(G, H, A, B, C, D, E, F, 2); |
144 | 0 | ROUND_17_64(F, G, H, A, B, C, D, E, 3); |
145 | 0 | ROUND_17_64(E, F, G, H, A, B, C, D, 4); |
146 | 0 | ROUND_17_64(D, E, F, G, H, A, B, C, 5); |
147 | 0 | ROUND_17_64(C, D, E, F, G, H, A, B, 6); |
148 | 0 | ROUND_17_64(B, C, D, E, F, G, H, A, 7); |
149 | 0 | ROUND_17_64(A, B, C, D, E, F, G, H, 8); |
150 | 0 | ROUND_17_64(H, A, B, C, D, E, F, G, 9); |
151 | 0 | ROUND_17_64(G, H, A, B, C, D, E, F, 10); |
152 | 0 | ROUND_17_64(F, G, H, A, B, C, D, E, 11); |
153 | 0 | ROUND_17_64(E, F, G, H, A, B, C, D, 12); |
154 | 0 | ROUND_17_64(D, E, F, G, H, A, B, C, 13); |
155 | 0 | ROUND_17_64(C, D, E, F, G, H, A, B, 14); |
156 | 0 | ROUND_17_64(B, C, D, E, F, G, H, A, 15); |
157 | 0 | } |
158 | |
|
159 | 0 | hash[0] += A, hash[1] += B, hash[2] += C, hash[3] += D; |
160 | 0 | hash[4] += E, hash[5] += F, hash[6] += G, hash[7] += H; |
161 | 0 | } |
162 | | |
163 | | /** |
164 | | * Calculate message hash. |
165 | | * Can be called repeatedly with chunks of the message to be hashed. |
166 | | * |
167 | | * @param ctx the algorithm context containing current hashing state |
168 | | * @param msg message chunk |
169 | | * @param size length of the message chunk |
170 | | */ |
171 | | void rhash_sha256_update(sha256_ctx* ctx, const unsigned char* msg, size_t size) |
172 | 0 | { |
173 | 0 | size_t index = (size_t)ctx->length & 63; |
174 | 0 | ctx->length += size; |
175 | | |
176 | | /* fill partial block */ |
177 | 0 | if (index) { |
178 | 0 | size_t left = sha256_block_size - index; |
179 | 0 | memcpy((char*)ctx->message + index, msg, (size < left ? size : left)); |
180 | 0 | if (size < left) return; |
181 | | |
182 | | /* process partial block */ |
183 | 0 | rhash_sha256_process_block(ctx->hash, (unsigned*)ctx->message); |
184 | 0 | msg += left; |
185 | 0 | size -= left; |
186 | 0 | } |
187 | 0 | while (size >= sha256_block_size) { |
188 | 0 | unsigned* aligned_message_block; |
189 | 0 | if (IS_ALIGNED_32(msg)) { |
190 | | /* the most common case is processing of an already aligned message |
191 | | without copying it */ |
192 | 0 | aligned_message_block = (unsigned*)msg; |
193 | 0 | } else { |
194 | 0 | memcpy(ctx->message, msg, sha256_block_size); |
195 | 0 | aligned_message_block = (unsigned*)ctx->message; |
196 | 0 | } |
197 | |
|
198 | 0 | rhash_sha256_process_block(ctx->hash, aligned_message_block); |
199 | 0 | msg += sha256_block_size; |
200 | 0 | size -= sha256_block_size; |
201 | 0 | } |
202 | 0 | if (size) { |
203 | 0 | memcpy(ctx->message, msg, size); /* save leftovers */ |
204 | 0 | } |
205 | 0 | } |
206 | | |
207 | | /** |
208 | | * Store calculated hash into the given array. |
209 | | * |
210 | | * @param ctx the algorithm context containing current hashing state |
211 | | * @param result calculated hash in binary form |
212 | | */ |
213 | | void rhash_sha256_final(sha256_ctx* ctx, unsigned char* result) |
214 | 0 | { |
215 | 0 | size_t index = ((unsigned)ctx->length & 63) >> 2; |
216 | 0 | unsigned shift = ((unsigned)ctx->length & 3) * 8; |
217 | | |
218 | | /* pad message and run for last block */ |
219 | | |
220 | | /* append the byte 0x80 to the message */ |
221 | 0 | ctx->message[index] &= le2me_32(~(0xFFFFFFFFu << shift)); |
222 | 0 | ctx->message[index++] ^= le2me_32(0x80u << shift); |
223 | | |
224 | | /* if no room left in the message to store 64-bit message length */ |
225 | 0 | if (index > 14) { |
226 | | /* then fill the rest with zeros and process it */ |
227 | 0 | while (index < 16) { |
228 | 0 | ctx->message[index++] = 0; |
229 | 0 | } |
230 | 0 | rhash_sha256_process_block(ctx->hash, ctx->message); |
231 | 0 | index = 0; |
232 | 0 | } |
233 | 0 | while (index < 14) { |
234 | 0 | ctx->message[index++] = 0; |
235 | 0 | } |
236 | 0 | ctx->message[14] = be2me_32( (unsigned)(ctx->length >> 29) ); |
237 | 0 | ctx->message[15] = be2me_32( (unsigned)(ctx->length << 3) ); |
238 | 0 | rhash_sha256_process_block(ctx->hash, ctx->message); |
239 | |
|
240 | 0 | if (result) be32_copy(result, 0, ctx->hash, ctx->digest_length); |
241 | 0 | } |