OpenCores
URL https://opencores.org/ocsvn/bluespec_md6/bluespec_md6/trunk

Subversion Repositories bluespec_md6

[/] [bluespec_md6/] [trunk/] [C_implementation/] [md6_compress.c] - Blame information for rev 9

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 kfleming
/* File:    md6_compress.c
2
** Author:  Ronald L. Rivest
3
**          (with optimizations by Jayant Krishnamurthy)
4
** Address: Room 32G-692 Stata Center
5
**          32 Vassar Street
6
**          Cambridge, MA 02139
7
** Email:   rivest@mit.edu
8
** Date:    9/25/2008
9
**
10
** (The following license is known as "The MIT License")
11
**
12
** Copyright (c) 2008 Ronald L. Rivest and Jayant Krishnamurthy
13
**
14
** Permission is hereby granted, free of charge, to any person obtaining a copy
15
** of this software and associated documentation files (the "Software"), to deal
16
** in the Software without restriction, including without limitation the rights
17
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
** copies of the Software, and to permit persons to whom the Software is
19
** furnished to do so, subject to the following conditions:
20
**
21
** The above copyright notice and this permission notice shall be included in
22
** all copies or substantial portions of the Software.
23
**
24
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30
** THE SOFTWARE.
31
**
32
** (end of license)
33
**
34
** This is part of the definition of the MD6 hash function.
35
** The files defining the md6 hash function are:
36
**    md6.h
37
**    md6_compress.c
38
**    md6_mode.c
39
**
40
** The files defining the interface between MD6 and the NIST SHA-3
41
** API are:
42
**    md6_nist.h
43
**    md6_nist.c
44
** The NIST SHA-3 API is defined in:
45
**    http://www.csrc.nist.gov/groups/ST/hash/documents/SHA3-C-API.pdf
46
**
47
** See  http://groups.csail.mit.edu/cis/md6  for more information.
48
**
49
*/
50
 
51
#include <stdio.h>
52
#include <stdlib.h>
53
#include <string.h>
54
 
55
#include "md6.h"
56
 
57
/* Useful macros: min and max */
58
#ifndef min
59
#define min(a,b) ((a)<(b)? (a) : (b))
60
#endif
61
#ifndef max
62
#define max(a,b) ((a)>(b)? (a) : (b))
63
#endif
64
 
65
/* Variables defining lengths of various values */
66
#define   w   md6_w  /* # bits in a word (64) */
67
#define   n   md6_n  /* # words in compression input (89) */
68
#define   c   md6_c  /* # words in compression output (16) */
69
#define   b   md6_b  /* # message words per compression input block (64) */
70
#define   v   md6_v  /* # words in control word (1) */
71
#define   u   md6_u  /* # words in unique nodeID (1) */
72
#define   k   md6_k  /* # key words per compression input block (8) */
73
#define   q   md6_q  /* # Q words per compression input block (15) */
74
 
75
 
76
/* "Tap positions" for feedback shift-register */
77
 
78
#if (n==89)
79
#define  t0   17     /* index for linear feedback */
80
#define  t1   18     /* index for first input to first and */
81
#define  t2   21     /* index for second input to first and */
82
#define  t3   31     /* index for first input to second and */
83
#define  t4   67     /* index for second input to second and */
84
#define  t5   89     /* last tap */
85
#endif
86
 
87
/* Loop-unrolling setup.
88
**
89
** Define macros for loop-unrolling within compression function
90
** These expand to:     loop_body(right-shift,left-shift,step)
91
** These are given for word sizes 64, 32, 16, and 8, although
92
** only w=64 is needed for the standard MD6 definition.
93
**
94
** Also given for each word size are the constants S0 and Smask
95
** needed in the recurrence for round constants.
96
*/
97
 
98
#if (w==64)                        /* for standard word size */
99
#define RL00 loop_body(10,11, 0)
100
#define RL01 loop_body( 5,24, 1)
101
#define RL02 loop_body(13, 9, 2)
102
#define RL03 loop_body(10,16, 3)
103
#define RL04 loop_body(11,15, 4)
104
#define RL05 loop_body(12, 9, 5)
105
#define RL06 loop_body( 2,27, 6)
106
#define RL07 loop_body( 7,15, 7)
107
#define RL08 loop_body(14, 6, 8)
108
#define RL09 loop_body(15, 2, 9)
109
#define RL10 loop_body( 7,29,10)
110
#define RL11 loop_body(13, 8,11)
111
#define RL12 loop_body(11,15,12)
112
#define RL13 loop_body( 7, 5,13)
113
#define RL14 loop_body( 6,31,14)
114
#define RL15 loop_body(12, 9,15)
115
 
