md5.c

00001 /*
00002  * Copyright (c) 2005-2012 by KoanLogic s.r.l. <http://www.koanlogic.com>
00003  * All rights reserved.
00004  *
00005  * This file is part of KLone, and as such it is subject to the license stated
00006  * in the LICENSE file which you have received as part of this distribution.
00007  *
00008  * $Id: md5.c,v 1.4 2006/01/09 12:38:38 tat Exp $
00009  */
00010 
00011 /*
00012   Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
00013 
00014   This software is provided 'as-is', without any express or implied
00015   warranty.  In no event will the authors be held liable for any damages
00016   arising from the use of this software.
00017 
00018   Permission is granted to anyone to use this software for any purpose,
00019   including commercial applications, and to alter it and redistribute it
00020   freely, subject to the following restrictions:
00021 
00022   1. The origin of this software must not be misrepresented; you must not
00023      claim that you wrote the original software. If you use this software
00024      in a product, an acknowledgment in the product documentation would be
00025      appreciated but is not required.
00026   2. Altered source versions must be plainly marked as such, and must not be
00027      misrepresented as being the original software.
00028   3. This notice may not be removed or altered from any source distribution.
00029 
00030   L. Peter Deutsch
00031   ghost@aladdin.com
00032 
00033  */
00034 /* $Id: md5.c,v 1.4 2006/01/09 12:38:38 tat Exp $ */
00035 /*
00036   Independent implementation of MD5 (RFC 1321).
00037 
00038   This code implements the MD5 Algorithm defined in RFC 1321, whose
00039   text is available at
00040         http://www.ietf.org/rfc/rfc1321.txt
00041   The code is derived from the text of the RFC, including the test suite
00042   (section A.5) but excluding the rest of Appendix A.  It does not include
00043   any code or documentation that is identified in the RFC as being
00044   copyrighted.
00045 
00046   The original and principal author of md5.c is L. Peter Deutsch
00047   <ghost@aladdin.com>.  Other authors are noted in the change history
00048   that follows (in reverse chronological order):
00049 
00050   2002-09-13 dms move out any static byteorder check 
00051                  because dynamic one cost nothing
00052   2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
00053         either statically or dynamically; added missing #include <string.h>
00054         in library.
00055   2002-03-11 lpd Corrected argument list for main(), and added int return
00056         type, in test program and T value program.
00057   2002-02-21 lpd Added missing #include <stdio.h> in test program.
00058   2000-07-03 lpd Patched to eliminate warnings about "constant is
00059         unsigned in ANSI C, signed in traditional"; made test program
00060         self-checking.
00061   1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
00062   1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
00063   1999-05-03 lpd Original version.
00064  */
00065 
00066 #include <string.h>
00067 #include <stdio.h>
00068 #include <sys/stat.h>
00069 #include <sys/types.h>
00070 #include <fcntl.h>
00071 #include <klone/md5.h>
00072 
00073 
00074 #define T_MASK ((md5_word_t)~0)
00075 #define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
00076 #define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
00077 #define T3    0x242070db
00078 #define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
00079 #define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
00080 #define T6    0x4787c62a
00081 #define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
00082 #define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
00083 #define T9    0x698098d8
00084 #define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
00085 #define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
00086 #define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
00087 #define T13    0x6b901122
00088 #define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
00089 #define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
00090 #define T16    0x49b40821
00091 #define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
00092 #define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
00093 #define T19    0x265e5a51
00094 #define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
00095 #define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
00096 #define T22    0x02441453
00097 #define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
00098 #define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
00099 #define T25    0x21e1cde6
00100 #define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
00101 #define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
00102 #define T28    0x455a14ed
00103 #define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
00104 #define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
00105 #define T31    0x676f02d9
00106 #define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
00107 #define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
00108 #define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
00109 #define T35    0x6d9d6122
00110 #define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
00111 #define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
00112 #define T38    0x4bdecfa9
00113 #define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
00114 #define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
00115 #define T41    0x289b7ec6
00116 #define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
00117 #define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
00118 #define T44    0x04881d05
00119 #define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
00120 #define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
00121 #define T47    0x1fa27cf8
00122 #define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
00123 #define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
00124 #define T50    0x432aff97
00125 #define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
00126 #define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
00127 #define T53    0x655b59c3
00128 #define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
00129 #define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
00130 #define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
00131 #define T57    0x6fa87e4f
00132 #define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
00133 #define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
00134 #define T60    0x4e0811a1
00135 #define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
00136 #define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
00137 #define T63    0x2ad7d2bb
00138 #define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
00139 
00140 
00141 static void
00142 md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
00143 {
00144     md5_word_t
00145         a = pms->abcd[0], b = pms->abcd[1],
00146         c = pms->abcd[2], d = pms->abcd[3];
00147     md5_word_t t;
00148     /* Define storage for little-endian or both types of CPUs. */
00149     md5_word_t xbuf[16];
00150     const md5_word_t *X;
00151 
00152         /*
00153          * Determine dynamically whether this is a big-endian or
00154          * little-endian machine, since we can use a more efficient
00155          * algorithm on the latter.
00156          */
00157         static const int w = 1;
00158 
00159         if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
00160         {
00161             /*
00162              * On little-endian machines, we can process properly aligned
00163              * data without copying it.
00164              */
00165             if (!((data - (const md5_byte_t *)0) & 3)) {
00166                 /* data are properly aligned */
00167                 X = (const md5_word_t *)data;
00168             } else {
00169                 /* not aligned */
00170                 memcpy(xbuf, data, 64);
00171                 X = xbuf;
00172             }
00173         }
00174         else                        /* dynamic big-endian */
00175         {
00176             /*
00177              * On big-endian machines, we must arrange the bytes in the
00178              * right order.
00179              */
00180             const md5_byte_t *xp = data;
00181             int i;
00182 
00183             X = xbuf;                /* (dynamic only) */
00184             for (i = 0; i < 16; ++i, xp += 4)
00185                 xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
00186         }
00187 
00188 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
00189 
00190     /* Round 1. */
00191     /* Let [abcd k s i] denote the operation
00192        a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
00193 #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
00194 #define SET(a, b, c, d, k, s, Ti)\
00195   t = a + F(b,c,d) + X[k] + Ti;\
00196   a = ROTATE_LEFT(t, s) + b
00197     /* Do the following 16 operations. */
00198     SET(a, b, c, d,  0,  7,  T1);
00199     SET(d, a, b, c,  1, 12,  T2);
00200     SET(c, d, a, b,  2, 17,  T3);
00201     SET(b, c, d, a,  3, 22,  T4);
00202     SET(a, b, c, d,  4,  7,  T5);
00203     SET(d, a, b, c,  5, 12,  T6);
00204     SET(c, d, a, b,  6, 17,  T7);
00205     SET(b, c, d, a,  7, 22,  T8);
00206     SET(a, b, c, d,  8,  7,  T9);
00207     SET(d, a, b, c,  9, 12, T10);
00208     SET(c, d, a, b, 10, 17, T11);
00209     SET(b, c, d, a, 11, 22, T12);
00210     SET(a, b, c, d, 12,  7, T13);
00211     SET(d, a, b, c, 13, 12, T14);
00212     SET(c, d, a, b, 14, 17, T15);
00213     SET(b, c, d, a, 15, 22, T16);
00214 #undef SET
00215 
00216      /* Round 2. */
00217      /* Let [abcd k s i] denote the operation
00218           a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
00219 #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
00220 #define SET(a, b, c, d, k, s, Ti)\
00221   t = a + G(b,c,d) + X[k] + Ti;\
00222   a = ROTATE_LEFT(t, s) + b
00223      /* Do the following 16 operations. */
00224     SET(a, b, c, d,  1,  5, T17);
00225     SET(d, a, b, c,  6,  9, T18);
00226     SET(c, d, a, b, 11, 14, T19);
00227     SET(b, c, d, a,  0, 20, T20);
00228     SET(a, b, c, d,  5,  5, T21);
00229     SET(d, a, b, c, 10,  9, T22);
00230     SET(c, d, a, b, 15, 14, T23);
00231     SET(b, c, d, a,  4, 20, T24);
00232     SET(a, b, c, d,  9,  5, T25);
00233     SET(d, a, b, c, 14,  9, T26);
00234     SET(c, d, a, b,  3, 14, T27);
00235     SET(b, c, d, a,  8, 20, T28);
00236     SET(a, b, c, d, 13,  5, T29);
00237     SET(d, a, b, c,  2,  9, T30);
00238     SET(c, d, a, b,  7, 14, T31);
00239     SET(b, c, d, a, 12, 20, T32);
00240 #undef SET
00241 
00242      /* Round 3. */
00243      /* Let [abcd k s t] denote the operation
00244           a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
00245 #define H(x, y, z) ((x) ^ (y) ^ (z))
00246 #define SET(a, b, c, d, k, s, Ti)\
00247   t = a + H(b,c,d) + X[k] + Ti;\
00248   a = ROTATE_LEFT(t, s) + b
00249      /* Do the following 16 operations. */
00250     SET(a, b, c, d,  5,  4, T33);
00251     SET(d, a, b, c,  8, 11, T34);
00252     SET(c, d, a, b, 11, 16, T35);
00253     SET(b, c, d, a, 14, 23, T36);
00254     SET(a, b, c, d,  1,  4, T37);
00255     SET(d, a, b, c,  4, 11, T38);
00256     SET(c, d, a, b,  7, 16, T39);
00257     SET(b, c, d, a, 10, 23, T40);
00258     SET(a, b, c, d, 13,  4, T41);
00259     SET(d, a, b, c,  0, 11, T42);
00260     SET(c, d, a, b,  3, 16, T43);
00261     SET(b, c, d, a,  6, 23, T44);
00262     SET(a, b, c, d,  9,  4, T45);
00263     SET(d, a, b, c, 12, 11, T46);
00264     SET(c, d, a, b, 15, 16, T47);
00265     SET(b, c, d, a,  2, 23, T48);
00266 #undef SET
00267 
00268      /* Round 4. */
00269      /* Let [abcd k s t] denote the operation
00270           a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
00271 #define I(x, y, z) ((y) ^ ((x) | ~(z)))
00272 #define SET(a, b, c, d, k, s, Ti)\
00273   t = a + I(b,c,d) + X[k] + Ti;\
00274   a = ROTATE_LEFT(t, s) + b
00275      /* Do the following 16 operations. */
00276     SET(a, b, c, d,  0,  6, T49);
00277     SET(d, a, b, c,  7, 10, T50);
00278     SET(c, d, a, b, 14, 15, T51);
00279     SET(b, c, d, a,  5, 21, T52);
00280     SET(a, b, c, d, 12,  6, T53);
00281     SET(d, a, b, c,  3, 10, T54);
00282     SET(c, d, a, b, 10, 15, T55);
00283     SET(b, c, d, a,  1, 21, T56);
00284     SET(a, b, c, d,  8,  6, T57);
00285     SET(d, a, b, c, 15, 10, T58);
00286     SET(c, d, a, b,  6, 15, T59);
00287     SET(b, c, d, a, 13, 21, T60);
00288     SET(a, b, c, d,  4,  6, T61);
00289     SET(d, a, b, c, 11, 10, T62);
00290     SET(c, d, a, b,  2, 15, T63);
00291     SET(b, c, d, a,  9, 21, T64);
00292 #undef SET
00293 
00294      /* Then perform the following additions. (That is increment each
00295         of the four registers by the value it had before this block
00296         was started.) */
00297     pms->abcd[0] += a;
00298     pms->abcd[1] += b;
00299     pms->abcd[2] += c;
00300     pms->abcd[3] += d;
00301 }
00302 
00303 void
00304 md5_init(md5_state_t *pms)
00305 {
00306     pms->count[0] = pms->count[1] = 0;
00307     pms->abcd[0] = 0x67452301;
00308     pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
00309     pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
00310     pms->abcd[3] = 0x10325476;
00311 }
00312 
00313 void
00314 md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
00315 {
00316     const md5_byte_t *p = data;
00317     int left = nbytes;
00318     int offset = (pms->count[0] >> 3) & 63;
00319     md5_word_t nbits = (md5_word_t)(nbytes << 3);
00320 
00321     if (nbytes <= 0)
00322         return;
00323 
00324     /* Update the message length. */
00325     pms->count[1] += nbytes >> 29;
00326     pms->count[0] += nbits;
00327     if (pms->count[0] < nbits)
00328         pms->count[1]++;
00329 
00330     /* Process an initial partial block. */
00331     if (offset) {
00332         int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
00333 
00334         memcpy(pms->buf + offset, p, copy);
00335         if (offset + copy < 64)
00336             return;
00337         p += copy;
00338         left -= copy;
00339         md5_process(pms, pms->buf);
00340     }
00341 
00342     /* Process full blocks. */
00343     for (; left >= 64; p += 64, left -= 64)
00344         md5_process(pms, p);
00345 
00346     /* Process a final partial block. */
00347     if (left)
00348         memcpy(pms->buf, p, left);
00349 }
00350 
00351 void
00352 md5_finish(md5_state_t *pms, md5_byte_t digest[16])
00353 {
00354     static const md5_byte_t pad[64] = {
00355         0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00356         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00357         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00358         0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00359     };
00360     md5_byte_t data[8];
00361     int i;
00362 
00363     /* Save the length before padding. */
00364     for (i = 0; i < 8; ++i)
00365         data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
00366     /* Pad to 56 bytes mod 64. */
00367     md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
00368     /* Append the length. */
00369     md5_append(pms, data, 8);
00370     for (i = 0; i < 16; ++i)
00371         digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
00372 }

←Products
Copyright © 2005-2012 - KoanLogic S.r.l. - All rights reserved