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