File Coverage

_sha512.c
Criterion Covered Total %
statement 68 84 80.9
branch 9 20 45.0
condition n/a
subroutine n/a
pod n/a
total 77 104 74.0


line stmt bran cond sub pod time code
1             /* sha512.c - an implementation of SHA-384/512 hash functions
2             * based on FIPS 180-3 (Federal Information Processing Standart).
3             *
4             * Copyright (c) 2010, Aleksey Kravchenko
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
19             #include "byte_order.h"
20             #include "sha512.h"
21              
22             /* SHA-384 and SHA-512 constants for 80 rounds. These qwords represent
23             * the first 64 bits of the fractional parts of the cube
24             * roots of the first 80 prime numbers. */
25             static const uint64_t rhash_k512[80] = {
26             I64(0x428a2f98d728ae22), I64(0x7137449123ef65cd), I64(0xb5c0fbcfec4d3b2f),
27             I64(0xe9b5dba58189dbbc), I64(0x3956c25bf348b538), I64(0x59f111f1b605d019),
28             I64(0x923f82a4af194f9b), I64(0xab1c5ed5da6d8118), I64(0xd807aa98a3030242),
29             I64(0x12835b0145706fbe), I64(0x243185be4ee4b28c), I64(0x550c7dc3d5ffb4e2),
30             I64(0x72be5d74f27b896f), I64(0x80deb1fe3b1696b1), I64(0x9bdc06a725c71235),
31             I64(0xc19bf174cf692694), I64(0xe49b69c19ef14ad2), I64(0xefbe4786384f25e3),
32             I64(0x0fc19dc68b8cd5b5), I64(0x240ca1cc77ac9c65), I64(0x2de92c6f592b0275),
33             I64(0x4a7484aa6ea6e483), I64(0x5cb0a9dcbd41fbd4), I64(0x76f988da831153b5),
34             I64(0x983e5152ee66dfab), I64(0xa831c66d2db43210), I64(0xb00327c898fb213f),
35             I64(0xbf597fc7beef0ee4), I64(0xc6e00bf33da88fc2), I64(0xd5a79147930aa725),
36             I64(0x06ca6351e003826f), I64(0x142929670a0e6e70), I64(0x27b70a8546d22ffc),
37             I64(0x2e1b21385c26c926), I64(0x4d2c6dfc5ac42aed), I64(0x53380d139d95b3df),
38             I64(0x650a73548baf63de), I64(0x766a0abb3c77b2a8), I64(0x81c2c92e47edaee6),
39             I64(0x92722c851482353b), I64(0xa2bfe8a14cf10364), I64(0xa81a664bbc423001),
40             I64(0xc24b8b70d0f89791), I64(0xc76c51a30654be30), I64(0xd192e819d6ef5218),
41             I64(0xd69906245565a910), I64(0xf40e35855771202a), I64(0x106aa07032bbd1b8),
42             I64(0x19a4c116b8d2d0c8), I64(0x1e376c085141ab53), I64(0x2748774cdf8eeb99),
43             I64(0x34b0bcb5e19b48a8), I64(0x391c0cb3c5c95a63), I64(0x4ed8aa4ae3418acb),
44             I64(0x5b9cca4f7763e373), I64(0x682e6ff3d6b2b8a3), I64(0x748f82ee5defb2fc),
45             I64(0x78a5636f43172f60), I64(0x84c87814a1f0ab72), I64(0x8cc702081a6439ec),
46             I64(0x90befffa23631e28), I64(0xa4506cebde82bde9), I64(0xbef9a3f7b2c67915),
47             I64(0xc67178f2e372532b), I64(0xca273eceea26619c), I64(0xd186b8c721c0c207),
48             I64(0xeada7dd6cde0eb1e), I64(0xf57d4f7fee6ed178), I64(0x06f067aa72176fba),
49             I64(0x0a637dc5a2c898a6), I64(0x113f9804bef90dae), I64(0x1b710b35131c471b),
50             I64(0x28db77f523047d84), I64(0x32caab7b40c72493), I64(0x3c9ebe0a15c9bebc),
51             I64(0x431d67c49c100d4c), I64(0x4cc5d4becb3e42b6), I64(0x597f299cfc657e2a),
52             I64(0x5fcb6fab3ad6faec), I64(0x6c44198c4a475817)
53             };
54              
55             /* The SHA512/384 functions defined by FIPS 180-3, 4.1.3 */
56             /* Optimized version of Ch(x,y,z)=((x & y) | (~x & z)) */
57             #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
58             /* Optimized version of Maj(x,y,z)=((x & y) ^ (x & z) ^ (y & z)) */
59             #define Maj(x,y,z) (((x) & (y)) ^ ((z) & ((x) ^ (y))))
60              
61             #define Sigma0(x) (ROTR64((x), 28) ^ ROTR64((x), 34) ^ ROTR64((x), 39))
62             #define Sigma1(x) (ROTR64((x), 14) ^ ROTR64((x), 18) ^ ROTR64((x), 41))
63             #define sigma0(x) (ROTR64((x), 1) ^ ROTR64((x), 8) ^ ((x) >> 7))
64             #define sigma1(x) (ROTR64((x), 19) ^ ROTR64((x), 61) ^ ((x) >> 6))
65              
66             /* Recalculate element n-th of circular buffer W using formula
67             * W[n] = sigma1(W[n - 2]) + W[n - 7] + sigma0(W[n - 15]) + W[n - 16]; */
68             #define RECALCULATE_W(W,n) (W[n] += \
69             (sigma1(W[(n - 2) & 15]) + W[(n - 7) & 15] + sigma0(W[(n - 15) & 15])))
70              
71             #define ROUND(a,b,c,d,e,f,g,h,k,data) { \
72             uint64_t T1 = h + Sigma1(e) + Ch(e,f,g) + k + (data); \
73             d += T1, h = T1 + Sigma0(a) + Maj(a,b,c); }
74             #define ROUND_1_16(a,b,c,d,e,f,g,h,n) \
75             ROUND(a,b,c,d,e,f,g,h, rhash_k512[n], W[n] = be2me_64(block[n]))
76             #define ROUND_17_80(a,b,c,d,e,f,g,h,n) \
77             ROUND(a,b,c,d,e,f,g,h, k[n], RECALCULATE_W(W, n))
78              
79             /**
80             * Initialize context before calculating hash.
81             *
82             * @param ctx context to initialize
83             */
84 2           void rhash_sha512_init(sha512_ctx* ctx)
85             {
86             /* Initial values. These words were obtained by taking the first 32
87             * bits of the fractional parts of the square roots of the first
88             * eight prime numbers. */
89             static const uint64_t SHA512_H0[8] = {
90             I64(0x6a09e667f3bcc908), I64(0xbb67ae8584caa73b), I64(0x3c6ef372fe94f82b),
91             I64(0xa54ff53a5f1d36f1), I64(0x510e527fade682d1), I64(0x9b05688c2b3e6c1f),
92             I64(0x1f83d9abfb41bd6b), I64(0x5be0cd19137e2179)
93             };
94              
95 2           ctx->length = 0;
96 2           ctx->digest_length = sha512_hash_size;
97              
98             /* initialize algorithm state */
99 2           memcpy(ctx->hash, SHA512_H0, sizeof(ctx->hash));
100 2           }
101              
102             /**
103             * Initialize context before calculaing hash.
104             *
105             * @param ctx context to initialize
106             */
107 2           void rhash_sha384_init(struct sha512_ctx* ctx)
108             {
109             /* Initial values from FIPS 180-3. These words were obtained by taking
110             * the first sixty-four bits of the fractional parts of the square
111             * roots of ninth through sixteenth prime numbers. */
112             static const uint64_t SHA384_H0[8] = {
113             I64(0xcbbb9d5dc1059ed8), I64(0x629a292a367cd507), I64(0x9159015a3070dd17),
114             I64(0x152fecd8f70e5939), I64(0x67332667ffc00b31), I64(0x8eb44a8768581511),
115             I64(0xdb0c2e0d64f98fa7), I64(0x47b5481dbefa4fa4)
116             };
117              
118 2           ctx->length = 0;
119 2           ctx->digest_length = sha384_hash_size;
120              
121 2           memcpy(ctx->hash, SHA384_H0, sizeof(ctx->hash));
122 2           }
123              
124             /**
125             * The core transformation. Process a 512-bit block.
126             *
127             * @param hash algorithm state
128             * @param block the message block to process
129             */
130 4           static void rhash_sha512_process_block(uint64_t hash[8], uint64_t block[16])
131             {
132             uint64_t A, B, C, D, E, F, G, H;
133             uint64_t W[16];
134             const uint64_t* k;
135             int i;
136              
137 4           A = hash[0], B = hash[1], C = hash[2], D = hash[3];
138 4           E = hash[4], F = hash[5], G = hash[6], H = hash[7];
139              
140             /* Compute SHA using alternate Method: FIPS 180-3 6.1.3 */
141 4           ROUND_1_16(A, B, C, D, E, F, G, H, 0);
142 4           ROUND_1_16(H, A, B, C, D, E, F, G, 1);
143 4           ROUND_1_16(G, H, A, B, C, D, E, F, 2);
144 4           ROUND_1_16(F, G, H, A, B, C, D, E, 3);
145 4           ROUND_1_16(E, F, G, H, A, B, C, D, 4);
146 4           ROUND_1_16(D, E, F, G, H, A, B, C, 5);
147 4           ROUND_1_16(C, D, E, F, G, H, A, B, 6);
148 4           ROUND_1_16(B, C, D, E, F, G, H, A, 7);
149 4           ROUND_1_16(A, B, C, D, E, F, G, H, 8);
150 4           ROUND_1_16(H, A, B, C, D, E, F, G, 9);
151 4           ROUND_1_16(G, H, A, B, C, D, E, F, 10);
152 4           ROUND_1_16(F, G, H, A, B, C, D, E, 11);
153 4           ROUND_1_16(E, F, G, H, A, B, C, D, 12);
154 4           ROUND_1_16(D, E, F, G, H, A, B, C, 13);
155 4           ROUND_1_16(C, D, E, F, G, H, A, B, 14);
156 4           ROUND_1_16(B, C, D, E, F, G, H, A, 15);
157              
158 20 100         for (i = 16, k = &rhash_k512[16]; i < 80; i += 16, k += 16) {
159 16           ROUND_17_80(A, B, C, D, E, F, G, H, 0);
160 16           ROUND_17_80(H, A, B, C, D, E, F, G, 1);
161 16           ROUND_17_80(G, H, A, B, C, D, E, F, 2);
162 16           ROUND_17_80(F, G, H, A, B, C, D, E, 3);
163 16           ROUND_17_80(E, F, G, H, A, B, C, D, 4);
164 16           ROUND_17_80(D, E, F, G, H, A, B, C, 5);
165 16           ROUND_17_80(C, D, E, F, G, H, A, B, 6);
166 16           ROUND_17_80(B, C, D, E, F, G, H, A, 7);
167 16           ROUND_17_80(A, B, C, D, E, F, G, H, 8);
168 16           ROUND_17_80(H, A, B, C, D, E, F, G, 9);
169 16           ROUND_17_80(G, H, A, B, C, D, E, F, 10);
170 16           ROUND_17_80(F, G, H, A, B, C, D, E, 11);
171 16           ROUND_17_80(E, F, G, H, A, B, C, D, 12);
172 16           ROUND_17_80(D, E, F, G, H, A, B, C, 13);
173 16           ROUND_17_80(C, D, E, F, G, H, A, B, 14);
174 16           ROUND_17_80(B, C, D, E, F, G, H, A, 15);
175             }
176              
177 4           hash[0] += A, hash[1] += B, hash[2] += C, hash[3] += D;
178 4           hash[4] += E, hash[5] += F, hash[6] += G, hash[7] += H;
179 4           }
180              
181             /**
182             * Calculate message hash.
183             * Can be called repeatedly with chunks of the message to be hashed.
184             *
185             * @param ctx the algorithm context containing current hashing state
186             * @param msg message chunk
187             * @param size length of the message chunk
188             */
189 4           void rhash_sha512_update(sha512_ctx* ctx, const unsigned char* msg, size_t size)
190             {
191 4           size_t index = (size_t)ctx->length & 127;
192 4           ctx->length += size;
193              
194             /* fill partial block */
195 4 50         if (index) {
196 0           size_t left = sha512_block_size - index;
197 0           memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
198 0 0         if (size < left) return;
199              
200             /* process partial block */
201 0           rhash_sha512_process_block(ctx->hash, ctx->message);
202 0           msg += left;
203 0           size -= left;
204             }
205 4 50         while (size >= sha512_block_size) {
206             uint64_t* aligned_message_block;
207 0 0         if (IS_ALIGNED_64(msg)) {
208             /* the most common case is processing of an already aligned message
209             without copying it */
210 0           aligned_message_block = (uint64_t*)msg;
211             } else {
212 0           memcpy(ctx->message, msg, sha512_block_size);
213 0           aligned_message_block = ctx->message;
214             }
215              
216 0           rhash_sha512_process_block(ctx->hash, aligned_message_block);
217 0           msg += sha512_block_size;
218 0           size -= sha512_block_size;
219             }
220 4 50         if (size) {
221 4           memcpy(ctx->message, msg, size); /* save leftovers */
222             }
223             }
224              
225             /**
226             * Store calculated hash into the given array.
227             *
228             * @param ctx the algorithm context containing current hashing state
229             * @param result calculated hash in binary form
230             */
231 4           void rhash_sha512_final(sha512_ctx* ctx, unsigned char* result)
232             {
233 4           size_t index = ((unsigned)ctx->length & 127) >> 3;
234 4           unsigned shift = ((unsigned)ctx->length & 7) * 8;
235              
236             /* pad message and process the last block */
237              
238             /* append the byte 0x80 to the message */
239 4           ctx->message[index] &= le2me_64( ~(I64(0xFFFFFFFFFFFFFFFF) << shift) );
240 4           ctx->message[index++] ^= le2me_64( I64(0x80) << shift );
241              
242             /* if no room left in the message to store 128-bit message length */
243 4 50         if (index >= 15) {
244 0 0         if (index == 15) ctx->message[index] = 0;
245 0           rhash_sha512_process_block(ctx->hash, ctx->message);
246 0           index = 0;
247             }
248 60 100         while (index < 15) {
249 56           ctx->message[index++] = 0;
250             }
251 4           ctx->message[15] = be2me_64(ctx->length << 3);
252 4           rhash_sha512_process_block(ctx->hash, ctx->message);
253              
254 4 50         if (result) be64_copy(result, 0, ctx->hash, ctx->digest_length);
255 4           }