1 /* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * The exported function:
20 * apr_sha1_base64(const char *clear, int len, char *out);
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:
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.
35 * See also the documentation in support/SHA1 as to hints on how to
36 * migrate an existing netscape installation and other supplied utitlites.
38 * This software also makes use of the following component:
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
48 #include "apr_base64.h"
49 #include "apr_strings.h"
51 #if APR_CHARSET_EBCDIC
52 #include "apr_xlate.h"
53 #endif /*APR_CHARSET_EBCDIC*/
56 /* a bit faster & bigger, if defined */
59 /* NIST's proposed modification to SHA, 7/11/94 */
60 #define USE_MODIFIED_SHA
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)
69 #define CONST1 0x5a827999L
70 #define CONST2 0x6ed9eba1L
71 #define CONST3 0x8f1bbcdcL
72 #define CONST4 0xca62c1d6L
76 #define ROT32(x,n) ((x << n) | (x >> (32 - n)))
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
82 #define SHA_BLOCKSIZE 64
84 #if APR_CHARSET_EBCDIC
85 static apr_xlate_t
*ebcdic2ascii_xlate
;
87 APU_DECLARE(apr_status_t
) apr_SHA1InitEBCDIC(apr_xlate_t
*x
)
92 /* Only single-byte conversion is supported.
94 rv
= apr_xlate_sb_get(x
, &onoff
);
98 if (!onoff
) { /* If conversion is not single-byte-only */
101 ebcdic2ascii_xlate
= x
;
106 /* do SHA transformation */
107 static void sha_transform(apr_sha1_ctx_t
*sha_info
)
110 apr_uint32_t temp
, A
, B
, C
, D
, E
, W
[80];
112 for (i
= 0; i
< 16; ++i
) {
113 W
[i
] = sha_info
->data
[i
];
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 */
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];
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);
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);
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);
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
) {
150 for (i
= 20; i
< 40; ++i
) {
153 for (i
= 40; i
< 60; ++i
) {
156 for (i
= 60; i
< 80; ++i
) {
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
;
169 char Char
[sizeof(long)];
172 static char isLittleEndian(void)
174 static union endianTest u
;
176 return (u
.Char
[0] == 1);
179 /* change endianness of data */
181 /* count is the number of bytes to do an endian flip */
182 static void maybe_byte_reverse(apr_uint32_t
*buffer
, int count
)
185 apr_byte_t ct
[4], *cp
;
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
) {
199 cp
+= sizeof(apr_uint32_t
);
204 /* initialize the SHA digest */
206 APU_DECLARE(void) apr_sha1_init(apr_sha1_ctx_t
*sha_info
)
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;
218 /* update the SHA digest */
220 APU_DECLARE(void) apr_sha1_update_binary(apr_sha1_ctx_t
*sha_info
,
221 const unsigned char *buffer
,
226 if ((sha_info
->count_lo
+ ((apr_uint32_t
) count
<< 3)) < sha_info
->count_lo
) {
227 ++sha_info
->count_hi
;
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
;
236 memcpy(((apr_byte_t
*) sha_info
->data
) + sha_info
->local
, 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
);
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
);
255 memcpy(sha_info
->data
, buffer
, count
);
256 sha_info
->local
= count
;
259 APU_DECLARE(void) apr_sha1_update(apr_sha1_ctx_t
*sha_info
, const char *buf
,
262 #if APR_CHARSET_EBCDIC
264 const apr_byte_t
*buffer
= (const apr_byte_t
*) buf
;
265 apr_size_t inbytes_left
, outbytes_left
;
267 if ((sha_info
->count_lo
+ ((apr_uint32_t
) count
<< 3)) < sha_info
->count_lo
) {
268 ++sha_info
->count_hi
;
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
;
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
,
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
);
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
);
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
;
307 apr_sha1_update_binary(sha_info
, (const unsigned char *) buf
, count
);
311 /* finish computing the SHA digest */
313 APU_DECLARE(void) apr_sha1_final(unsigned char digest
[APR_SHA1_DIGESTSIZE
],
314 apr_sha1_ctx_t
*sha_info
)
317 apr_uint32_t lo_bit_count
, hi_bit_count
, k
;
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);
330 memset(((apr_byte_t
*) sha_info
->data
) + count
, 0,
331 SHA_BLOCKSIZE
- 8 - count
);
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
);
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);
348 APU_DECLARE(void) apr_sha1_base64(const char *clear
, int len
, char *out
)
351 apr_sha1_ctx_t context
;
352 apr_byte_t digest
[APR_SHA1_DIGESTSIZE
];
354 if (strncmp(clear
, APR_SHA1PW_ID
, APR_SHA1PW_IDLEN
) == 0) {
355 clear
+= APR_SHA1PW_IDLEN
;
358 apr_sha1_init(&context
);
359 apr_sha1_update(&context
, clear
, len
);
360 apr_sha1_final(digest
, &context
);
362 /* private marker. */
363 apr_cpystrn(out
, APR_SHA1PW_ID
, APR_SHA1PW_IDLEN
+ 1);
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';
370 * output of base64 encoded SHA1 is always 28 chars + APR_SHA1PW_IDLEN