1 /* ====================================================================
2  * The Apache Software License, Version 1.1
3  *
4  * Copyright (c) 2000-2002 The Apache Software Foundation.  All rights
5  * reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  *
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in
16  *    the documentation and/or other materials provided with the
17  *    distribution.
18  *
19  * 3. The end-user documentation included with the redistribution,
20  *    if any, must include the following acknowledgment:
21  *       "This product includes software developed by the
22  *        Apache Software Foundation (http://www.apache.org/)."
23  *    Alternately, this acknowledgment may appear in the software itself,
24  *    if and wherever such third-party acknowledgments normally appear.
25  *
26  * 4. The names "Apache" and "Apache Software Foundation" must
27  *    not be used to endorse or promote products derived from this
28  *    software without prior written permission. For written
29  *    permission, please contact apache@apache.org.
30  *
31  * 5. Products derived from this software may not be called "Apache",
32  *    nor may "Apache" appear in their name, without prior written
33  *    permission of the Apache Software Foundation.
34  *
35  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46  * SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Apache Software Foundation.  For more
51  * information on the Apache Software Foundation, please see
52  * <http://www.apache.org/>.
53  *
54  * Portions of this software are based upon public domain software
55  * originally written at the National Center for Supercomputing Applications,
56  * University of Illinois, Urbana-Champaign.
57  *
58  * $Id: rdfstore_ap_sha1.c,v 1.1 2003/05/05 17:57:39 areggiori Exp $
59  */
60 
61 /*
62  *
63  * This software also makes use of the following component:
64  *
65  * NIST Secure Hash Algorithm
66  *  	heavily modified by Uwe Hollerbach uh@alumni.caltech edu
67  *	from Peter C. Gutmann's implementation as found in
68  *	Applied Cryptography by Bruce Schneier
69  *	This code is hereby placed in the public domain
70  */
71 
72 /*
73  *
74  * This file differes from the main Apache 1.3.x distribution
75  * because the EBCDIC support has been removed, the code has been
76  * made more stand alone (removed dependences with ap_config.h and ap.h)
77  * and ap_sha1_base64() has been taken off.
78  * In addition, all macros and subroutines have been local to rdfstore_ and RDFSTORE_
79  * namespace to avoid symbol conflicts with apache when the following code
80  * is run under apache Web server i.e. mod_perl or mod_php
81  *
82  */
83 
84 #include <string.h>
85 
86 #include "rdfstore_ap_sha1.h"
87 
88 /* a bit faster & bigger, if defined */
89 #define UNROLL_LOOPS
90 
91 /* NIST's proposed modification to SHA, 7/11/94 */
92 #define USE_MODIFIED_SHA
93 
94 /* SHA f()-functions */
95 #define f1(x,y,z)	((x & y) | (~x & z))
96 #define f2(x,y,z)	(x ^ y ^ z)
97 #define f3(x,y,z)	((x & y) | (x & z) | (y & z))
98 #define f4(x,y,z)	(x ^ y ^ z)
99 
100 /* SHA constants */
101 #define CONST1		0x5a827999L
102 #define CONST2		0x6ed9eba1L
103 #define CONST3		0x8f1bbcdcL
104 #define CONST4		0xca62c1d6L
105 
106 /* 32-bit rotate */
107 
108 #define ROT32(x,n)	((x << n) | (x >> (32 - n)))
109 
110 #define FUNC(n,i)						\
111     temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n;	\
112     E = D; D = C; C = ROT32(B,30); B = A; A = temp
113 
114 #define SHA_BLOCKSIZE           64
115 
116 typedef unsigned char RDFSTORE_AP_BYTE;
117 
118 /* do SHA transformation */
sha_transform(RDFSTORE_AP_SHA1_CTX * sha_info)119 static void sha_transform(RDFSTORE_AP_SHA1_CTX *sha_info)
120 {
121     int i;
122     RDFSTORE_AP_LONG temp, A, B, C, D, E, W[80];
123 
124     for (i = 0; i < 16; ++i) {
125 	W[i] = sha_info->data[i];
126     }
127     for (i = 16; i < 80; ++i) {
128 	W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
129 #ifdef USE_MODIFIED_SHA
130 	W[i] = ROT32(W[i], 1);
131 #endif /* USE_MODIFIED_SHA */
132     }
133     A = sha_info->digest[0];
134     B = sha_info->digest[1];
135     C = sha_info->digest[2];
136     D = sha_info->digest[3];
137     E = sha_info->digest[4];
138 #ifdef UNROLL_LOOPS
139     FUNC(1, 0);  FUNC(1, 1);  FUNC(1, 2);  FUNC(1, 3);  FUNC(1, 4);
140     FUNC(1, 5);  FUNC(1, 6);  FUNC(1, 7);  FUNC(1, 8);  FUNC(1, 9);
141     FUNC(1,10);  FUNC(1,11);  FUNC(1,12);  FUNC(1,13);  FUNC(1,14);
142     FUNC(1,15);  FUNC(1,16);  FUNC(1,17);  FUNC(1,18);  FUNC(1,19);
143 
144     FUNC(2,20);  FUNC(2,21);  FUNC(2,22);  FUNC(2,23);  FUNC(2,24);
145     FUNC(2,25);  FUNC(2,26);  FUNC(2,27);  FUNC(2,28);  FUNC(2,29);
146     FUNC(2,30);  FUNC(2,31);  FUNC(2,32);  FUNC(2,33);  FUNC(2,34);
147     FUNC(2,35);  FUNC(2,36);  FUNC(2,37);  FUNC(2,38);  FUNC(2,39);
148 
149     FUNC(3,40);  FUNC(3,41);  FUNC(3,42);  FUNC(3,43);  FUNC(3,44);
150     FUNC(3,45);  FUNC(3,46);  FUNC(3,47);  FUNC(3,48);  FUNC(3,49);
151     FUNC(3,50);  FUNC(3,51);  FUNC(3,52);  FUNC(3,53);  FUNC(3,54);
152     FUNC(3,55);  FUNC(3,56);  FUNC(3,57);  FUNC(3,58);  FUNC(3,59);
153 
154     FUNC(4,60);  FUNC(4,61);  FUNC(4,62);  FUNC(4,63);  FUNC(4,64);
155     FUNC(4,65);  FUNC(4,66);  FUNC(4,67);  FUNC(4,68);  FUNC(4,69);
156     FUNC(4,70);  FUNC(4,71);  FUNC(4,72);  FUNC(4,73);  FUNC(4,74);
157     FUNC(4,75);  FUNC(4,76);  FUNC(4,77);  FUNC(4,78);  FUNC(4,79);
158 #else /* !UNROLL_LOOPS */
159     for (i = 0; i < 20; ++i) {
160 	FUNC(1,i);
161     }
162     for (i = 20; i < 40; ++i) {
163 	FUNC(2,i);
164     }
165     for (i = 40; i < 60; ++i) {
166 	FUNC(3,i);
167     }
168     for (i = 60; i < 80; ++i) {
169 	FUNC(4,i);
170     }
171 #endif /* !UNROLL_LOOPS */
172     sha_info->digest[0] += A;
173     sha_info->digest[1] += B;
174     sha_info->digest[2] += C;
175     sha_info->digest[3] += D;
176     sha_info->digest[4] += E;
177 }
178 
179 union endianTest {
180     long Long;
181     char Char[sizeof(long)];
182 };
183 
isLittleEndian(void)184 static char isLittleEndian(void)
185 {
186     static union endianTest u;
187     u.Long = 1;
188     return (u.Char[0] == 1);
189 }
190 
191 /* change endianness of data */
192 
193 /* count is the number of bytes to do an endian flip */
maybe_byte_reverse(RDFSTORE_AP_LONG * buffer,int count)194 static void maybe_byte_reverse(RDFSTORE_AP_LONG *buffer, int count)
195 {
196     int i;
197     RDFSTORE_AP_BYTE ct[4], *cp;
198 
199     if (isLittleEndian()) {	/* do the swap only if it is little endian */
200 	count /= sizeof(RDFSTORE_AP_LONG);
201 	cp = (RDFSTORE_AP_BYTE *) buffer;
202 	for (i = 0; i < count; ++i) {
203 	    ct[0] = cp[0];
204 	    ct[1] = cp[1];
205 	    ct[2] = cp[2];
206 	    ct[3] = cp[3];
207 	    cp[0] = ct[3];
208 	    cp[1] = ct[2];
209 	    cp[2] = ct[1];
210 	    cp[3] = ct[0];
211 	    cp += sizeof(RDFSTORE_AP_LONG);
212 	}
213     }
214 }
215 
216 /* initialize the SHA digest */
217 
rdfstore_ap_SHA1Init(RDFSTORE_AP_SHA1_CTX * sha_info)218 void rdfstore_ap_SHA1Init(RDFSTORE_AP_SHA1_CTX *sha_info)
219 {
220     sha_info->digest[0] = 0x67452301L;
221     sha_info->digest[1] = 0xefcdab89L;
222     sha_info->digest[2] = 0x98badcfeL;
223     sha_info->digest[3] = 0x10325476L;
224     sha_info->digest[4] = 0xc3d2e1f0L;
225     sha_info->count_lo = 0L;
226     sha_info->count_hi = 0L;
227     sha_info->local = 0;
228 }
229 
230 /* update the SHA digest */
231 
rdfstore_ap_SHA1Update_binary(RDFSTORE_AP_SHA1_CTX * sha_info,const unsigned char * buffer,unsigned int count)232 void rdfstore_ap_SHA1Update_binary(RDFSTORE_AP_SHA1_CTX *sha_info,
233 				      const unsigned char *buffer,
234 				      unsigned int count)
235 {
236     unsigned int i;
237 
238     if ((sha_info->count_lo + ((RDFSTORE_AP_LONG) count << 3)) < sha_info->count_lo) {
239 	++sha_info->count_hi;
240     }
241     sha_info->count_lo += (RDFSTORE_AP_LONG) count << 3;
242     sha_info->count_hi += (RDFSTORE_AP_LONG) count >> 29;
243     if (sha_info->local) {
244 	i = SHA_BLOCKSIZE - sha_info->local;
245 	if (i > count) {
246 	    i = count;
247 	}
248 	memcpy(((RDFSTORE_AP_BYTE *) sha_info->data) + sha_info->local, buffer, i);
249 	count -= i;
250 	buffer += i;
251 	sha_info->local += i;
252 	if (sha_info->local == SHA_BLOCKSIZE) {
253 	    maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
254 	    sha_transform(sha_info);
255 	}
256 	else {
257 	    return;
258 	}
259     }
260     while (count >= SHA_BLOCKSIZE) {
261 	memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
262 	buffer += SHA_BLOCKSIZE;
263 	count -= SHA_BLOCKSIZE;
264 	maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
265 	sha_transform(sha_info);
266     }
267     memcpy(sha_info->data, buffer, count);
268     sha_info->local = count;
269 }
270 
rdfstore_ap_SHA1Update(RDFSTORE_AP_SHA1_CTX * sha_info,const char * buf,unsigned int count)271 void rdfstore_ap_SHA1Update(RDFSTORE_AP_SHA1_CTX *sha_info, const char *buf,
272 			       unsigned int count)
273 {
274     rdfstore_ap_SHA1Update_binary(sha_info, (const unsigned char *) buf, count);
275 }
276 
277 /* finish computing the SHA digest */
278 
rdfstore_ap_SHA1Final(unsigned char digest[RDFSTORE_SHA_DIGESTSIZE],RDFSTORE_AP_SHA1_CTX * sha_info)279 void rdfstore_ap_SHA1Final(unsigned char digest[RDFSTORE_SHA_DIGESTSIZE],
280                               RDFSTORE_AP_SHA1_CTX *sha_info)
281 {
282     int count, i, j;
283     RDFSTORE_AP_LONG lo_bit_count, hi_bit_count, k;
284 
285     lo_bit_count = sha_info->count_lo;
286     hi_bit_count = sha_info->count_hi;
287     count = (int) ((lo_bit_count >> 3) & 0x3f);
288     ((RDFSTORE_AP_BYTE *) sha_info->data)[count++] = 0x80;
289     if (count > SHA_BLOCKSIZE - 8) {
290 	memset(((RDFSTORE_AP_BYTE *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
291 	maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
292 	sha_transform(sha_info);
293 	memset((RDFSTORE_AP_BYTE *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
294     }
295     else {
296 	memset(((RDFSTORE_AP_BYTE *) sha_info->data) + count, 0,
297 	       SHA_BLOCKSIZE - 8 - count);
298     }
299     maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
300     sha_info->data[14] = hi_bit_count;
301     sha_info->data[15] = lo_bit_count;
302     sha_transform(sha_info);
303 
304     for (i = 0, j = 0; j < RDFSTORE_SHA_DIGESTSIZE; i++) {
305 	k = sha_info->digest[i];
306 	digest[j++] = (unsigned char) ((k >> 24) & 0xff);
307 	digest[j++] = (unsigned char) ((k >> 16) & 0xff);
308 	digest[j++] = (unsigned char) ((k >> 8) & 0xff);
309 	digest[j++] = (unsigned char) (k & 0xff);
310     }
311 }
312