linux/crypto/md5.c
<<
>>
Prefs
   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 * Copyright (c) Cryptoapi developers.
  10 * Copyright (c) 2002 James Morris <jmorris@intercode.com.au>
  11 * 
  12 * This program is free software; you can redistribute it and/or modify it
  13 * under the terms of the GNU General Public License as published by the Free
  14 * Software Foundation; either version 2 of the License, or (at your option) 
  15 * any later version.
  16 *
  17 */
  18#include <crypto/internal/hash.h>
  19#include <crypto/md5.h>
  20#include <linux/init.h>
  21#include <linux/module.h>
  22#include <linux/string.h>
  23#include <linux/types.h>
  24#include <linux/cryptohash.h>
  25#include <asm/byteorder.h>
  26
  27const u8 md5_zero_message_hash[MD5_DIGEST_SIZE] = {
  28        0xd4, 0x1d, 0x8c, 0xd9, 0x8f, 0x00, 0xb2, 0x04,
  29        0xe9, 0x80, 0x09, 0x98, 0xec, 0xf8, 0x42, 0x7e,
  30};
  31EXPORT_SYMBOL_GPL(md5_zero_message_hash);
  32
  33/* XXX: this stuff can be optimized */
  34static inline void le32_to_cpu_array(u32 *buf, unsigned int words)
  35{
  36        while (words--) {
  37                __le32_to_cpus(buf);
  38                buf++;
  39        }
  40}
  41
  42static inline void cpu_to_le32_array(u32 *buf, unsigned int words)
  43{
  44        while (words--) {
  45                __cpu_to_le32s(buf);
  46                buf++;
  47        }
  48}
  49
  50static inline void md5_transform_helper(struct md5_state *ctx)
  51{
  52        le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32));
  53        md5_transform(ctx->hash, ctx->block);
  54}
  55
  56static int md5_init(struct shash_desc *desc)
  57{
  58        struct md5_state *mctx = shash_desc_ctx(desc);
  59
  60        mctx->hash[0] = MD5_H0;
  61        mctx->hash[1] = MD5_H1;
  62        mctx->hash[2] = MD5_H2;
  63        mctx->hash[3] = MD5_H3;
  64        mctx->byte_count = 0;
  65
  66        return 0;
  67}
  68
  69static int md5_update(struct shash_desc *desc, const u8 *data, unsigned int len)
  70{
  71        struct md5_state *mctx = shash_desc_ctx(desc);
  72        const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f);
  73
  74        mctx->byte_count += len;
  75
  76        if (avail > len) {
  77                memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
  78                       data, len);
  79                return 0;
  80        }
  81
  82        memcpy((char *)mctx->block + (sizeof(mctx->block) - avail),
  83               data, avail);
  84
  85        md5_transform_helper(mctx);
  86        data += avail;
  87        len -= avail;
  88
  89        while (len >= sizeof(mctx->block)) {
  90                memcpy(mctx->block, data, sizeof(mctx->block));
  91                md5_transform_helper(mctx);
  92                data += sizeof(mctx->block);
  93                len -= sizeof(mctx->block);
  94        }
  95
  96        memcpy(mctx->block, data, len);
  97
  98        return 0;
  99}
 100
 101static int md5_final(struct shash_desc *desc, u8 *out)
 102{
 103        struct md5_state *mctx = shash_desc_ctx(desc);
 104        const unsigned int offset = mctx->byte_count & 0x3f;
 105        char *p = (char *)mctx->block + offset;
 106        int padding = 56 - (offset + 1);
 107
 108        *p++ = 0x80;
 109        if (padding < 0) {
 110                memset(p, 0x00, padding + sizeof (u64));
 111                md5_transform_helper(mctx);
 112                p = (char *)mctx->block;
 113                padding = 56;
 114        }
 115
 116        memset(p, 0, padding);
 117        mctx->block[14] = mctx->byte_count << 3;
 118        mctx->block[15] = mctx->byte_count >> 29;
 119        le32_to_cpu_array(mctx->block, (sizeof(mctx->block) -
 120                          sizeof(u64)) / sizeof(u32));
 121        md5_transform(mctx->hash, mctx->block);
 122        cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32));
 123        memcpy(out, mctx->hash, sizeof(mctx->hash));
 124        memset(mctx, 0, sizeof(*mctx));
 125
 126        return 0;
 127}
 128
 129static int md5_export(struct shash_desc *desc, void *out)
 130{
 131        struct md5_state *ctx = shash_desc_ctx(desc);
 132
 133        memcpy(out, ctx, sizeof(*ctx));
 134        return 0;
 135}
 136
 137static int md5_import(struct shash_desc *desc, const void *in)
 138{
 139        struct md5_state *ctx = shash_desc_ctx(desc);
 140
 141        memcpy(ctx, in, sizeof(*ctx));
 142        return 0;
 143}
 144
 145static struct shash_alg alg = {
 146        .digestsize     =       MD5_DIGEST_SIZE,
 147        .init           =       md5_init,
 148        .update         =       md5_update,
 149        .final          =       md5_final,
 150        .export         =       md5_export,
 151        .import         =       md5_import,
 152        .descsize       =       sizeof(struct md5_state),
 153        .statesize      =       sizeof(struct md5_state),
 154        .base           =       {
 155                .cra_name       =       "md5",
 156                .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
 157                .cra_blocksize  =       MD5_HMAC_BLOCK_SIZE,
 158                .cra_module     =       THIS_MODULE,
 159        }
 160};
 161
 162static int __init md5_mod_init(void)
 163{
 164        return crypto_register_shash(&alg);
 165}
 166
 167static void __exit md5_mod_fini(void)
 168{
 169        crypto_unregister_shash(&alg);
 170}
 171
 172module_init(md5_mod_init);
 173module_exit(md5_mod_fini);
 174
 175MODULE_LICENSE("GPL");
 176MODULE_DESCRIPTION("MD5 Message Digest Algorithm");
 177MODULE_ALIAS_CRYPTO("md5");
 178