116
const md6_word S0 = (md6_word)0x0123456789abcdefULL;
117
const md6_word Smask = (md6_word)0x7311c2812425cfa0ULL;
118
 
119
#elif (w==32)                      /* for variant word size */
120
#define RL00 loop_body( 5, 4, 0)
121
#define RL01 loop_body( 3, 7, 1)
122
#define RL02 loop_body( 6, 7, 2)
123
#define RL03 loop_body( 5, 9, 3)
124
#define RL04 loop_body( 4,13, 4)
125
#define RL05 loop_body( 6, 8, 5)
126
#define RL06 loop_body( 7, 4, 6)
127
#define RL07 loop_body( 3,14, 7)
128
#define RL08 loop_body( 5, 7, 8)
129
#define RL09 loop_body( 6, 4, 9)
130
#define RL10 loop_body( 5, 8,10)
131
#define RL11 loop_body( 5,11,11)
132
#define RL12 loop_body( 4, 5,12)
133
#define RL13 loop_body( 6, 8,13)
134
#define RL14 loop_body( 7, 2,14)
135
#define RL15 loop_body( 5,11,15)
136
 
137
const md6_word S0 = (md6_word)0x01234567UL;
138
const md6_word Smask = (md6_word)0x7311c281UL;
139
 
140
/* Loop-unrolling setup (continued).
141
**
142
*/
143
 
144
#elif (w==16)                      /* for variant word size */
145
 
146
#define RL00 loop_body( 5, 6, 0)
147
#define RL01 loop_body( 4, 7, 1)
148
#define RL02 loop_body( 3, 2, 2)
149
#define RL03 loop_body( 5, 4, 3)
150
#define RL04 loop_body( 7, 2, 4)
151
#define RL05 loop_body( 5, 6, 5)
152
#define RL06 loop_body( 5, 3, 6)
153
#define RL07 loop_body( 2, 7, 7)
154
#define RL08 loop_body( 4, 5, 8)
155
#define RL09 loop_body( 3, 7, 9)
156
#define RL10 loop_body( 4, 6,10)
157
#define RL11 loop_body( 3, 5,11)
158
#define RL12 loop_body( 4, 5,12)
159
#define RL13 loop_body( 7, 6,13)
160
#define RL14 loop_body( 7, 4,14)
161
#define RL15 loop_body( 2, 3,15)
162
 
163
const md6_word S0 = (md6_word)0x01234;
164
const md6_word Smask = (md6_word)0x7311;
165
 
166
#elif (w==8)                     /* for variant word size */
167
 
168
#define RL00 loop_body( 3, 2, 0)
169
#define RL01 loop_body( 3, 4, 1)
170
#define RL02 loop_body( 3, 2, 2)
171
#define RL03 loop_body( 4, 3, 3)
172
#define RL04 loop_body( 3, 2, 4)
173
#define RL05 loop_body( 3, 2, 5)
174
#define RL06 loop_body( 3, 2, 6)
175
#define RL07 loop_body( 3, 4, 7)
176
#define RL08 loop_body( 2, 3, 8)
177
#define RL09 loop_body( 2, 3, 9)
178
#define RL10 loop_body( 3, 2,10)
179
#define RL11 loop_body( 2, 3,11)
180
#define RL12 loop_body( 2, 3,12)
181
#define RL13 loop_body( 3, 4,13)
182
#define RL14 loop_body( 2, 3,14)
183
#define RL15 loop_body( 3, 4,15)
184
 
185
const md6_word S0 = (md6_word)0x01;
186
const md6_word Smask = (md6_word)0x73;
187
 
188
#endif
189
 
190
/* Main compression loop.
191
**
192
*/
193
 
