sha1.c 8.78 KB
Newer Older
1
/*	$PostgreSQL: pgsql/contrib/pgcrypto/sha1.c,v 1.14 2004/08/29 16:43:05 tgl Exp $ */
2
/*	   $KAME: sha1.c,v 1.3 2000/02/22 14:01:18 itojun Exp $    */
3 4 5 6 7 8 9 10 11

/*
 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
12
 *	  notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14 15
 *	  notice, this list of conditions and the following disclaimer in the
 *	  documentation and/or other materials provided with the distribution.
16
 * 3. Neither the name of the project nor the names of its contributors
17 18
 *	  may be used to endorse or promote products derived from this software
 *	  without specific prior written permission.
19 20 21 22
 *
 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.	IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
24 25 26 27 28 29 30 31 32 33 34 35 36 37
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
/*
 * FIPS pub 180-1: Secure Hash Algorithm (SHA-1)
 * based on: http://csrc.nist.gov/fips/fip180-1.txt
 * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org>
 */

38
#include "postgres.h"
39
#include "px.h"
40 41 42 43 44

#include "sha1.h"

/* sanity check */
#if BYTE_ORDER != BIG_ENDIAN
45 46 47
#if BYTE_ORDER != LITTLE_ENDIAN
#define unsupported 1
#endif
48 49 50 51 52
#endif

#ifndef unsupported

/* constant table */
53 54 55
static uint32 _K[] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6};

#define K(t)	_K[(t) / 20]
56

57 58 59 60
#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d)))
#define F1(b, c, d) (((b) ^ (c)) ^ (d))
#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d)))
#define F3(b, c, d) (((b) ^ (c)) ^ (d))
61

62
#define S(n, x)		(((x) << (n)) | ((x) >> (32 - n)))
63

64 65 66 67
#define H(n)	(ctxt->h.b32[(n)])
#define COUNT	(ctxt->count)
#define BCOUNT	(ctxt->c.b64[0] / 8)
#define W(n)	(ctxt->m.b32[(n)])
68

69 70
#define PUTBYTE(x) \
do { \
71 72 73 74 75 76
	ctxt->m.b8[(COUNT % 64)] = (x);		\
	COUNT++;				\
	COUNT %= 64;				\
	ctxt->c.b64[0] += 8;			\
	if (COUNT % 64 == 0)			\
		sha1_step(ctxt);		\
77
} while (0)
78

79 80
#define PUTPAD(x) \
do { \
81 82 83 84 85
	ctxt->m.b8[(COUNT % 64)] = (x);		\
	COUNT++;				\
	COUNT %= 64;				\
	if (COUNT % 64 == 0)			\
		sha1_step(ctxt);		\
86
} while (0)
87

88
static void sha1_step(struct sha1_ctxt *);
89 90

