~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr-util/crypto/apr_sha1.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
/*
 
18
 * The exported function:
 
19
 *
 
20
 *       apr_sha1_base64(const char *clear, int len, char *out);
 
21
 *
 
22
 * provides a means to SHA1 crypt/encode a plaintext password in
 
23
 * a way which makes password files compatible with those commonly
 
24
 * used in netscape web and ldap installations. It was put together
 
25
 * by Clinton Wong <clintdw@netcom.com>, who also notes that:
 
26
 *
 
27
 * Note: SHA1 support is useful for migration purposes, but is less
 
28
 *     secure than Apache's password format, since Apache's (MD5)
 
29
 *     password format uses a random eight character salt to generate
 
30
 *     one of many possible hashes for the same password.  Netscape
 
31
 *     uses plain SHA1 without a salt, so the same password
 
32
 *     will always generate the same hash, making it easier
 
33
 *     to break since the search space is smaller.
 
34
 *
 
35
 * See also the documentation in support/SHA1 as to hints on how to
 
36
 * migrate an existing netscape installation and other supplied utitlites.
 
37
 *
 
38
 * This software also makes use of the following component:
 
39
 *
 
40
 * NIST Secure Hash Algorithm
 
41
 *      heavily modified by Uwe Hollerbach uh@alumni.caltech edu
 
42
 *      from Peter C. Gutmann's implementation as found in
 
43
 *      Applied Cryptography by Bruce Schneier
 
44
 *      This code is hereby placed in the public domain
 
45
 */
 
46
 
 
47
#include "apr_sha1.h"
 
48
#include "apr_base64.h"
 
49
#include "apr_strings.h"
 
50
#include "apr_lib.h"
 
51
#if APR_CHARSET_EBCDIC
 
52
#include "apr_xlate.h"
 
53
#endif /*APR_CHARSET_EBCDIC*/
 
54
#include <string.h>
 
55
 
 
56
/* a bit faster & bigger, if defined */
 
57
#define UNROLL_LOOPS
 
58
 
 
59
/* NIST's proposed modification to SHA, 7/11/94 */
 
60
#define USE_MODIFIED_SHA
 
61
 
 
62
/* SHA f()-functions */
 
63
#define f1(x,y,z)       ((x & y) | (~x & z))
 
64
#define f2(x,y,z)       (x ^ y ^ z)
 
65
#define f3(x,y,z)       ((x & y) | (x & z) | (y & z))
 
66
#define f4(x,y,z)       (x ^ y ^ z)
 
67
 
 
68
/* SHA constants */
 
69
#define CONST1          0x5a827999L
 
70
#define CONST2          0x6ed9eba1L
 
71
#define CONST3          0x8f1bbcdcL
 
72
#define CONST4          0xca62c1d6L
 
73
 
 
74
/* 32-bit rotate */
 
75
 
 
76
#define ROT32(x,n)      ((x << n) | (x >> (32 - n)))
 
77
 
 
78
#define FUNC(n,i)                                               \
 
79
    temp = ROT32(A,5) + f##n(B,C,D) + E + W[i] + CONST##n;      \
 
80
    E = D; D = C; C = ROT32(B,30); B = A; A = temp
 
81
 
 
82
#define SHA_BLOCKSIZE           64
 
83
 
 
84
#if APR_CHARSET_EBCDIC
 
85
static apr_xlate_t *ebcdic2ascii_xlate;
 
86
 
 
87
APU_DECLARE(apr_status_t) apr_SHA1InitEBCDIC(apr_xlate_t *x)
 
88
{
 
89
    apr_status_t rv;
 
90
    int onoff;
 
91
 
 
92
    /* Only single-byte conversion is supported.
 
93
     */
 
94
    rv = apr_xlate_sb_get(x, &onoff);
 
95
    if (rv) {
 
96
        return rv;
 
97
    }
 
98
    if (!onoff) { /* If conversion is not single-byte-only */
 
99
        return APR_EINVAL;
 
100
    }
 
101
    ebcdic2ascii_xlate = x;
 
102
    return APR_SUCCESS;
 
103
}
 
104
#endif
 
105
 
 
106
/* do SHA transformation */
 
107
static void sha_transform(apr_sha1_ctx_t *sha_info)
 
