linux/crypto/sha1.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 <linux/init.h>
  20#include <linux/module.h>
  21#include <linux/mm.h>
  22#include <linux/crypto.h>
  23#include <linux/cryptohash.h>
  24#include <linux/types.h>
  25#include <asm/scatterlist.h>
  26#include <asm/byteorder.h>
  27
  28#define SHA1_DIGEST_SIZE        20
  29#define SHA1_HMAC_BLOCK_SIZE    64
  30
  31struct sha1_ctx {
  32        u64 count;
  33        u32 state[5];
  34        u8 buffer[64];
  35};
  36
  37static void sha1_init(struct crypto_tfm *tfm)
  38{
  39        struct sha1_ctx *sctx = crypto_tfm_ctx(tfm);
  40        static const struct sha1_ctx initstate = {
  41          0,
  42          { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 },
  43          { 0, }
  44        };
  45
  46        *sctx = initstate;
  47}
  48
  49static void sha1_update(struct crypto_tfm *tfm, const u8 *data,
  50                        unsigned int len)
  51{
  52        struct sha1_ctx *sctx = crypto_tfm_ctx(tfm);
  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
  82
  83/* Add padding and return the message digest. */
  84static void sha1_final(struct crypto_tfm *tfm, u8 *out)
  85{
  86        struct sha1_ctx *sctx = crypto_tfm_ctx(tfm);
  87        __be32 *dst = (__be32 *)out;
  88        u32 i, index, padlen;
  89        __be64 bits;
  90        static const u8 padding[64] = { 0x80, };
  91
  92        bits = cpu_to_be64(sctx->count << 3);
  93
  94        /* Pad out to 56 mod 64 */
  95        index = sctx->count & 0x3f;
  96        padlen = (index < 56) ? (56 - index) : ((64+56) - index);
  97        sha1_update(tfm, padding, padlen);
  98
  99        /* Append length */
 100        sha1_update(tfm, (const u8 *)&bits, sizeof(bits));
 101
 102        /* Store state in digest */
 103        for (i = 0; i < 5; i++)
 104                dst[i] = cpu_to_be32(sctx->state[i]);
 105
 106        /* Wipe context */
 107        memset(sctx, 0, sizeof *sctx);
 108}
 109
 110static struct crypto_alg alg = {
 111        .cra_name       =       "sha1",
 112        .cra_driver_name=       "sha1-generic",
 113        .cra_flags      =       CRYPTO_ALG_TYPE_DIGEST,
 114        .cra_blocksize  =       SHA1_HMAC_BLOCK_SIZE,
 115        .cra_ctxsize    =       sizeof(struct sha1_ctx),
 116        .cra_module     =       THIS_MODULE,
 117        .cra_alignmask  =       3,
 118        .cra_list       =       LIST_HEAD_INIT(alg.cra_list),
 119        .cra_u          =       { .digest = {
 120        .dia_digestsize =       SHA1_DIGEST_SIZE,
 121        .dia_init       =       sha1_init,
 122        .dia_update     =       sha1_update,
 123        .dia_final      =       sha1_final } }
 124};
 125
 126static int __init init(void)
 127{
 128        return crypto_register_alg(&alg);
 129}
 130
 131static void __exit fini(void)
 132{
 133        crypto_unregister_alg(&alg);
 134}
 135
 136module_init(init);
 137module_exit(fini);
 138
 139MODULE_LICENSE("GPL");
 140MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm");
 141
 142MODULE_ALIAS("sha1-generic");
 143
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.