Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Ard Biesheuvel and committed by
Herbert Xu
c4d5b9ff 9c521a20

+107 -1
+1 -1
include/crypto/sha.h
··· 65 65 #define SHA512_H7 0x5be0cd19137e2179ULL 66 66 67 67 struct sha1_state { 68 - u64 count; 69 68 u32 state[SHA1_DIGEST_SIZE / 4]; 69 + u64 count; 70 70 u8 buffer[SHA1_BLOCK_SIZE]; 71 71 }; 72 72
+106
include/crypto/sha1_base.h
··· 1 + /* 2 + * sha1_base.h - core logic for SHA-1 implementations 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 <linux/crypto.h> 14 + #include <linux/module.h> 15 + 16 + #include <asm/unaligned.h> 17 + 18 + typedef void (sha1_block_fn)(struct sha1_state *sst, u8 const *src, int blocks); 19 + 20 + static inline int sha1_base_init(struct shash_desc *desc) 21 + { 22 + struct sha1_state *sctx = shash_desc_ctx(desc); 23 + 24 + sctx->state[0] = SHA1_H0; 25 + sctx->state[1] = SHA1_H1; 26 + sctx->state[2] = SHA1_H2; 27 + sctx->state[3] = SHA1_H3; 28 + sctx->state[4] = SHA1_H4; 29 + sctx->count = 0; 30 + 31 + return 0; 32 + } 33 + 34 + static inline int sha1_base_do_update(struct shash_desc *desc, 35 + const u8 *data, 36 + unsigned int len, 37 + sha1_block_fn *block_fn) 38 + { 39 + struct sha1_state *sctx = shash_desc_ctx(desc); 40 + unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; 41 + 42 + sctx->count += len; 43 + 44 + if (unlikely((partial + len) >= SHA1_BLOCK_SIZE)) { 45 + int blocks; 46 + 47 + if (partial) { 48 + int p = SHA1_BLOCK_SIZE - partial; 49 + 50 + memcpy(sctx->buffer + partial, data, p); 51 + data += p; 52 + len -= p; 53 + 54 + block_fn(sctx, sctx->buffer, 1); 55 + } 56 + 57 + blocks = len / SHA1_BLOCK_SIZE; 58 + len %= SHA1_BLOCK_SIZE; 59 + 60 + if (blocks) { 61 + block_fn(sctx, data, blocks); 62 + data += blocks * SHA1_BLOCK_SIZE; 63 + } 64 + partial = 0; 65 + } 66 + if (len) 67 + memcpy(sctx->buffer + partial, data, len); 68 + 69 + return 0; 70 + } 71 + 72 + static inline int sha1_base_do_finalize(struct shash_desc *desc, 73 + sha1_block_fn *block_fn) 74 + { 75 + const int bit_offset = SHA1_BLOCK_SIZE - sizeof(__be64); 76 + struct sha1_state *sctx = shash_desc_ctx(desc); 77 + __be64 *bits = (__be64 *)(sctx->buffer + bit_offset); 78 + unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; 79 + 80 + sctx->buffer[partial++] = 0x80; 81 + if (partial > bit_offset) { 82 + memset(sctx->buffer + partial, 0x0, SHA1_BLOCK_SIZE - partial); 83 + partial = 0; 84 + 85 + block_fn(sctx, sctx->buffer, 1); 86 + } 87 + 88 + memset(sctx->buffer + partial, 0x0, bit_offset - partial); 89 + *bits = cpu_to_be64(sctx->count << 3); 90 + block_fn(sctx, sctx->buffer, 1); 91 + 92 + return 0; 93 + } 94 + 95 + static inline int sha1_base_finish(struct shash_desc *desc, u8 *out) 96 + { 97 + struct sha1_state *sctx = shash_desc_ctx(desc); 98 + __be32 *digest = (__be32 *)out; 99 + int i; 100 + 101 + for (i = 0; i < SHA1_DIGEST_SIZE / sizeof(__be32); i++) 102 + put_unaligned_be32(sctx->state[i], digest++); 103 + 104 + *sctx = (struct sha1_state){}; 105 + return 0; 106 + }