1/*
2 * Copyright (c) 1995, 1996, 1997, 1998 Kungliga Tekniska H�gskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * 3. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by the Kungliga Tekniska
20 *      H�gskolan and its contributors.
21 *
22 * 4. Neither the name of the Institute nor the names of its contributors
23 *    may be used to endorse or promote products derived from this software
24 *    without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 */
38
39#ifdef HAVE_CONFIG_H
40#include "config.h"
41
42RCSID("$Id: sha.c,v 1.4 2005/01/10 19:09:08 snsimon Exp $");
43#endif
44
45#include <stdlib.h>
46#include <string.h>
47
48#include "sha.h"
49
50#ifndef min
51#define min(a,b) (((a)>(b))?(b):(a))
52#endif
53
54#define A m->counter[0]
55#define B m->counter[1]
56#define C m->counter[2]
57#define D m->counter[3]
58#define E m->counter[4]
59#define X data
60
61void
62sha_init (struct sha *m)
63{
64  m->offset = 0;
65  m->sz = 0;
66  A = 0x67452301;
67  B = 0xefcdab89;
68  C = 0x98badcfe;
69  D = 0x10325476;
70  E = 0xc3d2e1f0;
71}
72
73static inline u_int32_t
74cshift (u_int32_t x, unsigned int n)
75{
76  return (x << n) | (x >> (32 - n));
77}
78
79#define F0(x,y,z) ((x & y) | (~x & z))
80#define F1(x,y,z) (x ^ y ^ z)
81#define F2(x,y,z) ((x & y) | (x & z) | (y & z))
82#define F3(x,y,z) F1(x,y,z)
83
84#define K0 0x5a827999
85#define K1 0x6ed9eba1
86#define K2 0x8f1bbcdc
87#define K3 0xca62c1d6
88
89#define DO(t,f,k) \
90do { \
91  u_int32_t temp; \
92 \
93  temp = cshift(AA, 5) + f(BB,CC,DD) + EE + data[t] + k; \
94  EE = DD; \
95  DD = CC; \
96  CC = cshift(BB, 30); \
97  BB = AA; \
98  AA = temp; \
99} while(0)
100
101static inline void
102calc (struct sha *m, u_int32_t *in)
103{
104  u_int32_t AA, BB, CC, DD, EE;
105  u_int32_t data[80];
106  int i;
107
108  AA = A;
109  BB = B;
110  CC = C;
111  DD = D;
112  EE = E;
113
114  for (i = 0; i < 16; ++i)
115    data[i] = in[i];
116  for (i = 16; i < 80; ++i)
117    data[i] = cshift(data[i-3] ^ data[i-8] ^ data[i-14] ^ data[i-16], 1);
118
119  /* t=[0,19] */
120
121  DO(0,F0,K0);
122  DO(1,F0,K0);
123  DO(2,F0,K0);
124  DO(3,F0,K0);
125  DO(4,F0,K0);
126  DO(5,F0,K0);
127  DO(6,F0,K0);
128  DO(7,F0,K0);
129  DO(8,F0,K0);
130  DO(9,F0,K0);
131  DO(10,F0,K0);
132  DO(11,F0,K0);
133  DO(12,F0,K0);
134  DO(13,F0,K0);
135  DO(14,F0,K0);
136  DO(15,F0,K0);
137  DO(16,F0,K0);
138  DO(17,F0,K0);
139  DO(18,F0,K0);
140  DO(19,F0,K0);
141
142  /* t=[20,39] */
143
144  DO(20,F1,K1);
145  DO(21,F1,K1);
146  DO(22,F1,K1);
147  DO(23,F1,K1);
148  DO(24,F1,K1);
149  DO(25,F1,K1);
150  DO(26,F1,K1);
151  DO(27,F1,K1);
152  DO(28,F1,K1);
153  DO(29,F1,K1);
154  DO(30,F1,K1);
155  DO(31,F1,K1);
156  DO(32,F1,K1);
157  DO(33,F1,K1);
158  DO(34,F1,K1);
159  DO(35,F1,K1);
160  DO(36,F1,K1);
161  DO(37,F1,K1);
162  DO(38,F1,K1);
163  DO(39,F1,K1);
164
165  /* t=[40,59] */
166
167  DO(40,F2,K2);
168  DO(41,F2,K2);
169  DO(42,F2,K2);
170  DO(43,F2,K2);
171  DO(44,F2,K2);
172  DO(45,F2,K2);
173  DO(46,F2,K2);
174  DO(47,F2,K2);
175  DO(48,F2,K2);
176  DO(49,F2,K2);
177  DO(50,F2,K2);
178  DO(51,F2,K2);
179  DO(52,F2,K2);
180  DO(53,F2,K2);
181  DO(54,F2,K2);
182  DO(55,F2,K2);
183  DO(56,F2,K2);
184  DO(57,F2,K2);
185  DO(58,F2,K2);
186  DO(59,F2,K2);
187
188  /* t=[60,79] */
189
190  DO(60,F3,K3);
191  DO(61,F3,K3);
192  DO(62,F3,K3);
193  DO(63,F3,K3);
194  DO(64,F3,K3);
195  DO(65,F3,K3);
196  DO(66,F3,K3);
197  DO(67,F3,K3);
198  DO(68,F3,K3);
199  DO(69,F3,K3);
200  DO(70,F3,K3);
201  DO(71,F3,K3);
202  DO(72,F3,K3);
203  DO(73,F3,K3);
204  DO(74,F3,K3);
205  DO(75,F3,K3);
206  DO(76,F3,K3);
207  DO(77,F3,K3);
208  DO(78,F3,K3);
209  DO(79,F3,K3);
210
211  A += AA;
212  B += BB;
213  C += CC;
214  D += DD;
215  E += EE;
216}
217
218/*
219 * From `Performance analysis of SHA' by Joseph D. Touch <touch@isi.edu>
220 */
221
222static inline u_int32_t
223swap_u_int32_t (u_int32_t t)
224{
225#if !defined(WORDS_BIGENDIAN)
226#define ROL(x,n) ((x)<<(n))|((x)>>(32-(n)))
227  u_int32_t temp1, temp2;
228
229  temp1   = ROL(t,16);
230  temp2   = temp1 >> 8;
231  temp1  &= 0x00ff00ff;
232  temp2  &= 0x00ff00ff;
233  temp1 <<= 8;
234  return temp1 | temp2;
235#else
236  return t;
237#endif
238}
239
240struct x32{
241  unsigned int a:32;
242  unsigned int b:32;
243};
244
245void
246sha_update (struct sha *m, const void *v, size_t len)
247{
248  const unsigned char *p = v;
249  m->sz += len;
250  while(len > 0){
251    size_t l = min(len, 64 - m->offset);
252    memcpy(m->save + m->offset, p, l);
253    m->offset += l;
254    p += l;
255    len -= l;
256    if(m->offset == 64){
257#if !defined(WORDS_BIGENDIAN) || defined(_CRAY)
258      int i;
259      u_int32_t current[16];
260      struct x32 *u = (struct x32*)m->save;
261      for(i = 0; i < 8; i++){
262	current[2*i+0] = swap_u_int32_t(u[i].a);
263	current[2*i+1] = swap_u_int32_t(u[i].b);
264      }
265      calc(m, current);
266#else
267      calc(m, (u_int32_t*)m->save);
268#endif
269      m->offset = 0;
270    }
271  }
272}
273
274void
275sha_finito (struct sha *m, void *res)
276{
277  static unsigned char zeros[72];
278  u_int32_t len;
279  unsigned int dstart = (120 - m->offset - 1) % 64 + 1;
280
281  *zeros = 0x80;
282  memset (zeros + 1, 0, sizeof(zeros) - 1);
283  len = 8 * m->sz;
284  zeros[dstart+7] = (len >> 0) & 0xff;
285  zeros[dstart+6] = (len >> 8) & 0xff;
286  zeros[dstart+5] = (len >> 16) & 0xff;
287  zeros[dstart+4] = (len >> 24) & 0xff;
288  sha_update (m, zeros, dstart + 8);
289  {
290      int i;
291      unsigned char *r = (unsigned char*)res;
292
293      for (i = 0; i < 5; ++i) {
294	  r[4*i+3] = m->counter[i] & 0xFF;
295	  r[4*i+2] = (m->counter[i] >> 8) & 0xFF;
296	  r[4*i+1] = (m->counter[i] >> 16) & 0xFF;
297	  r[4*i]   = (m->counter[i] >> 24) & 0xFF;
298      }
299  }
300#if 0
301  {
302    int i;
303    u_int32_t *r = (u_int32_t *)res;
304
305    for (i = 0; i < 5; ++i)
306      r[i] = swap_u_int32_t (m->counter[i]);
307  }
308#endif
309}
310