digest-whirlpool 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +42 -0
- data/README.rdoc +22 -0
- data/ext/digest/whirlpool/depend +6 -0
- data/ext/digest/whirlpool/extconf.rb +10 -0
- data/ext/digest/whirlpool/whirlpool-algorithm.c +473 -0
- data/ext/digest/whirlpool/whirlpool-algorithm.h +86 -0
- data/ext/digest/whirlpool/whirlpool-constants.h +1116 -0
- data/ext/digest/whirlpool/whirlpool-portability.h +142 -0
- data/ext/digest/whirlpool/whirlpool.c +49 -0
- metadata +67 -0
data/LICENSE
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
whirlpool-algorithm.c:
|
2
|
+
whirlpool-algorithm.h:
|
3
|
+
whirlpool-constants.h:
|
4
|
+
whirlpool-portability.h:
|
5
|
+
|
6
|
+
These files are under the new-style BSD license.
|
7
|
+
|
8
|
+
Copyright (c) 2006, Hongli Lai
|
9
|
+
All rights reserved.
|
10
|
+
|
11
|
+
Redistribution and use in source and binary forms, with or without
|
12
|
+
modification, are permitted provided that the following conditions
|
13
|
+
are met:
|
14
|
+
|
15
|
+
1. Redistributions of source code must retain the above copyright
|
16
|
+
notice, this list of conditions and the following disclaimer.
|
17
|
+
|
18
|
+
2. Redistributions in binary form must reproduce the above copyright
|
19
|
+
notice, this list of conditions and the following disclaimer in the
|
20
|
+
documentation and/or other materials provided with the distribution.
|
21
|
+
|
22
|
+
3. Neither the name of Hongli Lai nor the names of its contributors
|
23
|
+
may be used to endorse or promote products derived from this
|
24
|
+
software without specific prior written permission.
|
25
|
+
|
26
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
27
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
28
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
29
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
30
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
31
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
32
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
33
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
34
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
35
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
36
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
37
|
+
|
38
|
+
For the rest:
|
39
|
+
|
40
|
+
You can redistribute and/or modify it under the same terms as Ruby.
|
41
|
+
|
42
|
+
Copyright (c) 2006, 2009 Akinori MUSHA <knu@iDaemons.org>
|
data/README.rdoc
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
= Digest::Whirlpool - Ruby interface to the Whirlpool message digest algorithm
|
2
|
+
|
3
|
+
== Summary
|
4
|
+
|
5
|
+
Digest::Whirlpool is a Ruby library for calculating message digests
|
6
|
+
using the Whirlpool algorithm. The library interface corforms to the
|
7
|
+
standard Digest API.
|
8
|
+
|
9
|
+
More information about Whirlpool:
|
10
|
+
http://en.wikipedia.org/wiki/Whirlpool_%28algorithm%29
|
11
|
+
http://planeta.terra.com.br/informatica/paulobarreto/WhirlpoolPage.html
|
12
|
+
|
13
|
+
The C code is based on the sample implementation, as available on the
|
14
|
+
mentioned website.
|
15
|
+
|
16
|
+
== Requirements
|
17
|
+
|
18
|
+
- Ruby 1.8.6 or later
|
19
|
+
|
20
|
+
== License
|
21
|
+
|
22
|
+
See the file LICENSE.
|
@@ -0,0 +1,6 @@
|
|
1
|
+
whirlpool-algorithm.o: whirlpool-algorithm.c whirlpool-algorithm.h \
|
2
|
+
whirlpool-portability.h whirlpool-constants.h
|
3
|
+
whirlpool.o: whirlpool.c whirlpool-algorithm.h whirlpool-portability.h \
|
4
|
+
whirlpool-constants.h \
|
5
|
+
$(hdrdir)/digest.h $(hdrdir)/ruby.h \
|
6
|
+
$(topdir)/config.h $(hdrdir)/defines.h $(hdrdir)/intern.h
|
@@ -0,0 +1,473 @@
|
|
1
|
+
/**
|
2
|
+
* The Whirlpool hashing function.
|
3
|
+
*
|
4
|
+
* The Whirlpool algorithm was developed by
|
5
|
+
* Paulo S. L. M. Barreto and Vincent Rijmen.
|
6
|
+
*
|
7
|
+
* See
|
8
|
+
* P.S.L.M. Barreto, V. Rijmen,
|
9
|
+
* ``The Whirlpool hashing function,''
|
10
|
+
* NESSIE submission, 2000 (tweaked version, 2001),
|
11
|
+
* <https://www.cosic.esat.kuleuven.ac.be/nessie/workshop/submissions/whirlpool.zip>
|
12
|
+
*
|
13
|
+
* @version 3.0 (2003.03.12)
|
14
|
+
*
|
15
|
+
* Modified for use in this software package.
|
16
|
+
*/
|
17
|
+
#include <stdlib.h>
|
18
|
+
#include <string.h>
|
19
|
+
#include <limits.h>
|
20
|
+
#include "whirlpool-algorithm.h"
|
21
|
+
#include "whirlpool-portability.h"
|
22
|
+
#include "whirlpool-constants.h"
|
23
|
+
|
24
|
+
#ifdef __cplusplus
|
25
|
+
extern "C" {
|
26
|
+
#endif
|
27
|
+
|
28
|
+
|
29
|
+
/**
|
30
|
+
* The core Whirlpool transform.
|
31
|
+
*/
|
32
|
+
static void
|
33
|
+
processBuffer(WP_Struct * const structpointer) {
|
34
|
+
int i, r;
|
35
|
+
u64 K[8]; /* the round key */
|
36
|
+
u64 block[8]; /* mu(buffer) */
|
37
|
+
u64 state[8]; /* the cipher state */
|
38
|
+
u64 L[8];
|
39
|
+
u8 *buffer = structpointer->buffer;
|
40
|
+
|
41
|
+
/*
|
42
|
+
* map the buffer to a block:
|
43
|
+
*/
|
44
|
+
for (i = 0; i < 8; i++, buffer += 8) {
|
45
|
+
block[i] =
|
46
|
+
(((u64)buffer[0] ) << 56) ^
|
47
|
+
(((u64)buffer[1] & 0xffL) << 48) ^
|
48
|
+
(((u64)buffer[2] & 0xffL) << 40) ^
|
49
|
+
(((u64)buffer[3] & 0xffL) << 32) ^
|
50
|
+
(((u64)buffer[4] & 0xffL) << 24) ^
|
51
|
+
(((u64)buffer[5] & 0xffL) << 16) ^
|
52
|
+
(((u64)buffer[6] & 0xffL) << 8) ^
|
53
|
+
(((u64)buffer[7] & 0xffL) );
|
54
|
+
}
|
55
|
+
/*
|
56
|
+
* compute and apply K^0 to the cipher state:
|
57
|
+
*/
|
58
|
+
state[0] = block[0] ^ (K[0] = structpointer->hash[0]);
|
59
|
+
state[1] = block[1] ^ (K[1] = structpointer->hash[1]);
|
60
|
+
state[2] = block[2] ^ (K[2] = structpointer->hash[2]);
|
61
|
+
state[3] = block[3] ^ (K[3] = structpointer->hash[3]);
|
62
|
+
state[4] = block[4] ^ (K[4] = structpointer->hash[4]);
|
63
|
+
state[5] = block[5] ^ (K[5] = structpointer->hash[5]);
|
64
|
+
state[6] = block[6] ^ (K[6] = structpointer->hash[6]);
|
65
|
+
state[7] = block[7] ^ (K[7] = structpointer->hash[7]);
|
66
|
+
|
67
|
+
/*
|
68
|
+
* iterate over all rounds:
|
69
|
+
*/
|
70
|
+
for (r = 1; r <= R; r++) {
|
71
|
+
/*
|
72
|
+
* compute K^r from K^{r-1}:
|
73
|
+
*/
|
74
|
+
L[0] =
|
75
|
+
C0[(int)(K[0] >> 56) ] ^
|
76
|
+
C1[(int)(K[7] >> 48) & 0xff] ^
|
77
|
+
C2[(int)(K[6] >> 40) & 0xff] ^
|
78
|
+
C3[(int)(K[5] >> 32) & 0xff] ^
|
79
|
+
C4[(int)(K[4] >> 24) & 0xff] ^
|
80
|
+
C5[(int)(K[3] >> 16) & 0xff] ^
|
81
|
+
C6[(int)(K[2] >> 8) & 0xff] ^
|
82
|
+
C7[(int)(K[1] ) & 0xff] ^
|
83
|
+
rc[r];
|
84
|
+
L[1] =
|
85
|
+
C0[(int)(K[1] >> 56) ] ^
|
86
|
+
C1[(int)(K[0] >> 48) & 0xff] ^
|
87
|
+
C2[(int)(K[7] >> 40) & 0xff] ^
|
88
|
+
C3[(int)(K[6] >> 32) & 0xff] ^
|
89
|
+
C4[(int)(K[5] >> 24) & 0xff] ^
|
90
|
+
C5[(int)(K[4] >> 16) & 0xff] ^
|
91
|
+
C6[(int)(K[3] >> 8) & 0xff] ^
|
92
|
+
C7[(int)(K[2] ) & 0xff];
|
93
|
+
L[2] =
|
94
|
+
C0[(int)(K[2] >> 56) ] ^
|
95
|
+
C1[(int)(K[1] >> 48) & 0xff] ^
|
96
|
+
C2[(int)(K[0] >> 40) & 0xff] ^
|
97
|
+
C3[(int)(K[7] >> 32) & 0xff] ^
|
98
|
+
C4[(int)(K[6] >> 24) & 0xff] ^
|
99
|
+
C5[(int)(K[5] >> 16) & 0xff] ^
|
100
|
+
C6[(int)(K[4] >> 8) & 0xff] ^
|
101
|
+
C7[(int)(K[3] ) & 0xff];
|
102
|
+
L[3] =
|
103
|
+
C0[(int)(K[3] >> 56) ] ^
|
104
|
+
C1[(int)(K[2] >> 48) & 0xff] ^
|
105
|
+
C2[(int)(K[1] >> 40) & 0xff] ^
|
106
|
+
C3[(int)(K[0] >> 32) & 0xff] ^
|
107
|
+
C4[(int)(K[7] >> 24) & 0xff] ^
|
108
|
+
C5[(int)(K[6] >> 16) & 0xff] ^
|
109
|
+
C6[(int)(K[5] >> 8) & 0xff] ^
|
110
|
+
C7[(int)(K[4] ) & 0xff];
|
111
|
+
L[4] =
|
112
|
+
C0[(int)(K[4] >> 56) ] ^
|
113
|
+
C1[(int)(K[3] >> 48) & 0xff] ^
|
114
|
+
C2[(int)(K[2] >> 40) & 0xff] ^
|
115
|
+
C3[(int)(K[1] >> 32) & 0xff] ^
|
116
|
+
C4[(int)(K[0] >> 24) & 0xff] ^
|
117
|
+
C5[(int)(K[7] >> 16) & 0xff] ^
|
118
|
+
C6[(int)(K[6] >> 8) & 0xff] ^
|
119
|
+
C7[(int)(K[5] ) & 0xff];
|
120
|
+
L[5] =
|
121
|
+
C0[(int)(K[5] >> 56) ] ^
|
122
|
+
C1[(int)(K[4] >> 48) & 0xff] ^
|
123
|
+
C2[(int)(K[3] >> 40) & 0xff] ^
|
124
|
+
C3[(int)(K[2] >> 32) & 0xff] ^
|
125
|
+
C4[(int)(K[1] >> 24) & 0xff] ^
|
126
|
+
C5[(int)(K[0] >> 16) & 0xff] ^
|
127
|
+
C6[(int)(K[7] >> 8) & 0xff] ^
|
128
|
+
C7[(int)(K[6] ) & 0xff];
|
129
|
+
L[6] =
|
130
|
+
C0[(int)(K[6] >> 56) ] ^
|
131
|
+
C1[(int)(K[5] >> 48) & 0xff] ^
|
132
|
+
C2[(int)(K[4] >> 40) & 0xff] ^
|
133
|
+
C3[(int)(K[3] >> 32) & 0xff] ^
|
134
|
+
C4[(int)(K[2] >> 24) & 0xff] ^
|
135
|
+
C5[(int)(K[1] >> 16) & 0xff] ^
|
136
|
+
C6[(int)(K[0] >> 8) & 0xff] ^
|
137
|
+
C7[(int)(K[7] ) & 0xff];
|
138
|
+
L[7] =
|
139
|
+
C0[(int)(K[7] >> 56) ] ^
|
140
|
+
C1[(int)(K[6] >> 48) & 0xff] ^
|
141
|
+
C2[(int)(K[5] >> 40) & 0xff] ^
|
142
|
+
C3[(int)(K[4] >> 32) & 0xff] ^
|
143
|
+
C4[(int)(K[3] >> 24) & 0xff] ^
|
144
|
+
C5[(int)(K[2] >> 16) & 0xff] ^
|
145
|
+
C6[(int)(K[1] >> 8) & 0xff] ^
|
146
|
+
C7[(int)(K[0] ) & 0xff];
|
147
|
+
K[0] = L[0];
|
148
|
+
K[1] = L[1];
|
149
|
+
K[2] = L[2];
|
150
|
+
K[3] = L[3];
|
151
|
+
K[4] = L[4];
|
152
|
+
K[5] = L[5];
|
153
|
+
K[6] = L[6];
|
154
|
+
K[7] = L[7];
|
155
|
+
/*
|
156
|
+
* apply the r-th round transformation:
|
157
|
+
*/
|
158
|
+
L[0] =
|
159
|
+
C0[(int)(state[0] >> 56) ] ^
|
160
|
+
C1[(int)(state[7] >> 48) & 0xff] ^
|
161
|
+
C2[(int)(state[6] >> 40) & 0xff] ^
|
162
|
+
C3[(int)(state[5] >> 32) & 0xff] ^
|
163
|
+
C4[(int)(state[4] >> 24) & 0xff] ^
|
164
|
+
C5[(int)(state[3] >> 16) & 0xff] ^
|
165
|
+
C6[(int)(state[2] >> 8) & 0xff] ^
|
166
|
+
C7[(int)(state[1] ) & 0xff] ^
|
167
|
+
K[0];
|
168
|
+
L[1] =
|
169
|
+
C0[(int)(state[1] >> 56) ] ^
|
170
|
+
C1[(int)(state[0] >> 48) & 0xff] ^
|
171
|
+
C2[(int)(state[7] >> 40) & 0xff] ^
|
172
|
+
C3[(int)(state[6] >> 32) & 0xff] ^
|
173
|
+
C4[(int)(state[5] >> 24) & 0xff] ^
|
174
|
+
C5[(int)(state[4] >> 16) & 0xff] ^
|
175
|
+
C6[(int)(state[3] >> 8) & 0xff] ^
|
176
|
+
C7[(int)(state[2] ) & 0xff] ^
|
177
|
+
K[1];
|
178
|
+
L[2] =
|
179
|
+
C0[(int)(state[2] >> 56) ] ^
|
180
|
+
C1[(int)(state[1] >> 48) & 0xff] ^
|
181
|
+
C2[(int)(state[0] >> 40) & 0xff] ^
|
182
|
+
C3[(int)(state[7] >> 32) & 0xff] ^
|
183
|
+
C4[(int)(state[6] >> 24) & 0xff] ^
|
184
|
+
C5[(int)(state[5] >> 16) & 0xff] ^
|
185
|
+
C6[(int)(state[4] >> 8) & 0xff] ^
|
186
|
+
C7[(int)(state[3] ) & 0xff] ^
|
187
|
+
K[2];
|
188
|
+
L[3] =
|
189
|
+
C0[(int)(state[3] >> 56) ] ^
|
190
|
+
C1[(int)(state[2] >> 48) & 0xff] ^
|
191
|
+
C2[(int)(state[1] >> 40) & 0xff] ^
|
192
|
+
C3[(int)(state[0] >> 32) & 0xff] ^
|
193
|
+
C4[(int)(state[7] >> 24) & 0xff] ^
|
194
|
+
C5[(int)(state[6] >> 16) & 0xff] ^
|
195
|
+
C6[(int)(state[5] >> 8) & 0xff] ^
|
196
|
+
C7[(int)(state[4] ) & 0xff] ^
|
197
|
+
K[3];
|
198
|
+
L[4] =
|
199
|
+
C0[(int)(state[4] >> 56) ] ^
|
200
|
+
C1[(int)(state[3] >> 48) & 0xff] ^
|
201
|
+
C2[(int)(state[2] >> 40) & 0xff] ^
|
202
|
+
C3[(int)(state[1] >> 32) & 0xff] ^
|
203
|
+
C4[(int)(state[0] >> 24) & 0xff] ^
|
204
|
+
C5[(int)(state[7] >> 16) & 0xff] ^
|
205
|
+
C6[(int)(state[6] >> 8) & 0xff] ^
|
206
|
+
C7[(int)(state[5] ) & 0xff] ^
|
207
|
+
K[4];
|
208
|
+
L[5] =
|
209
|
+
C0[(int)(state[5] >> 56) ] ^
|
210
|
+
C1[(int)(state[4] >> 48) & 0xff] ^
|
211
|
+
C2[(int)(state[3] >> 40) & 0xff] ^
|
212
|
+
C3[(int)(state[2] >> 32) & 0xff] ^
|
213
|
+
C4[(int)(state[1] >> 24) & 0xff] ^
|
214
|
+
C5[(int)(state[0] >> 16) & 0xff] ^
|
215
|
+
C6[(int)(state[7] >> 8) & 0xff] ^
|
216
|
+
C7[(int)(state[6] ) & 0xff] ^
|
217
|
+
K[5];
|
218
|
+
L[6] =
|
219
|
+
C0[(int)(state[6] >> 56) ] ^
|
220
|
+
C1[(int)(state[5] >> 48) & 0xff] ^
|
221
|
+
C2[(int)(state[4] >> 40) & 0xff] ^
|
222
|
+
C3[(int)(state[3] >> 32) & 0xff] ^
|
223
|
+
C4[(int)(state[2] >> 24) & 0xff] ^
|
224
|
+
C5[(int)(state[1] >> 16) & 0xff] ^
|
225
|
+
C6[(int)(state[0] >> 8) & 0xff] ^
|
226
|
+
C7[(int)(state[7] ) & 0xff] ^
|
227
|
+
K[6];
|
228
|
+
L[7] =
|
229
|
+
C0[(int)(state[7] >> 56) ] ^
|
230
|
+
C1[(int)(state[6] >> 48) & 0xff] ^
|
231
|
+
C2[(int)(state[5] >> 40) & 0xff] ^
|
232
|
+
C3[(int)(state[4] >> 32) & 0xff] ^
|
233
|
+
C4[(int)(state[3] >> 24) & 0xff] ^
|
234
|
+
C5[(int)(state[2] >> 16) & 0xff] ^
|
235
|
+
C6[(int)(state[1] >> 8) & 0xff] ^
|
236
|
+
C7[(int)(state[0] ) & 0xff] ^
|
237
|
+
K[7];
|
238
|
+
state[0] = L[0];
|
239
|
+
state[1] = L[1];
|
240
|
+
state[2] = L[2];
|
241
|
+
state[3] = L[3];
|
242
|
+
state[4] = L[4];
|
243
|
+
state[5] = L[5];
|
244
|
+
state[6] = L[6];
|
245
|
+
state[7] = L[7];
|
246
|
+
}
|
247
|
+
|
248
|
+
/*
|
249
|
+
* apply the Miyaguchi-Preneel compression function:
|
250
|
+
*/
|
251
|
+
structpointer->hash[0] ^= state[0] ^ block[0];
|
252
|
+
structpointer->hash[1] ^= state[1] ^ block[1];
|
253
|
+
structpointer->hash[2] ^= state[2] ^ block[2];
|
254
|
+
structpointer->hash[3] ^= state[3] ^ block[3];
|
255
|
+
structpointer->hash[4] ^= state[4] ^ block[4];
|
256
|
+
structpointer->hash[5] ^= state[5] ^ block[5];
|
257
|
+
structpointer->hash[6] ^= state[6] ^ block[6];
|
258
|
+
structpointer->hash[7] ^= state[7] ^ block[7];
|
259
|
+
}
|
260
|
+
|
261
|
+
WP_Struct *
|
262
|
+
WP_Create() {
|
263
|
+
WP_Struct *wp;
|
264
|
+
|
265
|
+
wp = (WP_Struct *) malloc(sizeof(WP_Struct));
|
266
|
+
if (wp != NULL) {
|
267
|
+
WP_Init(wp);
|
268
|
+
}
|
269
|
+
return wp;
|
270
|
+
}
|
271
|
+
|
272
|
+
void
|
273
|
+
WP_Init(WP_Struct *wp) {
|
274
|
+
int i;
|
275
|
+
|
276
|
+
memset(wp->bitLength, 0, 32);
|
277
|
+
wp->bufferBits = wp->bufferPos = 0;
|
278
|
+
wp->buffer[0] = 0; /* it's only necessary to cleanup buffer[bufferPos] */
|
279
|
+
for (i = 0; i < 8; i++) {
|
280
|
+
wp->hash[i] = 0L; /* initial value */
|
281
|
+
}
|
282
|
+
}
|
283
|
+
|
284
|
+
void WP_Add(const unsigned char * const source,
|
285
|
+
unsigned long sourceBits,
|
286
|
+
WP_Struct * const structpointer) {
|
287
|
+
/*
|
288
|
+
sourcePos
|
289
|
+
|
|
290
|
+
+-------+-------+-------
|
291
|
+
||||||||||||||||||||| source
|
292
|
+
+-------+-------+-------
|
293
|
+
+-------+-------+-------+-------+-------+-------
|
294
|
+
|||||||||||||||||||||| buffer
|
295
|
+
+-------+-------+-------+-------+-------+-------
|
296
|
+
|
|
297
|
+
bufferPos
|
298
|
+
*/
|
299
|
+
int sourcePos = 0; /* index of leftmost source u8 containing data (1 to 8 bits). */
|
300
|
+
int sourceGap = (8 - ((int)sourceBits & 7)) & 7; /* space on source[sourcePos]. */
|
301
|
+
int bufferRem = structpointer->bufferBits & 7; /* occupied bits on buffer[bufferPos]. */
|
302
|
+
int i;
|
303
|
+
u32 b, carry;
|
304
|
+
u8 *buffer = structpointer->buffer;
|
305
|
+
u8 *bitLength = structpointer->bitLength;
|
306
|
+
int bufferBits = structpointer->bufferBits;
|
307
|
+
int bufferPos = structpointer->bufferPos;
|
308
|
+
|
309
|
+
/*
|
310
|
+
* This method maintains the invariant: bufferBits < DIGESTBITS
|
311
|
+
*/
|
312
|
+
|
313
|
+
/*
|
314
|
+
* tally the length of the added data:
|
315
|
+
*/
|
316
|
+
u64 value = sourceBits;
|
317
|
+
for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != LL(0)); i--) {
|
318
|
+
carry += bitLength[i] + ((u32)value & 0xff);
|
319
|
+
bitLength[i] = (u8)carry;
|
320
|
+
carry >>= 8;
|
321
|
+
value >>= 8;
|
322
|
+
}
|
323
|
+
/*
|
324
|
+
* process data in chunks of 8 bits (a more efficient approach would be to take whole-word chunks):
|
325
|
+
*/
|
326
|
+
while (sourceBits > 8) {
|
327
|
+
/* N.B. at least source[sourcePos] and source[sourcePos+1] contain data. */
|
328
|
+
/*
|
329
|
+
* take a byte from the source:
|
330
|
+
*/
|
331
|
+
b = ((source[sourcePos] << sourceGap) & 0xff) |
|
332
|
+
((source[sourcePos + 1] & 0xff) >> (8 - sourceGap));
|
333
|
+
/*
|
334
|
+
* process this byte:
|
335
|
+
*/
|
336
|
+
buffer[bufferPos++] |= (u8)(b >> bufferRem);
|
337
|
+
bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */
|
338
|
+
if (bufferBits == DIGESTBITS) {
|
339
|
+
/*
|
340
|
+
* process data block:
|
341
|
+
*/
|
342
|
+
processBuffer(structpointer);
|
343
|
+
/*
|
344
|
+
* reset buffer:
|
345
|
+
*/
|
346
|
+
bufferBits = bufferPos = 0;
|
347
|
+
}
|
348
|
+
buffer[bufferPos] = b << (8 - bufferRem);
|
349
|
+
bufferBits += bufferRem;
|
350
|
+
/*
|
351
|
+
* proceed to remaining data:
|
352
|
+
*/
|
353
|
+
sourceBits -= 8;
|
354
|
+
sourcePos++;
|
355
|
+
}
|
356
|
+
/* now 0 <= sourceBits <= 8;
|
357
|
+
* furthermore, all data (if any is left) is in source[sourcePos].
|
358
|
+
*/
|
359
|
+
if (sourceBits > 0) {
|
360
|
+
b = (source[sourcePos] << sourceGap) & 0xff; /* bits are left-justified on b. */
|
361
|
+
/*
|
362
|
+
* process the remaining bits:
|
363
|
+
*/
|
364
|
+
buffer[bufferPos] |= b >> bufferRem;
|
365
|
+
} else {
|
366
|
+
b = 0;
|
367
|
+
}
|
368
|
+
if (bufferRem + sourceBits < 8) {
|
369
|
+
/*
|
370
|
+
* all remaining data fits on buffer[bufferPos],
|
371
|
+
* and there still remains some space.
|
372
|
+
*/
|
373
|
+
bufferBits += sourceBits;
|
374
|
+
} else {
|
375
|
+
/*
|
376
|
+
* buffer[bufferPos] is full:
|
377
|
+
*/
|
378
|
+
bufferPos++;
|
379
|
+
bufferBits += 8 - bufferRem; /* bufferBits = 8*bufferPos; */
|
380
|
+
sourceBits -= 8 - bufferRem;
|
381
|
+
/* now 0 <= sourceBits < 8;
|
382
|
+
* furthermore, all data (if any is left) is in source[sourcePos].
|
383
|
+
*/
|
384
|
+
if (bufferBits == DIGESTBITS) {
|
385
|
+
/*
|
386
|
+
* process data block:
|
387
|
+
*/
|
388
|
+
processBuffer(structpointer);
|
389
|
+
/*
|
390
|
+
* reset buffer:
|
391
|
+
*/
|
392
|
+
bufferBits = bufferPos = 0;
|
393
|
+
}
|
394
|
+
buffer[bufferPos] = b << (8 - bufferRem);
|
395
|
+
bufferBits += (int)sourceBits;
|
396
|
+
}
|
397
|
+
structpointer->bufferBits = bufferBits;
|
398
|
+
structpointer->bufferPos = bufferPos;
|
399
|
+
}
|
400
|
+
|
401
|
+
void WP_Finalize(WP_Struct * const structpointer,
|
402
|
+
unsigned char * const result) {
|
403
|
+
int i;
|
404
|
+
u8 *buffer = structpointer->buffer;
|
405
|
+
u8 *bitLength = structpointer->bitLength;
|
406
|
+
int bufferBits = structpointer->bufferBits;
|
407
|
+
int bufferPos = structpointer->bufferPos;
|
408
|
+
u8 *digest = result;
|
409
|
+
|
410
|
+
/*
|
411
|
+
* This method uses the invariant: bufferBits < DIGESTBITS
|
412
|
+
*/
|
413
|
+
|
414
|
+
/*
|
415
|
+
* append a '1'-bit:
|
416
|
+
*/
|
417
|
+
buffer[bufferPos] |= 0x80U >> (bufferBits & 7);
|
418
|
+
bufferPos++; /* all remaining bits on the current u8 are set to zero. */
|
419
|
+
/*
|
420
|
+
* pad with zero bits to complete (N*WBLOCKBITS - LENGTHBITS) bits:
|
421
|
+
*/
|
422
|
+
if (bufferPos > WBLOCKBYTES - LENGTHBYTES) {
|
423
|
+
if (bufferPos < WBLOCKBYTES) {
|
424
|
+
memset(&buffer[bufferPos], 0, WBLOCKBYTES - bufferPos);
|
425
|
+
}
|
426
|
+
/*
|
427
|
+
* process data block:
|
428
|
+
*/
|
429
|
+
processBuffer(structpointer);
|
430
|
+
/*
|
431
|
+
* reset buffer:
|
432
|
+
*/
|
433
|
+
bufferPos = 0;
|
434
|
+
}
|
435
|
+
if (bufferPos < WBLOCKBYTES - LENGTHBYTES) {
|
436
|
+
memset(&buffer[bufferPos], 0, (WBLOCKBYTES - LENGTHBYTES) - bufferPos);
|
437
|
+
}
|
438
|
+
bufferPos = WBLOCKBYTES - LENGTHBYTES;
|
439
|
+
/*
|
440
|
+
* append bit length of hashed data:
|
441
|
+
*/
|
442
|
+
memcpy(&buffer[WBLOCKBYTES - LENGTHBYTES], bitLength, LENGTHBYTES);
|
443
|
+
/*
|
444
|
+
* process data block:
|
445
|
+
*/
|
446
|
+
processBuffer(structpointer);
|
447
|
+
/*
|
448
|
+
* return the completed message digest:
|
449
|
+
*/
|
450
|
+
for (i = 0; i < DIGESTBYTES/8; i++) {
|
451
|
+
digest[0] = (u8)(structpointer->hash[i] >> 56);
|
452
|
+
digest[1] = (u8)(structpointer->hash[i] >> 48);
|
453
|
+
digest[2] = (u8)(structpointer->hash[i] >> 40);
|
454
|
+
digest[3] = (u8)(structpointer->hash[i] >> 32);
|
455
|
+
digest[4] = (u8)(structpointer->hash[i] >> 24);
|
456
|
+
digest[5] = (u8)(structpointer->hash[i] >> 16);
|
457
|
+
digest[6] = (u8)(structpointer->hash[i] >> 8);
|
458
|
+
digest[7] = (u8)(structpointer->hash[i] );
|
459
|
+
digest += 8;
|
460
|
+
}
|
461
|
+
structpointer->bufferBits = bufferBits;
|
462
|
+
structpointer->bufferPos = bufferPos;
|
463
|
+
}
|
464
|
+
|
465
|
+
void
|
466
|
+
WP_Free(WP_Struct *wp) {
|
467
|
+
free(wp);
|
468
|
+
}
|
469
|
+
|
470
|
+
|
471
|
+
#ifdef __cplusplus
|
472
|
+
}
|
473
|
+
#endif
|