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