File Coverage

_has160.c
Criterion Covered Total %
statement 138 155 89.0
branch 8 18 44.4
condition n/a
subroutine n/a
pod n/a
total 146 173 84.3


line stmt bran cond sub pod time code
1             /* hash.c - an implementation of HAS-160 Algorithm.
2             *
3             * Copyright (c) 2009, Aleksey Kravchenko
4             *
5             * Permission to use, copy, modify, and/or distribute this software for any
6             * purpose with or without fee is hereby granted.
7             *
8             * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9             * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10             * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11             * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12             * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
13             * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14             * PERFORMANCE OF THIS SOFTWARE.
15             *
16             * HAS-160 is a cryptographic hash function designed for use with the
17             * Korean KCDSA digital signature algorithm. It derives from SHA-1,
18             * with assorted changes intended to increase its security.
19             * It produces a 160-bit message digest.
20             *
21             * HAS-160 was developed in 1998 by KISA
22             * (Korea Information Security Agency) + Academic.
23             */
24              
25             #include
26             #include "byte_order.h"
27             #include "has160.h"
28              
29             /**
30             * Initialize algorithm context before calculaing hash.
31             *
32             * @param ctx context to initialize
33             */
34 2           void rhash_has160_init(has160_ctx* ctx)
35             {
36 2           ctx->length = 0;
37              
38             /* initialize algorithm state */
39 2           ctx->hash[0] = 0x67452301;
40 2           ctx->hash[1] = 0xefcdab89;
41 2           ctx->hash[2] = 0x98badcfe;
42 2           ctx->hash[3] = 0x10325476;
43 2           ctx->hash[4] = 0xc3d2e1f0;
44 2           }
45              
46             /* HAS-160 boolean functions:
47             * F1(x,y,z) == (x AND y) OR ((NOT x) AND z) = ((y XOR z) AND x) XOR z
48             * F2(x,y,z) == x XOR y XOR z
49             * F3(x,y,z) == y XOR (x OR (NOT Z))
50             * F4(x,y,z) == x XOR y XOR z */
51             #define STEP_F1(A, B, C, D, E, msg, rot) \
52             E += ROTL32(A, rot) + (D ^ (B & (C ^ D))) + msg; \
53             B = ROTL32(B, 10);
54             #define STEP_F2(A, B, C, D, E, msg, rot) \
55             E += ROTL32(A, rot) + (B ^ C ^ D) + msg + 0x5A827999; \
56             B = ROTL32(B, 17);
57             #define STEP_F3(A, B, C, D, E, msg, rot) \
58             E += ROTL32(A, rot) + (C ^ (B | ~D)) + msg + 0x6ED9EBA1; \
59             B = ROTL32(B, 25);
60             #define STEP_F4(A, B, C, D, E, msg, rot) \
61             E += ROTL32(A, rot) + (B ^ C ^ D) + msg + 0x8F1BBCDC; \
62             B = ROTL32(B, 30);
63              
64             /**
65             * The core transformation. Process a 512-bit block.
66             *
67             * @param hash algorithm state
68             * @param block the message block to process
69             */
70 2           static void rhash_has160_process_block(unsigned* hash, const unsigned* block)
71             {
72             unsigned X[32];
73             {
74             unsigned j;
75 34 100         for (j = 0; j < 16; j++) {
76 32           X[j] = le2me_32(block[j]);
77             }
78              
79 2           X[16] = X[ 0] ^ X[ 1] ^ X[ 2] ^ X[ 3]; /* for rounds 1..20 */
80 2           X[17] = X[ 4] ^ X[ 5] ^ X[ 6] ^ X[ 7];
81 2           X[18] = X[ 8] ^ X[ 9] ^ X[10] ^ X[11];
82 2           X[19] = X[12] ^ X[13] ^ X[14] ^ X[15];
83 2           X[20] = X[ 3] ^ X[ 6] ^ X[ 9] ^ X[12]; /* for rounds 21..40 */
84 2           X[21] = X[ 2] ^ X[ 5] ^ X[ 8] ^ X[15];
85 2           X[22] = X[ 1] ^ X[ 4] ^ X[11] ^ X[14];
86 2           X[23] = X[ 0] ^ X[ 7] ^ X[10] ^ X[13];
87 2           X[24] = X[ 5] ^ X[ 7] ^ X[12] ^ X[14]; /* for rounds 41..60 */
88 2           X[25] = X[ 0] ^ X[ 2] ^ X[ 9] ^ X[11];
89 2           X[26] = X[ 4] ^ X[ 6] ^ X[13] ^ X[15];
90 2           X[27] = X[ 1] ^ X[ 3] ^ X[ 8] ^ X[10];
91 2           X[28] = X[ 2] ^ X[ 7] ^ X[ 8] ^ X[13]; /* for rounds 61..80 */
92 2           X[29] = X[ 3] ^ X[ 4] ^ X[ 9] ^ X[14];
93 2           X[30] = X[ 0] ^ X[ 5] ^ X[10] ^ X[15];
94 2           X[31] = X[ 1] ^ X[ 6] ^ X[11] ^ X[12];
95             }
96              
97              
98             {
99             unsigned A, B, C, D, E;
100              
101 2           A = hash[0];
102 2           B = hash[1];
103 2           C = hash[2];
104 2           D = hash[3];
105 2           E = hash[4];
106              
107 2           STEP_F1(A,B,C,D,E,X[18], 5);
108 2           STEP_F1(E,A,B,C,D,X[ 0],11);
109 2           STEP_F1(D,E,A,B,C,X[ 1], 7);
110 2           STEP_F1(C,D,E,A,B,X[ 2],15);
111 2           STEP_F1(B,C,D,E,A,X[ 3], 6);
112 2           STEP_F1(A,B,C,D,E,X[19],13);
113 2           STEP_F1(E,A,B,C,D,X[ 4], 8);
114 2           STEP_F1(D,E,A,B,C,X[ 5],14);
115 2           STEP_F1(C,D,E,A,B,X[ 6], 7);
116 2           STEP_F1(B,C,D,E,A,X[ 7],12);
117 2           STEP_F1(A,B,C,D,E,X[16], 9);
118 2           STEP_F1(E,A,B,C,D,X[ 8],11);
119 2           STEP_F1(D,E,A,B,C,X[ 9], 8);
120 2           STEP_F1(C,D,E,A,B,X[10],15);
121 2           STEP_F1(B,C,D,E,A,X[11], 6);
122 2           STEP_F1(A,B,C,D,E,X[17],12);
123 2           STEP_F1(E,A,B,C,D,X[12], 9);
124 2           STEP_F1(D,E,A,B,C,X[13],14);
125 2           STEP_F1(C,D,E,A,B,X[14], 5);
126 2           STEP_F1(B,C,D,E,A,X[15],13);
127              
128 2           STEP_F2(A,B,C,D,E,X[22], 5);
129 2           STEP_F2(E,A,B,C,D,X[ 3],11);
130 2           STEP_F2(D,E,A,B,C,X[ 6], 7);
131 2           STEP_F2(C,D,E,A,B,X[ 9],15);
132 2           STEP_F2(B,C,D,E,A,X[12], 6);
133 2           STEP_F2(A,B,C,D,E,X[23],13);
134 2           STEP_F2(E,A,B,C,D,X[15], 8);
135 2           STEP_F2(D,E,A,B,C,X[ 2],14);
136 2           STEP_F2(C,D,E,A,B,X[ 5], 7);
137 2           STEP_F2(B,C,D,E,A,X[ 8],12);
138 2           STEP_F2(A,B,C,D,E,X[20], 9);
139 2           STEP_F2(E,A,B,C,D,X[11],11);
140 2           STEP_F2(D,E,A,B,C,X[14], 8);
141 2           STEP_F2(C,D,E,A,B,X[ 1],15);
142 2           STEP_F2(B,C,D,E,A,X[ 4], 6);
143 2           STEP_F2(A,B,C,D,E,X[21],12);
144 2           STEP_F2(E,A,B,C,D,X[ 7], 9);
145 2           STEP_F2(D,E,A,B,C,X[10],14);
146 2           STEP_F2(C,D,E,A,B,X[13], 5);
147 2           STEP_F2(B,C,D,E,A,X[ 0],13);
148              
149 2           STEP_F3(A,B,C,D,E,X[26], 5);
150 2           STEP_F3(E,A,B,C,D,X[12],11);
151 2           STEP_F3(D,E,A,B,C,X[ 5], 7);
152 2           STEP_F3(C,D,E,A,B,X[14],15);
153 2           STEP_F3(B,C,D,E,A,X[ 7], 6);
154 2           STEP_F3(A,B,C,D,E,X[27],13);
155 2           STEP_F3(E,A,B,C,D,X[ 0], 8);
156 2           STEP_F3(D,E,A,B,C,X[ 9],14);
157 2           STEP_F3(C,D,E,A,B,X[ 2], 7);
158 2           STEP_F3(B,C,D,E,A,X[11],12);
159 2           STEP_F3(A,B,C,D,E,X[24], 9);
160 2           STEP_F3(E,A,B,C,D,X[ 4],11);
161 2           STEP_F3(D,E,A,B,C,X[13], 8);
162 2           STEP_F3(C,D,E,A,B,X[ 6],15);
163 2           STEP_F3(B,C,D,E,A,X[15], 6);
164 2           STEP_F3(A,B,C,D,E,X[25],12);
165 2           STEP_F3(E,A,B,C,D,X[ 8], 9);
166 2           STEP_F3(D,E,A,B,C,X[ 1],14);
167 2           STEP_F3(C,D,E,A,B,X[10], 5);
168 2           STEP_F3(B,C,D,E,A,X[ 3],13);
169              
170 2           STEP_F4(A,B,C,D,E,X[30], 5);
171 2           STEP_F4(E,A,B,C,D,X[ 7],11);
172 2           STEP_F4(D,E,A,B,C,X[ 2], 7);
173 2           STEP_F4(C,D,E,A,B,X[13],15);
174 2           STEP_F4(B,C,D,E,A,X[ 8], 6);
175 2           STEP_F4(A,B,C,D,E,X[31],13);
176 2           STEP_F4(E,A,B,C,D,X[ 3], 8);
177 2           STEP_F4(D,E,A,B,C,X[14],14);
178 2           STEP_F4(C,D,E,A,B,X[ 9], 7);
179 2           STEP_F4(B,C,D,E,A,X[ 4],12);
180 2           STEP_F4(A,B,C,D,E,X[28], 9);
181 2           STEP_F4(E,A,B,C,D,X[15],11);
182 2           STEP_F4(D,E,A,B,C,X[10], 8);
183 2           STEP_F4(C,D,E,A,B,X[ 5],15);
184 2           STEP_F4(B,C,D,E,A,X[ 0], 6);
185 2           STEP_F4(A,B,C,D,E,X[29],12);
186 2           STEP_F4(E,A,B,C,D,X[11], 9);
187 2           STEP_F4(D,E,A,B,C,X[ 6],14);
188 2           STEP_F4(C,D,E,A,B,X[ 1], 5);
189 2           STEP_F4(B,C,D,E,A,X[12],13);
190              
191 2           hash[0] += A;
192 2           hash[1] += B;
193 2           hash[2] += C;
194 2           hash[3] += D;
195 2           hash[4] += E;
196             }
197 2           }
198              
199             /**
200             * Calculate message hash.
201             * Can be called repeatedly with chunks of the message to be hashed.
202             *
203             * @param ctx the algorithm context containing current hashing state
204             * @param msg message chunk
205             * @param size length of the message chunk
206             */
207 2           void rhash_has160_update(has160_ctx* ctx, const unsigned char* msg, size_t size)
208             {
209 2           unsigned index = (unsigned)ctx->length & 63;
210 2           ctx->length += size;
211              
212             /* fill partial block */
213 2 50         if (index) {
214 0           unsigned left = has160_block_size - index;
215 0           memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
216 0 0         if (size < left) return;
217              
218             /* process partial block */
219 0           rhash_has160_process_block(ctx->hash, ctx->message);
220 0           msg += left;
221 0           size -= left;
222             }
223 2 50         while (size >= has160_block_size) {
224             unsigned* aligned_message_block;
225 0 0         if (IS_ALIGNED_32(msg)) {
226             /* the most common case is processing a 32-bit aligned message
227             without copying it */
228 0           aligned_message_block = (unsigned*)msg;
229             } else {
230 0           memcpy(ctx->message, msg, has160_block_size);
231 0           aligned_message_block = ctx->message;
232             }
233              
234 0           rhash_has160_process_block(ctx->hash, aligned_message_block);
235 0           msg += has160_block_size;
236 0           size -= has160_block_size;
237             }
238 2 50         if (size) {
239             /* save leftovers */
240 2           memcpy(ctx->message, msg, size);
241             }
242             }
243              
244             /**
245             * Compute and save calculated hash into the given array.
246             *
247             * @param ctx the algorithm context containing current hashing state
248             * @param result calculated hash in binary form
249             */
250 2           void rhash_has160_final(has160_ctx* ctx, unsigned char* result)
251             {
252 2           unsigned shift = ((unsigned)ctx->length & 3) * 8;
253 2           unsigned index = ((unsigned)ctx->length & 63) >> 2;
254              
255             /* pad message and run for last block */
256             #if IS_LITTLE_ENDIAN
257 2           ctx->message[index] &= ~(0xFFFFFFFFu << shift);
258 2           ctx->message[index++] ^= 0x80u << shift;
259             #else
260             ctx->message[index] &= ~(0xFFFFFFFFu >> shift);
261             ctx->message[index++] ^= 0x80000000u >> shift;
262             #endif
263              
264             /* if no room left in the message to store 64-bit message length */
265 2 50         if (index > 14) {
266             /* then fill the rest with zeros and process it */
267 0 0         while (index < 16) {
268 0           ctx->message[index++] = 0;
269             }
270 0           rhash_has160_process_block(ctx->hash, ctx->message);
271 0           index = 0;
272             }
273 28 100         while (index < 14) {
274 26           ctx->message[index++] = 0;
275             }
276 2           ctx->message[14] = le2me_32( (unsigned)(ctx->length << 3) );
277 2           ctx->message[15] = le2me_32( (unsigned)(ctx->length >> 29) );
278 2           rhash_has160_process_block(ctx->hash, ctx->message);
279              
280 2           le32_copy(result, 0, &ctx->hash, has160_hash_size);
281 2           }