static void
91
sha1_step(struct sha1_ctxt * ctxt)
92
{
93 94 95 96 97 98 99 100
	uint32		a,
				b,
				c,
				d,
				e;
	size_t		t,
				s;
	uint32		tmp;
101 102 103

#if BYTE_ORDER == LITTLE_ENDIAN
	struct sha1_ctxt tctxt;
104

105
	memmove(&tctxt.m.b8[0], &ctxt->m.b8[0], 64);
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
	ctxt->m.b8[0] = tctxt.m.b8[3];
	ctxt->m.b8[1] = tctxt.m.b8[2];
	ctxt->m.b8[2] = tctxt.m.b8[1];
	ctxt->m.b8[3] = tctxt.m.b8[0];
	ctxt->m.b8[4] = tctxt.m.b8[7];
	ctxt->m.b8[5] = tctxt.m.b8[6];
	ctxt->m.b8[6] = tctxt.m.b8[5];
	ctxt->m.b8[7] = tctxt.m.b8[4];
	ctxt->m.b8[8] = tctxt.m.b8[11];
	ctxt->m.b8[9] = tctxt.m.b8[10];
	ctxt->m.b8[10] = tctxt.m.b8[9];
	ctxt->m.b8[11] = tctxt.m.b8[8];
	ctxt->m.b8[12] = tctxt.m.b8[15];
	ctxt->m.b8[13] = tctxt.m.b8[14];
	ctxt->m.b8[14] = tctxt.m.b8[13];
	ctxt->m.b8[15] = tctxt.m.b8[12];
	ctxt->m.b8[16] = tctxt.m.b8[19];
	ctxt->m.b8[17] = tctxt.m.b8[18];
	ctxt->m.b8[18] = tctxt.m.b8[17];
	ctxt->m.b8[19] = tctxt.m.b8[16];
	ctxt->m.b8[20] = tctxt.m.b8[23];
	ctxt->m.b8[21] = tctxt.m.b8[22];
	ctxt->m.b8[22] = tctxt.m.b8[21];
	ctxt->m.b8[23] = tctxt.m.b8[20];
	ctxt->m.b8[24] = tctxt.m.b8[27];
	ctxt->m.b8[25] = tctxt.m.b8[26];
	ctxt->m.b8[26] = tctxt.m.b8[25];
	ctxt->m.b8[27] = tctxt.m.b8[24];
	ctxt->m.b8[28] = tctxt.m.b8[31];
	ctxt->m.b8[29] = tctxt.m.b8[30];
	ctxt->m.b8[30] = tctxt.m.b8[29];
	ctxt->m.b8[31] = tctxt.m.b8[28];
	ctxt->m.b8[32] = tctxt.m.b8[35];
	ctxt->m.b8[33] = tctxt.m.b8[34];
	ctxt->m.b8[34] = tctxt.m.b8[33];
	ctxt->m.b8[35] = tctxt.m.b8[32];
	ctxt->m.b8[36] = tctxt.m.b8[39];
	ctxt->m.b8[37] = tctxt.m.b8[38];
	ctxt->m.b8[38] = tctxt.m.b8[37];
	ctxt->m.b8[39] = tctxt.m.b8[36];
	ctxt->m.b8[40] = tctxt.m.b8[43];
	ctxt->m.b8[41] = tctxt.m.b8[42];
	ctxt->m.b8[42] = tctxt.m.b8[41];
	ctxt->m.b8[43] = tctxt.m.b8[40];
	ctxt->m.b8[44] = tctxt.m.b8[47];
	ctxt->m.b8[45] = tctxt.m.b8[46];
	ctxt->m.b8[46] = tctxt.m.b8[45];
	ctxt->m.b8[47] = tctxt.m.b8[44];
	ctxt->m.b8[48] = tctxt.m.b8[51];
	ctxt->m.b8[49] = tctxt.m.b8[50];
	ctxt->m.b8[50] = tctxt.m.b8[49];
	ctxt->m.b8[51] = tctxt.m.b8[48];
	ctxt->m.b8[52] = tctxt.m.b8[55];
	ctxt->m.b8[53] = tctxt.m.b8[54];
	ctxt->m.b8[54] = tctxt.m.b8[53];
	ctxt->m.b8[55] = tctxt.m.b8[52];
	ctxt->m.b8[56] = tctxt.m.b8[59];
	ctxt->m.b8[57] = tctxt.m.b8[58];
	ctxt->m.b8[58] = tctxt.m.b8[57];
	ctxt->m.b8[59] = tctxt.m.b8[56];
	ctxt->m.b8[60] = tctxt.m.b8[63];
	ctxt->m.b8[61] = tctxt.m.b8[62];
	ctxt->m.b8[62] = tctxt.m.b8[61];
	ctxt->m.b8[63] = tctxt.m.b8[60];
170 171
#endif

172 173 174 175 176
	a = H(0);
	b = H(1);
	c = H(2);
	d = H(3);
	e = H(4);
177

178 179
	for (t = 0; t < 20; t++)
	{
180
		s = t & 0x0f;
181 182
		if (t >= 16)
			W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
183
		tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t);
184 185 186 187 188
		e = d;
		d = c;
		c = S(30, b);
		b = a;
		a = tmp;
189
	}
190 191
	for (t = 20; t < 40; t++)
	{
192
		s = t & 0x0f;
193
		W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
194
		tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t);
195 196 197 198 199
		e = d;
		d = c;
		c = S(30, b);
		b = a;
		a = tmp;
200
	}
201 202
	for (t = 40; t < 60; t++)
	{
203
		s = t & 0x0f;
204
		W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
205
		tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t);
206 207 208 209 210
		e = d;
		d = c;
		c = S(30, b);
		b = a;
		a = tmp;
211
	}
212 213
	for (t = 60; t < 80; t++)
	{
214
		s = t & 0x0f;
215
		W(s) = S(1, W((s + 13) & 0x0f) ^ W((s + 8) & 0x0f) ^ W((s + 2) & 0x0f) ^ W(s));
216
		tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t);
217 218 219 220 221
		e = d;
		d = c;
		c = S(30, b);
		b = a;
		a = tmp;
222 223 224 225 226 227 228 229
	}

	H(0) = H(0) + a;
	H(1) = H(1) + b;
	H(2) = H(2) + c;
	H(3) = H(3) + d;
	H(4) = H(4) + e;

230
	memset(&ctxt->m.b8[0], 0, 64);
231 232 233 234 235
}

/*------------------------------------------------------------*/

