linux/arch/arm/crypto/sha1-ce-glue.c
<<
>>
Prefs
   1/*
   2 * sha1-ce-glue.c - SHA-1 secure hash using ARMv8 Crypto Extensions
   3 *
   4 * Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org>
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 */
  10
  11#include <crypto/internal/hash.h>
  12#include <crypto/sha.h>
  13#include <crypto/sha1_base.h>
  14#include <linux/cpufeature.h>
  15#include <linux/crypto.h>
  16#include <linux/module.h>
  17
  18#include <asm/hwcap.h>
  19#include <asm/neon.h>
  20#include <asm/simd.h>
  21
  22#include "sha1.h"
  23
  24MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
  25MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
  26MODULE_LICENSE("GPL v2");
  27
  28asmlinkage void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
  29                                  int blocks);
  30
  31static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
  32                          unsigned int len)
  33{
  34        struct sha1_state *sctx = shash_desc_ctx(desc);
  35
  36        if (!may_use_simd() ||
  37            (sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
  38                return sha1_update_arm(desc, data, len);
  39
  40        kernel_neon_begin();
  41        sha1_base_do_update(desc, data, len, sha1_ce_transform);
  42        kernel_neon_end();
  43
  44        return 0;
  45}
  46
  47static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
  48                         unsigned int len, u8 *out)
  49{
  50        if (!may_use_simd())
  51                return sha1_finup_arm(desc, data, len, out);
  52
  53        kernel_neon_begin();
  54        if (len)
  55                sha1_base_do_update(desc, data, len, sha1_ce_transform);
  56        sha1_base_do_finalize(desc, sha1_ce_transform);
  57        kernel_neon_end();
  58
  59        return sha1_base_finish(desc, out);
  60}
  61
  62static int sha1_ce_final(struct shash_desc *desc, u8 *out)
  63{
  64        return sha1_ce_finup(desc, NULL, 0, out);
  65}
  66
  67static struct shash_alg alg = {
  68        .init                   = sha1_base_init,
  69        .update                 = sha1_ce_update,
  70        .final                  = sha1_ce_final,
  71        .finup                  = sha1_ce_finup,
  72        .descsize               = sizeof(struct sha1_state),
  73        .digestsize             = SHA1_DIGEST_SIZE,
  74        .base                   = {
  75                .cra_name               = "sha1",
  76                .cra_driver_name        = "sha1-ce",
  77                .cra_priority           = 200,
  78                .cra_flags              = CRYPTO_ALG_TYPE_SHASH,
  79                .cra_blocksize          = SHA1_BLOCK_SIZE,
  80                .cra_module             = THIS_MODULE,
  81        }
  82};
  83
  84static int __init sha1_ce_mod_init(void)
  85{
  86        return crypto_register_shash(&alg);
  87}
  88
  89static void __exit sha1_ce_mod_fini(void)
  90{
  91        crypto_unregister_shash(&alg);
  92}
  93
  94module_cpu_feature_match(SHA1, sha1_ce_mod_init);
  95module_exit(sha1_ce_mod_fini);
  96