linux/include/crypto/sm3_base.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: GPL-2.0-only */
   2/*
   3 * sm3_base.h - core logic for SM3 implementations
   4 *
   5 * Copyright (C) 2017 ARM Limited or its affiliates.
   6 * Written by Gilad Ben-Yossef <gilad@benyossef.com>
   7 */
   8
   9#include <crypto/internal/hash.h>
  10#include <crypto/sm3.h>
  11#include <linux/crypto.h>
  12#include <linux/module.h>
  13#include <asm/unaligned.h>
  14
  15typedef void (sm3_block_fn)(struct sm3_state *sst, u8 const *src, int blocks);
  16
  17static inline int sm3_base_init(struct shash_desc *desc)
  18{
  19        struct sm3_state *sctx = shash_desc_ctx(desc);
  20
  21        sctx->state[0] = SM3_IVA;
  22        sctx->state[1] = SM3_IVB;
  23        sctx->state[2] = SM3_IVC;
  24        sctx->state[3] = SM3_IVD;
  25        sctx->state[4] = SM3_IVE;
  26        sctx->state[5] = SM3_IVF;
  27        sctx->state[6] = SM3_IVG;
  28        sctx->state[7] = SM3_IVH;
  29        sctx->count = 0;
  30
  31        return 0;
  32}
  33
  34static inline int sm3_base_do_update(struct shash_desc *desc,
  35                                      const u8 *data,
  36                                      unsigned int len,
  37                                      sm3_block_fn *block_fn)
  38{
  39        struct sm3_state *sctx = shash_desc_ctx(desc);
  40        unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
  41
  42        sctx->count += len;
  43
  44        if (unlikely((partial + len) >= SM3_BLOCK_SIZE)) {
  45                int blocks;
  46
  47                if (partial) {
  48                        int p = SM3_BLOCK_SIZE - partial;
  49
  50                        memcpy(sctx->buffer + partial, data, p);
  51                        data += p;
  52                        len -= p;
  53
  54                        block_fn(sctx, sctx->buffer, 1);
  55                }
  56
  57                blocks = len / SM3_BLOCK_SIZE;
  58                len %= SM3_BLOCK_SIZE;
  59
  60                if (blocks) {
  61                        block_fn(sctx, data, blocks);
  62                        data += blocks * SM3_BLOCK_SIZE;
  63                }
  64                partial = 0;
  65        }
  66        if (len)
  67                memcpy(sctx->buffer + partial, data, len);
  68
  69        return 0;
  70}
  71
  72static inline int sm3_base_do_finalize(struct shash_desc *desc,
  73                                        sm3_block_fn *block_fn)
  74{
  75        const int bit_offset = SM3_BLOCK_SIZE - sizeof(__be64);
  76        struct sm3_state *sctx = shash_desc_ctx(desc);
  77        __be64 *bits = (__be64 *)(sctx->buffer + bit_offset);
  78        unsigned int partial = sctx->count % SM3_BLOCK_SIZE;
  79
  80        sctx->buffer[partial++] = 0x80;
  81        if (partial > bit_offset) {
  82                memset(sctx->buffer + partial, 0x0, SM3_BLOCK_SIZE - partial);
  83                partial = 0;
  84
  85                block_fn(sctx, sctx->buffer, 1);
  86        }
  87
  88        memset(sctx->buffer + partial, 0x0, bit_offset - partial);
  89        *bits = cpu_to_be64(sctx->count << 3);
  90        block_fn(sctx, sctx->buffer, 1);
  91
  92        return 0;
  93}
  94
  95static inline int sm3_base_finish(struct shash_desc *desc, u8 *out)
  96{
  97        struct sm3_state *sctx = shash_desc_ctx(desc);
  98        __be32 *digest = (__be32 *)out;
  99        int i;
 100
 101        for (i = 0; i < SM3_DIGEST_SIZE / sizeof(__be32); i++)
 102                put_unaligned_be32(sctx->state[i], digest++);
 103
 104        *sctx = (struct sm3_state){};
 105        return 0;
 106}
 107