-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
crypto: sha1 - implement base layer for SHA-1
To reduce the number of copies of boilerplate code throughout the tree, this patch implements generic glue for the SHA-1 algorithm. This allows a specific arch or hardware implementation to only implement the special handling that it needs. The users need to supply an implementation of void (sha1_block_fn)(struct sha1_state *sst, u8 const *src, int blocks) and pass it to the SHA-1 base functions. For easy casting between the prototype above and existing block functions that take a 'u32 state[]' as their first argument, the 'state' member of struct sha1_state is moved to the base of the struct. 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
9c521a2
commit c4d5b9f
Showing
2 changed files
with
107 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
/* | ||
* sha1_base.h - core logic for SHA-1 implementations | ||
* | ||
* Copyright (C) 2015 Linaro Ltd <ard.biesheuvel@linaro.org> | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 as | ||
* published by the Free Software Foundation. | ||
*/ | ||
|
||
#include <crypto/internal/hash.h> | ||
#include <crypto/sha.h> | ||
#include <linux/crypto.h> | ||
#include <linux/module.h> | ||
|
||
#include <asm/unaligned.h> | ||
|
||
typedef void (sha1_block_fn)(struct sha1_state *sst, u8 const *src, int blocks); | ||
|
||
static inline int sha1_base_init(struct shash_desc *desc) | ||
{ | ||
struct sha1_state *sctx = shash_desc_ctx(desc); | ||
|
||
sctx->state[0] = SHA1_H0; | ||
sctx->state[1] = SHA1_H1; | ||
sctx->state[2] = SHA1_H2; | ||
sctx->state[3] = SHA1_H3; | ||
sctx->state[4] = SHA1_H4; | ||
sctx->count = 0; | ||
|
||
return 0; | ||
} | ||
|
||
static inline int sha1_base_do_update(struct shash_desc *desc, | ||
const u8 *data, | ||
unsigned int len, | ||
sha1_block_fn *block_fn) | ||
{ | ||
struct sha1_state *sctx = shash_desc_ctx(desc); | ||
unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; | ||
|
||
sctx->count += len; | ||
|
||
if (unlikely((partial + len) >= SHA1_BLOCK_SIZE)) { | ||
int blocks; | ||
|
||
if (partial) { | ||
int p = SHA1_BLOCK_SIZE - partial; | ||
|
||
memcpy(sctx->buffer + partial, data, p); | ||
data += p; | ||
len -= p; | ||
|
||
block_fn(sctx, sctx->buffer, 1); | ||
} | ||
|
||
blocks = len / SHA1_BLOCK_SIZE; | ||
len %= SHA1_BLOCK_SIZE; | ||
|
||
if (blocks) { | ||
block_fn(sctx, data, blocks); | ||
data += blocks * SHA1_BLOCK_SIZE; | ||
} | ||
partial = 0; | ||
} | ||
if (len) | ||
memcpy(sctx->buffer + partial, data, len); | ||
|
||
return 0; | ||
} | ||
|
||
static inline int sha1_base_do_finalize(struct shash_desc *desc, | ||
sha1_block_fn *block_fn) | ||
{ | ||
const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64); | ||
struct sha1_state *sctx = shash_desc_ctx(desc); | ||
__be64 *bits = (__be64 *)(sctx->buffer + bit_offset); | ||
unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; | ||
|
||
sctx->buffer[partial++] = 0x80; | ||
if (partial > bit_offset) { | ||
memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial); | ||
partial = 0; | ||
|
||
block_fn(sctx, sctx->buffer, 1); | ||
} | ||
|
||
memset(sctx->buffer + partial, 0x0, bit_offset - partial); | ||
*bits = cpu_to_be64(sctx->count << 3); | ||
block_fn(sctx, sctx->buffer, 1); | ||
|
||
return 0; | ||
} | ||
|
||
static inline int sha1_base_finish(struct shash_desc *desc, u8 *out) | ||
{ | ||
struct sha1_state *sctx = shash_desc_ctx(desc); | ||
__be32 *digest = (__be32 *)out; | ||
int i; | ||
|
||
for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++) | ||
put_unaligned_be32(sctx->state[i], digest++); | ||
|
||
*sctx = (struct sha1_state){}; | ||
return 0; | ||
} |