bottleneck testcase based on rubbos
[bottlenecks.git] / rubbos / app / tomcat-connectors-1.2.32-src / native / common / jk_md5.c
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 /*
19  * This is work is derived from material Copyright RSA Data Security, Inc.
20  *
21  * The RSA copyright statement and Licence for that original material is
22  * included below. This is followed by the Apache copyright statement and
23  * licence for the modifications made to that material.
24  */
25
26 /* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
27  */
28
29 /* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
30    rights reserved.
31
32    License to copy and use this software is granted provided that it
33    is identified as the "RSA Data Security, Inc. MD5 Message-Digest
34    Algorithm" in all material mentioning or referencing this software
35    or this function.
36
37    License is also granted to make and use derivative works provided
38    that such works are identified as "derived from the RSA Data
39    Security, Inc. MD5 Message-Digest Algorithm" in all material
40    mentioning or referencing the derived work.
41
42    RSA Data Security, Inc. makes no representations concerning either
43    the merchantability of this software or the suitability of this
44    software for any particular purpose. It is provided "as is"
45    without express or implied warranty of any kind.
46
47    These notices must be retained in any copies of any part of this
48    documentation and/or software.
49  */
50
51 /*
52  * The ap_MD5Encode() routine uses much code obtained from the FreeBSD 3.0
53  * MD5 crypt() function, which is licenced as follows:
54  * ----------------------------------------------------------------------------
55  * "THE BEER-WARE LICENSE" (Revision 42):
56  * <phk@login.dknet.dk> wrote this file.  As long as you retain this notice you
57  * can do whatever you want with this stuff. If we meet some day, and you think
58  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
59  * ----------------------------------------------------------------------------
60  */
61
62 /***************************************************************************
63  * Description: MD5 encoding wrapper                                       *
64  * Author:      Henri Gomez <hgomez@apache.org>                            *
65  * Version:     $Revision: 466585 $                                           *
66  ***************************************************************************/
67
68 /*
69  * JK MD5 Encoding function (jk_MD5Encode)
70  *
71  * Jk delegate MD5 encoding to ap_MD5Encode when used in Apache Web-Server.
72  * When another web-server is used like NES/IIS, we should use corresponding calls.
73  * NES/IIS specialists will add the necessary code but until that, I reused the code
74  * from Apache HTTP server.
75  * 
76  * Nota: If you use an EBCDIC system without Apache, you'll have to use MD5 encoding
77  * corresponding call or have a ebcdic2ascii() functions somewhere.
78  * For example current AS/400 have MD5 encoding support APIs but olders not....
79  */
80
81 #include "jk_global.h"
82 #include "jk_md5.h"
83
84 char *JK_METHOD jk_hextocstr(unsigned char *org, char *dst, int n)
85 {
86     char *os = dst;
87     unsigned char v;
88     static unsigned char zitohex[] = "0123456789ABCDEF";
89
90     while (--n >= 0) {
91         v = *org++;
92         *dst++ = zitohex[v >> 4];
93         *dst++ = zitohex[v & 0x0f];
94     }
95     *dst = 0;
96
97     return (os);
98 }
99
100 #ifndef USE_APACHE_MD5
101
102 /* Constants for MD5Transform routine.
103  */
104
105 #define S11 7
106 #define S12 12
107 #define S13 17
108 #define S14 22
109 #define S21 5
110 #define S22 9
111 #define S23 14
112 #define S24 20
113 #define S31 4
114 #define S32 11
115 #define S33 16
116 #define S34 23
117 #define S41 6
118 #define S42 10
119 #define S43 15
120 #define S44 21
121
122 static void MD5Transform(jk_uint32_t state[4], const unsigned char block[64]);
123 static void Encode(unsigned char *output, const jk_uint32_t * input, size_t len);
124 static void Decode(jk_uint32_t * output, const unsigned char *input, size_t len);
125 static void jk_MD5Init(JK_MD5_CTX * context);
126 static void jk_MD5Update(JK_MD5_CTX * context, const unsigned char *input,
127                          size_t inputLen);
128 /*static void jk_MD5Final(unsigned char digest[JK_MD5_DIGESTSIZE], JK_MD5_CTX *context);*/
129
130 static unsigned char PADDING[64] = {
131     0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
132     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
133     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
134 };
135
136 /* F, G, H and I are basic MD5 functions.
137  */
138 #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
139 #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
140 #define H(x, y, z) ((x) ^ (y) ^ (z))
141 #define I(x, y, z) ((y) ^ ((x) | (~z)))
142
143 /* ROTATE_LEFT rotates x left n bits.
144  */
145 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
146
147 /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
148    Rotation is separate from addition to prevent recomputation.
149  */
150 #define FF(a, b, c, d, x, s, ac) { \
151  (a) += F ((b), (c), (d)) + (x) + (jk_uint32_t)(ac); \
152  (a) = ROTATE_LEFT ((a), (s)); \
153  (a) += (b); \
154   }
155 #define GG(a, b, c, d, x, s, ac) { \
156  (a) += G ((b), (c), (d)) + (x) + (jk_uint32_t)(ac); \
157  (a) = ROTATE_LEFT ((a), (s)); \
158  (a) += (b); \
159   }
160 #define HH(a, b, c, d, x, s, ac) { \
161  (a) += H ((b), (c), (d)) + (x) + (jk_uint32_t)(ac); \
162  (a) = ROTATE_LEFT ((a), (s)); \
163  (a) += (b); \
164   }
165 #define II(a, b, c, d, x, s, ac) { \
166  (a) += I ((b), (c), (d)) + (x) + (jk_uint32_t)(ac); \
167  (a) = ROTATE_LEFT ((a), (s)); \
168  (a) += (b); \
169   }
170
171 /* MD5 initialization. Begins an MD5 operation, writing a new context.
172  */
173 static void jk_MD5Init(JK_MD5_CTX * context)
174 {
175     context->count[0] = context->count[1] = 0;
176     /* Load magic initialization constants. */
177     context->state[0] = 0x67452301;
178     context->state[1] = 0xefcdab89;
179     context->state[2] = 0x98badcfe;
180     context->state[3] = 0x10325476;
181 }
182
183 /* MD5 block update operation. Continues an MD5 message-digest
184    operation, processing another message block, and updating the
185    context.
186  */
187 static void jk_MD5Update(JK_MD5_CTX * context, const unsigned char *input,
188                          size_t inputLen)
189 {
190     size_t i, idx, partLen;
191
192     /* Compute number of bytes mod 64 */
193     idx = (size_t) ((context->count[0] >> 3) & 0x3F);
194
195     /* Update number of bits */
196     if ((context->count[0] += ((jk_uint32_t) inputLen << 3))
197         < ((jk_uint32_t) inputLen << 3)) {
198         context->count[1]++;
199     }
200     context->count[1] += (jk_uint32_t) inputLen >> 29;
201
202     partLen = 64 - idx;
203
204     /* Transform as many times as possible. */
205 #ifndef CHARSET_EBCDIC
206     if (inputLen >= partLen) {
207         memcpy(&context->buffer[idx], input, partLen);
208         MD5Transform(context->state, context->buffer);
209
210         for (i = partLen; i + 63 < inputLen; i += 64) {
211             MD5Transform(context->state, &input[i]);
212         }
213
214         idx = 0;
215     }
216     else {
217         i = 0;
218     }
219
220     /* Buffer remaining input */
221     memcpy(&context->buffer[idx], &input[i], inputLen - i);
222 #else /*CHARSET_EBCDIC */
223     if (inputLen >= partLen) {
224         ebcdic2ascii(&context->buffer[idx], input, partLen);
225         MD5Transform(context->state, context->buffer);
226
227         for (i = partLen; i + 63 < inputLen; i += 64) {
228             unsigned char inp_tmp[64];
229             ebcdic2ascii(inp_tmp, &input[i], 64);
230             MD5Transform(context->state, inp_tmp);
231         }
232
233         idx = 0;
234     }
235     else {
236         i = 0;
237     }
238
239     /* Buffer remaining input */
240     ebcdic2ascii(&context->buffer[idx], &input[i], inputLen - i);
241 #endif /*CHARSET_EBCDIC */
242 }
243
244 /* MD5 finalization. Ends an MD5 message-digest operation, writing the
245    the message digest and zeroizing the context.
246  */
247 static void JK_METHOD jk_MD5Final(unsigned char digest[16], JK_MD5_CTX * context)
248 {
249     unsigned char bits[8];
250     size_t idx, padLen;
251
252
253     /* Save number of bits */
254     Encode(bits, context->count, 8);
255
256 #ifdef CHARSET_EBCDIC
257     /* XXX: @@@: In order to make this no more complex than necessary,
258      * this kludge converts the bits[] array using the ascii-to-ebcdic
259      * table, because the following jk_MD5Update() re-translates
260      * its input (ebcdic-to-ascii).
261      * Otherwise, we would have to pass a "conversion" flag to jk_MD5Update()
262      */
263     ascii2ebcdic(bits, bits, 8);
264
265     /* Since everything is converted to ascii within jk_MD5Update(), 
266      * the initial 0x80 (PADDING[0]) must be stored as 0x20 
267      */
268     ascii2ebcdic(PADDING, PADDING, 1);
269 #endif /*CHARSET_EBCDIC */
270
271     /* Pad out to 56 mod 64. */
272     idx = (size_t) ((context->count[0] >> 3) & 0x3f);
273     padLen = (idx < 56) ? (56 - idx) : (120 - idx);
274     jk_MD5Update(context, (const unsigned char *)PADDING, padLen);
275
276     /* Append length (before padding) */
277     jk_MD5Update(context, (const unsigned char *)bits, 8);
278
279     /* Store state in digest */
280     Encode(digest, context->state, 16);
281
282     /* Zeroize sensitive information. */
283     memset(context, 0, sizeof(*context));
284 }
285
286 /* MD5 basic transformation. Transforms state based on block. */
287 static void MD5Transform(jk_uint32_t state[4], const unsigned char block[64])
288 {
289     jk_uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16];
290
291     Decode(x, block, 64);
292
293     /* Round 1 */
294     FF(a, b, c, d, x[0], S11, 0xd76aa478);      /* 1 */
295     FF(d, a, b, c, x[1], S12, 0xe8c7b756);      /* 2 */
296     FF(c, d, a, b, x[2], S13, 0x242070db);      /* 3 */
297     FF(b, c, d, a, x[3], S14, 0xc1bdceee);      /* 4 */
298     FF(a, b, c, d, x[4], S11, 0xf57c0faf);      /* 5 */
299     FF(d, a, b, c, x[5], S12, 0x4787c62a);      /* 6 */
300     FF(c, d, a, b, x[6], S13, 0xa8304613);      /* 7 */
301     FF(b, c, d, a, x[7], S14, 0xfd469501);      /* 8 */
302     FF(a, b, c, d, x[8], S11, 0x698098d8);      /* 9 */
303     FF(d, a, b, c, x[9], S12, 0x8b44f7af);      /* 10 */
304     FF(c, d, a, b, x[10], S13, 0xffff5bb1);     /* 11 */
305     FF(b, c, d, a, x[11], S14, 0x895cd7be);     /* 12 */
306     FF(a, b, c, d, x[12], S11, 0x6b901122);     /* 13 */
307     FF(d, a, b, c, x[13], S12, 0xfd987193);     /* 14 */
308     FF(c, d, a, b, x[14], S13, 0xa679438e);     /* 15 */
309     FF(b, c, d, a, x[15], S14, 0x49b40821);     /* 16 */
310
311     /* Round 2 */
312     GG(a, b, c, d, x[1], S21, 0xf61e2562);      /* 17 */
313     GG(d, a, b, c, x[6], S22, 0xc040b340);      /* 18 */
314     GG(c, d, a, b, x[11], S23, 0x265e5a51);     /* 19 */
315     GG(b, c, d, a, x[0], S24, 0xe9b6c7aa);      /* 20 */
316     GG(a, b, c, d, x[5], S21, 0xd62f105d);      /* 21 */
317     GG(d, a, b, c, x[10], S22, 0x2441453);      /* 22 */
318     GG(c, d, a, b, x[15], S23, 0xd8a1e681);     /* 23 */
319     GG(b, c, d, a, x[4], S24, 0xe7d3fbc8);      /* 24 */
320     GG(a, b, c, d, x[9], S21, 0x21e1cde6);      /* 25 */
321     GG(d, a, b, c, x[14], S22, 0xc33707d6);     /* 26 */
322     GG(c, d, a, b, x[3], S23, 0xf4d50d87);      /* 27 */
323     GG(b, c, d, a, x[8], S24, 0x455a14ed);      /* 28 */
324     GG(a, b, c, d, x[13], S21, 0xa9e3e905);     /* 29 */
325     GG(d, a, b, c, x[2], S22, 0xfcefa3f8);      /* 30 */
326     GG(c, d, a, b, x[7], S23, 0x676f02d9);      /* 31 */
327     GG(b, c, d, a, x[12], S24, 0x8d2a4c8a);     /* 32 */
328
329     /* Round 3 */
330     HH(a, b, c, d, x[5], S31, 0xfffa3942);      /* 33 */
331     HH(d, a, b, c, x[8], S32, 0x8771f681);      /* 34 */
332     HH(c, d, a, b, x[11], S33, 0x6d9d6122);     /* 35 */
333     HH(b, c, d, a, x[14], S34, 0xfde5380c);     /* 36 */
334     HH(a, b, c, d, x[1], S31, 0xa4beea44);      /* 37 */
335     HH(d, a, b, c, x[4], S32, 0x4bdecfa9);      /* 38 */
336     HH(c, d, a, b, x[7], S33, 0xf6bb4b60);      /* 39 */
337     HH(b, c, d, a, x[10], S34, 0xbebfbc70);     /* 40 */
338     HH(a, b, c, d, x[13], S31, 0x289b7ec6);     /* 41 */
339     HH(d, a, b, c, x[0], S32, 0xeaa127fa);      /* 42 */
340     HH(c, d, a, b, x[3], S33, 0xd4ef3085);      /* 43 */
341     HH(b, c, d, a, x[6], S34, 0x4881d05);       /* 44 */
342     HH(a, b, c, d, x[9], S31, 0xd9d4d039);      /* 45 */
343     HH(d, a, b, c, x[12], S32, 0xe6db99e5);     /* 46 */
344     HH(c, d, a, b, x[15], S33, 0x1fa27cf8);     /* 47 */
345     HH(b, c, d, a, x[2], S34, 0xc4ac5665);      /* 48 */
346
347     /* Round 4 */
348     II(a, b, c, d, x[0], S41, 0xf4292244);      /* 49 */
349     II(d, a, b, c, x[7], S42, 0x432aff97);      /* 50 */
350     II(c, d, a, b, x[14], S43, 0xab9423a7);     /* 51 */
351     II(b, c, d, a, x[5], S44, 0xfc93a039);      /* 52 */
352     II(a, b, c, d, x[12], S41, 0x655b59c3);     /* 53 */
353     II(d, a, b, c, x[3], S42, 0x8f0ccc92);      /* 54 */
354     II(c, d, a, b, x[10], S43, 0xffeff47d);     /* 55 */
355     II(b, c, d, a, x[1], S44, 0x85845dd1);      /* 56 */
356     II(a, b, c, d, x[8], S41, 0x6fa87e4f);      /* 57 */
357     II(d, a, b, c, x[15], S42, 0xfe2ce6e0);     /* 58 */
358     II(c, d, a, b, x[6], S43, 0xa3014314);      /* 59 */
359     II(b, c, d, a, x[13], S44, 0x4e0811a1);     /* 60 */
360     II(a, b, c, d, x[4], S41, 0xf7537e82);      /* 61 */
361     II(d, a, b, c, x[11], S42, 0xbd3af235);     /* 62 */
362     II(c, d, a, b, x[2], S43, 0x2ad7d2bb);      /* 63 */
363     II(b, c, d, a, x[9], S44, 0xeb86d391);      /* 64 */
364
365     state[0] += a;
366     state[1] += b;
367     state[2] += c;
368     state[3] += d;
369
370     /* Zeroize sensitive information. */
371     memset(x, 0, sizeof(x));
372 }
373
374 /* Encodes input (jk_uint32_t) into output (unsigned char). Assumes len is
375    a multiple of 4.
376  */
377 static void Encode(unsigned char *output, const jk_uint32_t * input, size_t len)
378 {
379     size_t i, j;
380     jk_uint32_t k;
381
382     for (i = 0, j = 0; j < len; i++, j += 4) {
383         k = input[i];
384         output[j] = (unsigned char)(k & 0xff);
385         output[j + 1] = (unsigned char)((k >> 8) & 0xff);
386         output[j + 2] = (unsigned char)((k >> 16) & 0xff);
387         output[j + 3] = (unsigned char)((k >> 24) & 0xff);
388     }
389 }
390
391 /* Decodes input (unsigned char) into output (jk_uint32_t). Assumes len is
392  * a multiple of 4.
393  */
394 static void Decode(jk_uint32_t * output, const unsigned char *input, size_t len)
395 {
396     size_t i, j;
397
398     for (i = 0, j = 0; j < len; i++, j += 4)
399         output[i] = ((jk_uint32_t) input[j]) | (((jk_uint32_t) input[j + 1]) << 8) |
400             (((jk_uint32_t) input[j + 2]) << 16) | (((jk_uint32_t) input[j + 3]) <<
401                                                  24);
402 }
403
404 char *JK_METHOD jk_md5(const unsigned char *org, const unsigned char *org2,
405                        char *dst)
406 {
407     JK_MD5_CTX ctx;
408     char buf[JK_MD5_DIGESTSIZE + 1];
409
410     jk_MD5Init(&ctx);
411     jk_MD5Update(&ctx, org, strlen((const char *)org));
412
413     if (org2 != NULL)
414         jk_MD5Update(&ctx, org2, strlen((const char *)org2));
415
416     jk_MD5Final((unsigned char *)buf, &ctx);
417     return (jk_hextocstr((unsigned char *)buf, dst, JK_MD5_DIGESTSIZE));
418 }
419
420 #else /* USE_APACHE_MD5 */
421
422 #include "httpd.h"
423 #include "http_config.h"
424
425 #ifdef STANDARD20_MODULE_STUFF
426
427 #include "apr_md5.h"
428 #define  AP_MD5_CTX     apr_md5_ctx_t
429 #define  ap_MD5Init     apr_md5_init
430 #define  ap_MD5Update   apr_md5_update
431 #define  ap_MD5Final    apr_md5_final
432
433 #else /* STANDARD20_MODULE_STUFF */
434
435 #include "ap_md5.h"
436
437 #endif /* STANDARD20_MODULE_STUFF */
438
439 char *JK_METHOD jk_md5(const unsigned char *org, const unsigned char *org2,
440                        char *dst)
441 {
442     AP_MD5_CTX ctx;
443     char buf[JK_MD5_DIGESTSIZE + 1];
444
445     ap_MD5Init(&ctx);
446     ap_MD5Update(&ctx, org, strlen((const char *)org));
447
448     if (org2 != NULL)
449         ap_MD5Update(&ctx, org2, strlen((const char *)org2));
450
451     ap_MD5Final((unsigned char *)buf, &ctx);
452     return (jk_hextocstr((unsigned char *)buf, dst, JK_MD5_DIGESTSIZE));
453 }
454
455 #endif /* USE_APACHE_MD5 */
456
457 /* Test values:
458  * ""                  D4 1D 8C D9 8F 00 B2 04  E9 80 09 98 EC F8 42 7E
459  * "a"                 0C C1 75 B9 C0 F1 B6 A8  31 C3 99 E2 69 77 26 61
460  * "abc                90 01 50 98 3C D2 4F B0  D6 96 3F 7D 28 E1 7F 72
461  * "message digest"    F9 6B 69 7D 7C B7 93 8D  52 5A 2F 31 AA F1 61 D0
462  *
463  */
464
465 #ifdef TEST_JKMD5
466
467 main(int argc, char **argv)
468 {
469     char xxx[(2 * JK_MD5_DIGESTSIZE) + 1];
470
471     if (argc > 1)
472         printf("%s => %s\n", argv[1], jk_md5(argv[1], NULL, xxx));
473 }
474
475 #endif