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