00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 #include "apr_sha1.h"
00048 #include "apr_base64.h"
00049 #include "apr_strings.h"
00050 #include "apr_lib.h"
00051 #if APR_CHARSET_EBCDIC
00052 #include "apr_xlate.h"
00053 #endif
00054 #include <string.h>
00055
00056
00057 #define UNROLL_LOOPS
00058
00059
00060 #define USE_MODIFIED_SHA
00061
00062
00063 #define f1(x,y,z) ((x & y) | (~x & z))
00064 #define f2(x,y,z) (x ^ y ^ z)
00065 #define f3(x,y,z) ((x & y) | (x & z) | (y & z))
00066 #define f4(x,y,z) (x ^ y ^ z)
00067
00068
00069 #define CONST1 0x5a827999L
00070 #define CONST2 0x6ed9eba1L
00071 #define CONST3 0x8f1bbcdcL
00072 #define CONST4 0xca62c1d6L
00073
00074
00075
00076 #define ROT32(x,n) ((x << n) | (x >> (32 - n)))
00077
00078 #define FUNC(n,i) \
00079 temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n; \
00080 E = D; D = C; C = ROT32(B,30); B = A; A = temp
00081
00082 #define SHA_BLOCKSIZE 64
00083
00084 #if APR_CHARSET_EBCDIC
00085 static apr_xlate_t *ebcdic2ascii_xlate;
00086
00087 APU_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x)
00088 {
00089 apr_status_t rv;
00090 int onoff;
00091
00092
00093
00094 rv = apr_xlate_get_sb(x, &onoff);
00095 if (rv) {
00096 return rv;
00097 }
00098 if (!onoff) {
00099 return APR_EINVAL;
00100 }
00101 ebcdic2ascii_xlate = x;
00102 return APR_SUCCESS;
00103 }
00104 #endif
00105
00106
00107 static void sha_transform(apr_sha1_ctx_t *sha_info)
00108 {
00109 int i;
00110 apr_uint32_t temp, A, B, C, D, E, W[80];
00111
00112 for (i = 0; i < 16; ++i) {
00113 W[i] = sha_info->data[i];
00114 }
00115 for (i = 16; i < 80; ++i) {
00116 W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
00117 #ifdef USE_MODIFIED_SHA
00118 W[i] = ROT32(W[i], 1);
00119 #endif
00120 }
00121 A = sha_info->digest[0];
00122 B = sha_info->digest[1];
00123 C = sha_info->digest[2];
00124 D = sha_info->digest[3];
00125 E = sha_info->digest[4];
00126 #ifdef UNROLL_LOOPS
00127 FUNC(1, 0); FUNC(1, 1); FUNC(1, 2); FUNC(1, 3); FUNC(1, 4);
00128 FUNC(1, 5); FUNC(1, 6); FUNC(1, 7); FUNC(1, 8); FUNC(1, 9);
00129 FUNC(1,10); FUNC(1,11); FUNC(1,12); FUNC(1,13); FUNC(1,14);
00130 FUNC(1,15); FUNC(1,16); FUNC(1,17); FUNC(1,18); FUNC(1,19);
00131
00132 FUNC(2,20); FUNC(2,21); FUNC(2,22); FUNC(2,23); FUNC(2,24);
00133 FUNC(2,25); FUNC(2,26); FUNC(2,27); FUNC(2,28); FUNC(2,29);
00134 FUNC(2,30); FUNC(2,31); FUNC(2,32); FUNC(2,33); FUNC(2,34);
00135 FUNC(2,35); FUNC(2,36); FUNC(2,37); FUNC(2,38); FUNC(2,39);
00136
00137 FUNC(3,40); FUNC(3,41); FUNC(3,42); FUNC(3,43); FUNC(3,44);
00138 FUNC(3,45); FUNC(3,46); FUNC(3,47); FUNC(3,48); FUNC(3,49);
00139 FUNC(3,50); FUNC(3,51); FUNC(3,52); FUNC(3,53); FUNC(3,54);
00140 FUNC(3,55); FUNC(3,56); FUNC(3,57); FUNC(3,58); FUNC(3,59);
00141
00142 FUNC(4,60); FUNC(4,61); FUNC(4,62); FUNC(4,63); FUNC(4,64);
00143 FUNC(4,65); FUNC(4,66); FUNC(4,67); FUNC(4,68); FUNC(4,69);
00144 FUNC(4,70); FUNC(4,71); FUNC(4,72); FUNC(4,73); FUNC(4,74);
00145 FUNC(4,75); FUNC(4,76); FUNC(4,77); FUNC(4,78); FUNC(4,79);
00146 #else
00147 for (i = 0; i < 20; ++i) {
00148 FUNC(1,i);
00149 }
00150 for (i = 20; i < 40; ++i) {
00151 FUNC(2,i);
00152 }
00153 for (i = 40; i < 60; ++i) {
00154 FUNC(3,i);
00155 }
00156 for (i = 60; i < 80; ++i) {
00157 FUNC(4,i);
00158 }
00159 #endif
00160 sha_info->digest[0] += A;
00161 sha_info->digest[1] += B;
00162 sha_info->digest[2] += C;
00163 sha_info->digest[3] += D;
00164 sha_info->digest[4] += E;
00165 }
00166
00167 union endianTest {
00168 long Long;
00169 char Char[sizeof(long)];
00170 };
00171
00172 static char isLittleEndian(void)
00173 {
00174 static union endianTest u;
00175 u.Long = 1;
00176 return (u.Char[0] == 1);
00177 }
00178
00179
00180
00181
00182 static void maybe_byte_reverse(apr_uint32_t *buffer, int count)
00183 {
00184 int i;
00185 apr_byte_t ct[4], *cp;
00186
00187 if (isLittleEndian()) {
00188 count /= sizeof(apr_uint32_t);
00189 cp = (apr_byte_t *) buffer;
00190 for (i = 0; i < count; ++i) {
00191 ct[0] = cp[0];
00192 ct[1] = cp[1];
00193 ct[2] = cp[2];
00194 ct[3] = cp[3];
00195 cp[0] = ct[3];
00196 cp[1] = ct[2];
00197 cp[2] = ct[1];
00198 cp[3] = ct[0];
00199 cp += sizeof(apr_uint32_t);
00200 }
00201 }
00202 }
00203
00204
00205
00206 APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info)
00207 {
00208 sha_info->digest[0] = 0x67452301L;
00209 sha_info->digest[1] = 0xefcdab89L;
00210 sha_info->digest[2] = 0x98badcfeL;
00211 sha_info->digest[3] = 0x10325476L;
00212 sha_info->digest[4] = 0xc3d2e1f0L;
00213 sha_info->count_lo = 0L;
00214 sha_info->count_hi = 0L;
00215 sha_info->local = 0;
00216 }
00217
00218
00219
00220 APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info,
00221 const unsigned char *buffer,
00222 unsigned int count)
00223 {
00224 unsigned int i;
00225
00226 if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
00227 ++sha_info->count_hi;
00228 }
00229 sha_info->count_lo += (apr_uint32_t) count << 3;
00230 sha_info->count_hi += (apr_uint32_t) count >> 29;
00231 if (sha_info->local) {
00232 i = SHA_BLOCKSIZE - sha_info->local;
00233 if (i > count) {
00234 i = count;
00235 }
00236 memcpy(((apr_byte_t *) sha_info->data) + sha_info->local, buffer, i);
00237 count -= i;
00238 buffer += i;
00239 sha_info->local += i;
00240 if (sha_info->local == SHA_BLOCKSIZE) {
00241 maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
00242 sha_transform(sha_info);
00243 }
00244 else {
00245 return;
00246 }
00247 }
00248 while (count >= SHA_BLOCKSIZE) {
00249 memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
00250 buffer += SHA_BLOCKSIZE;
00251 count -= SHA_BLOCKSIZE;
00252 maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
00253 sha_transform(sha_info);
00254 }
00255 memcpy(sha_info->data, buffer, count);
00256 sha_info->local = count;
00257 }
00258
00259 APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf,
00260 unsigned int count)
00261 {
00262 #if APR_CHARSET_EBCDIC
00263 int i;
00264 const apr_byte_t *buffer = (const apr_byte_t *) buf;
00265 apr_size_t inbytes_left, outbytes_left;
00266
00267 if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
00268 ++sha_info->count_hi;
00269 }
00270 sha_info->count_lo += (apr_uint32_t) count << 3;
00271 sha_info->count_hi += (apr_uint32_t) count >> 29;
00272
00273 if (sha_info->local) {
00274 i = SHA_BLOCKSIZE - sha_info->local;
00275 if (i > count) {
00276 i = count;
00277 }
00278 inbytes_left = outbytes_left = i;
00279 apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
00280 ((apr_byte_t *) sha_info->data) + sha_info->local,
00281 &outbytes_left);
00282 count -= i;
00283 buffer += i;
00284 sha_info->local += i;
00285 if (sha_info->local == SHA_BLOCKSIZE) {
00286 maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
00287 sha_transform(sha_info);
00288 }
00289 else {
00290 return;
00291 }
00292 }
00293 while (count >= SHA_BLOCKSIZE) {
00294 inbytes_left = outbytes_left = SHA_BLOCKSIZE;
00295 apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
00296 (apr_byte_t *) sha_info->data, &outbytes_left);
00297 buffer += SHA_BLOCKSIZE;
00298 count -= SHA_BLOCKSIZE;
00299 maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
00300 sha_transform(sha_info);
00301 }
00302 inbytes_left = outbytes_left = count;
00303 apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
00304 (apr_byte_t *) sha_info->data, &outbytes_left);
00305 sha_info->local = count;
00306 #else
00307 apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count);
00308 #endif
00309 }
00310
00311
00312
00313 APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE],
00314 apr_sha1_ctx_t *sha_info)
00315 {
00316 int count, i, j;
00317 apr_uint32_t lo_bit_count, hi_bit_count, k;
00318
00319 lo_bit_count = sha_info->count_lo;
00320 hi_bit_count = sha_info->count_hi;
00321 count = (int) ((lo_bit_count >> 3) & 0x3f);
00322 ((apr_byte_t *) sha_info->data)[count++] = 0x80;
00323 if (count > SHA_BLOCKSIZE - 8) {
00324 memset(((apr_byte_t *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
00325 maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
00326 sha_transform(sha_info);
00327 memset((apr_byte_t *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
00328 }
00329 else {
00330 memset(((apr_byte_t *) sha_info->data) + count, 0,
00331 SHA_BLOCKSIZE - 8 - count);
00332 }
00333 maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
00334 sha_info->data[14] = hi_bit_count;
00335 sha_info->data[15] = lo_bit_count;
00336 sha_transform(sha_info);
00337
00338 for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) {
00339 k = sha_info->digest[i];
00340 digest[j++] = (unsigned char) ((k >> 24) & 0xff);
00341 digest[j++] = (unsigned char) ((k >> 16) & 0xff);
00342 digest[j++] = (unsigned char) ((k >> 8) & 0xff);
00343 digest[j++] = (unsigned char) (k & 0xff);
00344 }
00345 }
00346
00347
00348 APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out)
00349 {
00350 int l;
00351 apr_sha1_ctx_t context;
00352 apr_byte_t digest[APR_SHA1_DIGESTSIZE];
00353
00354 if (strncmp(clear, APR_SHA1PW_ID, APR_SHA1PW_IDLEN) == 0) {
00355 clear += APR_SHA1PW_IDLEN;
00356 }
00357
00358 apr_sha1_init(&context);
00359 apr_sha1_update(&context, clear, len);
00360 apr_sha1_final(digest, &context);
00361
00362
00363 apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1);
00364
00365
00366 l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest));
00367 out[l + APR_SHA1PW_IDLEN] = '\0';
00368
00369
00370
00371
00372 }