1 /*
2  * This software is
3  * Copyright (c) 2018 magnum
4  * and it is hereby released to the general public under the following terms:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted.
8  */
9 
10 #ifndef _OPENCL_MD4_CTX_H
11 #define _OPENCL_MD4_CTX_H
12 
13 #include "opencl_misc.h"
14 #include "opencl_md4.h"
15 
16 typedef struct {
17 	uint total;        /* number of bytes processed  */
18 	uint state[4];     /* intermediate digest state  */
19 	uchar buffer[64];  /* data block being processed */
20 } MD4_CTX;
21 
22 #ifndef __MESA__
23 inline
24 #endif
_md4_process(MD4_CTX * ctx,const uchar data[64])25 void _md4_process(MD4_CTX *ctx, const uchar data[64]) {
26 	uint W[16], A, B, C, D;
27 
28 #if gpu_nvidia(DEVICE_INFO)
29 	if (!((size_t)data & 0x03)) {
30 		GET_UINT32_ALIGNED(W[ 0], data,  0);
31 		GET_UINT32_ALIGNED(W[ 1], data,  4);
32 		GET_UINT32_ALIGNED(W[ 2], data,  8);
33 		GET_UINT32_ALIGNED(W[ 3], data, 12);
34 		GET_UINT32_ALIGNED(W[ 4], data, 16);
35 		GET_UINT32_ALIGNED(W[ 5], data, 20);
36 		GET_UINT32_ALIGNED(W[ 6], data, 24);
37 		GET_UINT32_ALIGNED(W[ 7], data, 28);
38 		GET_UINT32_ALIGNED(W[ 8], data, 32);
39 		GET_UINT32_ALIGNED(W[ 9], data, 36);
40 		GET_UINT32_ALIGNED(W[10], data, 40);
41 		GET_UINT32_ALIGNED(W[11], data, 44);
42 		GET_UINT32_ALIGNED(W[12], data, 48);
43 		GET_UINT32_ALIGNED(W[13], data, 52);
44 		GET_UINT32_ALIGNED(W[14], data, 56);
45 		GET_UINT32_ALIGNED(W[15], data, 60);
46 	} else
47 #endif
48 	{
49 		GET_UINT32(W[ 0], data,  0);
50 		GET_UINT32(W[ 1], data,  4);
51 		GET_UINT32(W[ 2], data,  8);
52 		GET_UINT32(W[ 3], data, 12);
53 		GET_UINT32(W[ 4], data, 16);
54 		GET_UINT32(W[ 5], data, 20);
55 		GET_UINT32(W[ 6], data, 24);
56 		GET_UINT32(W[ 7], data, 28);
57 		GET_UINT32(W[ 8], data, 32);
58 		GET_UINT32(W[ 9], data, 36);
59 		GET_UINT32(W[10], data, 40);
60 		GET_UINT32(W[11], data, 44);
61 		GET_UINT32(W[12], data, 48);
62 		GET_UINT32(W[13], data, 52);
63 		GET_UINT32(W[14], data, 56);
64 		GET_UINT32(W[15], data, 60);
65 	}
66 
67 	A = ctx->state[0];
68 	B = ctx->state[1];
69 	C = ctx->state[2];
70 	D = ctx->state[3];
71 
72 	MD4(A, B, C, D, W);
73 
74 	ctx->state[0] += A;
75 	ctx->state[1] += B;
76 	ctx->state[2] += C;
77 	ctx->state[3] += D;
78 }
79 
80 /*
81  * MD4 context setup
82  */
83 #ifndef __MESA__
84 inline
85 #endif
MD4_Init(MD4_CTX * ctx)86 void MD4_Init(MD4_CTX *ctx) {
87 	ctx->total = 0;
88 
89 	ctx->state[0] = 0x67452301;
90 	ctx->state[1] = 0xefcdab89;
91 	ctx->state[2] = 0x98badcfe;
92 	ctx->state[3] = 0x10325476;
93 }
94 
95 /*
96  * MD4 process buffer
97  */
98 #ifndef __MESA__
99 inline
100 #endif
MD4_Update(MD4_CTX * ctx,const uchar * input,uint ilen)101 void MD4_Update(MD4_CTX *ctx, const uchar *input, uint ilen) {
102 	uint fill;
103 	uint left;
104 
105 	if (ilen <= 0)
106 		return;
107 
108 	left = ctx->total & 0x3F;
109 	fill = 64 - left;
110 
111 	ctx->total += ilen;
112 
113 	if (left && ilen >= fill)
114 	{
115 		memcpy_pp(ctx->buffer + left, input, fill);
116 		_md4_process(ctx, ctx->buffer);
117 		input += fill;
118 		ilen  -= fill;
119 		left = 0;
120 	}
121 
122 	while(ilen >= 64)
123 	{
124 		_md4_process(ctx, input);
125 		input += 64;
126 		ilen  -= 64;
127 	}
128 
129 	if (ilen > 0)
130 	{
131 		memcpy_pp(ctx->buffer + left, input, ilen);
132 	}
133 }
134 
135 /*
136  * MD4 final digest
137  */
138 #ifndef __MESA__
139 inline
140 #endif
MD4_Final(uchar output[20],MD4_CTX * ctx)141 void MD4_Final(uchar output[20], MD4_CTX *ctx) {
142 	uint last, padn;
143 	ulong bits;
144 	uchar msglen[8];
145 	uchar md4_padding[64] = { 0x80 /* , 0, 0 ... */ };
146 
147 	bits = ctx->total <<  3;
148 
149 	PUT_UINT64(bits, msglen, 0);
150 
151 	last = ctx->total & 0x3F;
152 	padn = (last < 56) ? (56 - last) : (120 - last);
153 
154 	MD4_Update(ctx, md4_padding, padn);
155 	MD4_Update(ctx, msglen, 8);
156 
157 #if gpu_nvidia(DEVICE_INFO)
158 	if (!((size_t)output & 0x03)) {
159 		PUT_UINT32_ALIGNED(ctx->state[0], output,  0);
160 		PUT_UINT32_ALIGNED(ctx->state[1], output,  4);
161 		PUT_UINT32_ALIGNED(ctx->state[2], output,  8);
162 		PUT_UINT32_ALIGNED(ctx->state[3], output, 12);
163 	} else
164 #endif
165 	{
166 		PUT_UINT32(ctx->state[0], output,  0);
167 		PUT_UINT32(ctx->state[1], output,  4);
168 		PUT_UINT32(ctx->state[2], output,  8);
169 		PUT_UINT32(ctx->state[3], output, 12);
170 	}
171 }
172 
173 #endif /* _OPENCL_MD4_CTX_H */
174