linux/include/crypto/sha1_base.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * sha1_base.h - core logic for SHA-1 implementations
   4 *
   5 * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
   6 */
   7
   8#ifndef _CRYPTO_SHA1_BASE_H
   9#define _CRYPTO_SHA1_BASE_H
  10
  11#include <crypto/internal/hash.h>
  12#include <crypto/sha1.h>
  13#include <linux/crypto.h>
  14#include <linux/module.h>
  15#include <linux/string.h>
  16
  17#include <asm/unaligned.h>
  18
  19typedef void (sha1_block_fn)(struct sha1_state *sst, u8 const *src, int blocks);
  20
  21static inline int sha1_base_init(struct shash_desc *desc)
  22{
  23        struct sha1_state *sctx = shash_desc_ctx(desc);
  24
  25        sctx->state[0] = SHA1_H0;
  26        sctx->state[1] = SHA1_H1;
  27        sctx->state[2] = SHA1_H2;
  28        sctx->state[3] = SHA1_H3;
  29        sctx->state[4] = SHA1_H4;
  30        sctx->count = 0;
  31
  32        return 0;
  33}
  34
  35static inline int sha1_base_do_update(struct shash_desc *desc,
  36                                      const u8 *data,
  37                                      unsigned int len,
  38                                      sha1_block_fn *block_fn)
  39{
  40        struct sha1_state *sctx = shash_desc_ctx(desc);
  41        unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
  42
  43        sctx->count += len;
  44
  45        if (unlikely((partial + len) >= SHA1_BLOCK_SIZE)) {
  46                int blocks;
  47
  48                if (partial) {
  49                        int p = SHA1_BLOCK_SIZE - partial;
  50
  51                        memcpy(sctx->buffer + partial, data, p);
  52                        data += p;
  53                        len -= p;
  54
  55                        block_fn(sctx, sctx->buffer, 1);
  56                }
  57
  58                blocks = len / SHA1_BLOCK_SIZE;
  59                len %= SHA1_BLOCK_SIZE;
  60
  61                if (blocks) {
  62                        block_fn(sctx, data, blocks);
  63                        data += blocks * SHA1_BLOCK_SIZE;
  64                }
  65                partial = 0;
  66        }
  67        if (len)
  68                memcpy(sctx->buffer + partial, data, len);
  69
  70        return 0;
  71}
  72
  73static inline int sha1_base_do_finalize(struct shash_desc *desc,
  74                                        sha1_block_fn *block_fn)
  75{
  76        const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64);
  77        struct sha1_state *sctx = shash_desc_ctx(desc);
  78        __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
  79        unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
  80
  81        sctx->buffer[partial++] = 0x80;
  82        if (partial > bit_offset) {
  83                memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial);
  84                partial = 0;
  85
  86                block_fn(sctx, sctx->buffer, 1);
  87        }
  88
  89        memset(sctx->buffer + partial, 0x0, bit_offset - partial);
  90        *bits = cpu_to_be64(sctx->count << 3);
  91        block_fn(sctx, sctx->buffer, 1);
  92
  93        return 0;
  94}
  95
  96static inline int sha1_base_finish(struct shash_desc *desc, u8 *out)
  97{
  98        struct sha1_state *sctx = shash_desc_ctx(desc);
  99        __be32 *digest = (__be32 *)out;
 100        int i;
 101
 102        for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
 103                put_unaligned_be32(sctx->state[i], digest++);
 104
 105        memzero_explicit(sctx, sizeof(*sctx));
 106        return 0;
 107}
 108
 109#endif /* _CRYPTO_SHA1_BASE_H */
 110