108
{
 
109
    int i;
 
110
    apr_uint32_t temp, A, B, C, D, E, W[80];
 
111
 
 
112
    for (i = 0; i < 16; ++i) {
 
113
        W[i] = sha_info->data[i];
 
114
    }
 
115
    for (i = 16; i < 80; ++i) {
 
116
        W[i] = W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16];
 
117
#ifdef USE_MODIFIED_SHA
 
118
        W[i] = ROT32(W[i], 1);
 
119
#endif /* USE_MODIFIED_SHA */
 
120
    }
 
121
    A = sha_info->digest[0];
 
122
    B = sha_info->digest[1];
 
123
    C = sha_info->digest[2];
 
124
    D = sha_info->digest[3];
 
125
    E = sha_info->digest[4];
 
126
#ifdef UNROLL_LOOPS
 
127
    FUNC(1, 0);  FUNC(1, 1);  FUNC(1, 2);  FUNC(1, 3);  FUNC(1, 4);
 
128
    FUNC(1, 5);  FUNC(1, 6);  FUNC(1, 7);  FUNC(1, 8);  FUNC(1, 9);
 
129
    FUNC(1,10);  FUNC(1,11);  FUNC(1,12);  FUNC(1,13);  FUNC(1,14);
 
130
    FUNC(1,15);  FUNC(1,16);  FUNC(1,17);  FUNC(1,18);  FUNC(1,19);
 
131
 
 
132
    FUNC(2,20);  FUNC(2,21);  FUNC(2,22);  FUNC(2,23);  FUNC(2,24);
 
133
    FUNC(2,25);  FUNC(2,26);  FUNC(2,27);  FUNC(2,28);  FUNC(2,29);
 
134
    FUNC(2,30);  FUNC(2,31);  FUNC(2,32);  FUNC(2,33);  FUNC(2,34);
 
135
    FUNC(2,35);  FUNC(2,36);  FUNC(2,37);  FUNC(2,38);  FUNC(2,39);
 
136
 
 
137
    FUNC(3,40);  FUNC(3,41);  FUNC(3,42);  FUNC(3,43);  FUNC(3,44);
 
138
    FUNC(3,45);  FUNC(3,46);  FUNC(3,47);  FUNC(3,48);  FUNC(3,49);
 
139
    FUNC(3,50);  FUNC(3,51);  FUNC(3,52);  FUNC(3,53);  FUNC(3,54);
 
140
    FUNC(3,55);  FUNC(3,56);  FUNC(3,57);  FUNC(3,58);  FUNC(3,59);
 
141
 
 
142
    FUNC(4,60);  FUNC(4,61);  FUNC(4,62);  FUNC(4,63);  FUNC(4,64);
 
143
    FUNC(4,65);  FUNC(4,66);  FUNC(4,67);  FUNC(4,68);  FUNC(4,69);
 
144
    FUNC(4,70);  FUNC(4,71);  FUNC(4,72);  FUNC(4,73);  FUNC(4,74);
 
145
    FUNC(4,75);  FUNC(4,76);  FUNC(4,77);  FUNC(4,78);  FUNC(4,79);
 
146
#else /* !UNROLL_LOOPS */
 
147
    for (i = 0; i < 20; ++i) {
 
148
        FUNC(1,i);
 
149
    }
 
150
    for (i = 20; i < 40; ++i) {
 
151
        FUNC(2,i);
 
152
    }
 
153
    for (i = 40; i < 60; ++i) {
 
154
        FUNC(3,i);
 
155
    }
 
156
    for (i = 60; i < 80; ++i) {
 
157
        FUNC(4,i);
 
158
    }
 
159
#endif /* !UNROLL_LOOPS */
 
160
    sha_info->digest[0] += A;
 
161
    sha_info->digest[1] += B;
 
162
    sha_info->digest[2] += C;
 
163
    sha_info->digest[3] += D;
 
164
    sha_info->digest[4] += E;
 
165
}
 
166
 
 
167
union endianTest {
 
168
    long Long;
 
169
    char Char[sizeof(long)];
 
170
};
 
171
 
 
172
static char isLittleEndian(void)
 
173
{
 
174
    static union endianTest u;
 
175
    u.Long = 1;
 
176
    return (u.Char[0] == 1);
 
177
}
 
178
 
 
179
/* change endianness of data */
 
180
 
 
181
/* count is the number of bytes to do an endian flip */
 
182
static void maybe_byte_reverse(apr_uint32_t *buffer, int count)
 