194
void md6_main_compression_loop( md6_word* A , int r )
195
/*
196
** Perform the md6 "main compression loop" on the array A.
197
** This is where most of the computation occurs; it is the "heart"
198
** of the md6 compression algorithm.
199
** Input:
200
**     A                  input array of length t+n already set up
201
**                        with input in the first n words.
202
**     r                  number of rounds to run (178); each is c steps
203
** Modifies:
204
**     A                  A[n..r*c+n-1] filled in.
205
*/
206
{ md6_word x, S;
207
  int i,j;
208
 
209
  /*
210
  ** main computation loop for md6 compression
211
  */
212
  S = S0;
213
  for (j = 0, i = n; j<r*c; j+=c)
214
    {
215
 
216
/* ***************************************************************** */
217
#define loop_body(rs,ls,step)                                       \
218
      x = S;                                /* feedback constant     */ \
219
      x ^= A[i+step-t5];                    /* end-around feedback   */ \
220
      x ^= A[i+step-t0];                    /* linear feedback       */ \
221
      x ^= ( A[i+step-t1] & A[i+step-t2] ); /* first quadratic term  */ \
222
      x ^= ( A[i+step-t3] & A[i+step-t4] ); /* second quadratic term */ \
223
      x ^= (x >> rs);                       /* right-shift           */ \
224
      A[i+step] = x ^ (x << ls);            /* left-shift            */
225
/* ***************************************************************** */
226
 
227
      /*
228
      ** Unroll loop c=16 times. (One "round" of computation.)
229
      ** Shift amounts are embedded in macros RLnn.
230
      */
231
      RL00 RL01 RL02 RL03 RL04 RL05 RL06 RL07
232
      RL08 RL09 RL10 RL11 RL12 RL13 RL14 RL15
233
 
234
      /* Advance round constant S to the next round constant. */
235
      S = (S << 1) ^ (S >> (w-1)) ^ (S & Smask);
236
      i += 16;
237
    }
238
}
239
 
240
/* ``Bare'' compression routine.
241
**
242
** Compresses n-word input to c-word output.
243
*/
244
 
245
int md6_compress( md6_word *C,
246
                  md6_word *N,
247
                  int r,
248
                  md6_word *A
249
                 )
250
/* Assumes n-word input array N has been fully set up.
251
** Input:
252
**   N               input array of n w-bit words (n=89)
253
**   A               working array of a = rc+n w-bit words
254
**                   A is OPTIONAL, may be given as NULL
255
**                   (then md6_compress allocates and uses its own A).
256
**   r               number of rounds
257
** Modifies:
258
**   C               output array of c w-bit words (c=16)
259
** Returns one of the following:
260
**   MD6_SUCCESS (0)
261
**   MD6_NULL_N
262
**   MD6_NULL_C
263
**   MD6_BAD_r
264
**   MD6_OUT_OF_MEMORY
265
*/
266
{ md6_word* A_as_given = A;
267
 
268
  /* check that input is sensible */
269
  if ( N == NULL) return MD6_NULL_N;
270
  if ( C == NULL) return MD6_NULL_C;
271
  if ( r<0 || r > md6_max_r) return MD6_BAD_r;
272
 
273
  if ( A == NULL) A = calloc(r*c+n,sizeof(md6_word));
274
  if ( A == NULL) return MD6_OUT_OF_MEMORY;
275
 
276
  memcpy( A, N, n*sizeof(md6_word) );    /* copy N to front of A */
277
 
278
  md6_main_compression_loop( A, r );          /* do all the work */
279
 
280
  memcpy( C, A+(r-1)*c+n, c*sizeof(md6_word) ); /* output into C */
281
 
282
  if ( A_as_given == NULL )           /* zero and free A if nec. */
283
    { memset(A,0,(r*c+n)*sizeof(md6_word)); /* contains key info */
284
      free(A);
285
    }
286
 
287
  return MD6_SUCCESS;
288
}
289
 
290
/* Control words.
291
*/
292
 
293
md6_control_word md6_make_control_word( int r,
294
                                        int L,
295
                                        int z,
296
                                        int p,
297
                                        int keylen,
298
                                        int d
299
                                        )
300
/* Construct control word V for given inputs.
301
** Input:
302
**   r = number of rounds
303
**   L = mode parameter (maximum tree height)
304
**   z = 1 iff this is final compression operation
305
**   p = number of pad bits in a block to be compressed
306
**   keylen = number of bytes in key
307
**   d = desired hash output length
308
**   Does not check inputs for validity.
309
** Returns:
310
**   V = constructed control word
311
*/
312
{ md6_control_word V;
313
  V = ( (((md6_control_word) 0) << 60) | /* reserved, width  4 bits */
314
        (((md6_control_word) r) << 48) |           /* width 12 bits */
315
        (((md6_control_word) L) << 40) |           /* width  8 bits */
316
        (((md6_control_word) z) << 36) |           /* width  4 bits */
317
        (((md6_control_word) p) << 20) |           /* width 16 bits */
318
        (((md6_control_word) keylen) << 12 ) |     /* width  8 bits */
319
        (((md6_control_word) d)) );                /* width 12 bits */
320
  return V;
321
}
322
 
323
/* Node ID's.
324
*/
325
 
326
md6_nodeID md6_make_nodeID( int ell,                     /* level number */
327
                              int i    /* index (0,1,2,...) within level */
328
                            )
