Blame crypto/apr_md5.c

Packit 383869
/*
Packit 383869
 * This is work is derived from material Copyright RSA Data Security, Inc.
Packit 383869
 *
Packit 383869
 * The RSA copyright statement and Licence for that original material is
Packit 383869
 * included below. This is followed by the Apache copyright statement and
Packit 383869
 * licence for the modifications made to that material.
Packit 383869
 */
Packit 383869
Packit 383869
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
Packit 383869
 */
Packit 383869
Packit 383869
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
Packit 383869
   rights reserved.
Packit 383869
Packit 383869
   License to copy and use this software is granted provided that it
Packit 383869
   is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Packit 383869
   Algorithm" in all material mentioning or referencing this software
Packit 383869
   or this function.
Packit 383869
Packit 383869
   License is also granted to make and use derivative works provided
Packit 383869
   that such works are identified as "derived from the RSA Data
Packit 383869
   Security, Inc. MD5 Message-Digest Algorithm" in all material
Packit 383869
   mentioning or referencing the derived work.
Packit 383869
Packit 383869
   RSA Data Security, Inc. makes no representations concerning either
Packit 383869
   the merchantability of this software or the suitability of this
Packit 383869
   software for any particular purpose. It is provided "as is"
Packit 383869
   without express or implied warranty of any kind.
Packit 383869
Packit 383869
   These notices must be retained in any copies of any part of this
Packit 383869
   documentation and/or software.
Packit 383869
 */
Packit 383869
Packit 383869
/* Licensed to the Apache Software Foundation (ASF) under one or more
Packit 383869
 * contributor license agreements.  See the NOTICE file distributed with
Packit 383869
 * this work for additional information regarding copyright ownership.
Packit 383869
 * The ASF licenses this file to You under the Apache License, Version 2.0
Packit 383869
 * (the "License"); you may not use this file except in compliance with
Packit 383869
 * the License.  You may obtain a copy of the License at
Packit 383869
 *
Packit 383869
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 383869
 *
Packit 383869
 * Unless required by applicable law or agreed to in writing, software
Packit 383869
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 383869
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 383869
 * See the License for the specific language governing permissions and
Packit 383869
 * limitations under the License.
Packit 383869
 */
Packit 383869
Packit 383869
/*
Packit 383869
 * The apr_md5_encode() routine uses much code obtained from the FreeBSD 3.0
Packit 383869
 * MD5 crypt() function, which is licenced as follows:
Packit 383869
 * ----------------------------------------------------------------------------
Packit 383869
 * "THE BEER-WARE LICENSE" (Revision 42):
Packit 383869
 * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
Packit 383869
 * can do whatever you want with this stuff. If we meet some day, and you think
Packit 383869
 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
Packit 383869
 * ----------------------------------------------------------------------------
Packit 383869
 */
Packit 383869
#include "apr_strings.h"
Packit 383869
#include "apr_md5.h"
Packit 383869
#include "apr_lib.h"
Packit 383869
#include "apu_config.h"
Packit 383869
Packit 383869
#if APR_HAVE_STRING_H
Packit 383869
#include <string.h>
Packit 383869
#endif
Packit 383869
Packit 383869
/* Constants for MD5Transform routine.
Packit 383869
 */
Packit 383869
Packit 383869
#define S11 7
Packit 383869
#define S12 12
Packit 383869
#define S13 17
Packit 383869
#define S14 22
Packit 383869
#define S21 5
Packit 383869
#define S22 9
Packit 383869
#define S23 14
Packit 383869
#define S24 20
Packit 383869
#define S31 4
Packit 383869
#define S32 11
Packit 383869
#define S33 16
Packit 383869
#define S34 23
Packit 383869
#define S41 6
Packit 383869
#define S42 10
Packit 383869
#define S43 15
Packit 383869
#define S44 21
Packit 383869
Packit 383869
static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64]);
Packit 383869
static void Encode(unsigned char *output, const apr_uint32_t *input,
Packit 383869
                   unsigned int len);
Packit 383869
static void Decode(apr_uint32_t *output, const unsigned char *input,
Packit 383869
                   unsigned int len);
