aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/crypto
diff options
context:
space:
mode:
authorMarkus Stockhausen <stockhausen@collogia.de>2015-01-30 09:39:29 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2015-02-27 04:48:46 -0500
commitc147028ccc249681ef1129fb4b09f71fe6b75715 (patch)
treef1db3d62383317efeae18a54d019864abb49f566 /arch/powerpc/crypto
parent6bb71004aa84054058baf4e8a58a53c4e29e5b9c (diff)
crypto: ppc/sha256 - glue
Glue code for crypto infrastructure. Call the assembler code where required. Disable preemption during calculation and enable SPE instructions in the kernel prior to the call. Avoid to disable preemption for too long. Take a little care about small input data. Kick out early for input chunks < 64 bytes and replace memset for context cleanup with simple loop. Signed-off-by: Markus Stockhausen <stockhausen@collogia.de> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'arch/powerpc/crypto')
-rw-r--r--arch/powerpc/crypto/sha256_spe_glue.c275
1 files changed, 275 insertions, 0 deletions
diff --git a/arch/powerpc/crypto/sha256_spe_glue.c b/arch/powerpc/crypto/sha256_spe_glue.c
new file mode 100644
index 000000000000..f4a616fe1a82
--- /dev/null
+++ b/arch/powerpc/crypto/sha256_spe_glue.c
@@ -0,0 +1,275 @@
1/*
2 * Glue code for SHA-256 implementation for SPE instructions (PPC)
3 *
4 * Based on generic implementation. The assembler module takes care
5 * about the SPE registers so it can run from interrupt context.
6 *
7 * Copyright (c) 2015 Markus Stockhausen <stockhausen@collogia.de>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the Free
11 * Software Foundation; either version 2 of the License, or (at your option)
12 * any later version.
13 *
14 */
15
16#include <crypto/internal/hash.h>
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/mm.h>
20#include <linux/cryptohash.h>
21#include <linux/types.h>
22#include <crypto/sha.h>
23#include <asm/byteorder.h>
24#include <asm/switch_to.h>
25#include <linux/hardirq.h>
26
27/*
28 * MAX_BYTES defines the number of bytes that are allowed to be processed
29 * between preempt_disable() and preempt_enable(). SHA256 takes ~2,000
30 * operations per 64 bytes. e500 cores can issue two arithmetic instructions
31 * per clock cycle using one 32/64 bit unit (SU1) and one 32 bit unit (SU2).
32 * Thus 1KB of input data will need an estimated maximum of 18,000 cycles.
33 * Headroom for cache misses included. Even with the low end model clocked
34 * at 667 MHz this equals to a critical time window of less than 27us.
35 *
36 */
37#define MAX_BYTES 1024
38
39extern void ppc_spe_sha256_transform(u32 *state, const u8 *src, u32 blocks);
40
41static void spe_begin(void)
42{
43 /* We just start SPE operations and will save SPE registers later. */
44 preempt_disable();
45 enable_kernel_spe();
46}
47
48static void spe_end(void)
49{
50 /* reenable preemption */
51 preempt_enable();
52}
53
54static inline void ppc_sha256_clear_context(struct sha256_state *sctx)
55{
56 int count = sizeof(struct sha256_state) >> 2;
57 u32 *ptr = (u32 *)sctx;
58
59 /* make sure we can clear the fast way */
60 BUILD_BUG_ON(sizeof(struct sha256_state) % 4);
61 do { *ptr++ = 0; } while (--count);
62}
63
64static int ppc_spe_sha256_init(struct shash_desc *desc)
65{
66 struct sha256_state *sctx = shash_desc_ctx(desc);
67
68 sctx->state[0] = SHA256_H0;
69 sctx->state[1] = SHA256_H1;
70 sctx->state[2] = SHA256_H2;
71 sctx->state[3] = SHA256_H3;
72 sctx->state[4] = SHA256_H4;
73 sctx->state[5] = SHA256_H5;
74 sctx->state[6] = SHA256_H6;
75 sctx->state[7] = SHA256_H7;
76 sctx->count = 0;
77
78 return 0;
79}
80
81static int ppc_spe_sha224_init(struct shash_desc *desc)
82{
83 struct sha256_state *sctx = shash_desc_ctx(desc);
84
85 sctx->state[0] = SHA224_H0;
86 sctx->state[1] = SHA224_H1;
87 sctx->state[2] = SHA224_H2;
88 sctx->state[3] = SHA224_H3;
89 sctx->state[4] = SHA224_H4;
90 sctx->state[5] = SHA224_H5;
91 sctx->state[6] = SHA224_H6;
92 sctx->state[7] = SHA224_H7;
93 sctx->count = 0;
94
95 return 0;
96}
97
98static int ppc_spe_sha256_update(struct shash_desc *desc, const u8 *data,
99 unsigned int len)
100{
101 struct sha256_state *sctx = shash_desc_ctx(desc);
102 const unsigned int offset = sctx->count & 0x3f;
103 const unsigned int avail = 64 - offset;
104 unsigned int bytes;
105 const u8 *src = data;
106
107 if (avail > len) {
108 sctx->count += len;
109 memcpy((char *)sctx->buf + offset, src, len);
110 return 0;
111 }
112
113 sctx->count += len;
114
115 if (offset) {
116 memcpy((char *)sctx->buf + offset, src, avail);
117
118 spe_begin();
119 ppc_spe_sha256_transform(sctx->state, (const u8 *)sctx->buf, 1);
120 spe_end();
121
122 len -= avail;
123 src += avail;
124 }
125
126 while (len > 63) {
127 /* cut input data into smaller blocks */
128 bytes = (len > MAX_BYTES) ? MAX_BYTES : len;
129 bytes = bytes & ~0x3f;
130
131 spe_begin();
132 ppc_spe_sha256_transform(sctx->state, src, bytes >> 6);
133 spe_end();
134
135 src += bytes;
136 len -= bytes;
137 };
138
139 memcpy((char *)sctx->buf, src, len);
140 return 0;
141}
142
143static int ppc_spe_sha256_final(struct shash_desc *desc, u8 *out)
144{
145 struct sha256_state *sctx = shash_desc_ctx(desc);
146 const unsigned int offset = sctx->count & 0x3f;
147 char *p = (char *)sctx->buf + offset;
148 int padlen;
149 __be64 *pbits = (__be64 *)(((char *)&sctx->buf) + 56);
150 __be32 *dst = (__be32 *)out;
151
152 padlen = 55 - offset;
153 *p++ = 0x80;
154
155 spe_begin();
156
157 if (padlen < 0) {
158 memset(p, 0x00, padlen + sizeof (u64));
159 ppc_spe_sha256_transform(sctx->state, sctx->buf, 1);
160 p = (char *)sctx->buf;
161 padlen = 56;
162 }
163
164 memset(p, 0, padlen);
165 *pbits = cpu_to_be64(sctx->count << 3);
166 ppc_spe_sha256_transform(sctx->state, sctx->buf, 1);
167
168 spe_end();
169
170 dst[0] = cpu_to_be32(sctx->state[0]);
171 dst[1] = cpu_to_be32(sctx->state[1]);
172 dst[2] = cpu_to_be32(sctx->state[2]);
173 dst[3] = cpu_to_be32(sctx->state[3]);
174 dst[4] = cpu_to_be32(sctx->state[4]);
175 dst[5] = cpu_to_be32(sctx->state[5]);
176 dst[6] = cpu_to_be32(sctx->state[6]);
177 dst[7] = cpu_to_be32(sctx->state[7]);
178
179 ppc_sha256_clear_context(sctx);
180 return 0;
181}
182
183static int ppc_spe_sha224_final(struct shash_desc *desc, u8 *out)
184{
185 u32 D[SHA256_DIGEST_SIZE >> 2];
186 __be32 *dst = (__be32 *)out;
187
188 ppc_spe_sha256_final(desc, (u8 *)D);
189
190 /* avoid bytewise memcpy */
191 dst[0] = D[0];
192 dst[1] = D[1];
193 dst[2] = D[2];
194 dst[3] = D[3];
195 dst[4] = D[4];
196 dst[5] = D[5];
197 dst[6] = D[6];
198
199 /* clear sensitive data */
200 memzero_explicit(D, SHA256_DIGEST_SIZE);
201 return 0;
202}
203
204static int ppc_spe_sha256_export(struct shash_desc *desc, void *out)
205{
206 struct sha256_state *sctx = shash_desc_ctx(desc);
207
208 memcpy(out, sctx, sizeof(*sctx));
209 return 0;
210}
211
212static int ppc_spe_sha256_import(struct shash_desc *desc, const void *in)
213{
214 struct sha256_state *sctx = shash_desc_ctx(desc);
215
216 memcpy(sctx, in, sizeof(*sctx));
217 return 0;
218}
219
220static struct shash_alg algs[2] = { {
221 .digestsize = SHA256_DIGEST_SIZE,
222 .init = ppc_spe_sha256_init,
223 .update = ppc_spe_sha256_update,
224 .final = ppc_spe_sha256_final,
225 .export = ppc_spe_sha256_export,
226 .import = ppc_spe_sha256_import,
227 .descsize = sizeof(struct sha256_state),
228 .statesize = sizeof(struct sha256_state),
229 .base = {
230 .cra_name = "sha256",
231 .cra_driver_name= "sha256-ppc-spe",
232 .cra_priority = 300,
233 .cra_flags = CRYPTO_ALG_TYPE_SHASH,
234 .cra_blocksize = SHA256_BLOCK_SIZE,
235 .cra_module = THIS_MODULE,
236 }
237}, {
238 .digestsize = SHA224_DIGEST_SIZE,
239 .init = ppc_spe_sha224_init,
240 .update = ppc_spe_sha256_update,
241 .final = ppc_spe_sha224_final,
242 .export = ppc_spe_sha256_export,
243 .import = ppc_spe_sha256_import,
244 .descsize = sizeof(struct sha256_state),
245 .statesize = sizeof(struct sha256_state),
246 .base = {
247 .cra_name = "sha224",
248 .cra_driver_name= "sha224-ppc-spe",
249 .cra_priority = 300,
250 .cra_flags = CRYPTO_ALG_TYPE_SHASH,
251 .cra_blocksize = SHA224_BLOCK_SIZE,
252 .cra_module = THIS_MODULE,
253 }
254} };
255
256static int __init ppc_spe_sha256_mod_init(void)
257{
258 return crypto_register_shashes(algs, ARRAY_SIZE(algs));
259}
260
261static void __exit ppc_spe_sha256_mod_fini(void)
262{
263 crypto_unregister_shashes(algs, ARRAY_SIZE(algs));
264}
265
266module_init(ppc_spe_sha256_mod_init);
267module_exit(ppc_spe_sha256_mod_fini);
268
269MODULE_LICENSE("GPL");
270MODULE_DESCRIPTION("SHA-224 and SHA-256 Secure Hash Algorithm, SPE optimized");
271
272MODULE_ALIAS_CRYPTO("sha224");
273MODULE_ALIAS_CRYPTO("sha224-ppc-spe");
274MODULE_ALIAS_CRYPTO("sha256");
275MODULE_ALIAS_CRYPTO("sha256-ppc-spe");