Changelog update
[public/netxms.git] / src / libnetxms / sha2.cpp
1 /*
2 * FIPS 180-2 SHA-224/256/384/512 implementation
3 * Last update: 02/02/2007
4 * Issue date: 04/30/2005
5 *
6 * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #define UNROLL_LOOPS /* Enable loops unrolling */
35
36 #include "libnetxms.h"
37 #include "sha2.h"
38
39 #define SHFR(x, n) (x >> n)
40 #define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
41 #define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
42 #define CH(x, y, z) ((x & y) ^ (~x & z))
43 #define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
44
45 #define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
46 #define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
47 #define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
48 #define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
49
50 #define UNPACK32(x, str) \
51 { \
52 *((str) + 3) = (BYTE) ((x) ); \
53 *((str) + 2) = (BYTE) ((x) >> 8); \
54 *((str) + 1) = (BYTE) ((x) >> 16); \
55 *((str) + 0) = (BYTE) ((x) >> 24); \
56 }
57
58 #define PACK32(str, x) \
59 { \
60 *(x) = ((UINT32) *((str) + 3) ) \
61 | ((UINT32) *((str) + 2) << 8) \
62 | ((UINT32) *((str) + 1) << 16) \
63 | ((UINT32) *((str) + 0) << 24); \
64 }
65
66 #define UNPACK64(x, str) \
67 { \
68 *((str) + 7) = (BYTE) ((x) ); \
69 *((str) + 6) = (BYTE) ((x) >> 8); \
70 *((str) + 5) = (BYTE) ((x) >> 16); \
71 *((str) + 4) = (BYTE) ((x) >> 24); \
72 *((str) + 3) = (BYTE) ((x) >> 32); \
73 *((str) + 2) = (BYTE) ((x) >> 40); \
74 *((str) + 1) = (BYTE) ((x) >> 48); \
75 *((str) + 0) = (BYTE) ((x) >> 56); \
76 }
77
78 #define PACK64(str, x) \
79 { \
80 *(x) = ((uint64) *((str) + 7) ) \
81 | ((uint64) *((str) + 6) << 8) \
82 | ((uint64) *((str) + 5) << 16) \
83 | ((uint64) *((str) + 4) << 24) \
84 | ((uint64) *((str) + 3) << 32) \
85 | ((uint64) *((str) + 2) << 40) \
86 | ((uint64) *((str) + 1) << 48) \
87 | ((uint64) *((str) + 0) << 56); \
88 }
89
90 /* Macros used for loops unrolling */
91
92 #define SHA256_SCR(i) \
93 { \
94 w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
95 + SHA256_F3(w[i - 15]) + w[i - 16]; \
96 }
97
98 #define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
99 { \
100 t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
101 + sha256_k[j] + w[j]; \
102 t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
103 wv[d] += t1; \
104 wv[h] = t1 + t2; \
105 }
106
107 UINT32 sha256_h0[8] =
108 {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
109 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
110
111 UINT32 sha256_k[64] =
112 {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
113 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
114 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
115 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
116 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
117 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
118 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
119 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
120 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
121 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
122 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
123 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
124 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
125 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
126 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
127 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
128
129 /* SHA-256 functions */
130
131 static void sha256_transf(sha256_ctx *ctx, const unsigned char *message, unsigned int block_nb)
132 {
133 UINT32 w[64];
134 UINT32 wv[8];
135 UINT32 t1, t2;
136 const unsigned char *sub_block;
137 int i;
138
139 #ifndef UNROLL_LOOPS
140 int j;
141 #endif
142
143 for (i = 0; i < (int) block_nb; i++) {
144 sub_block = message + (i << 6);
145
146 #ifndef UNROLL_LOOPS
147 for (j = 0; j < 16; j++) {
148 PACK32(&sub_block[j << 2], &w[j]);
149 }
150
151 for (j = 16; j < 64; j++) {
152 SHA256_SCR(j);
153 }
154
155 for (j = 0; j < 8; j++) {
156 wv[j] = ctx->h[j];
157 }
158
159 for (j = 0; j < 64; j++) {
160 t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
161 + sha256_k[j] + w[j];
162 t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
163 wv[7] = wv[6];
164 wv[6] = wv[5];
165 wv[5] = wv[4];
166 wv[4] = wv[3] + t1;
167 wv[3] = wv[2];
168 wv[2] = wv[1];
169 wv[1] = wv[0];
170 wv[0] = t1 + t2;
171 }
172
173 for (j = 0; j < 8; j++) {
174 ctx->h[j] += wv[j];
175 }
176 #else
177 PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
178 PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
179 PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
180 PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
181 PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
182 PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
183 PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
184 PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
185
186 SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
187 SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
188 SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
189 SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
190 SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
191 SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
192 SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
193 SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
194 SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
195 SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
196 SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
197 SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
198
199 wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
200 wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
201 wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
202 wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
203
204 SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
205 SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
206 SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
207 SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
208 SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
209 SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
210 SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
211 SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
212 SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
213 SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
214 SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
215 SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
216 SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
217 SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
218 SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
219 SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
220 SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
221 SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
222 SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
223 SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
224 SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
225 SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
226 SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
227 SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
228 SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
229 SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
230 SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
231 SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
232 SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
233 SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
234 SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
235 SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
236
237 ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
238 ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
239 ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
240 ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
241 #endif /* !UNROLL_LOOPS */
242 }
243 }
244
245 void I_sha256_init(sha256_ctx *ctx)
246 {
247 #ifndef UNROLL_LOOPS
248 int i;
249 for (i = 0; i < 8; i++) {
250 ctx->h[i] = sha256_h0[i];
251 }
252 #else
253 ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
254 ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
255 ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
256 ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
257 #endif /* !UNROLL_LOOPS */
258
259 ctx->len = 0;
260 ctx->tot_len = 0;
261 }
262
263 void I_sha256_update(sha256_ctx *ctx, const unsigned char *message, unsigned int len)
264 {
265 unsigned int block_nb;
266 unsigned int new_len, rem_len, tmp_len;
267 const unsigned char *shifted_message;
268
269 tmp_len = SHA256_BLOCK_SIZE - ctx->len;
270 rem_len = len < tmp_len ? len : tmp_len;
271
272 memcpy(&ctx->block[ctx->len], message, rem_len);
273
274 if (ctx->len + len < SHA256_BLOCK_SIZE) {
275 ctx->len += len;
276 return;
277 }
278
279 new_len = len - rem_len;
280 block_nb = new_len / SHA256_BLOCK_SIZE;
281
282 shifted_message = message + rem_len;
283
284 sha256_transf(ctx, ctx->block, 1);
285 sha256_transf(ctx, shifted_message, block_nb);
286
287 rem_len = new_len % SHA256_BLOCK_SIZE;
288
289 memcpy(ctx->block, &shifted_message[block_nb << 6],
290 rem_len);
291
292 ctx->len = rem_len;
293 ctx->tot_len += (block_nb + 1) << 6;
294 }
295
296 void I_sha256_final(sha256_ctx *ctx, unsigned char *digest)
297 {
298 unsigned int block_nb;
299 unsigned int pm_len;
300 unsigned int len_b;
301
302 #ifndef UNROLL_LOOPS
303 int i;
304 #endif
305
306 block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
307 < (ctx->len % SHA256_BLOCK_SIZE)));
308
309 len_b = (ctx->tot_len + ctx->len) << 3;
310 pm_len = block_nb << 6;
311
312 memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
313 ctx->block[ctx->len] = 0x80;
314 UNPACK32(len_b, ctx->block + pm_len - 4);
315
316 sha256_transf(ctx, ctx->block, block_nb);
317
318 #ifndef UNROLL_LOOPS
319 for (i = 0 ; i < 8; i++) {
320 UNPACK32(ctx->h[i], &digest[i << 2]);
321 }
322 #else
323 UNPACK32(ctx->h[0], &digest[ 0]);
324 UNPACK32(ctx->h[1], &digest[ 4]);
325 UNPACK32(ctx->h[2], &digest[ 8]);
326 UNPACK32(ctx->h[3], &digest[12]);
327 UNPACK32(ctx->h[4], &digest[16]);
328 UNPACK32(ctx->h[5], &digest[20]);
329 UNPACK32(ctx->h[6], &digest[24]);
330 UNPACK32(ctx->h[7], &digest[28]);
331 #endif /* !UNROLL_LOOPS */
332 }