183
{
 
184
    int i;
 
185
    apr_byte_t ct[4], *cp;
 
186
 
 
187
    if (isLittleEndian()) {     /* do the swap only if it is little endian */
 
188
        count /= sizeof(apr_uint32_t);
 
189
        cp = (apr_byte_t *) buffer;
 
190
        for (i = 0; i < count; ++i) {
 
191
            ct[0] = cp[0];
 
192
            ct[1] = cp[1];
 
193
            ct[2] = cp[2];
 
194
            ct[3] = cp[3];
 
195
            cp[0] = ct[3];
 
196
            cp[1] = ct[2];
 
197
            cp[2] = ct[1];
 
198
            cp[3] = ct[0];
 
199
            cp += sizeof(apr_uint32_t);
 
200
        }
 
201
    }
 
202
}
 
203
 
 
204
/* initialize the SHA digest */
 
205
 
 
206
APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t *sha_info)
 
207
{
 
208
    sha_info->digest[0] = 0x67452301L;
 
209
    sha_info->digest[1] = 0xefcdab89L;
 
210
    sha_info->digest[2] = 0x98badcfeL;
 
211
    sha_info->digest[3] = 0x10325476L;
 
212
    sha_info->digest[4] = 0xc3d2e1f0L;
 
213
    sha_info->count_lo = 0L;
 
214
    sha_info->count_hi = 0L;
 
215
    sha_info->local = 0;
 
216
}
 
217
 
 
218
/* update the SHA digest */
 
219
 
 
220
APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t *sha_info,
 
221
                                     const unsigned char *buffer,
 
222
                                     unsigned int count)
 
223
{
 
224
    unsigned int i;
 
225
 
 
226
    if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
 
227
        ++sha_info->count_hi;
 
228
    }
 
229
    sha_info->count_lo += (apr_uint32_t) count << 3;
 
230
    sha_info->count_hi += (apr_uint32_t) count >> 29;
 
231
    if (sha_info->local) {
 
232
        i = SHA_BLOCKSIZE - sha_info->local;
 
233
        if (i > count) {
 
234
            i = count;
 
235
        }
 
236
        memcpy(((apr_byte_t *) sha_info->data) + sha_info->local, buffer, i);
 
237
        count -= i;
 
238
        buffer += i;
 
239
        sha_info->local += i;
 
240
        if (sha_info->local == SHA_BLOCKSIZE) {
 
241
            maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
 
242
            sha_transform(sha_info);
 
243
        }
 
244
        else {
 
245
            return;
 
246
        }
 
247
    }
 
248
    while (count >= SHA_BLOCKSIZE) {
 
249
        memcpy(sha_info->data, buffer, SHA_BLOCKSIZE);
 
250
        buffer += SHA_BLOCKSIZE;
 
251
        count -= SHA_BLOCKSIZE;
 
252
        maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
 
253
        sha_transform(sha_info);
 
254
    }
 
255
    memcpy(sha_info->data, buffer, count);
 
256
    sha_info->local = count;
 
257
}
 
258
 
 
259
APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t *sha_info, const char *buf,
 
260
                              unsigned int count)
 
261
{
 
262
#if APR_CHARSET_EBCDIC
 
263
    int i;
 
264
    const apr_byte_t *buffer = (const apr_byte_t *) buf;
 
265
    apr_size_t inbytes_left, outbytes_left;
 
266
 
 
267
    if ((sha_info->count_lo + ((apr_uint32_t) count << 3)) < sha_info->count_lo) {
 
268
        ++sha_info->count_hi;
 
269
    }
 
270
    sha_info->count_lo += (apr_uint32_t) count << 3;
 
271
    sha_info->count_hi += (apr_uint32_t) count >> 29;
 
272
    /* Is there a remainder of the previous Update operation? */
 
273
    if (sha_info->local) {
 
274
        i = SHA_BLOCKSIZE - sha_info->local;
 
275
        if (i > count) {
 
276
            i = count;
 
277
        }
 
278
        inbytes_left = outbytes_left = i;
 
279
        apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
 
280
                              ((apr_byte_t *) sha_info->data) + sha_info->local,
 
281
                              &outbytes_left);
 
282
        count -= i;
 
283
        buffer += i;
 
284
        sha_info->local += i;
 
285
        if (sha_info->local == SHA_BLOCKSIZE) {
 
286
            maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
 
287
            sha_transform(sha_info);
 
288
        }
 
289
        else {
 
290
            return;
 
291
        }
 
292
    }
 
