[BACK]Return to md5.c CVS log [TXT][DIR] Up to [local] / sys / crypto

Annotation of sys/crypto/md5.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: md5.c,v 1.1 2004/05/07 14:42:26 millert Exp $ */
                      2:
                      3: /*
                      4:  * This code implements the MD5 message-digest algorithm.
                      5:  * The algorithm is due to Ron Rivest. This code was
                      6:  * written by Colin Plumb in 1993, no copyright is claimed.
                      7:  * This code is in the public domain; do with it what you wish.
                      8:  *
                      9:  * Equivalent code is available from RSA Data Security, Inc.
                     10:  * This code has been tested against that, and is equivalent,
                     11:  * except that you don't need to include two pages of legalese
                     12:  * with every copy.
                     13:  *
                     14:  * To compute the message digest of a chunk of bytes, declare an
                     15:  * MD5Context structure, pass it to MD5Init, call MD5Update as
                     16:  * needed on buffers full of bytes, and then call MD5Final, which
                     17:  * will fill a supplied 16-byte array with the digest.
                     18:  */
                     19:
                     20: #include <sys/param.h>
                     21: #include <sys/systm.h>
                     22: #include <crypto/md5.h>
                     23:
                     24: #define PUT_64BIT_LE(cp, value) do {                                   \
                     25:        (cp)[7] = (value) >> 56;                                        \
                     26:        (cp)[6] = (value) >> 48;                                        \
                     27:        (cp)[5] = (value) >> 40;                                        \
                     28:        (cp)[4] = (value) >> 32;                                        \
                     29:        (cp)[3] = (value) >> 24;                                        \
                     30:        (cp)[2] = (value) >> 16;                                        \
                     31:        (cp)[1] = (value) >> 8;                                         \
                     32:        (cp)[0] = (value); } while (0)
                     33:
                     34: #define PUT_32BIT_LE(cp, value) do {                                   \
                     35:        (cp)[3] = (value) >> 24;                                        \
                     36:        (cp)[2] = (value) >> 16;                                        \
                     37:        (cp)[1] = (value) >> 8;                                         \
                     38:        (cp)[0] = (value); } while (0)
                     39:
                     40: static u_int8_t PADDING[MD5_BLOCK_LENGTH] = {
                     41:        0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     42:        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                     43:        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                     44: };
                     45:
                     46: /*
                     47:  * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
                     48:  * initialization constants.
                     49:  */
                     50: void
                     51: MD5Init(MD5_CTX *ctx)
                     52: {
                     53:        ctx->count = 0;
                     54:        ctx->state[0] = 0x67452301;
                     55:        ctx->state[1] = 0xefcdab89;
                     56:        ctx->state[2] = 0x98badcfe;
                     57:        ctx->state[3] = 0x10325476;
                     58: }
                     59:
                     60: /*
                     61:  * Update context to reflect the concatenation of another buffer full
                     62:  * of bytes.
                     63:  */
                     64: void
                     65: MD5Update(MD5_CTX *ctx, const unsigned char *input, size_t len)
                     66: {
                     67:        size_t have, need;
                     68:
                     69:        /* Check how many bytes we already have and how many more we need. */
                     70:        have = (size_t)((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
                     71:        need = MD5_BLOCK_LENGTH - have;
                     72:
                     73:        /* Update bitcount */
                     74:        ctx->count += (u_int64_t)len << 3;
                     75:
                     76:        if (len >= need) {
                     77:                if (have != 0) {
                     78:                        bcopy(input, ctx->buffer + have, need);
                     79:                        MD5Transform(ctx->state, ctx->buffer);
                     80:                        input += need;
                     81:                        len -= need;
                     82:                        have = 0;
                     83:                }
                     84:
                     85:                /* Process data in MD5_BLOCK_LENGTH-byte chunks. */
                     86:                while (len >= MD5_BLOCK_LENGTH) {
                     87:                        MD5Transform(ctx->state, input);
                     88:                        input += MD5_BLOCK_LENGTH;
                     89:                        len -= MD5_BLOCK_LENGTH;
                     90:                }
                     91:        }
                     92:
                     93:        /* Handle any remaining bytes of data. */
                     94:        if (len != 0)
                     95:                bcopy(input, ctx->buffer + have, len);
                     96: }
                     97:
                     98: /*
                     99:  * Final wrapup - pad to 64-byte boundary with the bit pattern
                    100:  * 1 0* (64-bit count of bits processed, MSB-first)
                    101:  */
                    102: void
                    103: MD5Final(unsigned char digest[MD5_DIGEST_LENGTH], MD5_CTX *ctx)
                    104: {
                    105:        u_int8_t count[8];
                    106:        size_t padlen;
                    107:        int i;
                    108:
                    109:        /* Convert count to 8 bytes in little endian order. */
                    110:        PUT_64BIT_LE(count, ctx->count);
                    111:
                    112:        /* Pad out to 56 mod 64. */
                    113:        padlen = MD5_BLOCK_LENGTH -
                    114:            ((ctx->count >> 3) & (MD5_BLOCK_LENGTH - 1));
                    115:        if (padlen < 1 + 8)
                    116:                padlen += MD5_BLOCK_LENGTH;
                    117:        MD5Update(ctx, PADDING, padlen - 8);            /* padlen - 8 <= 64 */
                    118:        MD5Update(ctx, count, 8);
                    119:
                    120:        if (digest != NULL) {
                    121:                for (i = 0; i < 4; i++)
                    122:                        PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
                    123:        }
                    124:        bzero(ctx, sizeof(*ctx));       /* in case it's sensitive */
                    125: }
                    126:
                    127:
                    128: /* The four core functions - F1 is optimized somewhat */
                    129:
                    130: /* #define F1(x, y, z) (x & y | ~x & z) */
                    131: #define F1(x, y, z) (z ^ (x & (y ^ z)))
                    132: #define F2(x, y, z) F1(z, x, y)
                    133: #define F3(x, y, z) (x ^ y ^ z)
                    134: #define F4(x, y, z) (y ^ (x | ~z))
                    135:
                    136: /* This is the central step in the MD5 algorithm. */
                    137: #define MD5STEP(f, w, x, y, z, data, s) \
                    138:        ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
                    139:
                    140: /*
                    141:  * The core of the MD5 algorithm, this alters an existing MD5 hash to
                    142:  * reflect the addition of 16 longwords of new data.  MD5Update blocks
                    143:  * the data and converts bytes into longwords for this routine.
                    144:  */
                    145: void
                    146: MD5Transform(u_int32_t state[4], const u_int8_t block[MD5_BLOCK_LENGTH])
                    147: {
                    148:        u_int32_t a, b, c, d, in[MD5_BLOCK_LENGTH / 4];
                    149:
                    150: #if BYTE_ORDER == LITTLE_ENDIAN
                    151:        bcopy(block, in, sizeof(in));
                    152: #else
                    153:        for (a = 0; a < MD5_BLOCK_LENGTH / 4; a++) {
                    154:                in[a] = (u_int32_t)(
                    155:                    (u_int32_t)(block[a * 4 + 0]) |
                    156:                    (u_int32_t)(block[a * 4 + 1]) <<  8 |
                    157:                    (u_int32_t)(block[a * 4 + 2]) << 16 |
                    158:                    (u_int32_t)(block[a * 4 + 3]) << 24);
                    159:        }
                    160: #endif
                    161:
                    162:        a = state[0];
                    163:        b = state[1];
                    164:        c = state[2];
                    165:        d = state[3];
                    166:
                    167:        MD5STEP(F1, a, b, c, d, in[ 0] + 0xd76aa478,  7);
                    168:        MD5STEP(F1, d, a, b, c, in[ 1] + 0xe8c7b756, 12);
                    169:        MD5STEP(F1, c, d, a, b, in[ 2] + 0x242070db, 17);
                    170:        MD5STEP(F1, b, c, d, a, in[ 3] + 0xc1bdceee, 22);
                    171:        MD5STEP(F1, a, b, c, d, in[ 4] + 0xf57c0faf,  7);
                    172:        MD5STEP(F1, d, a, b, c, in[ 5] + 0x4787c62a, 12);
                    173:        MD5STEP(F1, c, d, a, b, in[ 6] + 0xa8304613, 17);
                    174:        MD5STEP(F1, b, c, d, a, in[ 7] + 0xfd469501, 22);
                    175:        MD5STEP(F1, a, b, c, d, in[ 8] + 0x698098d8,  7);
                    176:        MD5STEP(F1, d, a, b, c, in[ 9] + 0x8b44f7af, 12);
                    177:        MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
                    178:        MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
                    179:        MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122,  7);
                    180:        MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
                    181:        MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
                    182:        MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
                    183:
                    184:        MD5STEP(F2, a, b, c, d, in[ 1] + 0xf61e2562,  5);
                    185:        MD5STEP(F2, d, a, b, c, in[ 6] + 0xc040b340,  9);
                    186:        MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
                    187:        MD5STEP(F2, b, c, d, a, in[ 0] + 0xe9b6c7aa, 20);
                    188:        MD5STEP(F2, a, b, c, d, in[ 5] + 0xd62f105d,  5);
                    189:        MD5STEP(F2, d, a, b, c, in[10] + 0x02441453,  9);
                    190:        MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
                    191:        MD5STEP(F2, b, c, d, a, in[ 4] + 0xe7d3fbc8, 20);
                    192:        MD5STEP(F2, a, b, c, d, in[ 9] + 0x21e1cde6,  5);
                    193:        MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6,  9);
                    194:        MD5STEP(F2, c, d, a, b, in[ 3] + 0xf4d50d87, 14);
                    195:        MD5STEP(F2, b, c, d, a, in[ 8] + 0x455a14ed, 20);
                    196:        MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905,  5);
                    197:        MD5STEP(F2, d, a, b, c, in[ 2] + 0xfcefa3f8,  9);
                    198:        MD5STEP(F2, c, d, a, b, in[ 7] + 0x676f02d9, 14);
                    199:        MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
                    200:
                    201:        MD5STEP(F3, a, b, c, d, in[ 5] + 0xfffa3942,  4);
                    202:        MD5STEP(F3, d, a, b, c, in[ 8] + 0x8771f681, 11);
                    203:        MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
                    204:        MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
                    205:        MD5STEP(F3, a, b, c, d, in[ 1] + 0xa4beea44,  4);
                    206:        MD5STEP(F3, d, a, b, c, in[ 4] + 0x4bdecfa9, 11);
                    207:        MD5STEP(F3, c, d, a, b, in[ 7] + 0xf6bb4b60, 16);
                    208:        MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
                    209:        MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6,  4);
                    210:        MD5STEP(F3, d, a, b, c, in[ 0] + 0xeaa127fa, 11);
                    211:        MD5STEP(F3, c, d, a, b, in[ 3] + 0xd4ef3085, 16);
                    212:        MD5STEP(F3, b, c, d, a, in[ 6] + 0x04881d05, 23);
                    213:        MD5STEP(F3, a, b, c, d, in[ 9] + 0xd9d4d039,  4);
                    214:        MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
                    215:        MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
                    216:        MD5STEP(F3, b, c, d, a, in[2 ] + 0xc4ac5665, 23);
                    217:
                    218:        MD5STEP(F4, a, b, c, d, in[ 0] + 0xf4292244,  6);
                    219:        MD5STEP(F4, d, a, b, c, in[7 ] + 0x432aff97, 10);
                    220:        MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
                    221:        MD5STEP(F4, b, c, d, a, in[5 ] + 0xfc93a039, 21);
                    222:        MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3,  6);
                    223:        MD5STEP(F4, d, a, b, c, in[3 ] + 0x8f0ccc92, 10);
                    224:        MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
                    225:        MD5STEP(F4, b, c, d, a, in[1 ] + 0x85845dd1, 21);
                    226:        MD5STEP(F4, a, b, c, d, in[8 ] + 0x6fa87e4f,  6);
                    227:        MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
                    228:        MD5STEP(F4, c, d, a, b, in[6 ] + 0xa3014314, 15);
                    229:        MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
                    230:        MD5STEP(F4, a, b, c, d, in[4 ] + 0xf7537e82,  6);
                    231:        MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
                    232:        MD5STEP(F4, c, d, a, b, in[2 ] + 0x2ad7d2bb, 15);
                    233:        MD5STEP(F4, b, c, d, a, in[9 ] + 0xeb86d391, 21);
                    234:
                    235:        state[0] += a;
                    236:        state[1] += b;
                    237:        state[2] += c;
                    238:        state[3] += d;
                    239: }

CVSweb