Packit 383869
Packit 383869
static const unsigned char PADDING[64] =
Packit 383869
{
Packit 383869
    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit 383869
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
Packit 383869
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Packit 383869
};
Packit 383869
Packit 383869
#if APR_CHARSET_EBCDIC
Packit 383869
static apr_xlate_t *xlate_ebcdic_to_ascii; /* used in apr_md5_encode() */
Packit 383869
#endif
Packit 383869
#define DO_XLATE 0
Packit 383869
#define SKIP_XLATE 1
Packit 383869
Packit 383869
/* F, G, H and I are basic MD5 functions.
Packit 383869
 */
Packit 383869
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
Packit 383869
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
Packit 383869
#define H(x, y, z) ((x) ^ (y) ^ (z))
Packit 383869
#define I(x, y, z) ((y) ^ ((x) | (~z)))
Packit 383869
Packit 383869
/* ROTATE_LEFT rotates x left n bits.
Packit 383869
 */
Packit 383869
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
Packit 383869
Packit 383869
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Packit 383869
 * Rotation is separate from addition to prevent recomputation.
Packit 383869
 */
Packit 383869
#define FF(a, b, c, d, x, s, ac) { \
Packit 383869
 (a) += F ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
Packit 383869
 (a) = ROTATE_LEFT ((a), (s)); \
Packit 383869
 (a) += (b); \
Packit 383869
  }
Packit 383869
#define GG(a, b, c, d, x, s, ac) { \
Packit 383869
 (a) += G ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
Packit 383869
 (a) = ROTATE_LEFT ((a), (s)); \
Packit 383869
 (a) += (b); \
Packit 383869
  }
Packit 383869
#define HH(a, b, c, d, x, s, ac) { \
Packit 383869
 (a) += H ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
Packit 383869
 (a) = ROTATE_LEFT ((a), (s)); \
Packit 383869
 (a) += (b); \
Packit 383869
  }
Packit 383869
#define II(a, b, c, d, x, s, ac) { \
Packit 383869
 (a) += I ((b), (c), (d)) + (x) + (apr_uint32_t)(ac); \
Packit 383869
 (a) = ROTATE_LEFT ((a), (s)); \
Packit 383869
 (a) += (b); \
Packit 383869
  }
Packit 383869
Packit 383869
/* MD5 initialization. Begins an MD5 operation, writing a new context.
Packit 383869
 */
Packit 383869
APU_DECLARE(apr_status_t) apr_md5_init(apr_md5_ctx_t *context)
Packit 383869
{
Packit 383869
    context->count[0] = context->count[1] = 0;
Packit 383869
    
Packit 383869
    /* Load magic initialization constants. */
Packit 383869
    context->state[0] = 0x67452301;
Packit 383869
    context->state[1] = 0xefcdab89;
Packit 383869
    context->state[2] = 0x98badcfe;
Packit 383869
    context->state[3] = 0x10325476;
Packit 383869
    context->xlate = NULL;
Packit 383869
    
Packit 383869
    return APR_SUCCESS;
Packit 383869
}
Packit 383869
Packit 383869
/* MD5 translation setup.  Provides the APR translation handle
Packit 383869
 * to be used for translating the content before calculating the
Packit 383869
 * digest.
Packit 383869
 */
Packit 383869
APU_DECLARE(apr_status_t) apr_md5_set_xlate(apr_md5_ctx_t *context, 
Packit 383869
                                            apr_xlate_t *xlate)
Packit 383869
{
Packit 383869
#if APR_HAS_XLATE
Packit 383869
    apr_status_t rv;
Packit 383869
    int is_sb;
Packit 383869
Packit 383869
    /* TODO: remove the single-byte-only restriction from this code
Packit 383869
     */
Packit 383869
    rv = apr_xlate_sb_get(xlate, &is_sb);
Packit 383869
    if (rv != APR_SUCCESS) {
Packit 383869
        return rv;
Packit 383869
    }
Packit 383869
    if (!is_sb) {
Packit 383869
        return APR_EINVAL;
Packit 383869
    }
Packit 383869
    context->xlate = xlate;
Packit 383869
    return APR_SUCCESS;
Packit 383869
#else
Packit 383869
    return APR_ENOTIMPL;
Packit 383869
#endif /* APR_HAS_XLATE */
Packit 383869
}
Packit 383869
Packit 383869
/* MD5 block update operation. Continues an MD5 message-digest
Packit 383869
 * operation, processing another message block, and updating the
Packit 383869
 * context.
Packit 383869
 */
