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