329
/* Make "unique nodeID" U based on level ell and position i
330
** within level; place it at specified destination.
331
** Inputs:
332
**    dest = address of where nodeID U should be placed
333
**    ell = integer level number, 1 <= ell <= ...
334
**    i = index within level, i = 0, 1, 2,...
335
** Returns
336
**    U = constructed nodeID
337
*/
338
{ md6_nodeID U;
339
  U = ( (((md6_nodeID) ell) << 56) |
340
        ((md6_nodeID) i) );
341
  return U;
342
}
343
 
344
/* Assembling components of compression input.
345
*/
346
 
347
void md6_pack( md6_word*N,
348
               const md6_word* Q,
349
               md6_word* K,
350
               int ell, int i,
351
               int r, int L, int z, int p, int keylen, int d,
352
               md6_word* B )
353
/* Pack data before compression into n-word array N.
354
*/
355
{ int j;
356
  int ni;
357
  md6_nodeID U;
358
  md6_control_word V;
359
 
360
  ni = 0;
361
 
362
  for (j=0;j<q;j++) N[ni++] = Q[j];       /* Q: Q in words     0--14 */
363
 
364
  for (j=0;j<k;j++) N[ni++] = K[j];       /* K: key in words  15--22 */
365
 
366
  U = md6_make_nodeID(ell,i);             /* U: unique node ID in 23 */
367
  /* The following also works for variants
368
  ** in which u=0.
369
  */
370
  memcpy((unsigned char *)&N[ni],
371
         &U,
372
         min(u*(w/8),sizeof(md6_nodeID)));
373
  ni += u;
374
 
375
  V = md6_make_control_word(
376
                        r,L,z,p,keylen,d);/* V: control word in   24 */
377
  /* The following also works for variants
378
  ** in which v=0.
379
  */
380
  memcpy((unsigned char *)&N[ni],
381
         &V,
382
         min(v*(w/8),sizeof(md6_control_word)));
383
  ni += v;
384
 
385
  memcpy(N+ni,B,b*sizeof(md6_word));      /* B: data words    25--88 */
386
}
387
 
388
/* Standard compress: assemble components and then compress
389
*/
390
 
391
int md6_standard_compress( md6_word* C,
392
                           const md6_word* Q,
393
                           md6_word* K,
394
                           int ell, int i,
395
                           int r, int L, int z, int p, int keylen, int d,
396
                           md6_word* B
397
                           )
398
/* Perform md6 block compression using all the "standard" inputs.
399
** Input:
400
**     Q              q-word (q=15) approximation to (sqrt(6)-2)
401
**     K              k-word key input (k=8)
402
**     ell            level number
403
**     i              index within level
404
**     r              number of rounds in this compression operation
405
**     L              mode parameter (max tree height)
406
**     z              1 iff this is the very last compression
407
**     p              number of padding bits of input in payload B
408
**     keylen         number of bytes in key
409
**     d              desired output hash bit length
410
**     B              b-word (64-word) data input block (with zero padding)
411
** Modifies:
412
**     C              c-word output array (c=16)
413
** Returns one of the following:
414
**   MD6_SUCCESS (0)   MD6_BAD_p
415
**   MD6_NULL_B        MD6_BAD_HASHLEN
416
**   MD6_NULL_C        MD6_NULL_K
417
**   MD6_BAD_r         MD6_NULL_Q
418
**   MD6_BAD_ELL       MD6_OUT_OF_MEMORY
419
*/
420
{ md6_word N[md6_n];
421
  md6_word A[5000];       /* MS VS can't handle variable size here */
422
 
423
  /* check that input values are sensible */
424
  if ( (C == NULL) ) return MD6_NULL_C;
425
  if ( (B == NULL) ) return MD6_NULL_B;
426
  if ( (r<0) | (r>md6_max_r) ) return MD6_BAD_r;
427
  if ( (L<0) | (L>255) ) return MD6_BAD_L;
428
  if ( (ell < 0) || (ell > 255) ) return MD6_BAD_ELL;
429
  if ( (p < 0) || (p > b*w ) ) return MD6_BAD_p;
430
  if ( (d <= 0) || (d > c*w/2) ) return MD6_BADHASHLEN;
431
  if ( (K == NULL) ) return MD6_NULL_K;
432
  if ( (Q == NULL) ) return MD6_NULL_Q;
433
 
434
  /* pack components into N for compression */
435
  md6_pack(N,Q,K,ell,i,r,L,z,p,keylen,d,B);
436
 
437
  /* call compression hook if it is defined. */
438
  /* -- for testing and debugging.           */
439
  if (compression_hook != NULL)
440
    compression_hook(C,Q,K,ell,i,r,L,z,p,keylen,d,B);
441
 
442
  return md6_compress(C,N,r,A);
443
}
444
/* end of md6_compress.c */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.