Skip to content

Commit

Permalink
crypto: arm/sha1 - move SHA-1 ARM asm 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 ca14258 commit 90451d6
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 98 deletions.
3 changes: 2 additions & 1 deletion arch/arm/crypto/sha1-ce-glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@
#include <linux/crypto.h>
#include <linux/module.h>

#include <asm/crypto/sha1.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");
Expand Down
3 changes: 3 additions & 0 deletions arch/arm/include/asm/crypto/sha1.h → arch/arm/crypto/sha1.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@
extern int sha1_update_arm(struct shash_desc *desc, const u8 *data,
unsigned int len);

extern int sha1_finup_arm(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out);

#endif
112 changes: 16 additions & 96 deletions arch/arm/crypto/sha1_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,127 +22,47 @@
#include <linux/cryptohash.h>
#include <linux/types.h>
#include <crypto/sha.h>
#include <crypto/sha1_base.h>
#include <asm/byteorder.h>
#include <asm/crypto/sha1.h>

#include "sha1.h"

asmlinkage void sha1_block_data_order(u32 *digest,
const unsigned char *data, unsigned int rounds);


static int sha1_init(struct shash_desc *desc)
{
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 sha1_state *sctx, const u8 *data,
unsigned int len, unsigned int partial)
{
unsigned int done = 0;

sctx->count += len;

if (partial) {
done = SHA1_BLOCK_SIZE - partial;
memcpy(sctx->buffer + partial, data, done);
sha1_block_data_order(sctx->state, sctx->buffer, 1);
}

if (len - done >= SHA1_BLOCK_SIZE) {
const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE;
sha1_block_data_order(sctx->state, data + done, rounds);
done += rounds * SHA1_BLOCK_SIZE;
}

memcpy(sctx->buffer, data + done, len - done);
return 0;
}


int sha1_update_arm(struct shash_desc *desc, const u8 *data,
unsigned int len)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
unsigned int partial = sctx->count % SHA1_BLOCK_SIZE;
int res;
/* make sure casting to sha1_block_fn() is safe */
BUILD_BUG_ON(offsetof(struct sha1_state, state) != 0);

/* Handle the fast case right here */
if (partial + len < SHA1_BLOCK_SIZE) {
sctx->count += len;
memcpy(sctx->buffer + partial, data, len);
return 0;
}
res = __sha1_update(sctx, data, len, partial);
return res;
return sha1_base_do_update(desc, data, len,
(sha1_block_fn *)sha1_block_data_order);
}
EXPORT_SYMBOL_GPL(sha1_update_arm);


/* Add padding and return the message digest. */
static int sha1_final(struct shash_desc *desc, u8 *out)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
unsigned int i, index, padlen;
__be32 *dst = (__be32 *)out;
__be64 bits;
static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, };

bits = cpu_to_be64(sctx->count << 3);

/* Pad out to 56 mod 64 and append length */
index = sctx->count % SHA1_BLOCK_SIZE;
padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index);
/* We need to fill a whole block for __sha1_update() */
if (padlen <= 56) {
sctx->count += padlen;
memcpy(sctx->buffer + index, padding, padlen);
} else {
__sha1_update(sctx, padding, padlen, index);
}
__sha1_update(sctx, (const u8 *)&bits, sizeof(bits), 56);

/* Store state in digest */
for (i = 0; i < 5; i++)
dst[i] = cpu_to_be32(sctx->state[i]);

/* Wipe context */
memset(sctx, 0, sizeof(*sctx));
return 0;
sha1_base_do_finalize(desc, (sha1_block_fn *)sha1_block_data_order);
return sha1_base_finish(desc, out);
}


static int sha1_export(struct shash_desc *desc, void *out)
int sha1_finup_arm(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
memcpy(out, sctx, sizeof(*sctx));
return 0;
sha1_base_do_update(desc, data, len,
(sha1_block_fn *)sha1_block_data_order);
return sha1_final(desc, out);
}


static int sha1_import(struct shash_desc *desc, const void *in)
{
struct sha1_state *sctx = shash_desc_ctx(desc);
memcpy(sctx, in, sizeof(*sctx));
return 0;
}

EXPORT_SYMBOL_GPL(sha1_finup_arm);

static struct shash_alg alg = {
.digestsize = SHA1_DIGEST_SIZE,
.init = sha1_init,
.init = sha1_base_init,
.update = sha1_update_arm,
.final = sha1_final,
.export = sha1_export,
.import = sha1_import,
.finup = sha1_finup_arm,
.descsize = sizeof(struct sha1_state),
.statesize = sizeof(struct sha1_state),
.base = {
.cra_name = "sha1",
.cra_driver_name= "sha1-asm",
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/crypto/sha1_neon_glue.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@
#include <asm/byteorder.h>
#include <asm/neon.h>
#include <asm/simd.h>
#include <asm/crypto/sha1.h>

#include "sha1.h"

asmlinkage void sha1_transform_neon(void *state_h, const char *data,
unsigned int rounds);
Expand Down

0 comments on commit 90451d6

Please sign in to comment.