diff options
author | Aaro Koskinen <aaro.koskinen@iki.fi> | 2015-03-08 16:07:46 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-03-24 10:15:43 -0400 |
commit | 041a80c5c0cd408311261dc31db31adf3de00905 (patch) | |
tree | 944a0e76d705c4b3609474088a917b10ebbf7e9c /arch | |
parent | 8ab368303caa9daa16b811963fcd693897a3a401 (diff) |
CRYPTO: Octeon: Add SHA512 module
Add OCTEON SHA512 module.
Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: David S. Miller <davem@davemloft.net>
Cc: linux-crypto@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/9496/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/cavium-octeon/crypto/Makefile | 1 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/crypto/octeon-sha512.c | 277 |
2 files changed, 278 insertions, 0 deletions
diff --git a/arch/mips/cavium-octeon/crypto/Makefile b/arch/mips/cavium-octeon/crypto/Makefile index 47806a5c5d71..f7aa9d5d3b87 100644 --- a/arch/mips/cavium-octeon/crypto/Makefile +++ b/arch/mips/cavium-octeon/crypto/Makefile | |||
@@ -7,3 +7,4 @@ obj-y += octeon-crypto.o | |||
7 | obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o | 7 | obj-$(CONFIG_CRYPTO_MD5_OCTEON) += octeon-md5.o |
8 | obj-$(CONFIG_CRYPTO_SHA1_OCTEON) += octeon-sha1.o | 8 | obj-$(CONFIG_CRYPTO_SHA1_OCTEON) += octeon-sha1.o |
9 | obj-$(CONFIG_CRYPTO_SHA256_OCTEON) += octeon-sha256.o | 9 | obj-$(CONFIG_CRYPTO_SHA256_OCTEON) += octeon-sha256.o |
10 | obj-$(CONFIG_CRYPTO_SHA512_OCTEON) += octeon-sha512.o | ||
diff --git a/arch/mips/cavium-octeon/crypto/octeon-sha512.c b/arch/mips/cavium-octeon/crypto/octeon-sha512.c new file mode 100644 index 000000000000..d5fb3c6f22ae --- /dev/null +++ b/arch/mips/cavium-octeon/crypto/octeon-sha512.c | |||
@@ -0,0 +1,277 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * SHA-512 and SHA-384 Secure Hash Algorithm. | ||
5 | * | ||
6 | * Adapted for OCTEON by Aaro Koskinen <aaro.koskinen@iki.fi>. | ||
7 | * | ||
8 | * Based on crypto/sha512_generic.c, which is: | ||
9 | * | ||
10 | * Copyright (c) Jean-Luc Cooke <jlcooke@certainkey.com> | ||
11 | * Copyright (c) Andrew McDonald <andrew@mcdonald.org.uk> | ||
12 | * Copyright (c) 2003 Kyle McMartin <kyle@debian.org> | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2, or (at your option) any | ||
17 | * later version. | ||
18 | */ | ||
19 | |||
20 | #include <linux/mm.h> | ||
21 | #include <crypto/sha.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/types.h> | ||
24 | #include <linux/module.h> | ||
25 | #include <asm/byteorder.h> | ||
26 | #include <asm/octeon/octeon.h> | ||
27 | #include <crypto/internal/hash.h> | ||
28 | |||
29 | #include "octeon-crypto.h" | ||
30 | |||
31 | /* | ||
32 | * We pass everything as 64-bit. OCTEON can handle misaligned data. | ||
33 | */ | ||
34 | |||
35 | static void octeon_sha512_store_hash(struct sha512_state *sctx) | ||
36 | { | ||
37 | write_octeon_64bit_hash_sha512(sctx->state[0], 0); | ||
38 | write_octeon_64bit_hash_sha512(sctx->state[1], 1); | ||
39 | write_octeon_64bit_hash_sha512(sctx->state[2], 2); | ||
40 | write_octeon_64bit_hash_sha512(sctx->state[3], 3); | ||
41 | write_octeon_64bit_hash_sha512(sctx->state[4], 4); | ||
42 | write_octeon_64bit_hash_sha512(sctx->state[5], 5); | ||
43 | write_octeon_64bit_hash_sha512(sctx->state[6], 6); | ||
44 | write_octeon_64bit_hash_sha512(sctx->state[7], 7); | ||
45 | } | ||
46 | |||
47 | static void octeon_sha512_read_hash(struct sha512_state *sctx) | ||
48 | { | ||
49 | sctx->state[0] = read_octeon_64bit_hash_sha512(0); | ||
50 | sctx->state[1] = read_octeon_64bit_hash_sha512(1); | ||
51 | sctx->state[2] = read_octeon_64bit_hash_sha512(2); | ||
52 | sctx->state[3] = read_octeon_64bit_hash_sha512(3); | ||
53 | sctx->state[4] = read_octeon_64bit_hash_sha512(4); | ||
54 | sctx->state[5] = read_octeon_64bit_hash_sha512(5); | ||
55 | sctx->state[6] = read_octeon_64bit_hash_sha512(6); | ||
56 | sctx->state[7] = read_octeon_64bit_hash_sha512(7); | ||
57 | } | ||
58 | |||
59 | static void octeon_sha512_transform(const void *_block) | ||
60 | { | ||
61 | const u64 *block = _block; | ||
62 | |||
63 | write_octeon_64bit_block_sha512(block[0], 0); | ||
64 | write_octeon_64bit_block_sha512(block[1], 1); | ||
65 | write_octeon_64bit_block_sha512(block[2], 2); | ||
66 | write_octeon_64bit_block_sha512(block[3], 3); | ||
67 | write_octeon_64bit_block_sha512(block[4], 4); | ||
68 | write_octeon_64bit_block_sha512(block[5], 5); | ||
69 | write_octeon_64bit_block_sha512(block[6], 6); | ||
70 | write_octeon_64bit_block_sha512(block[7], 7); | ||
71 | write_octeon_64bit_block_sha512(block[8], 8); | ||
72 | write_octeon_64bit_block_sha512(block[9], 9); | ||
73 | write_octeon_64bit_block_sha512(block[10], 10); | ||
74 | write_octeon_64bit_block_sha512(block[11], 11); | ||
75 | write_octeon_64bit_block_sha512(block[12], 12); | ||
76 | write_octeon_64bit_block_sha512(block[13], 13); | ||
77 | write_octeon_64bit_block_sha512(block[14], 14); | ||
78 | octeon_sha512_start(block[15]); | ||
79 | } | ||
80 | |||
81 | static int octeon_sha512_init(struct shash_desc *desc) | ||
82 | { | ||
83 | struct sha512_state *sctx = shash_desc_ctx(desc); | ||
84 | |||
85 | sctx->state[0] = SHA512_H0; | ||
86 | sctx->state[1] = SHA512_H1; | ||
87 | sctx->state[2] = SHA512_H2; | ||
88 | sctx->state[3] = SHA512_H3; | ||
89 | sctx->state[4] = SHA512_H4; | ||
90 | sctx->state[5] = SHA512_H5; | ||
91 | sctx->state[6] = SHA512_H6; | ||
92 | sctx->state[7] = SHA512_H7; | ||
93 | sctx->count[0] = sctx->count[1] = 0; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static int octeon_sha384_init(struct shash_desc *desc) | ||
99 | { | ||
100 | struct sha512_state *sctx = shash_desc_ctx(desc); | ||
101 | |||
102 | sctx->state[0] = SHA384_H0; | ||
103 | sctx->state[1] = SHA384_H1; | ||
104 | sctx->state[2] = SHA384_H2; | ||
105 | sctx->state[3] = SHA384_H3; | ||
106 | sctx->state[4] = SHA384_H4; | ||
107 | sctx->state[5] = SHA384_H5; | ||
108 | sctx->state[6] = SHA384_H6; | ||
109 | sctx->state[7] = SHA384_H7; | ||
110 | sctx->count[0] = sctx->count[1] = 0; | ||
111 | |||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static void __octeon_sha512_update(struct sha512_state *sctx, const u8 *data, | ||
116 | unsigned int len) | ||
117 | { | ||
118 | unsigned int part_len; | ||
119 | unsigned int index; | ||
120 | unsigned int i; | ||
121 | |||
122 | /* Compute number of bytes mod 128. */ | ||
123 | index = sctx->count[0] % SHA512_BLOCK_SIZE; | ||
124 | |||
125 | /* Update number of bytes. */ | ||
126 | if ((sctx->count[0] += len) < len) | ||
127 | sctx->count[1]++; | ||
128 | |||
129 | part_len = SHA512_BLOCK_SIZE - index; | ||
130 | |||
131 | /* Transform as many times as possible. */ | ||
132 | if (len >= part_len) { | ||
133 | memcpy(&sctx->buf[index], data, part_len); | ||
134 | octeon_sha512_transform(sctx->buf); | ||
135 | |||
136 | for (i = part_len; i + SHA512_BLOCK_SIZE <= len; | ||
137 | i += SHA512_BLOCK_SIZE) | ||
138 | octeon_sha512_transform(&data[i]); | ||
139 | |||
140 | index = 0; | ||
141 | } else { | ||
142 | i = 0; | ||
143 | } | ||
144 | |||
145 | /* Buffer remaining input. */ | ||
146 | memcpy(&sctx->buf[index], &data[i], len - i); | ||
147 | } | ||
148 | |||
149 | static int octeon_sha512_update(struct shash_desc *desc, const u8 *data, | ||
150 | unsigned int len) | ||
151 | { | ||
152 | struct sha512_state *sctx = shash_desc_ctx(desc); | ||
153 | struct octeon_cop2_state state; | ||
154 | unsigned long flags; | ||
155 | |||
156 | /* | ||
157 | * Small updates never reach the crypto engine, so the generic sha512 is | ||
158 | * faster because of the heavyweight octeon_crypto_enable() / | ||
159 | * octeon_crypto_disable(). | ||
160 | */ | ||
161 | if ((sctx->count[0] % SHA512_BLOCK_SIZE) + len < SHA512_BLOCK_SIZE) | ||
162 | return crypto_sha512_update(desc, data, len); | ||
163 | |||
164 | flags = octeon_crypto_enable(&state); | ||
165 | octeon_sha512_store_hash(sctx); | ||
166 | |||
167 | __octeon_sha512_update(sctx, data, len); | ||
168 | |||
169 | octeon_sha512_read_hash(sctx); | ||
170 | octeon_crypto_disable(&state, flags); | ||
171 | |||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | static int octeon_sha512_final(struct shash_desc *desc, u8 *hash) | ||
176 | { | ||
177 | struct sha512_state *sctx = shash_desc_ctx(desc); | ||
178 | static u8 padding[128] = { 0x80, }; | ||
179 | struct octeon_cop2_state state; | ||
180 | __be64 *dst = (__be64 *)hash; | ||
181 | unsigned int pad_len; | ||
182 | unsigned long flags; | ||
183 | unsigned int index; | ||
184 | __be64 bits[2]; | ||
185 | int i; | ||
186 | |||
187 | /* Save number of bits. */ | ||
188 | bits[1] = cpu_to_be64(sctx->count[0] << 3); | ||
189 | bits[0] = cpu_to_be64(sctx->count[1] << 3 | sctx->count[0] >> 61); | ||
190 | |||
191 | /* Pad out to 112 mod 128. */ | ||
192 | index = sctx->count[0] & 0x7f; | ||
193 | pad_len = (index < 112) ? (112 - index) : ((128+112) - index); | ||
194 | |||
195 | flags = octeon_crypto_enable(&state); | ||
196 | octeon_sha512_store_hash(sctx); | ||
197 | |||
198 | __octeon_sha512_update(sctx, padding, pad_len); | ||
199 | |||
200 | /* Append length (before padding). */ | ||
201 | __octeon_sha512_update(sctx, (const u8 *)bits, sizeof(bits)); | ||
202 | |||
203 | octeon_sha512_read_hash(sctx); | ||
204 | octeon_crypto_disable(&state, flags); | ||
205 | |||
206 | /* Store state in digest. */ | ||
207 | for (i = 0; i < 8; i++) | ||
208 | dst[i] = cpu_to_be64(sctx->state[i]); | ||
209 | |||
210 | /* Zeroize sensitive information. */ | ||
211 | memset(sctx, 0, sizeof(struct sha512_state)); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int octeon_sha384_final(struct shash_desc *desc, u8 *hash) | ||
217 | { | ||
218 | u8 D[64]; | ||
219 | |||
220 | octeon_sha512_final(desc, D); | ||
221 | |||
222 | memcpy(hash, D, 48); | ||
223 | memzero_explicit(D, 64); | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | static struct shash_alg octeon_sha512_algs[2] = { { | ||
229 | .digestsize = SHA512_DIGEST_SIZE, | ||
230 | .init = octeon_sha512_init, | ||
231 | .update = octeon_sha512_update, | ||
232 | .final = octeon_sha512_final, | ||
233 | .descsize = sizeof(struct sha512_state), | ||
234 | .base = { | ||
235 | .cra_name = "sha512", | ||
236 | .cra_driver_name= "octeon-sha512", | ||
237 | .cra_priority = OCTEON_CR_OPCODE_PRIORITY, | ||
238 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
239 | .cra_blocksize = SHA512_BLOCK_SIZE, | ||
240 | .cra_module = THIS_MODULE, | ||
241 | } | ||
242 | }, { | ||
243 | .digestsize = SHA384_DIGEST_SIZE, | ||
244 | .init = octeon_sha384_init, | ||
245 | .update = octeon_sha512_update, | ||
246 | .final = octeon_sha384_final, | ||
247 | .descsize = sizeof(struct sha512_state), | ||
248 | .base = { | ||
249 | .cra_name = "sha384", | ||
250 | .cra_driver_name= "octeon-sha384", | ||
251 | .cra_priority = OCTEON_CR_OPCODE_PRIORITY, | ||
252 | .cra_flags = CRYPTO_ALG_TYPE_SHASH, | ||
253 | .cra_blocksize = SHA384_BLOCK_SIZE, | ||
254 | .cra_module = THIS_MODULE, | ||
255 | } | ||
256 | } }; | ||
257 | |||
258 | static int __init octeon_sha512_mod_init(void) | ||
259 | { | ||
260 | if (!octeon_has_crypto()) | ||
261 | return -ENOTSUPP; | ||
262 | return crypto_register_shashes(octeon_sha512_algs, | ||
263 | ARRAY_SIZE(octeon_sha512_algs)); | ||
264 | } | ||
265 | |||
266 | static void __exit octeon_sha512_mod_fini(void) | ||
267 | { | ||
268 | crypto_unregister_shashes(octeon_sha512_algs, | ||
269 | ARRAY_SIZE(octeon_sha512_algs)); | ||
270 | } | ||
271 | |||
272 | module_init(octeon_sha512_mod_init); | ||
273 | module_exit(octeon_sha512_mod_fini); | ||
274 | |||
275 | MODULE_LICENSE("GPL"); | ||
276 | MODULE_DESCRIPTION("SHA-512 and SHA-384 Secure Hash Algorithms (OCTEON)"); | ||
277 | MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>"); | ||