Annotation of qemu/roms/ipxe/src/crypto/md5.c, revision 1.1.1.1

1.1       root        1: /* 
                      2:  * Cryptographic API.
                      3:  *
                      4:  * MD5 Message Digest Algorithm (RFC1321).
                      5:  *
                      6:  * Derived from cryptoapi implementation, originally based on the
                      7:  * public domain implementation written by Colin Plumb in 1993.
                      8:  *
                      9:  * Reduced object size by around 50% compared to the original Linux
                     10:  * version for use in Etherboot by Michael Brown.
                     11:  *
                     12:  * Copyright (c) Cryptoapi developers.
                     13:  * Copyright (c) 2002 James Morris <[email protected]>
                     14:  * Copyright (c) 2006 Michael Brown <[email protected]>
                     15:  * 
                     16:  * This program is free software; you can redistribute it and/or modify it
                     17:  * under the terms of the GNU General Public License as published by the Free
                     18:  * Software Foundation; either version 2 of the License, or (at your option) 
                     19:  * any later version.
                     20:  *
                     21:  */
                     22: 
                     23: FILE_LICENCE ( GPL2_OR_LATER );
                     24: 
                     25: #include <stdint.h>
                     26: #include <string.h>
                     27: #include <byteswap.h>
                     28: #include <ipxe/crypto.h>
                     29: #include <ipxe/md5.h>
                     30: 
                     31: struct md5_step {
                     32:        u32 ( * f ) ( u32 b, u32 c, u32 d );
                     33:        u8 coefficient;
                     34:        u8 constant;
                     35: };
                     36: 
                     37: static u32 f1(u32 b, u32 c, u32 d)
                     38: {
                     39:        return ( d ^ ( b & ( c ^ d ) ) );
                     40: }
                     41: 
                     42: static u32 f2(u32 b, u32 c, u32 d)
                     43: {
                     44:        return ( c ^ ( d & ( b ^ c ) ) );
                     45: }
                     46: 
                     47: static u32 f3(u32 b, u32 c, u32 d)
                     48: {
                     49:        return ( b ^ c ^ d );
                     50: }
                     51: 
                     52: static u32 f4(u32 b, u32 c, u32 d)
                     53: {
                     54:        return ( c ^ ( b | ~d ) );
                     55: }
                     56: 
                     57: static struct md5_step md5_steps[4] = {
                     58:        {
                     59:                .f = f1,
                     60:                .coefficient = 1,
                     61:                .constant = 0,
                     62:        },
                     63:        {
                     64:                .f = f2,
                     65:                .coefficient = 5,
                     66:                .constant = 1,
                     67:        },
                     68:        {
                     69:                .f = f3,
                     70:                .coefficient = 3,
                     71:                .constant = 5,
                     72:        },
                     73:        {
                     74:                .f = f4,
                     75:                .coefficient = 7,
                     76:                .constant = 0,
                     77:        }
                     78: };
                     79: 
                     80: static const u8 r[64] = {
                     81:        7,12,17,22,7,12,17,22,7,12,17,22,7,12,17,22,
                     82:        5,9,14,20,5,9,14,20,5,9,14,20,5,9,14,20,
                     83:        4,11,16,23,4,11,16,23,4,11,16,23,4,11,16,23,
                     84:        6,10,15,21,6,10,15,21,6,10,15,21,6,10,15,21
                     85: };
                     86: 
                     87: static const u32 k[64] = {
                     88:        0xd76aa478UL, 0xe8c7b756UL, 0x242070dbUL, 0xc1bdceeeUL,
                     89:        0xf57c0fafUL, 0x4787c62aUL, 0xa8304613UL, 0xfd469501UL,
                     90:        0x698098d8UL, 0x8b44f7afUL, 0xffff5bb1UL, 0x895cd7beUL,
                     91:        0x6b901122UL, 0xfd987193UL, 0xa679438eUL, 0x49b40821UL,
                     92:        0xf61e2562UL, 0xc040b340UL, 0x265e5a51UL, 0xe9b6c7aaUL,
                     93:        0xd62f105dUL, 0x02441453UL, 0xd8a1e681UL, 0xe7d3fbc8UL,
                     94:        0x21e1cde6UL, 0xc33707d6UL, 0xf4d50d87UL, 0x455a14edUL,
                     95:        0xa9e3e905UL, 0xfcefa3f8UL, 0x676f02d9UL, 0x8d2a4c8aUL,
                     96:        0xfffa3942UL, 0x8771f681UL, 0x6d9d6122UL, 0xfde5380cUL,
                     97:        0xa4beea44UL, 0x4bdecfa9UL, 0xf6bb4b60UL, 0xbebfbc70UL,
                     98:        0x289b7ec6UL, 0xeaa127faUL, 0xd4ef3085UL, 0x04881d05UL,
                     99:        0xd9d4d039UL, 0xe6db99e5UL, 0x1fa27cf8UL, 0xc4ac5665UL,
                    100:        0xf4292244UL, 0x432aff97UL, 0xab9423a7UL, 0xfc93a039UL,
                    101:        0x655b59c3UL, 0x8f0ccc92UL, 0xffeff47dUL, 0x85845dd1UL,
                    102:        0x6fa87e4fUL, 0xfe2ce6e0UL, 0xa3014314UL, 0x4e0811a1UL,
                    103:        0xf7537e82UL, 0xbd3af235UL, 0x2ad7d2bbUL, 0xeb86d391UL,
                    104: };
                    105: 
                    106: static void md5_transform(u32 *hash, const u32 *in)
                    107: {
                    108:        u32 a, b, c, d, f, g, temp;
                    109:        int i;
                    110:        struct md5_step *step;
                    111: 
                    112:        a = hash[0];
                    113:        b = hash[1];
                    114:        c = hash[2];
                    115:        d = hash[3];
                    116: 
                    117:        for ( i = 0 ; i < 64 ; i++ ) {
                    118:                step = &md5_steps[i >> 4];
                    119:                f = step->f ( b, c, d );
                    120:                g = ( ( i * step->coefficient + step->constant ) & 0xf );
                    121:                temp = d;
                    122:                d = c;
                    123:                c = b;
                    124:                a += ( f + k[i] + in[g] );
                    125:                a = ( ( a << r[i] ) | ( a >> ( 32-r[i] ) ) );
                    126:                b += a;
                    127:                a = temp;
                    128:        }
                    129: 
                    130:        hash[0] += a;
                    131:        hash[1] += b;
                    132:        hash[2] += c;
                    133:        hash[3] += d;
                    134: }
                    135: 
                    136: /* XXX: this stuff can be optimized */
                    137: static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
                    138: {
                    139:        while (words--) {
                    140:                le32_to_cpus(buf);
                    141:                buf++;
                    142:        }
                    143: }
                    144: 
                    145: static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
                    146: {
                    147:        while (words--) {
                    148:                cpu_to_le32s(buf);
                    149:                buf++;
                    150:        }
                    151: }
                    152: 
                    153: static inline void md5_transform_helper(struct md5_ctx *ctx)
                    154: {
                    155:        le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32));
                    156:        md5_transform(ctx->hash, ctx->block);
                    157: }
                    158: 
                    159: static void md5_init(void *context)
                    160: {
                    161:        struct md5_ctx *mctx = context;
                    162: 
                    163:        mctx->hash[0] = 0x67452301;
                    164:        mctx->hash[1] = 0xefcdab89;
                    165:        mctx->hash[2] = 0x98badcfe;
                    166:        mctx->hash[3] = 0x10325476;
                    167:        mctx->byte_count = 0;
                    168: }
                    169: 
                    170: static void md5_update(void *context, const void *data, size_t len)
                    171: {
                    172:        struct md5_ctx *mctx = context;
                    173:        const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
                    174: 
                    175:        mctx->byte_count += len;
                    176: 
                    177:        if (avail > len) {
                    178:                memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
                    179:                       data, len);
                    180:                return;
                    181:        }
                    182: 
                    183:        memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
                    184:               data, avail);
                    185: 
                    186:        md5_transform_helper(mctx);
                    187:        data += avail;
                    188:        len -= avail;
                    189: 
                    190:        while (len >= sizeof(mctx->block)) {
                    191:                memcpy(mctx->block, data, sizeof(mctx->block));
                    192:                md5_transform_helper(mctx);
                    193:                data += sizeof(mctx->block);
                    194:                len -= sizeof(mctx->block);
                    195:        }
                    196: 
                    197:        memcpy(mctx->block, data, len);
                    198: }
                    199: 
                    200: static void md5_final(void *context, void *out)
                    201: {
                    202:        struct md5_ctx *mctx = context;
                    203:        const unsigned int offset = mctx->byte_count & 0x3f;
                    204:        char *p = (char *)mctx->block + offset;
                    205:        int padding = 56 - (offset + 1);
                    206: 
                    207:        *p++ = 0x80;
                    208:        if (padding < 0) {
                    209:                memset(p, 0x00, padding + sizeof (u64));
                    210:                md5_transform_helper(mctx);
                    211:                p = (char *)mctx->block;
                    212:                padding = 56;
                    213:        }
                    214: 
                    215:        memset(p, 0, padding);
                    216:        mctx->block[14] = mctx->byte_count << 3;
                    217:        mctx->block[15] = mctx->byte_count >> 29;
                    218:        le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
                    219:                          sizeof(u64)) / sizeof(u32));
                    220:        md5_transform(mctx->hash, mctx->block);
                    221:        cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
                    222:        memcpy(out, mctx->hash, sizeof(mctx->hash));
                    223:        memset(mctx, 0, sizeof(*mctx));
                    224: }
                    225: 
                    226: struct digest_algorithm md5_algorithm = {
                    227:        .name           = "md5",
                    228:        .ctxsize        = MD5_CTX_SIZE,
                    229:        .blocksize      = ( MD5_BLOCK_WORDS * 4 ),
                    230:        .digestsize     = MD5_DIGEST_SIZE,
                    231:        .init           = md5_init,
                    232:        .update         = md5_update,
                    233:        .final          = md5_final,
                    234: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.