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/crypto.h>
  15#include <linux/module.h>
  16
  17#include <asm/hwcap.h>
  18#include <asm/neon.h>
  19#include <asm/simd.h>
  20
  21#include "sha1.h"
  22
  23MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
  24MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
  25MODULE_LICENSE("GPL v2");
  26
  27asmlinkage void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
  28                                  int blocks);
  29
  30static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
  31                          unsigned int len)
  32{
  33        struct sha1_state *sctx = shash_desc_ctx(desc);
  34
  35        if (!may_use_simd() ||
  36            (sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
  37                return sha1_update_arm(desc, data, len);
  38
  39        kernel_neon_begin();
  40        sha1_base_do_update(desc, data, len, sha1_ce_transform);
  41        kernel_neon_end();
  42
  43        return 0;
  44}
  45
  46static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
  47                         unsigned int len, u8 *out)
  48{
  49        if (!may_use_simd())
  50                return sha1_finup_arm(desc, data, len, out);
  51
  52        kernel_neon_begin();
  53        if (len)
  54                sha1_base_do_update(desc, data, len, sha1_ce_transform);
  55        sha1_base_do_finalize(desc, sha1_ce_transform);
  56        kernel_neon_end();
  57
  58        return sha1_base_finish(desc, out);
  59}
  60
  61static int sha1_ce_final(struct shash_desc *desc, u8 *out)
  62{
  63        return sha1_ce_finup(desc, NULL, 0, out);
  64}
  65
  66static struct shash_alg alg = {
  67        .init                   = sha1_base_init,
  68        .update                 = sha1_ce_update,
  69        .final                  = sha1_ce_final,
  70        .finup                  = sha1_ce_finup,
  71        .descsize               = sizeof(struct sha1_state),
  72        .digestsize             = SHA1_DIGEST_SIZE,
  73        .base                   = {
  74                .cra_name               = "sha1",
  75                .cra_driver_name        = "sha1-ce",
  76                .cra_priority           = 200,
  77                .cra_flags              = CRYPTO_ALG_TYPE_SHASH,
  78                .cra_blocksize          = SHA1_BLOCK_SIZE,
  79                .cra_module             = THIS_MODULE,
  80        }
  81};
  82
  83static int __init sha1_ce_mod_init(void)
  84{
  85        if (!(elf_hwcap2 & HWCAP2_SHA1))
  86                return -ENODEV;
  87        return crypto_register_shash(&alg);
  88}
  89
  90static void __exit sha1_ce_mod_fini(void)
  91{
  92        crypto_unregister_shash(&alg);
  93}
  94
  95module_init(sha1_ce_mod_init);
  96module_exit(sha1_ce_mod_fini);
  97