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