1251876Speter/*
2251876Speter * This is work is derived from material Copyright RSA Data Security, Inc.
3251876Speter *
4251876Speter * The RSA copyright statement and Licence for that original material is
5251876Speter * included below. This is followed by the Apache copyright statement and
6251876Speter * licence for the modifications made to that material.
7251876Speter */
8251876Speter
9251876Speter/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
10251876Speter */
11251876Speter
12251876Speter/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
13251876Speter   rights reserved.
14251876Speter
15251876Speter   License to copy and use this software is granted provided that it
16251876Speter   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
17251876Speter   Algorithm" in all material mentioning or referencing this software
18251876Speter   or this function.
19251876Speter
20251876Speter   License is also granted to make and use derivative works provided
21251876Speter   that such works are identified as "derived from the RSA Data
22251876Speter   Security, Inc. MD5 Message-Digest Algorithm" in all material
23251876Speter   mentioning or referencing the derived work.
24251876Speter
25251876Speter   RSA Data Security, Inc. makes no representations concerning either
26251876Speter   the merchantability of this software or the suitability of this
27251876Speter   software for any particular purpose. It is provided "as is"
28251876Speter   without express or implied warranty of any kind.
29251876Speter
30251876Speter   These notices must be retained in any copies of any part of this
31251876Speter   documentation and/or software.
32251876Speter */
33251876Speter
34251876Speter/* Licensed to the Apache Software Foundation (ASF) under one or more
35251876Speter * contributor license agreements.  See the NOTICE file distributed with
36251876Speter * this work for additional information regarding copyright ownership.
37251876Speter * The ASF licenses this file to You under the Apache License, Version 2.0
38251876Speter * (the "License"); you may not use this file except in compliance with
39251876Speter * the License.  You may obtain a copy of the License at
40251876Speter *
41251876Speter *     http://www.apache.org/licenses/LICENSE-2.0
42251876Speter *
43251876Speter * Unless required by applicable law or agreed to in writing, software
44251876Speter * distributed under the License is distributed on an "AS IS" BASIS,
45251876Speter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
46251876Speter * See the License for the specific language governing permissions and
47251876Speter * limitations under the License.
48251876Speter */
49251876Speter
50251876Speter/*
51251876Speter * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
52251876Speter * MD5 crypt() function, which is licenced as follows:
53251876Speter * ----------------------------------------------------------------------------
54251876Speter * "THE BEER-WARE LICENSE" (Revision 42):
55251876Speter * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
56251876Speter * can do whatever you want with this stuff. If we meet some day, and you think
57251876Speter * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
58251876Speter * ----------------------------------------------------------------------------
59251876Speter */
60251876Speter#include "apr_strings.h"
61251876Speter#include "apr_md5.h"
62251876Speter#include "apr_lib.h"
63251876Speter#include "apu_config.h"
64251876Speter
65251876Speter#if APR_HAVE_STRING_H
66251876Speter#include <string.h>
67251876Speter#endif
68251876Speter
69251876Speter/* Constants for MD5Transform routine.
70251876Speter */
71251876Speter
72251876Speter#define S11 7
73251876Speter#define S12 12
74251876Speter#define S13 17
75251876Speter#define S14 22
76251876Speter#define S21 5
77251876Speter#define S22 9
78251876Speter#define S23 14
79251876Speter#define S24 20
80251876Speter#define S31 4
81251876Speter#define S32 11
82251876Speter#define S33 16
83251876Speter#define S34 23
84251876Speter#define S41 6
85251876Speter#define S42 10
86251876Speter#define S43 15
87251876Speter#define S44 21
88251876Speter
89251876Speterstatic void MD5Transform(apr_uint32_t state[4], const unsigned char block[64]);
90251876Speterstatic void Encode(unsigned char *output, const apr_uint32_t *input,
91251876Speter                   unsigned int len);
92251876Speterstatic void Decode(apr_uint32_t *output, const unsigned char *input,
93251876Speter                   unsigned int len);
94251876Speter
95251876Speterstatic const unsigned char PADDING[64] =
96251876Speter{
97251876Speter    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
98251876Speter    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
99251876Speter    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
100251876Speter};
101251876Speter
102251876Speter#if APR_CHARSET_EBCDIC
103251876Speterstatic apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md5_encode() */
104251876Speter#endif
105251876Speter#define DO_XLATE 0
106251876Speter#define SKIP_XLATE 1
107251876Speter
108251876Speter/* F, G, H and I are basic MD5 functions.
109251876Speter */
110251876Speter#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
111251876Speter#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
112251876Speter#define H(x, y, z) ((x) ^ (y) ^ (z))
113251876Speter#define I(x, y, z) ((y) ^ ((x) | (~z)))
114251876Speter
115251876Speter/* ROTATE_LEFT rotates x left n bits.
116251876Speter */
117251876Speter#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
118251876Speter
119251876Speter/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
120251876Speter * Rotation is separate from addition to prevent recomputation.
121251876Speter */
122251876Speter#define FF(a, b, c, d, x, s, ac) { \
123251876Speter (a) += F ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
124251876Speter (a) = ROTATE_LEFT ((a), (s)); \
125251876Speter (a) += (b); \
126251876Speter  }
127251876Speter#define GG(a, b, c, d, x, s, ac) { \
128251876Speter (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
129251876Speter (a) = ROTATE_LEFT ((a), (s)); \
130251876Speter (a) += (b); \
131251876Speter  }
132251876Speter#define HH(a, b, c, d, x, s, ac) { \
133251876Speter (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
134251876Speter (a) = ROTATE_LEFT ((a), (s)); \
135251876Speter (a) += (b); \
136251876Speter  }
137251876Speter#define II(a, b, c, d, x, s, ac) { \
138251876Speter (a) += I ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
139251876Speter (a) = ROTATE_LEFT ((a), (s)); \
140251876Speter (a) += (b); \
141251876Speter  }
142251876Speter
143251876Speter/* MD5 initialization. Begins an MD5 operation, writing a new context.
144251876Speter */
145251876SpeterAPU_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context)
146251876Speter{
147251876Speter    context->count[0] = context->count[1] = 0;
148251876Speter
149251876Speter    /* Load magic initialization constants. */
150251876Speter    context->state[0] = 0x67452301;
151251876Speter    context->state[1] = 0xefcdab89;
152251876Speter    context->state[2] = 0x98badcfe;
153251876Speter    context->state[3] = 0x10325476;
154251876Speter    context->xlate = NULL;
155251876Speter
156251876Speter    return APR_SUCCESS;
157251876Speter}
158251876Speter
159251876Speter/* MD5 translation setup.  Provides the APR translation handle
160251876Speter * to be used for translating the content before calculating the
161251876Speter * digest.
162251876Speter */
163251876SpeterAPU_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context,
164251876Speter                                            apr_xlate_t *xlate)
165251876Speter{
166251876Speter#if APR_HAS_XLATE
167251876Speter    apr_status_t rv;
168251876Speter    int is_sb;
169251876Speter
170251876Speter    /* TODO: remove the single-byte-only restriction from this code
171251876Speter     */
172251876Speter    rv = apr_xlate_sb_get(xlate, &is_sb);
173251876Speter    if (rv != APR_SUCCESS) {
174251876Speter        return rv;
175251876Speter    }
176251876Speter    if (!is_sb) {
177251876Speter        return APR_EINVAL;
178251876Speter    }
179251876Speter    context->xlate = xlate;
180251876Speter    return APR_SUCCESS;
181251876Speter#else
182251876Speter    return APR_ENOTIMPL;
183251876Speter#endif /* APR_HAS_XLATE */
184251876Speter}
185251876Speter
186251876Speter/* MD5 block update operation. Continues an MD5 message-digest
187251876Speter * operation, processing another message block, and updating the
188251876Speter * context.
189251876Speter */
190251876Speterstatic apr_status_t md5_update_buffer(apr_md5_ctx_t *context,
191251876Speter                                      const void *vinput,
192251876Speter                                      apr_size_t inputLen,
193251876Speter                                      int xlate_buffer)
194251876Speter{
195251876Speter    const unsigned char *input = vinput;
196251876Speter    unsigned int i, idx, partLen;
197251876Speter#if APR_HAS_XLATE
198251876Speter    apr_size_t inbytes_left, outbytes_left;
199251876Speter#endif
200251876Speter
201251876Speter    /* Compute number of bytes mod 64 */
202251876Speter    idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
203251876Speter
204251876Speter    /* Update number of bits */
205251876Speter    if ((context->count[0] += ((apr_uint32_t)inputLen << 3))
206251876Speter            < ((apr_uint32_t)inputLen << 3))
207251876Speter        context->count[1]++;
208251876Speter    context->count[1] += (apr_uint32_t)inputLen >> 29;
209251876Speter
210251876Speter    partLen = 64 - idx;
211251876Speter
212251876Speter    /* Transform as many times as possible. */
213251876Speter#if !APR_HAS_XLATE
214251876Speter    if (inputLen >= partLen) {
215251876Speter        memcpy(&context->buffer[idx], input, partLen);
216251876Speter        MD5Transform(context->state, context->buffer);
217251876Speter
218251876Speter        for (i = partLen; i + 63 < inputLen; i += 64)
219251876Speter            MD5Transform(context->state, &input[i]);
220251876Speter
221251876Speter        idx = 0;
222251876Speter    }
223251876Speter    else
224251876Speter        i = 0;
225251876Speter
226251876Speter    /* Buffer remaining input */
227251876Speter    memcpy(&context->buffer[idx], &input[i], inputLen - i);
228251876Speter#else /*APR_HAS_XLATE*/
229251876Speter    if (inputLen >= partLen) {
230251876Speter        if (context->xlate && (xlate_buffer == DO_XLATE)) {
231251876Speter            inbytes_left = outbytes_left = partLen;
232251876Speter            apr_xlate_conv_buffer(context->xlate, (const char *)input,
233251876Speter                                  &inbytes_left,
234251876Speter                                  (char *)&context->buffer[idx],
235251876Speter                                  &outbytes_left);
236251876Speter        }
237251876Speter        else {
238251876Speter            memcpy(&context->buffer[idx], input, partLen);
239251876Speter        }
240251876Speter        MD5Transform(context->state, context->buffer);
241251876Speter
242251876Speter        for (i = partLen; i + 63 < inputLen; i += 64) {
243251876Speter            if (context->xlate && (xlate_buffer == DO_XLATE)) {
244251876Speter                unsigned char inp_tmp[64];
245251876Speter                inbytes_left = outbytes_left = 64;
246251876Speter                apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
247251876Speter                                      &inbytes_left, (char *)inp_tmp,
248251876Speter                                      &outbytes_left);
249251876Speter                MD5Transform(context->state, inp_tmp);
250251876Speter            }
251251876Speter            else {
252251876Speter                MD5Transform(context->state, &input[i]);
253251876Speter            }
254251876Speter        }
255251876Speter
256251876Speter        idx = 0;
257251876Speter    }
258251876Speter    else
259251876Speter        i = 0;
260251876Speter
261251876Speter    /* Buffer remaining input */
262251876Speter    if (context->xlate && (xlate_buffer == DO_XLATE)) {
263251876Speter        inbytes_left = outbytes_left = inputLen - i;
264251876Speter        apr_xlate_conv_buffer(context->xlate, (const char *)&input[i],
265251876Speter                              &inbytes_left, (char *)&context->buffer[idx],
266251876Speter                              &outbytes_left);
267251876Speter    }
268251876Speter    else {
269251876Speter        memcpy(&context->buffer[idx], &input[i], inputLen - i);
270251876Speter    }
271251876Speter#endif /*APR_HAS_XLATE*/
272251876Speter    return APR_SUCCESS;
273251876Speter}
274251876Speter
275251876Speter/* MD5 block update operation. API with the default setting
276251876Speter * for EBCDIC translations
277251876Speter */
278251876SpeterAPU_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
279251876Speter                                         const void *input,
280251876Speter                                         apr_size_t inputLen)
281251876Speter{
282251876Speter    return md5_update_buffer(context, input, inputLen, DO_XLATE);
283251876Speter}
284251876Speter
285251876Speter/* MD5 finalization. Ends an MD5 message-digest operation, writing the
286251876Speter * the message digest and zeroizing the context.
287251876Speter */
288251876SpeterAPU_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
289251876Speter                                        apr_md5_ctx_t *context)
290251876Speter{
291251876Speter    unsigned char bits[8];
292251876Speter    unsigned int idx, padLen;
293251876Speter
294251876Speter    /* Save number of bits */
295251876Speter    Encode(bits, context->count, 8);
296251876Speter
297251876Speter#if APR_HAS_XLATE
298251876Speter    /* apr_md5_update() should not translate for this final round. */
299251876Speter    context->xlate = NULL;
300251876Speter#endif /*APR_HAS_XLATE*/
301251876Speter
302251876Speter    /* Pad out to 56 mod 64. */
303251876Speter    idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
304251876Speter    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
305251876Speter    apr_md5_update(context, PADDING, padLen);
306251876Speter
307251876Speter    /* Append length (before padding) */
308251876Speter    apr_md5_update(context, bits, 8);
309251876Speter
310251876Speter    /* Store state in digest */
311251876Speter    Encode(digest, context->state, APR_MD5_DIGESTSIZE);
312251876Speter
313251876Speter    /* Zeroize sensitive information. */
314251876Speter    memset(context, 0, sizeof(*context));
315251876Speter
316251876Speter    return APR_SUCCESS;
317251876Speter}
318251876Speter
319251876Speter/* MD5 in one step (init, update, final)
320251876Speter */
321251876SpeterAPU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
322251876Speter                                  const void *_input,
323251876Speter                                  apr_size_t inputLen)
324251876Speter{
325251876Speter    const unsigned char *input = _input;
326251876Speter    apr_md5_ctx_t ctx;
327251876Speter    apr_status_t rv;
328251876Speter
329251876Speter    apr_md5_init(&ctx);
330251876Speter
331251876Speter    if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
332251876Speter        return rv;
333251876Speter
334251876Speter    return apr_md5_final(digest, &ctx);
335251876Speter}
336251876Speter
337251876Speter/* MD5 basic transformation. Transforms state based on block. */
338251876Speterstatic void MD5Transform(apr_uint32_t state[4], const unsigned char block[64])
339251876Speter{
340251876Speter    apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
341253734Speter                 tmpbuf[APR_MD5_DIGESTSIZE];
342253734Speter    const apr_uint32_t *x;
343251876Speter
344253734Speter#if !APR_IS_BIGENDIAN
345253734Speter    if ((apr_uintptr_t)block % sizeof(apr_uint32_t) == 0) {
346253734Speter        x = (apr_uint32_t *)block;
347253734Speter    } else
348253734Speter#endif
349253734Speter    {
350253734Speter        Decode(tmpbuf, block, 64);
351253734Speter	x = tmpbuf;
352253734Speter    }
353251876Speter
354251876Speter    /* Round 1 */
355251876Speter    FF(a, b, c, d, x[0],  S11, 0xd76aa478); /* 1 */
356251876Speter    FF(d, a, b, c, x[1],  S12, 0xe8c7b756); /* 2 */
357251876Speter    FF(c, d, a, b, x[2],  S13, 0x242070db); /* 3 */
358251876Speter    FF(b, c, d, a, x[3],  S14, 0xc1bdceee); /* 4 */
359251876Speter    FF(a, b, c, d, x[4],  S11, 0xf57c0faf); /* 5 */
360251876Speter    FF(d, a, b, c, x[5],  S12, 0x4787c62a); /* 6 */
361251876Speter    FF(c, d, a, b, x[6],  S13, 0xa8304613); /* 7 */
362251876Speter    FF(b, c, d, a, x[7],  S14, 0xfd469501); /* 8 */
363251876Speter    FF(a, b, c, d, x[8],  S11, 0x698098d8); /* 9 */
364251876Speter    FF(d, a, b, c, x[9],  S12, 0x8b44f7af); /* 10 */
365251876Speter    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
366251876Speter    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
367251876Speter    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
368251876Speter    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
369251876Speter    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
370251876Speter    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
371251876Speter
372251876Speter    /* Round 2 */
373251876Speter    GG(a, b, c, d, x[1],  S21, 0xf61e2562); /* 17 */
374251876Speter    GG(d, a, b, c, x[6],  S22, 0xc040b340); /* 18 */
375251876Speter    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
376251876Speter    GG(b, c, d, a, x[0],  S24, 0xe9b6c7aa); /* 20 */
377251876Speter    GG(a, b, c, d, x[5],  S21, 0xd62f105d); /* 21 */
378251876Speter    GG(d, a, b, c, x[10], S22, 0x2441453);  /* 22 */
379251876Speter    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
380251876Speter    GG(b, c, d, a, x[4],  S24, 0xe7d3fbc8); /* 24 */
381251876Speter    GG(a, b, c, d, x[9],  S21, 0x21e1cde6); /* 25 */
382251876Speter    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
383251876Speter    GG(c, d, a, b, x[3],  S23, 0xf4d50d87); /* 27 */
384251876Speter    GG(b, c, d, a, x[8],  S24, 0x455a14ed); /* 28 */
385251876Speter    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
386251876Speter    GG(d, a, b, c, x[2],  S22, 0xfcefa3f8); /* 30 */
387251876Speter    GG(c, d, a, b, x[7],  S23, 0x676f02d9); /* 31 */
388251876Speter    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
389251876Speter
390251876Speter    /* Round 3 */
391251876Speter    HH(a, b, c, d, x[5],  S31, 0xfffa3942); /* 33 */
392251876Speter    HH(d, a, b, c, x[8],  S32, 0x8771f681); /* 34 */
393251876Speter    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
394251876Speter    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
395251876Speter    HH(a, b, c, d, x[1],  S31, 0xa4beea44); /* 37 */
396251876Speter    HH(d, a, b, c, x[4],  S32, 0x4bdecfa9); /* 38 */
397251876Speter    HH(c, d, a, b, x[7],  S33, 0xf6bb4b60); /* 39 */
398251876Speter    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
399251876Speter    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
400251876Speter    HH(d, a, b, c, x[0],  S32, 0xeaa127fa); /* 42 */
401251876Speter    HH(c, d, a, b, x[3],  S33, 0xd4ef3085); /* 43 */
402251876Speter    HH(b, c, d, a, x[6],  S34, 0x4881d05);  /* 44 */
403251876Speter    HH(a, b, c, d, x[9],  S31, 0xd9d4d039); /* 45 */
404251876Speter    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
405251876Speter    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
406251876Speter    HH(b, c, d, a, x[2],  S34, 0xc4ac5665); /* 48 */
407251876Speter
408251876Speter    /* Round 4 */
409251876Speter    II(a, b, c, d, x[0],  S41, 0xf4292244); /* 49 */
410251876Speter    II(d, a, b, c, x[7],  S42, 0x432aff97); /* 50 */
411251876Speter    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
412251876Speter    II(b, c, d, a, x[5],  S44, 0xfc93a039); /* 52 */
413251876Speter    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
414251876Speter    II(d, a, b, c, x[3],  S42, 0x8f0ccc92); /* 54 */
415251876Speter    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
416251876Speter    II(b, c, d, a, x[1],  S44, 0x85845dd1); /* 56 */
417251876Speter    II(a, b, c, d, x[8],  S41, 0x6fa87e4f); /* 57 */
418251876Speter    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
419251876Speter    II(c, d, a, b, x[6],  S43, 0xa3014314); /* 59 */
420251876Speter    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
421251876Speter    II(a, b, c, d, x[4],  S41, 0xf7537e82); /* 61 */
422251876Speter    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
423251876Speter    II(c, d, a, b, x[2],  S43, 0x2ad7d2bb); /* 63 */
424251876Speter    II(b, c, d, a, x[9],  S44, 0xeb86d391); /* 64 */
425251876Speter
426251876Speter    state[0] += a;
427251876Speter    state[1] += b;
428251876Speter    state[2] += c;
429251876Speter    state[3] += d;
430251876Speter
431253734Speter#if !APR_IS_BIGENDIAN
432253734Speter    if (x == tmpbuf)
433253734Speter#endif
434253734Speter    {
435253734Speter        /* Zeroize sensitive information. */
436253734Speter        memset(tmpbuf, 0, sizeof(tmpbuf));
437253734Speter    }
438251876Speter}
439251876Speter
440251876Speter/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
441251876Speter * a multiple of 4.
442251876Speter */
443251876Speterstatic void Encode(unsigned char *output, const apr_uint32_t *input,
444251876Speter                   unsigned int len)
445251876Speter{
446251876Speter    unsigned int i, j;
447251876Speter    apr_uint32_t k;
448251876Speter
449251876Speter    for (i = 0, j = 0; j < len; i++, j += 4) {
450251876Speter        k = input[i];
451251876Speter        output[j]     = (unsigned char)(k & 0xff);
452251876Speter        output[j + 1] = (unsigned char)((k >> 8) & 0xff);
453251876Speter        output[j + 2] = (unsigned char)((k >> 16) & 0xff);
454251876Speter        output[j + 3] = (unsigned char)((k >> 24) & 0xff);
455251876Speter    }
456251876Speter}
457251876Speter
458251876Speter/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
459251876Speter * a multiple of 4.
460251876Speter */
461251876Speterstatic void Decode(apr_uint32_t *output, const unsigned char *input,
462251876Speter                   unsigned int len)
463251876Speter{
464251876Speter    unsigned int i, j;
465251876Speter
466251876Speter    for (i = 0, j = 0; j < len; i++, j += 4)
467251876Speter        output[i] = ((apr_uint32_t)input[j])             |
468251876Speter                    (((apr_uint32_t)input[j + 1]) << 8)  |
469251876Speter                    (((apr_uint32_t)input[j + 2]) << 16) |
470251876Speter                    (((apr_uint32_t)input[j + 3]) << 24);
471251876Speter}
472251876Speter
473251876Speter#if APR_CHARSET_EBCDIC
474251876SpeterAPU_DECLARE(apr_status_t) apr_MD5InitEBCDIC(apr_xlate_t *xlate)
475251876Speter{
476251876Speter    xlate_ebcdic_to_ascii = xlate;
477251876Speter    return APR_SUCCESS;
478251876Speter}
479251876Speter#endif
480251876Speter
481251876Speter/*
482251876Speter * Define the Magic String prefix that identifies a password as being
483251876Speter * hashed using our algorithm.
484251876Speter */
485253734Speterstatic const char * const apr1_id = "$apr1$";
486251876Speter
487251876Speter/*
488251876Speter * The following MD5 password encryption code was largely borrowed from
489251876Speter * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
490251876Speter * licenced as stated at the top of this file.
491251876Speter */
492251876Speter
493251876Speterstatic void to64(char *s, unsigned long v, int n)
494251876Speter{
495251876Speter    static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
496251876Speter        "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
497251876Speter
498251876Speter    while (--n >= 0) {
499251876Speter        *s++ = itoa64[v&0x3f];
500251876Speter        v >>= 6;
501251876Speter    }
502251876Speter}
503251876Speter
504251876SpeterAPU_DECLARE(apr_status_t) apr_md5_encode(const char *pw, const char *salt,
505251876Speter                             char *result, apr_size_t nbytes)
506251876Speter{
507251876Speter    /*
508251876Speter     * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
509251876Speter     * plus 4 for the '$' separators, plus the password hash itself.
510251876Speter     * Let's leave a goodly amount of leeway.
511251876Speter     */
512251876Speter
513251876Speter    char passwd[120], *p;
514251876Speter    const char *sp, *ep;
515251876Speter    unsigned char final[APR_MD5_DIGESTSIZE];
516251876Speter    apr_ssize_t sl, pl, i;
517251876Speter    apr_md5_ctx_t ctx, ctx1;
518251876Speter    unsigned long l;
519251876Speter
520251876Speter    /*
521251876Speter     * Refine the salt first.  It's possible we were given an already-hashed
522251876Speter     * string as the salt argument, so extract the actual salt value from it
523251876Speter     * if so.  Otherwise just use the string up to the first '$' as the salt.
524251876Speter     */
525251876Speter    sp = salt;
526251876Speter
527251876Speter    /*
528251876Speter     * If it starts with the magic string, then skip that.
529251876Speter     */
530251876Speter    if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
531251876Speter        sp += strlen(apr1_id);
532251876Speter    }
533251876Speter
534251876Speter    /*
535251876Speter     * It stops at the first '$' or 8 chars, whichever comes first
536251876Speter     */
537251876Speter    for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
538251876Speter        continue;
539251876Speter    }
540251876Speter
541251876Speter    /*
542251876Speter     * Get the length of the true salt
543251876Speter     */
544251876Speter    sl = ep - sp;
545251876Speter
546251876Speter    /*
547251876Speter     * 'Time to make the doughnuts..'
548251876Speter     */
549251876Speter    apr_md5_init(&ctx);
550251876Speter#if APR_CHARSET_EBCDIC
551251876Speter    apr_md5_set_xlate(&ctx, xlate_ebcdic_to_ascii);
552251876Speter#endif
553251876Speter
554251876Speter    /*
555251876Speter     * The password first, since that is what is most unknown
556251876Speter     */
557251876Speter    apr_md5_update(&ctx, pw, strlen(pw));
558251876Speter
559251876Speter    /*
560251876Speter     * Then our magic string
561251876Speter     */
562251876Speter    apr_md5_update(&ctx, apr1_id, strlen(apr1_id));
563251876Speter
564251876Speter    /*
565251876Speter     * Then the raw salt
566251876Speter     */
567251876Speter    apr_md5_update(&ctx, sp, sl);
568251876Speter
569251876Speter    /*
570251876Speter     * Then just as many characters of the MD5(pw, salt, pw)
571251876Speter     */
572251876Speter    apr_md5_init(&ctx1);
573251876Speter#if APR_CHARSET_EBCDIC
574251876Speter    apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
575251876Speter#endif
576251876Speter    apr_md5_update(&ctx1, pw, strlen(pw));
577251876Speter    apr_md5_update(&ctx1, sp, sl);
578251876Speter    apr_md5_update(&ctx1, pw, strlen(pw));
579251876Speter    apr_md5_final(final, &ctx1);
580251876Speter    for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
581251876Speter        md5_update_buffer(&ctx, final,
582251876Speter                      (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl, SKIP_XLATE);
583251876Speter    }
584251876Speter
585251876Speter    /*
586251876Speter     * Don't leave anything around in vm they could use.
587251876Speter     */
588251876Speter    memset(final, 0, sizeof(final));
589251876Speter
590251876Speter    /*
591251876Speter     * Then something really weird...
592251876Speter     */
593251876Speter    for (i = strlen(pw); i != 0; i >>= 1) {
594251876Speter        if (i & 1) {
595251876Speter            md5_update_buffer(&ctx, final, 1, SKIP_XLATE);
596251876Speter        }
597251876Speter        else {
598251876Speter            apr_md5_update(&ctx, pw, 1);
599251876Speter        }
600251876Speter    }
601251876Speter
602251876Speter    /*
603251876Speter     * Now make the output string.  We know our limitations, so we
604251876Speter     * can use the string routines without bounds checking.
605251876Speter     */
606251876Speter    strcpy(passwd, apr1_id);
607251876Speter    strncat(passwd, sp, sl);
608251876Speter    strcat(passwd, "$");
609251876Speter
610251876Speter    apr_md5_final(final, &ctx);
611251876Speter
612251876Speter    /*
613251876Speter     * And now, just to make sure things don't run too fast..
614251876Speter     * On a 60 Mhz Pentium this takes 34 msec, so you would
615251876Speter     * need 30 seconds to build a 1000 entry dictionary...
616251876Speter     */
617251876Speter    for (i = 0; i < 1000; i++) {
618251876Speter        apr_md5_init(&ctx1);
619251876Speter         /*
620251876Speter          * apr_md5_final clears out ctx1.xlate at the end of each loop,
621251876Speter          * so need to to set it each time through
622251876Speter          */
623251876Speter#if APR_CHARSET_EBCDIC
624251876Speter        apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
625251876Speter#endif
626251876Speter        if (i & 1) {
627251876Speter            apr_md5_update(&ctx1, pw, strlen(pw));
628251876Speter        }
629251876Speter        else {
630251876Speter            md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
631251876Speter        }
632251876Speter        if (i % 3) {
633251876Speter            apr_md5_update(&ctx1, sp, sl);
634251876Speter        }
635251876Speter
636251876Speter        if (i % 7) {
637251876Speter            apr_md5_update(&ctx1, pw, strlen(pw));
638251876Speter        }
639251876Speter
640251876Speter        if (i & 1) {
641251876Speter            md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
642251876Speter        }
643251876Speter        else {
644251876Speter            apr_md5_update(&ctx1, pw, strlen(pw));
645251876Speter        }
646251876Speter        apr_md5_final(final,&ctx1);
647251876Speter    }
648251876Speter
649251876Speter    p = passwd + strlen(passwd);
650251876Speter
651251876Speter    l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
652251876Speter    l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
653251876Speter    l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
654251876Speter    l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
655251876Speter    l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
656251876Speter    l =                    final[11]                ; to64(p, l, 2); p += 2;
657251876Speter    *p = '\0';
658251876Speter
659251876Speter    /*
660251876Speter     * Don't leave anything around in vm they could use.
661251876Speter     */
662251876Speter    memset(final, 0, sizeof(final));
663251876Speter
664251876Speter    apr_cpystrn(result, passwd, nbytes - 1);
665251876Speter    return APR_SUCCESS;
666251876Speter}
667