Skip to content

Commit

Permalink
crypto: arm/sha1-ce - move SHA-1 ARMv8 implementation to base layer
Browse files Browse the repository at this point in the history
This removes all the boilerplate from the existing implementation,
and replaces it with calls into the base layer.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Ard Biesheuvel authored and Herbert Xu committed Apr 10, 2015
1 parent 51e515f commit dde0098
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 98 deletions.
1 change: 0 additions & 1 deletion arch/arm/crypto/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ config CRYPTO_SHA1_ARM_CE
tristate "SHA1 digest algorithm (ARM v8 Crypto Extensions)"
depends on KERNEL_MODE_NEON
select CRYPTO_SHA1_ARM
select CRYPTO_SHA1
select CRYPTO_HASH
help
SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented
Expand Down
23 changes: 7 additions & 16 deletions arch/arm/crypto/sha1-ce-core.S
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
.word 0xca62c1d6, 0xca62c1d6, 0xca62c1d6, 0xca62c1d6

/*
* void sha1_ce_transform(int blocks, u8 const *src, u32 *state,
* u8 *head);
* void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
* int blocks);
*/
ENTRY(sha1_ce_transform)
/* load round constants */
Expand All @@ -71,23 +71,14 @@ ENTRY(sha1_ce_transform)
vld1.32 {k2-k3}, [ip, :128]

/* load state */
vld1.32 {dga}, [r2]
vldr dgbs, [r2, #16]

/* load partial input (if supplied) */
teq r3, #0
beq 0f
vld1.32 {q8-q9}, [r3]!
vld1.32 {q10-q11}, [r3]
teq r0, #0
b 1f
vld1.32 {dga}, [r0]
vldr dgbs, [r0, #16]

/* load input */
0: vld1.32 {q8-q9}, [r1]!
vld1.32 {q10-q11}, [r1]!
subs r0, r0, #1
subs r2, r2, #1

1:
#ifndef CONFIG_CPU_BIG_ENDIAN
vrev32.8 q8, q8
vrev32.8 q9, q9
Expand Down Expand Up @@ -128,7 +119,7 @@ ENTRY(sha1_ce_transform)
bne 0b

/* store new state */
vst1.32 {dga}, [r2]
vstr dgbs, [r2, #16]
vst1.32 {dga}, [r0]
vstr dgbs, [r0, #16]
bx lr
ENDPROC(sha1_ce_transform)
107 changes: 26 additions & 81 deletions arch/arm/crypto/sha1-ce-glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,121 +10,66 @@

#include <crypto/internal/hash.h>
#include <crypto/sha.h>
#include <crypto/sha1_base.h>
#include <linux/crypto.h>
#include <linux/module.h>

#include <asm/hwcap.h>
#include <asm/neon.h>
#include <asm/simd.h>
#include <asm/unaligned.h>

#include "sha1.h"

MODULE_DESCRIPTION("SHA1 secure hash using ARMv8 Crypto Extensions");
MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
MODULE_LICENSE("GPL v2");

asmlinkage void sha1_ce_transform(int blocks, u8 const *src, u32 *state,
u8 *head);
asmlinkage void sha1_ce_transform(struct sha1_state *sst, u8 const *src,
int blocks);

static int sha1_init(struct shash_desc *desc)
static int sha1_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha1_state *sctx = shash_desc_ctx(desc);

*sctx = (struct sha1_state){
.state = { SHA1_H0, SHA1_H1, SHA1_H2, SHA1_H3, SHA1_H4 },
};
return 0;
}

static int sha1_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
unsigned int partial;

if (!may_use_simd())
if (!may_use_simd() ||
(sctx->count % SHA1_BLOCK_SIZE) + len < SHA1_BLOCK_SIZE)
return sha1_update_arm(desc, data, len);

partial = sctx->count % SHA1_BLOCK_SIZE;
sctx->count += len;

if ((partial + len) >= SHA1_BLOCK_SIZE) {
int blocks;
kernel_neon_begin();
sha1_base_do_update(desc, data, len, sha1_ce_transform);
kernel_neon_end();

if (partial) {
int p = SHA1_BLOCK_SIZE - partial;

memcpy(sctx->buffer + partial, data, p);
data += p;
len -= p;
}

blocks = len / SHA1_BLOCK_SIZE;
len %= SHA1_BLOCK_SIZE;

kernel_neon_begin();
sha1_ce_transform(blocks, data, sctx->state,
partial ? sctx->buffer : NULL);
kernel_neon_end();

data += blocks * SHA1_BLOCK_SIZE;
partial = 0;
}
if (len)
memcpy(sctx->buffer + partial, data, len);
return 0;
}

static int sha1_final(struct shash_desc *desc, u8 *out)
static int sha1_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };

struct sha1_state *sctx = shash_desc_ctx(desc);
__be64 bits = cpu_to_be64(sctx->count << 3);
__be32 *dst = (__be32 *)out;
int i;

u32 padlen = SHA1_BLOCK_SIZE
- ((sctx->count + sizeof(bits)) % SHA1_BLOCK_SIZE);

sha1_update(desc, padding, padlen);
sha1_update(desc, (const u8 *)&bits, sizeof(bits));

for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++)
put_unaligned_be32(sctx->state[i], dst++);

*sctx = (struct sha1_state){};
return 0;
}
if (!may_use_simd())
return sha1_finup_arm(desc, data, len, out);

static int sha1_export(struct shash_desc *desc, void *out)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
struct sha1_state *dst = out;
kernel_neon_begin();
if (len)
sha1_base_do_update(desc, data, len, sha1_ce_transform);
sha1_base_do_finalize(desc, sha1_ce_transform);
kernel_neon_end();

*dst = *sctx;
return 0;
return sha1_base_finish(desc, out);
}

static int sha1_import(struct shash_desc *desc, const void *in)
static int sha1_ce_final(struct shash_desc *desc, u8 *out)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
struct sha1_state const *src = in;

*sctx = *src;
return 0;
return sha1_ce_finup(desc, NULL, 0, out);
}

static struct shash_alg alg = {
.init = sha1_init,
.update = sha1_update,
.final = sha1_final,
.export = sha1_export,
.import = sha1_import,
.init = sha1_base_init,
.update = sha1_ce_update,
.final = sha1_ce_final,
.finup = sha1_ce_finup,
.descsize = sizeof(struct sha1_state),
.digestsize = SHA1_DIGEST_SIZE,
.statesize = sizeof(struct sha1_state),
.base = {
.cra_name = "sha1",
.cra_driver_name = "sha1-ce",
Expand Down

0 comments on commit dde0098

Please sign in to comment.