[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     ! 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