Skip to content

Commit

Permalink
crypto: arm/sha2-ce - move SHA-224/256 ARMv8 implementation to base l…
Browse files Browse the repository at this point in the history
…ayer

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 b59e2ae commit 9205b94
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 137 deletions.
2 changes: 1 addition & 1 deletion arch/arm/crypto/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ config CRYPTO_SHA1_ARM_CE
config CRYPTO_SHA2_ARM_CE
tristate "SHA-224/256 digest algorithm (ARM v8 Crypto Extensions)"
depends on KERNEL_MODE_NEON
select CRYPTO_SHA256
select CRYPTO_SHA256_ARM
select CRYPTO_HASH
help
SHA-256 secure hash standard (DFIPS 180-2) implemented
Expand Down
19 changes: 5 additions & 14 deletions arch/arm/crypto/sha2-ce-core.S
Original file line number Diff line number Diff line change
Expand Up @@ -69,27 +69,18 @@
.word 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2

/*
* void sha2_ce_transform(int blocks, u8 const *src, u32 *state,
* u8 *head);
* void sha2_ce_transform(struct sha256_state *sst, u8 const *src,
int blocks);
*/
ENTRY(sha2_ce_transform)
/* load state */
vld1.32 {dga-dgb}, [r2]

/* load partial input (if supplied) */
teq r3, #0
beq 0f
vld1.32 {q0-q1}, [r3]!
vld1.32 {q2-q3}, [r3]
teq r0, #0
b 1f
vld1.32 {dga-dgb}, [r0]

/* load input */
0: vld1.32 {q0-q1}, [r1]!
vld1.32 {q2-q3}, [r1]!
subs r0, r0, #1
subs r2, r2, #1

1:
#ifndef CONFIG_CPU_BIG_ENDIAN
vrev32.8 q0, q0
vrev32.8 q1, q1
Expand Down Expand Up @@ -129,6 +120,6 @@ ENTRY(sha2_ce_transform)
bne 0b

/* store new state */
vst1.32 {dga-dgb}, [r2]
vst1.32 {dga-dgb}, [r0]
bx lr
ENDPROC(sha2_ce_transform)
155 changes: 33 additions & 122 deletions arch/arm/crypto/sha2-ce-glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

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

Expand All @@ -18,148 +19,60 @@
#include <asm/neon.h>
#include <asm/unaligned.h>

#include "sha256_glue.h"

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

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

static int sha224_init(struct shash_desc *desc)
static int sha2_ce_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha256_state *sctx = shash_desc_ctx(desc);

*sctx = (struct sha256_state){
.state = {
SHA224_H0, SHA224_H1, SHA224_H2, SHA224_H3,
SHA224_H4, SHA224_H5, SHA224_H6, SHA224_H7,
}
};
return 0;
}
if (!may_use_simd() ||
(sctx->count % SHA256_BLOCK_SIZE) + len < SHA256_BLOCK_SIZE)
return crypto_sha256_arm_update(desc, data, len);

static int sha256_init(struct shash_desc *desc)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
kernel_neon_begin();
sha256_base_do_update(desc, data, len,
(sha256_block_fn *)sha2_ce_transform);
kernel_neon_end();

*sctx = (struct sha256_state){
.state = {
SHA256_H0, SHA256_H1, SHA256_H2, SHA256_H3,
SHA256_H4, SHA256_H5, SHA256_H6, SHA256_H7,
}
};
return 0;
}

static int sha2_update(struct shash_desc *desc, const u8 *data,
unsigned int len)
static int sha2_ce_finup(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
unsigned int partial;

if (!may_use_simd())
return crypto_sha256_update(desc, data, len);

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

if ((partial + len) >= SHA256_BLOCK_SIZE) {
int blocks;

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

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

blocks = len / SHA256_BLOCK_SIZE;
len %= SHA256_BLOCK_SIZE;
return crypto_sha256_arm_finup(desc, data, len, out);

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

data += blocks * SHA256_BLOCK_SIZE;
partial = 0;
}
kernel_neon_begin();
if (len)
memcpy(sctx->buf + partial, data, len);
return 0;
}

static void sha2_final(struct shash_desc *desc)
{
static const u8 padding[SHA256_BLOCK_SIZE] = { 0x80, };
sha256_base_do_update(desc, data, len,
(sha256_block_fn *)sha2_ce_transform);
sha256_base_do_finalize(desc, (sha256_block_fn *)sha2_ce_transform);
kernel_neon_end();

struct sha256_state *sctx = shash_desc_ctx(desc);
__be64 bits = cpu_to_be64(sctx->count << 3);
u32 padlen = SHA256_BLOCK_SIZE
- ((sctx->count + sizeof(bits)) % SHA256_BLOCK_SIZE);

sha2_update(desc, padding, padlen);
sha2_update(desc, (const u8 *)&bits, sizeof(bits));
return sha256_base_finish(desc, out);
}

static int sha224_final(struct shash_desc *desc, u8 *out)
static int sha2_ce_final(struct shash_desc *desc, u8 *out)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
__be32 *dst = (__be32 *)out;
int i;

sha2_final(desc);

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

*sctx = (struct sha256_state){};
return 0;
}

static int sha256_final(struct shash_desc *desc, u8 *out)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
__be32 *dst = (__be32 *)out;
int i;

sha2_final(desc);

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

*sctx = (struct sha256_state){};
return 0;
}

static int sha2_export(struct shash_desc *desc, void *out)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
struct sha256_state *dst = out;

*dst = *sctx;
return 0;
}

static int sha2_import(struct shash_desc *desc, const void *in)
{
struct sha256_state *sctx = shash_desc_ctx(desc);
struct sha256_state const *src = in;

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

static struct shash_alg algs[] = { {
.init = sha224_init,
.update = sha2_update,
.final = sha224_final,
.export = sha2_export,
.import = sha2_import,
.init = sha224_base_init,
.update = sha2_ce_update,
.final = sha2_ce_final,
.finup = sha2_ce_finup,
.descsize = sizeof(struct sha256_state),
.digestsize = SHA224_DIGEST_SIZE,
.statesize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha224",
.cra_driver_name = "sha224-ce",
Expand All @@ -169,14 +82,12 @@ static struct shash_alg algs[] = { {
.cra_module = THIS_MODULE,
}
}, {
.init = sha256_init,
.update = sha2_update,
.final = sha256_final,
.export = sha2_export,
.import = sha2_import,
.init = sha256_base_init,
.update = sha2_ce_update,
.final = sha2_ce_final,
.finup = sha2_ce_finup,
.descsize = sizeof(struct sha256_state),
.digestsize = SHA256_DIGEST_SIZE,
.statesize = sizeof(struct sha256_state),
.base = {
.cra_name = "sha256",
.cra_driver_name = "sha256-ce",
Expand Down

0 comments on commit 9205b94

Please sign in to comment.