293
    while (count >= SHA_BLOCKSIZE) {
 
294
        inbytes_left = outbytes_left = SHA_BLOCKSIZE;
 
295
        apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
 
296
                              (apr_byte_t *) sha_info->data, &outbytes_left);
 
297
        buffer += SHA_BLOCKSIZE;
 
298
        count -= SHA_BLOCKSIZE;
 
299
        maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
 
300
        sha_transform(sha_info);
 
301
    }
 
302
    inbytes_left = outbytes_left = count;
 
303
    apr_xlate_conv_buffer(ebcdic2ascii_xlate, buffer, &inbytes_left,
 
304
                          (apr_byte_t *) sha_info->data, &outbytes_left);
 
305
    sha_info->local = count;
 
306
#else
 
307
    apr_sha1_update_binary(sha_info, (const unsigned char *) buf, count);
 
308
#endif
 
309
}
 
310
 
 
311
/* finish computing the SHA digest */
 
312
 
 
313
APU_DECLARE(void) apr_sha1_final(unsigned char digest[APR_SHA1_DIGESTSIZE],
 
314
                             apr_sha1_ctx_t *sha_info)
 
315
{
 
316
    int count, i, j;
 
317
    apr_uint32_t lo_bit_count, hi_bit_count, k;
 
318
 
 
319
    lo_bit_count = sha_info->count_lo;
 
320
    hi_bit_count = sha_info->count_hi;
 
321
    count = (int) ((lo_bit_count >> 3) & 0x3f);
 
322
    ((apr_byte_t *) sha_info->data)[count++] = 0x80;
 
323
    if (count > SHA_BLOCKSIZE - 8) {
 
324
        memset(((apr_byte_t *) sha_info->data) + count, 0, SHA_BLOCKSIZE - count);
 
325
        maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
 
326
        sha_transform(sha_info);
 
327
        memset((apr_byte_t *) sha_info->data, 0, SHA_BLOCKSIZE - 8);
 
328
    }
 
329
    else {
 
330
        memset(((apr_byte_t *) sha_info->data) + count, 0,
 
331
               SHA_BLOCKSIZE - 8 - count);
 
332
    }
 
333
    maybe_byte_reverse(sha_info->data, SHA_BLOCKSIZE);
 
334
    sha_info->data[14] = hi_bit_count;
 
335
    sha_info->data[15] = lo_bit_count;
 
336
    sha_transform(sha_info);
 
337
 
 
338
    for (i = 0, j = 0; j < APR_SHA1_DIGESTSIZE; i++) {
 
339
        k = sha_info->digest[i];
 
340
        digest[j++] = (unsigned char) ((k >> 24) & 0xff);
 
341
        digest[j++] = (unsigned char) ((k >> 16) & 0xff);
 
342
        digest[j++] = (unsigned char) ((k >> 8) & 0xff);
 
343
        digest[j++] = (unsigned char) (k & 0xff);
 
344
    }
 
345
}
 
346
 
 
347
 
 
348
APU_DECLARE(void) apr_sha1_base64(const char *clear, int len, char *out)
 
349
{
 
350
    int l;
 
351
    apr_sha1_ctx_t context;
 
352
    apr_byte_t digest[APR_SHA1_DIGESTSIZE];
 
353
 
 
354
    if (strncmp(clear, APR_SHA1PW_ID, APR_SHA1PW_IDLEN) == 0) {
 
355
        clear += APR_SHA1PW_IDLEN;
 
356
    }
 
357
 
 
358
    apr_sha1_init(&context);
 
359
    apr_sha1_update(&context, clear, len);
 
360
    apr_sha1_final(digest, &context);
 
361
 
 
362
    /* private marker. */
 
363
    apr_cpystrn(out, APR_SHA1PW_ID, APR_SHA1PW_IDLEN + 1);
 
364
 
 
365
    /* SHA1 hash is always 20 chars */
 
366
    l = apr_base64_encode_binary(out + APR_SHA1PW_IDLEN, digest, sizeof(digest));
 
367
    out[l + APR_SHA1PW_IDLEN] = '\0';
 
368
 
 
369
    /*
 
370
     * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN
 
371
     */
 
372
}