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