linux/include/crypto/sha512_base.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * sha512_base.h - core logic for SHA-512 implementations
   4 *
   5 * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
   6 */
   7
   8#ifndef _CRYPTO_SHA512_BASE_H
   9#define _CRYPTO_SHA512_BASE_H
  10
  11#include <crypto/internal/hash.h>
  12#include <crypto/sha.h>
  13#include <linux/crypto.h>
  14#include <linux/module.h>
  15
  16#include <asm/unaligned.h>
  17
  18typedef void (sha512_block_fn)(struct sha512_state *sst, u8 const *src,
  19                               int blocks);
  20
  21static inline int sha384_base_init(struct shash_desc *desc)
  22{
  23        struct sha512_state *sctx = shash_desc_ctx(desc);
  24
  25        sctx->state[0] = SHA384_H0;
  26        sctx->state[1] = SHA384_H1;
  27        sctx->state[2] = SHA384_H2;
  28        sctx->state[3] = SHA384_H3;
  29        sctx->state[4] = SHA384_H4;
  30        sctx->state[5] = SHA384_H5;
  31        sctx->state[6] = SHA384_H6;
  32        sctx->state[7] = SHA384_H7;
  33        sctx->count[0] = sctx->count[1] = 0;
  34
  35        return 0;
  36}
  37
  38static inline int sha512_base_init(struct shash_desc *desc)
  39{
  40        struct sha512_state *sctx = shash_desc_ctx(desc);
  41
  42        sctx->state[0] = SHA512_H0;
  43        sctx->state[1] = SHA512_H1;
  44        sctx->state[2] = SHA512_H2;
  45        sctx->state[3] = SHA512_H3;
  46        sctx->state[4] = SHA512_H4;
  47        sctx->state[5] = SHA512_H5;
  48        sctx->state[6] = SHA512_H6;
  49        sctx->state[7] = SHA512_H7;
  50        sctx->count[0] = sctx->count[1] = 0;
  51
  52        return 0;
  53}
  54
  55static inline int sha512_base_do_update(struct shash_desc *desc,
  56                                        const u8 *data,
  57                                        unsigned int len,
  58                                        sha512_block_fn *block_fn)
  59{
  60        struct sha512_state *sctx = shash_desc_ctx(desc);
  61        unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
  62
  63        sctx->count[0] += len;
  64        if (sctx->count[0] < len)
  65                sctx->count[1]++;
  66
  67        if (unlikely((partial + len) >= SHA512_BLOCK_SIZE)) {
  68                int blocks;
  69
  70                if (partial) {
  71                        int p = SHA512_BLOCK_SIZE - partial;
  72
  73                        memcpy(sctx->buf + partial, data, p);
  74                        data += p;
  75                        len -= p;
  76
  77                        block_fn(sctx, sctx->buf, 1);
  78                }
  79
  80                blocks = len / SHA512_BLOCK_SIZE;
  81                len %= SHA512_BLOCK_SIZE;
  82
  83                if (blocks) {
  84                        block_fn(sctx, data, blocks);
  85                        data += blocks * SHA512_BLOCK_SIZE;
  86                }
  87                partial = 0;
  88        }
  89        if (len)
  90                memcpy(sctx->buf + partial, data, len);
  91
  92        return 0;
  93}
  94
  95static inline int sha512_base_do_finalize(struct shash_desc *desc,
  96                                          sha512_block_fn *block_fn)
  97{
  98        const int bit_offset = SHA512_BLOCK_SIZE - sizeof(__be64[2]);
  99        struct sha512_state *sctx = shash_desc_ctx(desc);
 100        __be64 *bits = (__be64 *)(sctx->buf + bit_offset);
 101        unsigned int partial = sctx->count[0] % SHA512_BLOCK_SIZE;
 102
 103        sctx->buf[partial++] = 0x80;
 104        if (partial > bit_offset) {
 105                memset(sctx->buf + partial, 0x0, SHA512_BLOCK_SIZE - partial);
 106                partial = 0;
 107
 108                block_fn(sctx, sctx->buf, 1);
 109        }
 110
 111        memset(sctx->buf + partial, 0x0, bit_offset - partial);
 112        bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61);
 113        bits[1] = cpu_to_be64(sctx->count[0] << 3);
 114        block_fn(sctx, sctx->buf, 1);
 115
 116        return 0;
 117}
 118
 119static inline int sha512_base_finish(struct shash_desc *desc, u8 *out)
 120{
 121        unsigned int digest_size = crypto_shash_digestsize(desc->tfm);
 122        struct sha512_state *sctx = shash_desc_ctx(desc);
 123        __be64 *digest = (__be64 *)out;
 124        int i;
 125
 126        for (i = 0; digest_size > 0; i++, digest_size -= sizeof(__be64))
 127                put_unaligned_be64(sctx->state[i], digest++);
 128
 129        *sctx = (struct sha512_state){};
 130        return 0;
 131}
 132
 133#endif /* _CRYPTO_SHA512_BASE_H */
 134