Packit 383869
static apr_status_t md5_update_buffer(apr_md5_ctx_t *context,
Packit 383869
                                      const void *vinput,
Packit 383869
                                      apr_size_t inputLen,
Packit 383869
                                      int xlate_buffer)
Packit 383869
{
Packit 383869
    const unsigned char *input = vinput;
Packit 383869
    unsigned int i, idx, partLen;
Packit 383869
#if APR_HAS_XLATE
Packit 383869
    apr_size_t inbytes_left, outbytes_left;
Packit 383869
#endif
Packit 383869
Packit 383869
    /* Compute number of bytes mod 64 */
Packit 383869
    idx = (unsigned int)((context->count[0] >> 3) & 0x3F);
Packit 383869
Packit 383869
    /* Update number of bits */
Packit 383869
    if ((context->count[0] += ((apr_uint32_t)inputLen << 3)) 
Packit 383869
            < ((apr_uint32_t)inputLen << 3))
Packit 383869
        context->count[1]++;
Packit 383869
    context->count[1] += (apr_uint32_t)inputLen >> 29;
Packit 383869
Packit 383869
    partLen = 64 - idx;
Packit 383869
Packit 383869
    /* Transform as many times as possible. */
Packit 383869
#if !APR_HAS_XLATE
Packit 383869
    if (inputLen >= partLen) {
Packit 383869
        memcpy(&context->buffer[idx], input, partLen);
Packit 383869
        MD5Transform(context->state, context->buffer);
Packit 383869
Packit 383869
        for (i = partLen; i + 63 < inputLen; i += 64)
Packit 383869
            MD5Transform(context->state, &input[i]);
Packit 383869
Packit 383869
        idx = 0;
Packit 383869
    }
Packit 383869
    else
Packit 383869
        i = 0;
Packit 383869
Packit 383869
    /* Buffer remaining input */
Packit 383869
    memcpy(&context->buffer[idx], &input[i], inputLen - i);
Packit 383869
#else /*APR_HAS_XLATE*/
Packit 383869
    if (inputLen >= partLen) {
Packit 383869
        if (context->xlate && (xlate_buffer == DO_XLATE)) {
Packit 383869
            inbytes_left = outbytes_left = partLen;
Packit 383869
            apr_xlate_conv_buffer(context->xlate, (const char *)input, 
Packit 383869
                                  &inbytes_left,
Packit 383869
                                  (char *)&context->buffer[idx], 
Packit 383869
                                  &outbytes_left);
Packit 383869
        }
Packit 383869
        else {
Packit 383869
            memcpy(&context->buffer[idx], input, partLen);
Packit 383869
        }
Packit 383869
        MD5Transform(context->state, context->buffer);
Packit 383869
Packit 383869
        for (i = partLen; i + 63 < inputLen; i += 64) {
Packit 383869
            if (context->xlate && (xlate_buffer == DO_XLATE)) {
Packit 383869
                unsigned char inp_tmp[64];
Packit 383869
                inbytes_left = outbytes_left = 64;
Packit 383869
                apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
Packit 383869
                                      &inbytes_left, (char *)inp_tmp, 
Packit 383869
                                      &outbytes_left);
Packit 383869
                MD5Transform(context->state, inp_tmp);
Packit 383869
            }
Packit 383869
            else {
Packit 383869
                MD5Transform(context->state, &input[i]);
Packit 383869
            }
Packit 383869
        }
Packit 383869
Packit 383869
        idx = 0;
Packit 383869
    }
Packit 383869
    else
Packit 383869
        i = 0;
Packit 383869
Packit 383869
    /* Buffer remaining input */
Packit 383869
    if (context->xlate && (xlate_buffer == DO_XLATE)) {
Packit 383869
        inbytes_left = outbytes_left = inputLen - i;
Packit 383869
        apr_xlate_conv_buffer(context->xlate, (const char *)&input[i], 
Packit 383869
                              &inbytes_left, (char *)&context->buffer[idx], 
Packit 383869
                              &outbytes_left);
Packit 383869
    }
Packit 383869
    else {
Packit 383869
        memcpy(&context->buffer[idx], &input[i], inputLen - i);
Packit 383869
    }
Packit 383869
#endif /*APR_HAS_XLATE*/
Packit 383869
    return APR_SUCCESS;