void
236
sha1_init(struct sha1_ctxt * ctxt)
237
{
238
	memset(ctxt, 0, sizeof(struct sha1_ctxt));
239 240 241 242 243 244 245 246
	H(0) = 0x67452301;
	H(1) = 0xefcdab89;
	H(2) = 0x98badcfe;
	H(3) = 0x10325476;
	H(4) = 0xc3d2e1f0;
}

void
247
sha1_pad(struct sha1_ctxt * ctxt)
248
{
249 250
	size_t		padlen;			/* pad length in bytes */
	size_t		padstart;
251 252 253 254 255

	PUTPAD(0x80);

	padstart = COUNT % 64;
	padlen = 64 - padstart;
256 257
	if (padlen < 8)
	{
258
		memset(&ctxt->m.b8[padstart], 0, padlen);
259 260 261 262
		COUNT += padlen;
		COUNT %= 64;
		sha1_step(ctxt);
		padstart = COUNT % 64;	/* should be 0 */
263
		padlen = 64 - padstart; /* should be 64 */
264
	}
265
	memset(&ctxt->m.b8[padstart], 0, padlen - 8);
266 267 268
	COUNT += (padlen - 8);
	COUNT %= 64;
#if BYTE_ORDER == BIG_ENDIAN
269 270 271 272 273 274 275 276
	PUTPAD(ctxt->c.b8[0]);
	PUTPAD(ctxt->c.b8[1]);
	PUTPAD(ctxt->c.b8[2]);
	PUTPAD(ctxt->c.b8[3]);
	PUTPAD(ctxt->c.b8[4]);
	PUTPAD(ctxt->c.b8[5]);
	PUTPAD(ctxt->c.b8[6]);
	PUTPAD(ctxt->c.b8[7]);
277
#else
278 279 280 281 282 283 284 285
	PUTPAD(ctxt->c.b8[7]);
	PUTPAD(ctxt->c.b8[6]);
	PUTPAD(ctxt->c.b8[5]);
	PUTPAD(ctxt->c.b8[4]);
	PUTPAD(ctxt->c.b8[3]);
	PUTPAD(ctxt->c.b8[2]);
	PUTPAD(ctxt->c.b8[1]);
	PUTPAD(ctxt->c.b8[0]);
286 287 288 289
#endif
}

void
290
sha1_loop(struct sha1_ctxt * ctxt, const uint8 *input0, size_t len)
291
{
292
	const uint8 *input;
293 294 295 296
	size_t		gaplen;
	size_t		gapstart;
	size_t		off;
	size_t		copysiz;
297

298
	input = (const uint8 *) input0;
299 300
	off = 0;

301 302
	while (off < len)
	{
303 304 305 306
		gapstart = COUNT % 64;
		gaplen = 64 - gapstart;

		copysiz = (gaplen < len - off) ? gaplen : len - off;
307
		memmove(&ctxt->m.b8[gapstart], &input[off], copysiz);
308 309 310 311 312 313 314 315 316 317
		COUNT += copysiz;
		COUNT %= 64;
		ctxt->c.b64[0] += copysiz * 8;
		if (COUNT % 64 == 0)
			sha1_step(ctxt);
		off += copysiz;
	}
}

void
318
sha1_result(struct sha1_ctxt * ctxt, uint8 *digest0)
319
{
320
	uint8	   *digest;
321

322
	digest = (uint8 *) digest0;
323 324
	sha1_pad(ctxt);
#if BYTE_ORDER == BIG_ENDIAN
325
	memmove(digest, &ctxt->h.b8[0], 20);
326
#else
327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
	digest[0] = ctxt->h.b8[3];
	digest[1] = ctxt->h.b8[2];
	digest[2] = ctxt->h.b8[1];
	digest[3] = ctxt->h.b8[0];
	digest[4] = ctxt->h.b8[7];
	digest[5] = ctxt->h.b8[6];
	digest[6] = ctxt->h.b8[5];
	digest[7] = ctxt->h.b8[4];
	digest[8] = ctxt->h.b8[11];
	digest[9] = ctxt->h.b8[10];
	digest[10] = ctxt->h.b8[9];
	digest[11] = ctxt->h.b8[8];
	digest[12] = ctxt->h.b8[15];
	digest[13] = ctxt->h.b8[14];
	digest[14] = ctxt->h.b8[13];
	digest[15] = ctxt->h.b8[12];
	digest[16] = ctxt->h.b8[19];
	digest[17] = ctxt->h.b8[18];
	digest[18] = ctxt->h.b8[17];
	digest[19] = ctxt->h.b8[16];
347 348
#endif
}
349

350
#endif   /* unsupported */