1 /*
2 * This software is Copyright (c) 2017 magnum
3 * and it is hereby released to the general public under the following terms:
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted.
7 */
8
9 #ifndef _OPENCL_SHA2_CTX_H
10 #define _OPENCL_SHA2_CTX_H
11
12 #include "opencl_misc.h"
13 #include "opencl_sha2.h"
14
15 #ifndef MAYBE_VOLATILE
16 #define MAYBE_VOLATILE
17 #endif
18
19 /*
20 * SHA-256 context setup
21 */
22
23 typedef struct {
24 uint total; /* number of bytes processed */
25 uint state[8]; /* intermediate digest state */
26 uchar buffer[64]; /* data block being processed */
27 } SHA256_CTX;
28
29 inline
SHA256_Init(SHA256_CTX * ctx)30 void SHA256_Init(SHA256_CTX *ctx) {
31 uint i;
32
33 ctx->total = 0;
34
35 for (i = 0; i < 8; i++)
36 ctx->state[i] = h[i];
37 }
38
39 inline
_sha256_process(SHA256_CTX * ctx,const uchar data[64])40 void _sha256_process(SHA256_CTX *ctx, const uchar data[64]) {
41 MAYBE_VOLATILE uint t, W[16], A, B, C, D, E, F, G, H;
42
43 #if gpu_nvidia(DEVICE_INFO)
44 if (!((size_t)data & 0x03)) {
45 GET_UINT32BE_ALIGNED(W[ 0], data, 0);
46 GET_UINT32BE_ALIGNED(W[ 1], data, 4);
47 GET_UINT32BE_ALIGNED(W[ 2], data, 8);
48 GET_UINT32BE_ALIGNED(W[ 3], data, 12);
49 GET_UINT32BE_ALIGNED(W[ 4], data, 16);
50 GET_UINT32BE_ALIGNED(W[ 5], data, 20);
51 GET_UINT32BE_ALIGNED(W[ 6], data, 24);
52 GET_UINT32BE_ALIGNED(W[ 7], data, 28);
53 GET_UINT32BE_ALIGNED(W[ 8], data, 32);
54 GET_UINT32BE_ALIGNED(W[ 9], data, 36);
55 GET_UINT32BE_ALIGNED(W[10], data, 40);
56 GET_UINT32BE_ALIGNED(W[11], data, 44);
57 GET_UINT32BE_ALIGNED(W[12], data, 48);
58 GET_UINT32BE_ALIGNED(W[13], data, 52);
59 GET_UINT32BE_ALIGNED(W[14], data, 56);
60 GET_UINT32BE_ALIGNED(W[15], data, 60);
61 } else
62 #endif
63 {
64 GET_UINT32BE(W[ 0], data, 0);
65 GET_UINT32BE(W[ 1], data, 4);
66 GET_UINT32BE(W[ 2], data, 8);
67 GET_UINT32BE(W[ 3], data, 12);
68 GET_UINT32BE(W[ 4], data, 16);
69 GET_UINT32BE(W[ 5], data, 20);
70 GET_UINT32BE(W[ 6], data, 24);
71 GET_UINT32BE(W[ 7], data, 28);
72 GET_UINT32BE(W[ 8], data, 32);
73 GET_UINT32BE(W[ 9], data, 36);
74 GET_UINT32BE(W[10], data, 40);
75 GET_UINT32BE(W[11], data, 44);
76 GET_UINT32BE(W[12], data, 48);
77 GET_UINT32BE(W[13], data, 52);
78 GET_UINT32BE(W[14], data, 56);
79 GET_UINT32BE(W[15], data, 60);
80 }
81
82 A = ctx->state[0];
83 B = ctx->state[1];
84 C = ctx->state[2];
85 D = ctx->state[3];
86 E = ctx->state[4];
87 F = ctx->state[5];
88 G = ctx->state[6];
89 H = ctx->state[7];
90
91 SHA256(A, B, C, D, E, F, G, H, W);
92
93 ctx->state[0] += A;
94 ctx->state[1] += B;
95 ctx->state[2] += C;
96 ctx->state[3] += D;
97 ctx->state[4] += E;
98 ctx->state[5] += F;
99 ctx->state[6] += G;
100 ctx->state[7] += H;
101 }
102
103 /*
104 * SHA-256 process buffer
105 */
106 inline
SHA256_Update(SHA256_CTX * ctx,const uchar * input,uint ilen)107 void SHA256_Update(SHA256_CTX *ctx, const uchar *input, uint ilen) {
108 uint fill;
109 uint left;
110
111 if (ilen <= 0)
112 return;
113
114 left = ctx->total & 0x3F;
115 fill = 64 - left;
116
117 ctx->total += ilen;
118
119 if (left && ilen >= fill)
120 {
121 memcpy_pp(ctx->buffer + left, input, fill);
122 _sha256_process(ctx, ctx->buffer);
123 input += fill;
124 ilen -= fill;
125 left = 0;
126 }
127
128 while(ilen >= 64)
129 {
130 _sha256_process(ctx, input);
131 input += 64;
132 ilen -= 64;
133 }
134
135 if (ilen > 0)
136 {
137 memcpy_pp(ctx->buffer + left, input, ilen);
138 }
139 }
140
141 /*
142 * SHA-256 final digest
143 */
144 inline
SHA256_Final(uchar output[32],SHA256_CTX * ctx)145 void SHA256_Final(uchar output[32], SHA256_CTX *ctx) {
146 uint last, padn;
147 ulong bits;
148 uchar msglen[8];
149 uchar sha256_padding[64] = { 0x80 /* , 0, 0 ... */ };
150
151 bits = ctx->total << 3;
152
153 PUT_UINT64BE(bits, msglen, 0);
154
155 last = ctx->total & 0x3F;
156 padn = (last < 56) ? (56 - last) : (120 - last);
157
158 SHA256_Update(ctx, sha256_padding, padn);
159 SHA256_Update(ctx, msglen, 8);
160
161 #if gpu_nvidia(DEVICE_INFO)
162 if (!((size_t)output & 0x03)) {
163 PUT_UINT32BE_ALIGNED(ctx->state[0], output, 0);
164 PUT_UINT32BE_ALIGNED(ctx->state[1], output, 4);
165 PUT_UINT32BE_ALIGNED(ctx->state[2], output, 8);
166 PUT_UINT32BE_ALIGNED(ctx->state[3], output, 12);
167 PUT_UINT32BE_ALIGNED(ctx->state[4], output, 16);
168 PUT_UINT32BE_ALIGNED(ctx->state[5], output, 20);
169 PUT_UINT32BE_ALIGNED(ctx->state[6], output, 24);
170 PUT_UINT32BE_ALIGNED(ctx->state[7], output, 28);
171 } else
172 #endif
173 {
174 PUT_UINT32BE(ctx->state[0], output, 0);
175 PUT_UINT32BE(ctx->state[1], output, 4);
176 PUT_UINT32BE(ctx->state[2], output, 8);
177 PUT_UINT32BE(ctx->state[3], output, 12);
178 PUT_UINT32BE(ctx->state[4], output, 16);
179 PUT_UINT32BE(ctx->state[5], output, 20);
180 PUT_UINT32BE(ctx->state[6], output, 24);
181 PUT_UINT32BE(ctx->state[7], output, 28);
182 }
183 }
184
185 /*
186 * SHA-512 context setup
187 */
188
189 typedef struct {
190 uint total; /* number of bytes processed */
191 ulong state[8]; /* intermediate digest state */
192 uchar buffer[128]; /* data block being processed */
193 } SHA512_CTX;
194
195 inline
SHA512_Init(SHA512_CTX * ctx)196 void SHA512_Init(SHA512_CTX *ctx) {
197 ctx->total = 0;
198 ctx->state[0] = SHA2_INIT_A;
199 ctx->state[1] = SHA2_INIT_B;
200 ctx->state[2] = SHA2_INIT_C;
201 ctx->state[3] = SHA2_INIT_D;
202 ctx->state[4] = SHA2_INIT_E;
203 ctx->state[5] = SHA2_INIT_F;
204 ctx->state[6] = SHA2_INIT_G;
205 ctx->state[7] = SHA2_INIT_H;
206 }
207
208 inline
_sha512_process(SHA512_CTX * ctx,const uchar data[128])209 void _sha512_process(SHA512_CTX *ctx, const uchar data[128]) {
210 ulong t, W[16], A, B, C, D, E, F, G, H;
211
212 #if gpu_nvidia(DEVICE_INFO)
213 if (!((size_t)data & 0x07)) {
214 GET_UINT64BE_ALIGNED(W[ 0], data, 0);
215 GET_UINT64BE_ALIGNED(W[ 1], data, 8);
216 GET_UINT64BE_ALIGNED(W[ 2], data, 16);
217 GET_UINT64BE_ALIGNED(W[ 3], data, 24);
218 GET_UINT64BE_ALIGNED(W[ 4], data, 32);
219 GET_UINT64BE_ALIGNED(W[ 5], data, 40);
220 GET_UINT64BE_ALIGNED(W[ 6], data, 48);
221 GET_UINT64BE_ALIGNED(W[ 7], data, 56);
222 GET_UINT64BE_ALIGNED(W[ 8], data, 64);
223 GET_UINT64BE_ALIGNED(W[ 9], data, 72);
224 GET_UINT64BE_ALIGNED(W[10], data, 80);
225 GET_UINT64BE_ALIGNED(W[11], data, 88);
226 GET_UINT64BE_ALIGNED(W[12], data, 96);
227 GET_UINT64BE_ALIGNED(W[13], data, 104);
228 GET_UINT64BE_ALIGNED(W[14], data, 112);
229 GET_UINT64BE_ALIGNED(W[15], data, 120);
230 } else
231 #endif
232 {
233 GET_UINT64BE(W[ 0], data, 0);
234 GET_UINT64BE(W[ 1], data, 8);
235 GET_UINT64BE(W[ 2], data, 16);
236 GET_UINT64BE(W[ 3], data, 24);
237 GET_UINT64BE(W[ 4], data, 32);
238 GET_UINT64BE(W[ 5], data, 40);
239 GET_UINT64BE(W[ 6], data, 48);
240 GET_UINT64BE(W[ 7], data, 56);
241 GET_UINT64BE(W[ 8], data, 64);
242 GET_UINT64BE(W[ 9], data, 72);
243 GET_UINT64BE(W[10], data, 80);
244 GET_UINT64BE(W[11], data, 88);
245 GET_UINT64BE(W[12], data, 96);
246 GET_UINT64BE(W[13], data, 104);
247 GET_UINT64BE(W[14], data, 112);
248 GET_UINT64BE(W[15], data, 120);
249 }
250
251 A = ctx->state[0];
252 B = ctx->state[1];
253 C = ctx->state[2];
254 D = ctx->state[3];
255 E = ctx->state[4];
256 F = ctx->state[5];
257 G = ctx->state[6];
258 H = ctx->state[7];
259
260 SHA512(A, B, C, D, E, F, G, H, W);
261
262 ctx->state[0] += A;
263 ctx->state[1] += B;
264 ctx->state[2] += C;
265 ctx->state[3] += D;
266 ctx->state[4] += E;
267 ctx->state[5] += F;
268 ctx->state[6] += G;
269 ctx->state[7] += H;
270 }
271
272 /*
273 * SHA-512 process buffer
274 */
275 inline
SHA512_Update(SHA512_CTX * ctx,const uchar * input,uint ilen)276 void SHA512_Update(SHA512_CTX *ctx, const uchar *input, uint ilen) {
277 uint fill;
278 uint left;
279
280 if (ilen <= 0)
281 return;
282
283 left = ctx->total & 0x7F;
284 fill = 128 - left;
285
286 ctx->total += ilen;
287
288 if (left && ilen >= fill)
289 {
290 memcpy_pp(ctx->buffer + left, input, fill);
291 _sha512_process(ctx, ctx->buffer);
292 input += fill;
293 ilen -= fill;
294 left = 0;
295 }
296
297 while(ilen >= 128)
298 {
299 _sha512_process(ctx, input);
300 input += 128;
301 ilen -= 128;
302 }
303
304 if (ilen > 0)
305 {
306 memcpy_pp(ctx->buffer + left, input, ilen);
307 }
308 }
309
310 /*
311 * SHA-512 final digest
312 */
313 inline
SHA512_Final(uchar output[64],SHA512_CTX * ctx)314 void SHA512_Final(uchar output[64], SHA512_CTX *ctx) {
315 uint last, padn;
316 ulong bits;
317 uchar msglen[16];
318 uchar sha512_padding[128] = { 0x80 /* , 0, 0 ... */ };
319
320 bits = ctx->total << 3;
321
322 PUT_UINT64BE(0UL, msglen, 0);
323 PUT_UINT64BE(bits, msglen, 8);
324
325 last = ctx->total & 0x7F;
326 padn = (last < 112) ? (112 - last) : (240 - last);
327
328 SHA512_Update(ctx, sha512_padding, padn);
329 SHA512_Update(ctx, msglen, 16);
330
331 #if gpu_nvidia(DEVICE_INFO)
332 if (!((size_t)output & 0x07)) {
333 PUT_UINT64BE_ALIGNED(ctx->state[0], output, 0);
334 PUT_UINT64BE_ALIGNED(ctx->state[1], output, 8);
335 PUT_UINT64BE_ALIGNED(ctx->state[2], output, 16);
336 PUT_UINT64BE_ALIGNED(ctx->state[3], output, 24);
337 PUT_UINT64BE_ALIGNED(ctx->state[4], output, 32);
338 PUT_UINT64BE_ALIGNED(ctx->state[5], output, 40);
339 PUT_UINT64BE_ALIGNED(ctx->state[6], output, 48);
340 PUT_UINT64BE_ALIGNED(ctx->state[7], output, 56);
341 } else
342 #endif
343 {
344 PUT_UINT64BE(ctx->state[0], output, 0);
345 PUT_UINT64BE(ctx->state[1], output, 8);
346 PUT_UINT64BE(ctx->state[2], output, 16);
347 PUT_UINT64BE(ctx->state[3], output, 24);
348 PUT_UINT64BE(ctx->state[4], output, 32);
349 PUT_UINT64BE(ctx->state[5], output, 40);
350 PUT_UINT64BE(ctx->state[6], output, 48);
351 PUT_UINT64BE(ctx->state[7], output, 56);
352 }
353 }
354
355 #endif /* _OPENCL_SHA2_CTX_H */
356