Packit 383869
}
Packit 383869
Packit 383869
/* MD5 block update operation. API with the default setting 
Packit 383869
 * for EBCDIC translations
Packit 383869
 */  
Packit 383869
APU_DECLARE(apr_status_t) apr_md5_update(apr_md5_ctx_t *context,
Packit 383869
                                         const void *input,
Packit 383869
                                         apr_size_t inputLen)
Packit 383869
{
Packit 383869
    return md5_update_buffer(context, input, inputLen, DO_XLATE);
Packit 383869
}
Packit 383869
Packit 383869
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
Packit 383869
 * the message digest and zeroizing the context.
Packit 383869
 */
Packit 383869
APU_DECLARE(apr_status_t) apr_md5_final(unsigned char digest[APR_MD5_DIGESTSIZE],
Packit 383869
                                        apr_md5_ctx_t *context)
Packit 383869
{
Packit 383869
    unsigned char bits[8];
Packit 383869
    unsigned int idx, padLen;
Packit 383869
Packit 383869
    /* Save number of bits */
Packit 383869
    Encode(bits, context->count, 8);
Packit 383869
Packit 383869
#if APR_HAS_XLATE
Packit 383869
    /* apr_md5_update() should not translate for this final round. */
Packit 383869
    context->xlate = NULL;
Packit 383869
#endif /*APR_HAS_XLATE*/
Packit 383869
Packit 383869
    /* Pad out to 56 mod 64. */
Packit 383869
    idx = (unsigned int)((context->count[0] >> 3) & 0x3f);
Packit 383869
    padLen = (idx < 56) ? (56 - idx) : (120 - idx);
Packit 383869
    apr_md5_update(context, PADDING, padLen);
Packit 383869
Packit 383869
    /* Append length (before padding) */
Packit 383869
    apr_md5_update(context, bits, 8);
Packit 383869
Packit 383869
    /* Store state in digest */
Packit 383869
    Encode(digest, context->state, APR_MD5_DIGESTSIZE);
Packit 383869
Packit 383869
    /* Zeroize sensitive information. */
Packit 383869
    memset(context, 0, sizeof(*context));
Packit 383869
    
Packit 383869
    return APR_SUCCESS;
Packit 383869
}
Packit 383869
Packit 383869
/* MD5 in one step (init, update, final)
Packit 383869
 */
Packit 383869
APU_DECLARE(apr_status_t) apr_md5(unsigned char digest[APR_MD5_DIGESTSIZE],
Packit 383869
                                  const void *_input,
Packit 383869
                                  apr_size_t inputLen)
