Header And Logo

PostgreSQL
| The world's most advanced open source database.

md5.c

Go to the documentation of this file.
00001 /*     $KAME: md5.c,v 1.3 2000/02/22 14:01:17 itojun Exp $     */
00002 
00003 /*
00004  * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the project nor the names of its contributors
00016  *    may be used to endorse or promote products derived from this software
00017  *    without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
00020  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022  * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
00023  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00024  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00025  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00026  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00027  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00028  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * contrib/pgcrypto/md5.c
00032  */
00033 
00034 #include "postgres.h"
00035 
00036 #include <sys/param.h>
00037 
00038 #include "md5.h"
00039 
00040 #define SHIFT(X, s) (((X) << (s)) | ((X) >> (32 - (s))))
00041 
00042 #define F(X, Y, Z) (((X) & (Y)) | ((~X) & (Z)))
00043 #define G(X, Y, Z) (((X) & (Z)) | ((Y) & (~Z)))
00044 #define H(X, Y, Z) ((X) ^ (Y) ^ (Z))
00045 #define I(X, Y, Z) ((Y) ^ ((X) | (~Z)))
00046 
00047 #define ROUND1(a, b, c, d, k, s, i) \
00048 do { \
00049     (a) = (a) + F((b), (c), (d)) + X[(k)] + T[(i)]; \
00050     (a) = SHIFT((a), (s)); \
00051     (a) = (b) + (a); \
00052 } while (0)
00053 
00054 #define ROUND2(a, b, c, d, k, s, i) \
00055 do { \
00056     (a) = (a) + G((b), (c), (d)) + X[(k)] + T[(i)]; \
00057     (a) = SHIFT((a), (s)); \
00058     (a) = (b) + (a); \
00059 } while (0)
00060 
00061 #define ROUND3(a, b, c, d, k, s, i) \
00062 do { \
00063     (a) = (a) + H((b), (c), (d)) + X[(k)] + T[(i)]; \
00064     (a) = SHIFT((a), (s)); \
00065     (a) = (b) + (a); \
00066 } while (0)
00067 
00068 #define ROUND4(a, b, c, d, k, s, i) \
00069 do { \
00070     (a) = (a) + I((b), (c), (d)) + X[(k)] + T[(i)]; \
00071     (a) = SHIFT((a), (s)); \
00072     (a) = (b) + (a); \
00073 } while (0)
00074 
00075 #define Sa   7
00076 #define Sb  12
00077 #define Sc  17
00078 #define Sd  22
00079 
00080 #define Se   5
00081 #define Sf   9
00082 #define Sg  14
00083 #define Sh  20
00084 
00085 #define Si   4
00086 #define Sj  11
00087 #define Sk  16
00088 #define Sl  23
00089 
00090 #define Sm   6
00091 #define Sn  10
00092 #define So  15
00093 #define Sp  21
00094 
00095 #define MD5_A0  0x67452301
00096 #define MD5_B0  0xefcdab89
00097 #define MD5_C0  0x98badcfe
00098 #define MD5_D0  0x10325476
00099 
00100 /* Integer part of 4294967296 times abs(sin(i)), where i is in radians. */
00101 static const uint32 T[65] = {
00102     0,
00103     0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
00104     0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
00105     0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
00106     0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
00107 
00108     0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
00109     0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8,
00110     0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
00111     0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
00112 
00113     0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
00114     0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
00115     0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
00116     0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
00117 
00118     0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
00119     0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
00120     0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
00121     0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
00122 };
00123 
00124 static const uint8 md5_paddat[MD5_BUFLEN] = {
00125     0x80, 0, 0, 0, 0, 0, 0, 0,
00126     0, 0, 0, 0, 0, 0, 0, 0,
00127     0, 0, 0, 0, 0, 0, 0, 0,
00128     0, 0, 0, 0, 0, 0, 0, 0,
00129     0, 0, 0, 0, 0, 0, 0, 0,
00130     0, 0, 0, 0, 0, 0, 0, 0,
00131     0, 0, 0, 0, 0, 0, 0, 0,
00132     0, 0, 0, 0, 0, 0, 0, 0,
00133 };
00134 
00135 static void md5_calc(uint8 *, md5_ctxt *);
00136 
00137 void
00138 md5_init(md5_ctxt *ctxt)
00139 {
00140     ctxt->md5_n = 0;
00141     ctxt->md5_i = 0;
00142     ctxt->md5_sta = MD5_A0;
00143     ctxt->md5_stb = MD5_B0;
00144     ctxt->md5_stc = MD5_C0;
00145     ctxt->md5_std = MD5_D0;
00146     memset(ctxt->md5_buf, 0, sizeof(ctxt->md5_buf));
00147 }
00148 
00149 void
00150 md5_loop(md5_ctxt *ctxt, const uint8 *input, unsigned len)
00151 {
00152     unsigned int gap,
00153                 i;
00154 
00155     ctxt->md5_n += len * 8;     /* byte to bit */
00156     gap = MD5_BUFLEN - ctxt->md5_i;
00157 
00158     if (len >= gap)
00159     {
00160         memmove(ctxt->md5_buf + ctxt->md5_i, input, gap);
00161         md5_calc(ctxt->md5_buf, ctxt);
00162 
00163         for (i = gap; i + MD5_BUFLEN <= len; i += MD5_BUFLEN)
00164             md5_calc((uint8 *) (input + i), ctxt);
00165 
00166         ctxt->md5_i = len - i;
00167         memmove(ctxt->md5_buf, input + i, ctxt->md5_i);
00168     }
00169     else
00170     {
00171         memmove(ctxt->md5_buf + ctxt->md5_i, input, len);
00172         ctxt->md5_i += len;
00173     }
00174 }
00175 
00176 void
00177 md5_pad(md5_ctxt *ctxt)
00178 {
00179     unsigned int gap;
00180 
00181     /* Don't count up padding. Keep md5_n. */
00182     gap = MD5_BUFLEN - ctxt->md5_i;
00183     if (gap > 8)
00184     {
00185         memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat,
00186                 gap - sizeof(ctxt->md5_n));
00187     }
00188     else
00189     {
00190         /* including gap == 8 */
00191         memmove(ctxt->md5_buf + ctxt->md5_i, md5_paddat, gap);
00192         md5_calc(ctxt->md5_buf, ctxt);
00193         memmove(ctxt->md5_buf, md5_paddat + gap,
00194                 MD5_BUFLEN - sizeof(ctxt->md5_n));
00195     }
00196 
00197     /* 8 byte word */
00198 #ifndef WORDS_BIGENDIAN
00199     memmove(&ctxt->md5_buf[56], &ctxt->md5_n8[0], 8);
00200 #else
00201     ctxt->md5_buf[56] = ctxt->md5_n8[7];
00202     ctxt->md5_buf[57] = ctxt->md5_n8[6];
00203     ctxt->md5_buf[58] = ctxt->md5_n8[5];
00204     ctxt->md5_buf[59] = ctxt->md5_n8[4];
00205     ctxt->md5_buf[60] = ctxt->md5_n8[3];
00206     ctxt->md5_buf[61] = ctxt->md5_n8[2];
00207     ctxt->md5_buf[62] = ctxt->md5_n8[1];
00208     ctxt->md5_buf[63] = ctxt->md5_n8[0];
00209 #endif
00210 
00211     md5_calc(ctxt->md5_buf, ctxt);
00212 }
00213 
00214 void
00215 md5_result(uint8 *digest, md5_ctxt *ctxt)
00216 {
00217     /* 4 byte words */
00218 #ifndef WORDS_BIGENDIAN
00219     memmove(digest, &ctxt->md5_st8[0], 16);
00220 #else
00221     digest[0] = ctxt->md5_st8[3];
00222     digest[1] = ctxt->md5_st8[2];
00223     digest[2] = ctxt->md5_st8[1];
00224     digest[3] = ctxt->md5_st8[0];
00225     digest[4] = ctxt->md5_st8[7];
00226     digest[5] = ctxt->md5_st8[6];
00227     digest[6] = ctxt->md5_st8[5];
00228     digest[7] = ctxt->md5_st8[4];
00229     digest[8] = ctxt->md5_st8[11];
00230     digest[9] = ctxt->md5_st8[10];
00231     digest[10] = ctxt->md5_st8[9];
00232     digest[11] = ctxt->md5_st8[8];
00233     digest[12] = ctxt->md5_st8[15];
00234     digest[13] = ctxt->md5_st8[14];
00235     digest[14] = ctxt->md5_st8[13];
00236     digest[15] = ctxt->md5_st8[12];
00237 #endif
00238 }
00239 
00240 #ifdef WORDS_BIGENDIAN
00241 static uint32 X[16];
00242 #endif
00243 
00244 static void
00245 md5_calc(uint8 *b64, md5_ctxt *ctxt)
00246 {
00247     uint32      A = ctxt->md5_sta;
00248     uint32      B = ctxt->md5_stb;
00249     uint32      C = ctxt->md5_stc;
00250     uint32      D = ctxt->md5_std;
00251 
00252 #ifndef WORDS_BIGENDIAN
00253     uint32     *X = (uint32 *) b64;
00254 #else
00255     /* 4 byte words */
00256     /* what a brute force but fast! */
00257     uint8      *y = (uint8 *) X;
00258 
00259     y[0] = b64[3];
00260     y[1] = b64[2];
00261     y[2] = b64[1];
00262     y[3] = b64[0];
00263     y[4] = b64[7];
00264     y[5] = b64[6];
00265     y[6] = b64[5];
00266     y[7] = b64[4];
00267     y[8] = b64[11];
00268     y[9] = b64[10];
00269     y[10] = b64[9];
00270     y[11] = b64[8];
00271     y[12] = b64[15];
00272     y[13] = b64[14];
00273     y[14] = b64[13];
00274     y[15] = b64[12];
00275     y[16] = b64[19];
00276     y[17] = b64[18];
00277     y[18] = b64[17];
00278     y[19] = b64[16];
00279     y[20] = b64[23];
00280     y[21] = b64[22];
00281     y[22] = b64[21];
00282     y[23] = b64[20];
00283     y[24] = b64[27];
00284     y[25] = b64[26];
00285     y[26] = b64[25];
00286     y[27] = b64[24];
00287     y[28] = b64[31];
00288     y[29] = b64[30];
00289     y[30] = b64[29];
00290     y[31] = b64[28];
00291     y[32] = b64[35];
00292     y[33] = b64[34];
00293     y[34] = b64[33];
00294     y[35] = b64[32];
00295     y[36] = b64[39];
00296     y[37] = b64[38];
00297     y[38] = b64[37];
00298     y[39] = b64[36];
00299     y[40] = b64[43];
00300     y[41] = b64[42];
00301     y[42] = b64[41];
00302     y[43] = b64[40];
00303     y[44] = b64[47];
00304     y[45] = b64[46];
00305     y[46] = b64[45];
00306     y[47] = b64[44];
00307     y[48] = b64[51];
00308     y[49] = b64[50];
00309     y[50] = b64[49];
00310     y[51] = b64[48];
00311     y[52] = b64[55];
00312     y[53] = b64[54];
00313     y[54] = b64[53];
00314     y[55] = b64[52];
00315     y[56] = b64[59];
00316     y[57] = b64[58];
00317     y[58] = b64[57];
00318     y[59] = b64[56];
00319     y[60] = b64[63];
00320     y[61] = b64[62];
00321     y[62] = b64[61];
00322     y[63] = b64[60];
00323 #endif
00324 
00325     ROUND1(A, B, C, D, 0, Sa, 1);
00326     ROUND1(D, A, B, C, 1, Sb, 2);
00327     ROUND1(C, D, A, B, 2, Sc, 3);
00328     ROUND1(B, C, D, A, 3, Sd, 4);
00329     ROUND1(A, B, C, D, 4, Sa, 5);
00330     ROUND1(D, A, B, C, 5, Sb, 6);
00331     ROUND1(C, D, A, B, 6, Sc, 7);
00332     ROUND1(B, C, D, A, 7, Sd, 8);
00333     ROUND1(A, B, C, D, 8, Sa, 9);
00334     ROUND1(D, A, B, C, 9, Sb, 10);
00335     ROUND1(C, D, A, B, 10, Sc, 11);
00336     ROUND1(B, C, D, A, 11, Sd, 12);
00337     ROUND1(A, B, C, D, 12, Sa, 13);
00338     ROUND1(D, A, B, C, 13, Sb, 14);
00339     ROUND1(C, D, A, B, 14, Sc, 15);
00340     ROUND1(B, C, D, A, 15, Sd, 16);
00341 
00342     ROUND2(A, B, C, D, 1, Se, 17);
00343     ROUND2(D, A, B, C, 6, Sf, 18);
00344     ROUND2(C, D, A, B, 11, Sg, 19);
00345     ROUND2(B, C, D, A, 0, Sh, 20);
00346     ROUND2(A, B, C, D, 5, Se, 21);
00347     ROUND2(D, A, B, C, 10, Sf, 22);
00348     ROUND2(C, D, A, B, 15, Sg, 23);
00349     ROUND2(B, C, D, A, 4, Sh, 24);
00350     ROUND2(A, B, C, D, 9, Se, 25);
00351     ROUND2(D, A, B, C, 14, Sf, 26);
00352     ROUND2(C, D, A, B, 3, Sg, 27);
00353     ROUND2(B, C, D, A, 8, Sh, 28);
00354     ROUND2(A, B, C, D, 13, Se, 29);
00355     ROUND2(D, A, B, C, 2, Sf, 30);
00356     ROUND2(C, D, A, B, 7, Sg, 31);
00357     ROUND2(B, C, D, A, 12, Sh, 32);
00358 
00359     ROUND3(A, B, C, D, 5, Si, 33);
00360     ROUND3(D, A, B, C, 8, Sj, 34);
00361     ROUND3(C, D, A, B, 11, Sk, 35);
00362     ROUND3(B, C, D, A, 14, Sl, 36);
00363     ROUND3(A, B, C, D, 1, Si, 37);
00364     ROUND3(D, A, B, C, 4, Sj, 38);
00365     ROUND3(C, D, A, B, 7, Sk, 39);
00366     ROUND3(B, C, D, A, 10, Sl, 40);
00367     ROUND3(A, B, C, D, 13, Si, 41);
00368     ROUND3(D, A, B, C, 0, Sj, 42);
00369     ROUND3(C, D, A, B, 3, Sk, 43);
00370     ROUND3(B, C, D, A, 6, Sl, 44);
00371     ROUND3(A, B, C, D, 9, Si, 45);
00372     ROUND3(D, A, B, C, 12, Sj, 46);
00373     ROUND3(C, D, A, B, 15, Sk, 47);
00374     ROUND3(B, C, D, A, 2, Sl, 48);
00375 
00376     ROUND4(A, B, C, D, 0, Sm, 49);
00377     ROUND4(D, A, B, C, 7, Sn, 50);
00378     ROUND4(C, D, A, B, 14, So, 51);
00379     ROUND4(B, C, D, A, 5, Sp, 52);
00380     ROUND4(A, B, C, D, 12, Sm, 53);
00381     ROUND4(D, A, B, C, 3, Sn, 54);
00382     ROUND4(C, D, A, B, 10, So, 55);
00383     ROUND4(B, C, D, A, 1, Sp, 56);
00384     ROUND4(A, B, C, D, 8, Sm, 57);
00385     ROUND4(D, A, B, C, 15, Sn, 58);
00386     ROUND4(C, D, A, B, 6, So, 59);
00387     ROUND4(B, C, D, A, 13, Sp, 60);
00388     ROUND4(A, B, C, D, 4, Sm, 61);
00389     ROUND4(D, A, B, C, 11, Sn, 62);
00390     ROUND4(C, D, A, B, 2, So, 63);
00391     ROUND4(B, C, D, A, 9, Sp, 64);
00392 
00393     ctxt->md5_sta += A;
00394     ctxt->md5_stb += B;
00395     ctxt->md5_stc += C;
00396     ctxt->md5_std += D;
00397 }