linux/crypto/sha1_generic.c
<<
>>
Prefs
   1/*
   2 * Cryptographic API.
   3 *
   4 * SHA1 Secure Hash Algorithm.
   5 *
   6 * Derived from cryptoapi implementation, adapted for in-place
   7 * scatterlist interface.
   8 *
   9 * Copyright (c) Alan Smithee.
  10 * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk>
  11 * Copyright (c) Jean-Francois Dive <jef@linuxbe.org>
  12 *
  13 * This program is free software; you can redistribute it and/or modify it
  14 * under the terms of the GNU General Public License as published by the Free
  15 * Software Foundation; either version 2 of the License, or (at your option)
  16 * any later version.
  17 *
  18 */
  19#include <crypto/internal/hash.h>
  20#include <linux/init.h>
  21#include <linux/module.h>
  22#include <linux/mm.h>
  23#include <linux/cryptohash.h>
  24#include <linux/types.h>
  25#include <crypto/sha.h>
  26#include <asm/byteorder.h>
  27
  28struct sha1_ctx {
  29        u64 count;
  30        u32 state[5];
  31        u8 buffer[64];
  32};
  33
  34static int sha1_init(struct shash_desc *desc)
  35{
  36        struct sha1_ctx *sctx = shash_desc_ctx(desc);
  37
  38        static const struct sha1_ctx initstate = {
  39          0,
  40          { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
  41          { 0, }
  42        };
  43
  44        *sctx = initstate;
  45
  46        return 0;
  47}
  48
  49static int sha1_update(struct shash_desc *desc, const u8 *data,
  50                        unsigned int len)
  51{
  52        struct sha1_ctx *sctx = shash_desc_ctx(desc);
  53        unsigned int partial, done;
  54        const u8 *src;
  55
  56        partial = sctx->count & 0x3f;
  57        sctx->count += len;
  58        done = 0;
  59        src = data;
  60
  61        if ((partial + len) > 63) {
  62                u32 temp[SHA_WORKSPACE_WORDS];
  63
  64                if (partial) {
  65                        done = -partial;
  66                        memcpy(sctx->buffer + partial, data, done + 64);
  67                        src = sctx->buffer;
  68                }
  69
  70                do {
  71                        sha_transform(sctx->state, src, temp);
  72                        done += 64;
  73                        src = data + done;
  74                } while (done + 63 < len);
  75
  76                memset(temp, 0, sizeof(temp));
  77                partial = 0;
  78        }
  79        memcpy(sctx->buffer + partial, src, len - done);
  80
  81        return 0;
  82}
  83
  84
  85/* Add padding and return the message digest. */
  86static int sha1_final(struct shash_desc *desc, u8 *out)
  87{
  88        struct sha1_ctx *sctx = shash_desc_ctx(desc);
  89        __be32 *dst = (__be32 *)out;
  90        u32 i, index, padlen;
  91        __be64 bits;
  92        static const u8 padding[64] = { 0x80, };
  93
  94        bits = cpu_to_be64(sctx->count << 3);
  95
  96        /* Pad out to 56 mod 64 */
  97        index = sctx->count & 0x3f;
  98        padlen = (index < 56) ? (56 - index) : ((64+56) - index);
  99        sha1_update(desc, padding, padlen);
 100
 101        /* Append length */
 102        sha1_update(desc, (const u8 *)&bits, sizeof(bits));
 103
 104        /* Store state in digest */
 105        for (i = 0; i < 5; i++)
 106                dst[i] = cpu_to_be32(sctx->state[i]);
 107
 108        /* Wipe context */
 109        memset(sctx, 0, sizeof *sctx);
 110
 111        return 0;
 112}
 113
 114static struct shash_alg alg = {
 115        .digestsize     =       SHA1_DIGEST_SIZE,
 116        .init           =       sha1_init,
 117        .update         =       sha1_update,
 118        .final          =       sha1_final,
 119        .descsize       =       sizeof(struct sha1_ctx),
 120        .base           =       {
 121                .cra_name       =       "sha1",
 122                .cra_driver_name=       "sha1-generic",
 123                .cra_flags      =       CRYPTO_ALG_TYPE_SHASH,
 124                .cra_blocksize  =       SHA1_BLOCK_SIZE,
 125                .cra_module     =       THIS_MODULE,
 126        }
 127};
 128
 129static int __init sha1_generic_mod_init(void)
 130{
 131        return crypto_register_shash(&alg);
 132}
 133
 134static void __exit sha1_generic_mod_fini(void)
 135{
 136        crypto_unregister_shash(&alg);
 137}
 138
 139module_init(sha1_generic_mod_init);
 140module_exit(sha1_generic_mod_fini);
 141
 142MODULE_LICENSE("GPL");
 143MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
 144
 145MODULE_ALIAS("sha1");
 146