Packit 383869
{
Packit 383869
    const unsigned char *input = _input;
Packit 383869
    apr_md5_ctx_t ctx;
Packit 383869
    apr_status_t rv;
Packit 383869
Packit 383869
    apr_md5_init(&ctx;;
Packit 383869
Packit 383869
    if ((rv = apr_md5_update(&ctx, input, inputLen)) != APR_SUCCESS)
Packit 383869
        return rv;
Packit 383869
Packit 383869
    return apr_md5_final(digest, &ctx;;
Packit 383869
}
Packit 383869
Packit 383869
/* MD5 basic transformation. Transforms state based on block. */
Packit 383869
static void MD5Transform(apr_uint32_t state[4], const unsigned char block[64])
Packit 383869
{
Packit 383869
    apr_uint32_t a = state[0], b = state[1], c = state[2], d = state[3],
Packit 383869
                 tmpbuf[APR_MD5_DIGESTSIZE];
Packit 383869
    const apr_uint32_t *x;
Packit 383869
Packit 383869
#if !APR_IS_BIGENDIAN
Packit 383869
    if ((apr_uintptr_t)block % sizeof(apr_uint32_t) == 0) {
Packit 383869
        x = (apr_uint32_t *)block;
Packit 383869
    } else
Packit 383869
#endif
Packit 383869
    {
Packit 383869
        Decode(tmpbuf, block, 64);
Packit 383869
	x = tmpbuf;
Packit 383869
    }
Packit 383869
Packit 383869
    /* Round 1 */
Packit 383869
    FF(a, b, c, d, x[0],  S11, 0xd76aa478); /* 1 */
Packit 383869
    FF(d, a, b, c, x[1],  S12, 0xe8c7b756); /* 2 */
Packit 383869
    FF(c, d, a, b, x[2],  S13, 0x242070db); /* 3 */
Packit 383869
    FF(b, c, d, a, x[3],  S14, 0xc1bdceee); /* 4 */
Packit 383869
    FF(a, b, c, d, x[4],  S11, 0xf57c0faf); /* 5 */
Packit 383869
    FF(d, a, b, c, x[5],  S12, 0x4787c62a); /* 6 */
Packit 383869
    FF(c, d, a, b, x[6],  S13, 0xa8304613); /* 7 */
Packit 383869
    FF(b, c, d, a, x[7],  S14, 0xfd469501); /* 8 */
Packit 383869
    FF(a, b, c, d, x[8],  S11, 0x698098d8); /* 9 */
Packit 383869
    FF(d, a, b, c, x[9],  S12, 0x8b44f7af); /* 10 */
Packit 383869
    FF(c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
Packit 383869
    FF(b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
Packit 383869
    FF(a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
Packit 383869
    FF(d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
Packit 383869
    FF(c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
Packit 383869
    FF(b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
Packit 383869
Packit 383869
    /* Round 2 */
Packit 383869
    GG(a, b, c, d, x[1],  S21, 0xf61e2562); /* 17 */
Packit 383869
    GG(d, a, b, c, x[6],  S22, 0xc040b340); /* 18 */
Packit 383869
    GG(c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
Packit 383869
    GG(b, c, d, a, x[0],  S24, 0xe9b6c7aa); /* 20 */
Packit 383869
    GG(a, b, c, d, x[5],  S21, 0xd62f105d); /* 21 */
Packit 383869
    GG(d, a, b, c, x[10], S22, 0x2441453);  /* 22 */
Packit 383869
    GG(c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
Packit 383869
    GG(b, c, d, a, x[4],  S24, 0xe7d3fbc8); /* 24 */
Packit 383869
    GG(a, b, c, d, x[9],  S21, 0x21e1cde6); /* 25 */
Packit 383869
    GG(d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
Packit 383869
    GG(c, d, a, b, x[3],  S23, 0xf4d50d87); /* 27 */
Packit 383869
    GG(b, c, d, a, x[8],  S24, 0x455a14ed); /* 28 */
Packit 383869
    GG(a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
Packit 383869
    GG(d, a, b, c, x[2],  S22, 0xfcefa3f8); /* 30 */
Packit 383869
    GG(c, d, a, b, x[7],  S23, 0x676f02d9); /* 31 */
Packit 383869
    GG(b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
Packit 383869
Packit 383869
    /* Round 3 */
Packit 383869
    HH(a, b, c, d, x[5],  S31, 0xfffa3942); /* 33 */
Packit 383869
    HH(d, a, b, c, x[8],  S32, 0x8771f681); /* 34 */
Packit 383869
    HH(c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
Packit 383869
    HH(b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
Packit 383869
    HH(a, b, c, d, x[1],  S31, 0xa4beea44); /* 37 */
Packit 383869
    HH(d, a, b, c, x[4],  S32, 0x4bdecfa9); /* 38 */
Packit 383869
    HH(c, d, a, b, x[7],  S33, 0xf6bb4b60); /* 39 */
Packit 383869
    HH(b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
Packit 383869
    HH(a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
Packit 383869
    HH(d, a, b, c, x[0],  S32, 0xeaa127fa); /* 42 */
Packit 383869
    HH(c, d, a, b, x[3],  S33, 0xd4ef3085); /* 43 */
Packit 383869
    HH(b, c, d, a, x[6],  S34, 0x4881d05);  /* 44 */
Packit 383869
    HH(a, b, c, d, x[9],  S31, 0xd9d4d039); /* 45 */
Packit 383869
    HH(d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
Packit 383869
    HH(c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
Packit 383869
    HH(b, c, d, a, x[2],  S34, 0xc4ac5665); /* 48 */
Packit 383869
Packit 383869
    /* Round 4 */
Packit 383869
    II(a, b, c, d, x[0],  S41, 0xf4292244); /* 49 */
Packit 383869
    II(d, a, b, c, x[7],  S42, 0x432aff97); /* 50 */
Packit 383869
    II(c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
Packit 383869
    II(b, c, d, a, x[5],  S44, 0xfc93a039); /* 52 */
Packit 383869
    II(a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
Packit 383869
    II(d, a, b, c, x[3],  S42, 0x8f0ccc92); /* 54 */
Packit 383869
    II(c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
Packit 383869
    II(b, c, d, a, x[1],  S44, 0x85845dd1); /* 56 */
Packit 383869
    II(a, b, c, d, x[8],  S41, 0x6fa87e4f); /* 57 */
Packit 383869
    II(d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
Packit 383869
    II(c, d, a, b, x[6],  S43, 0xa3014314); /* 59 */
Packit 383869
    II(b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
Packit 383869
    II(a, b, c, d, x[4],  S41, 0xf7537e82); /* 61 */
Packit 383869
    II(d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
Packit 383869
    II(c, d, a, b, x[2],  S43, 0x2ad7d2bb); /* 63 */
Packit 383869
    II(b, c, d, a, x[9],  S44, 0xeb86d391); /* 64 */
Packit 383869
Packit 383869
    state[0] += a;
Packit 383869
    state[1] += b;
Packit 383869
    state[2] += c;
Packit 383869
    state[3] += d;
Packit 383869
Packit 383869
#if !APR_IS_BIGENDIAN
Packit 383869
    if (x == tmpbuf)
Packit 383869
#endif
Packit 383869
    {
Packit 383869
        /* Zeroize sensitive information. */
Packit 383869
        memset(tmpbuf, 0, sizeof(tmpbuf));
Packit 383869
    }
Packit 383869
}
Packit 383869
Packit 383869
/* Encodes input (apr_uint32_t) into output (unsigned char). Assumes len is
Packit 383869
 * a multiple of 4.
Packit 383869
 */
Packit 383869
static void Encode(unsigned char *output, const apr_uint32_t *input,
Packit 383869
                   unsigned int len)
Packit 383869
{
Packit 383869
    unsigned int i, j;
Packit 383869
    apr_uint32_t k;
Packit 383869
Packit 383869
    for (i = 0, j = 0; j < len; i++, j += 4) {
Packit 383869
        k = input[i];
Packit 383869
        output[j]     = (unsigned char)(k & 0xff);
Packit 383869
        output[j + 1] = (unsigned char)((k >> 8) & 0xff);
Packit 383869
        output[j + 2] = (unsigned char)((k >> 16) & 0xff);
Packit 383869
        output[j + 3] = (unsigned char)((k >> 24) & 0xff);
Packit 383869
    }
Packit 383869
}
Packit 383869
Packit 383869
/* Decodes input (unsigned char) into output (apr_uint32_t). Assumes len is
Packit 383869
 * a multiple of 4.
Packit 383869
 */
Packit 383869
static void Decode(apr_uint32_t *output, const unsigned char *input,
Packit 383869
                   unsigned int len)
Packit 383869
{
Packit 383869
    unsigned int i, j;
Packit 383869
Packit 383869
    for (i = 0, j = 0; j < len; i++, j += 4)
Packit 383869
        output[i] = ((apr_uint32_t)input[j])             |
Packit 383869
                    (((apr_uint32_t)input[j + 1]) << 8)  |
Packit 383869
                    (((apr_uint32_t)input[j + 2]) << 16) |
Packit 383869
                    (((apr_uint32_t)input[j + 3]) << 24);
Packit 383869
}
Packit 383869
Packit 383869
#if APR_CHARSET_EBCDIC
Packit 383869
APU_DECLARE(apr_status_t) apr_MD5InitEBCDIC(apr_xlate_t *xlate)
Packit 383869
{
Packit 383869
    xlate_ebcdic_to_ascii = xlate;
Packit 383869
    return APR_SUCCESS;
Packit 383869
}
Packit 383869
#endif
Packit 383869
Packit 383869
/*
Packit 383869
 * Define the Magic String prefix that identifies a password as being
Packit 383869
 * hashed using our algorithm.
Packit 383869
 */
Packit 383869
static const char * const apr1_id = "$apr1$";
Packit 383869
Packit 383869
/*
Packit 383869
 * The following MD5 password encryption code was largely borrowed from
Packit 383869
 * the FreeBSD 3.0 /usr/src/lib/libcrypt/crypt.c file, which is
Packit 383869
 * licenced as stated at the top of this file.
Packit 383869
 */
Packit 383869
Packit 383869
static void to64(char *s, unsigned long v, int n)
Packit 383869
{
Packit 383869
    static unsigned char itoa64[] =         /* 0 ... 63 => ASCII - 64 */
Packit 383869
        "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
Packit 383869
Packit 383869
    while (--n >= 0) {
Packit 383869
        *s++ = itoa64[v&0x3f];
Packit 383869
        v >>= 6;
Packit 383869
    }
Packit 383869
}
Packit 383869
Packit 383869
APU_DECLARE(apr_status_t) apr_md5_encode(const char *pw, const char *salt,
Packit 383869
                             char *result, apr_size_t nbytes)
Packit 383869
{
Packit 383869
    /*
Packit 383869
     * Minimum size is 8 bytes for salt, plus 1 for the trailing NUL,
Packit 383869
     * plus 4 for the '$' separators, plus the password hash itself.
Packit 383869
     * Let's leave a goodly amount of leeway.
Packit 383869
     */
Packit 383869
Packit 383869
    char passwd[120], *p;
Packit 383869
    const char *sp, *ep;
Packit 383869
    unsigned char final[APR_MD5_DIGESTSIZE];
Packit 383869
    apr_ssize_t sl, pl, i;
Packit 383869
    apr_md5_ctx_t ctx, ctx1;
Packit 383869
    unsigned long l;
Packit 383869
Packit 383869
    /* 
Packit 383869
     * Refine the salt first.  It's possible we were given an already-hashed
Packit 383869
     * string as the salt argument, so extract the actual salt value from it
Packit 383869
     * if so.  Otherwise just use the string up to the first '$' as the salt.
Packit 383869
     */
Packit 383869
    sp = salt;
Packit 383869
Packit 383869
    /*
Packit 383869
     * If it starts with the magic string, then skip that.
Packit 383869
     */
Packit 383869
    if (!strncmp(sp, apr1_id, strlen(apr1_id))) {
Packit 383869
        sp += strlen(apr1_id);
Packit 383869
    }
Packit 383869
Packit 383869
    /*
Packit 383869
     * It stops at the first '$' or 8 chars, whichever comes first
Packit 383869
     */
Packit 383869
    for (ep = sp; (*ep != '\0') && (*ep != '$') && (ep < (sp + 8)); ep++) {
Packit 383869
        continue;
Packit 383869
    }
Packit 383869
Packit 383869
    /*
Packit 383869
     * Get the length of the true salt
Packit 383869
     */
Packit 383869
    sl = ep - sp;
Packit 383869
Packit 383869
    /*
Packit 383869
     * 'Time to make the doughnuts..'
Packit 383869
     */
Packit 383869
    apr_md5_init(&ctx;;
Packit 383869
#if APR_CHARSET_EBCDIC
Packit 383869
    apr_md5_set_xlate(&ctx, xlate_ebcdic_to_ascii);
Packit 383869
#endif
Packit 383869
    
Packit 383869
    /*
Packit 383869
     * The password first, since that is what is most unknown
Packit 383869
     */
Packit 383869
    apr_md5_update(&ctx, pw, strlen(pw));
Packit 383869
Packit 383869
    /*
Packit 383869
     * Then our magic string
Packit 383869
     */
Packit 383869
    apr_md5_update(&ctx, apr1_id, strlen(apr1_id));
Packit 383869
Packit 383869
    /*
Packit 383869
     * Then the raw salt
Packit 383869
     */
Packit 383869
    apr_md5_update(&ctx, sp, sl);
Packit 383869
Packit 383869
    /*
Packit 383869
     * Then just as many characters of the MD5(pw, salt, pw)
Packit 383869
     */
Packit 383869
    apr_md5_init(&ctx1);
Packit 383869
#if APR_CHARSET_EBCDIC
Packit 383869
    apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
Packit 383869
#endif
Packit 383869
    apr_md5_update(&ctx1, pw, strlen(pw));
Packit 383869
    apr_md5_update(&ctx1, sp, sl);
Packit 383869
    apr_md5_update(&ctx1, pw, strlen(pw));
Packit 383869
    apr_md5_final(final, &ctx1);
Packit 383869
    for (pl = strlen(pw); pl > 0; pl -= APR_MD5_DIGESTSIZE) {
Packit 383869
        md5_update_buffer(&ctx, final,
Packit 383869
                      (pl > APR_MD5_DIGESTSIZE) ? APR_MD5_DIGESTSIZE : pl, SKIP_XLATE);
Packit 383869
    }
Packit 383869
Packit 383869
    /*
Packit 383869
     * Don't leave anything around in vm they could use.
Packit 383869
     */
Packit 383869
    memset(final, 0, sizeof(final));
Packit 383869
Packit 383869
    /*
Packit 383869
     * Then something really weird...
Packit 383869
     */
Packit 383869
    for (i = strlen(pw); i != 0; i >>= 1) {
Packit 383869
        if (i & 1) {
Packit 383869
            md5_update_buffer(&ctx, final, 1, SKIP_XLATE);
Packit 383869
        }
Packit 383869
        else {
Packit 383869
            apr_md5_update(&ctx, pw, 1);
Packit 383869
        }
Packit 383869
    }
Packit 383869
Packit 383869
    /*
Packit 383869
     * Now make the output string.  We know our limitations, so we
Packit 383869
     * can use the string routines without bounds checking.
Packit 383869
     */
Packit 383869
    strcpy(passwd, apr1_id);
Packit 383869
    strncat(passwd, sp, sl);
Packit 383869
    strcat(passwd, "$");
Packit 383869
Packit 383869
    apr_md5_final(final, &ctx;;
Packit 383869
Packit 383869
    /*
Packit 383869
     * And now, just to make sure things don't run too fast..
Packit 383869
     * On a 60 Mhz Pentium this takes 34 msec, so you would
Packit 383869
     * need 30 seconds to build a 1000 entry dictionary...
Packit 383869
     */
Packit 383869
    for (i = 0; i < 1000; i++) {
Packit 383869
        apr_md5_init(&ctx1);
Packit 383869
         /*
Packit 383869
          * apr_md5_final clears out ctx1.xlate at the end of each loop,
Packit 383869
          * so need to to set it each time through
Packit 383869
          */
Packit 383869
#if APR_CHARSET_EBCDIC
Packit 383869
        apr_md5_set_xlate(&ctx1, xlate_ebcdic_to_ascii);
Packit 383869
#endif
Packit 383869
        if (i & 1) {
Packit 383869
            apr_md5_update(&ctx1, pw, strlen(pw));
Packit 383869
        }
Packit 383869
        else {
Packit 383869
            md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
Packit 383869
        }
Packit 383869
        if (i % 3) {
Packit 383869
            apr_md5_update(&ctx1, sp, sl);
Packit 383869
        }
Packit 383869
Packit 383869
        if (i % 7) {
Packit 383869
            apr_md5_update(&ctx1, pw, strlen(pw));
Packit 383869
        }
Packit 383869
Packit 383869
        if (i & 1) {
Packit 383869
            md5_update_buffer(&ctx1, final, APR_MD5_DIGESTSIZE, SKIP_XLATE);
Packit 383869
        }
Packit 383869
        else {
Packit 383869
            apr_md5_update(&ctx1, pw, strlen(pw));
Packit 383869
        }
Packit 383869
        apr_md5_final(final,&ctx1);
Packit 383869
    }
Packit 383869
Packit 383869
    p = passwd + strlen(passwd);
Packit 383869
Packit 383869
    l = (final[ 0]<<16) | (final[ 6]<<8) | final[12]; to64(p, l, 4); p += 4;
Packit 383869
    l = (final[ 1]<<16) | (final[ 7]<<8) | final[13]; to64(p, l, 4); p += 4;
Packit 383869
    l = (final[ 2]<<16) | (final[ 8]<<8) | final[14]; to64(p, l, 4); p += 4;
Packit 383869
    l = (final[ 3]<<16) | (final[ 9]<<8) | final[15]; to64(p, l, 4); p += 4;
Packit 383869
    l = (final[ 4]<<16) | (final[10]<<8) | final[ 5]; to64(p, l, 4); p += 4;
Packit 383869
    l =                    final[11]                ; to64(p, l, 2); p += 2;
Packit 383869
    *p = '\0';
Packit 383869
Packit 383869
    /*
Packit 383869
     * Don't leave anything around in vm they could use.
Packit 383869
     */
Packit 383869
    memset(final, 0, sizeof(final));
Packit 383869
Packit 383869
    apr_cpystrn(result, passwd, nbytes - 1);
Packit 383869
    return APR_SUCCESS;
Packit 383869
}