Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/* Glue code for DES encryption optimized for sparc64 crypto opcodes.
3 *
4 * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
5 */
6
7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9#include <linux/crypto.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/mm.h>
13#include <linux/types.h>
14#include <crypto/algapi.h>
15#include <crypto/internal/des.h>
16#include <crypto/internal/skcipher.h>
17
18#include <asm/fpumacro.h>
19#include <asm/pstate.h>
20#include <asm/elf.h>
21
22#include "opcodes.h"
23
24struct des_sparc64_ctx {
25 u64 encrypt_expkey[DES_EXPKEY_WORDS / 2];
26 u64 decrypt_expkey[DES_EXPKEY_WORDS / 2];
27};
28
29struct des3_ede_sparc64_ctx {
30 u64 encrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
31 u64 decrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
32};
33
34static void encrypt_to_decrypt(u64 *d, const u64 *e)
35{
36 const u64 *s = e + (DES_EXPKEY_WORDS / 2) - 1;
37 int i;
38
39 for (i = 0; i < DES_EXPKEY_WORDS / 2; i++)
40 *d++ = *s--;
41}
42
43extern void des_sparc64_key_expand(const u32 *input_key, u64 *key);
44
45static int des_set_key(struct crypto_tfm *tfm, const u8 *key,
46 unsigned int keylen)
47{
48 struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
49 int err;
50
51 /* Even though we have special instructions for key expansion,
52 * we call des_verify_key() so that we don't have to write our own
53 * weak key detection code.
54 */
55 err = crypto_des_verify_key(tfm, key);
56 if (err)
57 return err;
58
59 des_sparc64_key_expand((const u32 *) key, &dctx->encrypt_expkey[0]);
60 encrypt_to_decrypt(&dctx->decrypt_expkey[0], &dctx->encrypt_expkey[0]);
61
62 return 0;
63}
64
65static int des_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *key,
66 unsigned int keylen)
67{
68 return des_set_key(crypto_skcipher_tfm(tfm), key, keylen);
69}
70
71extern void des_sparc64_crypt(const u64 *key, const u64 *input,
72 u64 *output);
73
74static void sparc_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
75{
76 struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
77 const u64 *K = ctx->encrypt_expkey;
78
79 des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
80}
81
82static void sparc_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
83{
84 struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
85 const u64 *K = ctx->decrypt_expkey;
86
87 des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
88}
89
90extern void des_sparc64_load_keys(const u64 *key);
91
92extern void des_sparc64_ecb_crypt(const u64 *input, u64 *output,
93 unsigned int len);
94
95static int __ecb_crypt(struct skcipher_request *req, bool encrypt)
96{
97 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
98 const struct des_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm);
99 struct skcipher_walk walk;
100 unsigned int nbytes;
101 int err;
102
103 err = skcipher_walk_virt(&walk, req, true);
104 if (err)
105 return err;
106
107 if (encrypt)
108 des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
109 else
110 des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
111 while ((nbytes = walk.nbytes) != 0) {
112 des_sparc64_ecb_crypt(walk.src.virt.addr, walk.dst.virt.addr,
113 round_down(nbytes, DES_BLOCK_SIZE));
114 err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE);
115 }
116 fprs_write(0);
117 return err;
118}
119
120static int ecb_encrypt(struct skcipher_request *req)
121{
122 return __ecb_crypt(req, true);
123}
124
125static int ecb_decrypt(struct skcipher_request *req)
126{
127 return __ecb_crypt(req, false);
128}
129
130extern void des_sparc64_cbc_encrypt(const u64 *input, u64 *output,
131 unsigned int len, u64 *iv);
132
133extern void des_sparc64_cbc_decrypt(const u64 *input, u64 *output,
134 unsigned int len, u64 *iv);
135
136static int __cbc_crypt(struct skcipher_request *req, bool encrypt)
137{
138 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
139 const struct des_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm);
140 struct skcipher_walk walk;
141 unsigned int nbytes;
142 int err;
143
144 err = skcipher_walk_virt(&walk, req, true);
145 if (err)
146 return err;
147
148 if (encrypt)
149 des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
150 else
151 des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
152 while ((nbytes = walk.nbytes) != 0) {
153 if (encrypt)
154 des_sparc64_cbc_encrypt(walk.src.virt.addr,
155 walk.dst.virt.addr,
156 round_down(nbytes,
157 DES_BLOCK_SIZE),
158 walk.iv);
159 else
160 des_sparc64_cbc_decrypt(walk.src.virt.addr,
161 walk.dst.virt.addr,
162 round_down(nbytes,
163 DES_BLOCK_SIZE),
164 walk.iv);
165 err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE);
166 }
167 fprs_write(0);
168 return err;
169}
170
171static int cbc_encrypt(struct skcipher_request *req)
172{
173 return __cbc_crypt(req, true);
174}
175
176static int cbc_decrypt(struct skcipher_request *req)
177{
178 return __cbc_crypt(req, false);
179}
180
181static int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key,
182 unsigned int keylen)
183{
184 struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
185 u64 k1[DES_EXPKEY_WORDS / 2];
186 u64 k2[DES_EXPKEY_WORDS / 2];
187 u64 k3[DES_EXPKEY_WORDS / 2];
188 int err;
189
190 err = crypto_des3_ede_verify_key(tfm, key);
191 if (err)
192 return err;
193
194 des_sparc64_key_expand((const u32 *)key, k1);
195 key += DES_KEY_SIZE;
196 des_sparc64_key_expand((const u32 *)key, k2);
197 key += DES_KEY_SIZE;
198 des_sparc64_key_expand((const u32 *)key, k3);
199
200 memcpy(&dctx->encrypt_expkey[0], &k1[0], sizeof(k1));
201 encrypt_to_decrypt(&dctx->encrypt_expkey[DES_EXPKEY_WORDS / 2], &k2[0]);
202 memcpy(&dctx->encrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
203 &k3[0], sizeof(k3));
204
205 encrypt_to_decrypt(&dctx->decrypt_expkey[0], &k3[0]);
206 memcpy(&dctx->decrypt_expkey[DES_EXPKEY_WORDS / 2],
207 &k2[0], sizeof(k2));
208 encrypt_to_decrypt(&dctx->decrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
209 &k1[0]);
210
211 return 0;
212}
213
214static int des3_ede_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *key,
215 unsigned int keylen)
216{
217 return des3_ede_set_key(crypto_skcipher_tfm(tfm), key, keylen);
218}
219
220extern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input,
221 u64 *output);
222
223static void sparc_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
224{
225 struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
226 const u64 *K = ctx->encrypt_expkey;
227
228 des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
229}
230
231static void sparc_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
232{
233 struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
234 const u64 *K = ctx->decrypt_expkey;
235
236 des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
237}
238
239extern void des3_ede_sparc64_load_keys(const u64 *key);
240
241extern void des3_ede_sparc64_ecb_crypt(const u64 *expkey, const u64 *input,
242 u64 *output, unsigned int len);
243
244static int __ecb3_crypt(struct skcipher_request *req, bool encrypt)
245{
246 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
247 const struct des3_ede_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm);
248 struct skcipher_walk walk;
249 const u64 *K;
250 unsigned int nbytes;
251 int err;
252
253 err = skcipher_walk_virt(&walk, req, true);
254 if (err)
255 return err;
256
257 if (encrypt)
258 K = &ctx->encrypt_expkey[0];
259 else
260 K = &ctx->decrypt_expkey[0];
261 des3_ede_sparc64_load_keys(K);
262 while ((nbytes = walk.nbytes) != 0) {
263 des3_ede_sparc64_ecb_crypt(K, walk.src.virt.addr,
264 walk.dst.virt.addr,
265 round_down(nbytes, DES_BLOCK_SIZE));
266 err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE);
267 }
268 fprs_write(0);
269 return err;
270}
271
272static int ecb3_encrypt(struct skcipher_request *req)
273{
274 return __ecb3_crypt(req, true);
275}
276
277static int ecb3_decrypt(struct skcipher_request *req)
278{
279 return __ecb3_crypt(req, false);
280}
281
282extern void des3_ede_sparc64_cbc_encrypt(const u64 *expkey, const u64 *input,
283 u64 *output, unsigned int len,
284 u64 *iv);
285
286extern void des3_ede_sparc64_cbc_decrypt(const u64 *expkey, const u64 *input,
287 u64 *output, unsigned int len,
288 u64 *iv);
289
290static int __cbc3_crypt(struct skcipher_request *req, bool encrypt)
291{
292 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
293 const struct des3_ede_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm);
294 struct skcipher_walk walk;
295 const u64 *K;
296 unsigned int nbytes;
297 int err;
298
299 err = skcipher_walk_virt(&walk, req, true);
300 if (err)
301 return err;
302
303 if (encrypt)
304 K = &ctx->encrypt_expkey[0];
305 else
306 K = &ctx->decrypt_expkey[0];
307 des3_ede_sparc64_load_keys(K);
308 while ((nbytes = walk.nbytes) != 0) {
309 if (encrypt)
310 des3_ede_sparc64_cbc_encrypt(K, walk.src.virt.addr,
311 walk.dst.virt.addr,
312 round_down(nbytes,
313 DES_BLOCK_SIZE),
314 walk.iv);
315 else
316 des3_ede_sparc64_cbc_decrypt(K, walk.src.virt.addr,
317 walk.dst.virt.addr,
318 round_down(nbytes,
319 DES_BLOCK_SIZE),
320 walk.iv);
321 err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE);
322 }
323 fprs_write(0);
324 return err;
325}
326
327static int cbc3_encrypt(struct skcipher_request *req)
328{
329 return __cbc3_crypt(req, true);
330}
331
332static int cbc3_decrypt(struct skcipher_request *req)
333{
334 return __cbc3_crypt(req, false);
335}
336
337static struct crypto_alg cipher_algs[] = {
338 {
339 .cra_name = "des",
340 .cra_driver_name = "des-sparc64",
341 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
342 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
343 .cra_blocksize = DES_BLOCK_SIZE,
344 .cra_ctxsize = sizeof(struct des_sparc64_ctx),
345 .cra_alignmask = 7,
346 .cra_module = THIS_MODULE,
347 .cra_u = {
348 .cipher = {
349 .cia_min_keysize = DES_KEY_SIZE,
350 .cia_max_keysize = DES_KEY_SIZE,
351 .cia_setkey = des_set_key,
352 .cia_encrypt = sparc_des_encrypt,
353 .cia_decrypt = sparc_des_decrypt
354 }
355 }
356 }, {
357 .cra_name = "des3_ede",
358 .cra_driver_name = "des3_ede-sparc64",
359 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
360 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
361 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
362 .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
363 .cra_alignmask = 7,
364 .cra_module = THIS_MODULE,
365 .cra_u = {
366 .cipher = {
367 .cia_min_keysize = DES3_EDE_KEY_SIZE,
368 .cia_max_keysize = DES3_EDE_KEY_SIZE,
369 .cia_setkey = des3_ede_set_key,
370 .cia_encrypt = sparc_des3_ede_encrypt,
371 .cia_decrypt = sparc_des3_ede_decrypt
372 }
373 }
374 }
375};
376
377static struct skcipher_alg skcipher_algs[] = {
378 {
379 .base.cra_name = "ecb(des)",
380 .base.cra_driver_name = "ecb-des-sparc64",
381 .base.cra_priority = SPARC_CR_OPCODE_PRIORITY,
382 .base.cra_blocksize = DES_BLOCK_SIZE,
383 .base.cra_ctxsize = sizeof(struct des_sparc64_ctx),
384 .base.cra_alignmask = 7,
385 .base.cra_module = THIS_MODULE,
386 .min_keysize = DES_KEY_SIZE,
387 .max_keysize = DES_KEY_SIZE,
388 .setkey = des_set_key_skcipher,
389 .encrypt = ecb_encrypt,
390 .decrypt = ecb_decrypt,
391 }, {
392 .base.cra_name = "cbc(des)",
393 .base.cra_driver_name = "cbc-des-sparc64",
394 .base.cra_priority = SPARC_CR_OPCODE_PRIORITY,
395 .base.cra_blocksize = DES_BLOCK_SIZE,
396 .base.cra_ctxsize = sizeof(struct des_sparc64_ctx),
397 .base.cra_alignmask = 7,
398 .base.cra_module = THIS_MODULE,
399 .min_keysize = DES_KEY_SIZE,
400 .max_keysize = DES_KEY_SIZE,
401 .ivsize = DES_BLOCK_SIZE,
402 .setkey = des_set_key_skcipher,
403 .encrypt = cbc_encrypt,
404 .decrypt = cbc_decrypt,
405 }, {
406 .base.cra_name = "ecb(des3_ede)",
407 .base.cra_driver_name = "ecb-des3_ede-sparc64",
408 .base.cra_priority = SPARC_CR_OPCODE_PRIORITY,
409 .base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
410 .base.cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
411 .base.cra_alignmask = 7,
412 .base.cra_module = THIS_MODULE,
413 .min_keysize = DES3_EDE_KEY_SIZE,
414 .max_keysize = DES3_EDE_KEY_SIZE,
415 .setkey = des3_ede_set_key_skcipher,
416 .encrypt = ecb3_encrypt,
417 .decrypt = ecb3_decrypt,
418 }, {
419 .base.cra_name = "cbc(des3_ede)",
420 .base.cra_driver_name = "cbc-des3_ede-sparc64",
421 .base.cra_priority = SPARC_CR_OPCODE_PRIORITY,
422 .base.cra_blocksize = DES3_EDE_BLOCK_SIZE,
423 .base.cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
424 .base.cra_alignmask = 7,
425 .base.cra_module = THIS_MODULE,
426 .min_keysize = DES3_EDE_KEY_SIZE,
427 .max_keysize = DES3_EDE_KEY_SIZE,
428 .ivsize = DES3_EDE_BLOCK_SIZE,
429 .setkey = des3_ede_set_key_skcipher,
430 .encrypt = cbc3_encrypt,
431 .decrypt = cbc3_decrypt,
432 }
433};
434
435static bool __init sparc64_has_des_opcode(void)
436{
437 unsigned long cfr;
438
439 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
440 return false;
441
442 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
443 if (!(cfr & CFR_DES))
444 return false;
445
446 return true;
447}
448
449static int __init des_sparc64_mod_init(void)
450{
451 int err;
452
453 if (!sparc64_has_des_opcode()) {
454 pr_info("sparc64 des opcodes not available.\n");
455 return -ENODEV;
456 }
457 pr_info("Using sparc64 des opcodes optimized DES implementation\n");
458 err = crypto_register_algs(cipher_algs, ARRAY_SIZE(cipher_algs));
459 if (err)
460 return err;
461 err = crypto_register_skciphers(skcipher_algs,
462 ARRAY_SIZE(skcipher_algs));
463 if (err)
464 crypto_unregister_algs(cipher_algs, ARRAY_SIZE(cipher_algs));
465 return err;
466}
467
468static void __exit des_sparc64_mod_fini(void)
469{
470 crypto_unregister_algs(cipher_algs, ARRAY_SIZE(cipher_algs));
471 crypto_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs));
472}
473
474module_init(des_sparc64_mod_init);
475module_exit(des_sparc64_mod_fini);
476
477MODULE_LICENSE("GPL");
478MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
479
480MODULE_ALIAS_CRYPTO("des");
481MODULE_ALIAS_CRYPTO("des3_ede");
482
483#include "crop_devid.c"
1// SPDX-License-Identifier: GPL-2.0-only
2/* Glue code for DES encryption optimized for sparc64 crypto opcodes.
3 *
4 * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
5 */
6
7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9#include <linux/crypto.h>
10#include <linux/init.h>
11#include <linux/module.h>
12#include <linux/mm.h>
13#include <linux/types.h>
14#include <crypto/algapi.h>
15#include <crypto/internal/des.h>
16
17#include <asm/fpumacro.h>
18#include <asm/pstate.h>
19#include <asm/elf.h>
20
21#include "opcodes.h"
22
23struct des_sparc64_ctx {
24 u64 encrypt_expkey[DES_EXPKEY_WORDS / 2];
25 u64 decrypt_expkey[DES_EXPKEY_WORDS / 2];
26};
27
28struct des3_ede_sparc64_ctx {
29 u64 encrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
30 u64 decrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
31};
32
33static void encrypt_to_decrypt(u64 *d, const u64 *e)
34{
35 const u64 *s = e + (DES_EXPKEY_WORDS / 2) - 1;
36 int i;
37
38 for (i = 0; i < DES_EXPKEY_WORDS / 2; i++)
39 *d++ = *s--;
40}
41
42extern void des_sparc64_key_expand(const u32 *input_key, u64 *key);
43
44static int des_set_key(struct crypto_tfm *tfm, const u8 *key,
45 unsigned int keylen)
46{
47 struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
48 int err;
49
50 /* Even though we have special instructions for key expansion,
51 * we call des_verify_key() so that we don't have to write our own
52 * weak key detection code.
53 */
54 err = crypto_des_verify_key(tfm, key);
55 if (err)
56 return err;
57
58 des_sparc64_key_expand((const u32 *) key, &dctx->encrypt_expkey[0]);
59 encrypt_to_decrypt(&dctx->decrypt_expkey[0], &dctx->encrypt_expkey[0]);
60
61 return 0;
62}
63
64extern void des_sparc64_crypt(const u64 *key, const u64 *input,
65 u64 *output);
66
67static void sparc_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
68{
69 struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
70 const u64 *K = ctx->encrypt_expkey;
71
72 des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
73}
74
75static void sparc_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
76{
77 struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
78 const u64 *K = ctx->decrypt_expkey;
79
80 des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
81}
82
83extern void des_sparc64_load_keys(const u64 *key);
84
85extern void des_sparc64_ecb_crypt(const u64 *input, u64 *output,
86 unsigned int len);
87
88#define DES_BLOCK_MASK (~(DES_BLOCK_SIZE - 1))
89
90static int __ecb_crypt(struct blkcipher_desc *desc,
91 struct scatterlist *dst, struct scatterlist *src,
92 unsigned int nbytes, bool encrypt)
93{
94 struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
95 struct blkcipher_walk walk;
96 int err;
97
98 blkcipher_walk_init(&walk, dst, src, nbytes);
99 err = blkcipher_walk_virt(desc, &walk);
100 desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
101
102 if (encrypt)
103 des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
104 else
105 des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
106 while ((nbytes = walk.nbytes)) {
107 unsigned int block_len = nbytes & DES_BLOCK_MASK;
108
109 if (likely(block_len)) {
110 des_sparc64_ecb_crypt((const u64 *)walk.src.virt.addr,
111 (u64 *) walk.dst.virt.addr,
112 block_len);
113 }
114 nbytes &= DES_BLOCK_SIZE - 1;
115 err = blkcipher_walk_done(desc, &walk, nbytes);
116 }
117 fprs_write(0);
118 return err;
119}
120
121static int ecb_encrypt(struct blkcipher_desc *desc,
122 struct scatterlist *dst, struct scatterlist *src,
123 unsigned int nbytes)
124{
125 return __ecb_crypt(desc, dst, src, nbytes, true);
126}
127
128static int ecb_decrypt(struct blkcipher_desc *desc,
129 struct scatterlist *dst, struct scatterlist *src,
130 unsigned int nbytes)
131{
132 return __ecb_crypt(desc, dst, src, nbytes, false);
133}
134
135extern void des_sparc64_cbc_encrypt(const u64 *input, u64 *output,
136 unsigned int len, u64 *iv);
137
138static int cbc_encrypt(struct blkcipher_desc *desc,
139 struct scatterlist *dst, struct scatterlist *src,
140 unsigned int nbytes)
141{
142 struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
143 struct blkcipher_walk walk;
144 int err;
145
146 blkcipher_walk_init(&walk, dst, src, nbytes);
147 err = blkcipher_walk_virt(desc, &walk);
148 desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
149
150 des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
151 while ((nbytes = walk.nbytes)) {
152 unsigned int block_len = nbytes & DES_BLOCK_MASK;
153
154 if (likely(block_len)) {
155 des_sparc64_cbc_encrypt((const u64 *)walk.src.virt.addr,
156 (u64 *) walk.dst.virt.addr,
157 block_len, (u64 *) walk.iv);
158 }
159 nbytes &= DES_BLOCK_SIZE - 1;
160 err = blkcipher_walk_done(desc, &walk, nbytes);
161 }
162 fprs_write(0);
163 return err;
164}
165
166extern void des_sparc64_cbc_decrypt(const u64 *input, u64 *output,
167 unsigned int len, u64 *iv);
168
169static int cbc_decrypt(struct blkcipher_desc *desc,
170 struct scatterlist *dst, struct scatterlist *src,
171 unsigned int nbytes)
172{
173 struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
174 struct blkcipher_walk walk;
175 int err;
176
177 blkcipher_walk_init(&walk, dst, src, nbytes);
178 err = blkcipher_walk_virt(desc, &walk);
179 desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
180
181 des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
182 while ((nbytes = walk.nbytes)) {
183 unsigned int block_len = nbytes & DES_BLOCK_MASK;
184
185 if (likely(block_len)) {
186 des_sparc64_cbc_decrypt((const u64 *)walk.src.virt.addr,
187 (u64 *) walk.dst.virt.addr,
188 block_len, (u64 *) walk.iv);
189 }
190 nbytes &= DES_BLOCK_SIZE - 1;
191 err = blkcipher_walk_done(desc, &walk, nbytes);
192 }
193 fprs_write(0);
194 return err;
195}
196
197static int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key,
198 unsigned int keylen)
199{
200 struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
201 u64 k1[DES_EXPKEY_WORDS / 2];
202 u64 k2[DES_EXPKEY_WORDS / 2];
203 u64 k3[DES_EXPKEY_WORDS / 2];
204 int err;
205
206 err = crypto_des3_ede_verify_key(tfm, key);
207 if (err)
208 return err;
209
210 des_sparc64_key_expand((const u32 *)key, k1);
211 key += DES_KEY_SIZE;
212 des_sparc64_key_expand((const u32 *)key, k2);
213 key += DES_KEY_SIZE;
214 des_sparc64_key_expand((const u32 *)key, k3);
215
216 memcpy(&dctx->encrypt_expkey[0], &k1[0], sizeof(k1));
217 encrypt_to_decrypt(&dctx->encrypt_expkey[DES_EXPKEY_WORDS / 2], &k2[0]);
218 memcpy(&dctx->encrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
219 &k3[0], sizeof(k3));
220
221 encrypt_to_decrypt(&dctx->decrypt_expkey[0], &k3[0]);
222 memcpy(&dctx->decrypt_expkey[DES_EXPKEY_WORDS / 2],
223 &k2[0], sizeof(k2));
224 encrypt_to_decrypt(&dctx->decrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
225 &k1[0]);
226
227 return 0;
228}
229
230extern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input,
231 u64 *output);
232
233static void sparc_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
234{
235 struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
236 const u64 *K = ctx->encrypt_expkey;
237
238 des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
239}
240
241static void sparc_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
242{
243 struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
244 const u64 *K = ctx->decrypt_expkey;
245
246 des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
247}
248
249extern void des3_ede_sparc64_load_keys(const u64 *key);
250
251extern void des3_ede_sparc64_ecb_crypt(const u64 *expkey, const u64 *input,
252 u64 *output, unsigned int len);
253
254static int __ecb3_crypt(struct blkcipher_desc *desc,
255 struct scatterlist *dst, struct scatterlist *src,
256 unsigned int nbytes, bool encrypt)
257{
258 struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
259 struct blkcipher_walk walk;
260 const u64 *K;
261 int err;
262
263 blkcipher_walk_init(&walk, dst, src, nbytes);
264 err = blkcipher_walk_virt(desc, &walk);
265 desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
266
267 if (encrypt)
268 K = &ctx->encrypt_expkey[0];
269 else
270 K = &ctx->decrypt_expkey[0];
271 des3_ede_sparc64_load_keys(K);
272 while ((nbytes = walk.nbytes)) {
273 unsigned int block_len = nbytes & DES_BLOCK_MASK;
274
275 if (likely(block_len)) {
276 const u64 *src64 = (const u64 *)walk.src.virt.addr;
277 des3_ede_sparc64_ecb_crypt(K, src64,
278 (u64 *) walk.dst.virt.addr,
279 block_len);
280 }
281 nbytes &= DES_BLOCK_SIZE - 1;
282 err = blkcipher_walk_done(desc, &walk, nbytes);
283 }
284 fprs_write(0);
285 return err;
286}
287
288static int ecb3_encrypt(struct blkcipher_desc *desc,
289 struct scatterlist *dst, struct scatterlist *src,
290 unsigned int nbytes)
291{
292 return __ecb3_crypt(desc, dst, src, nbytes, true);
293}
294
295static int ecb3_decrypt(struct blkcipher_desc *desc,
296 struct scatterlist *dst, struct scatterlist *src,
297 unsigned int nbytes)
298{
299 return __ecb3_crypt(desc, dst, src, nbytes, false);
300}
301
302extern void des3_ede_sparc64_cbc_encrypt(const u64 *expkey, const u64 *input,
303 u64 *output, unsigned int len,
304 u64 *iv);
305
306static int cbc3_encrypt(struct blkcipher_desc *desc,
307 struct scatterlist *dst, struct scatterlist *src,
308 unsigned int nbytes)
309{
310 struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
311 struct blkcipher_walk walk;
312 const u64 *K;
313 int err;
314
315 blkcipher_walk_init(&walk, dst, src, nbytes);
316 err = blkcipher_walk_virt(desc, &walk);
317 desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
318
319 K = &ctx->encrypt_expkey[0];
320 des3_ede_sparc64_load_keys(K);
321 while ((nbytes = walk.nbytes)) {
322 unsigned int block_len = nbytes & DES_BLOCK_MASK;
323
324 if (likely(block_len)) {
325 const u64 *src64 = (const u64 *)walk.src.virt.addr;
326 des3_ede_sparc64_cbc_encrypt(K, src64,
327 (u64 *) walk.dst.virt.addr,
328 block_len,
329 (u64 *) walk.iv);
330 }
331 nbytes &= DES_BLOCK_SIZE - 1;
332 err = blkcipher_walk_done(desc, &walk, nbytes);
333 }
334 fprs_write(0);
335 return err;
336}
337
338extern void des3_ede_sparc64_cbc_decrypt(const u64 *expkey, const u64 *input,
339 u64 *output, unsigned int len,
340 u64 *iv);
341
342static int cbc3_decrypt(struct blkcipher_desc *desc,
343 struct scatterlist *dst, struct scatterlist *src,
344 unsigned int nbytes)
345{
346 struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
347 struct blkcipher_walk walk;
348 const u64 *K;
349 int err;
350
351 blkcipher_walk_init(&walk, dst, src, nbytes);
352 err = blkcipher_walk_virt(desc, &walk);
353 desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
354
355 K = &ctx->decrypt_expkey[0];
356 des3_ede_sparc64_load_keys(K);
357 while ((nbytes = walk.nbytes)) {
358 unsigned int block_len = nbytes & DES_BLOCK_MASK;
359
360 if (likely(block_len)) {
361 const u64 *src64 = (const u64 *)walk.src.virt.addr;
362 des3_ede_sparc64_cbc_decrypt(K, src64,
363 (u64 *) walk.dst.virt.addr,
364 block_len,
365 (u64 *) walk.iv);
366 }
367 nbytes &= DES_BLOCK_SIZE - 1;
368 err = blkcipher_walk_done(desc, &walk, nbytes);
369 }
370 fprs_write(0);
371 return err;
372}
373
374static struct crypto_alg algs[] = { {
375 .cra_name = "des",
376 .cra_driver_name = "des-sparc64",
377 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
378 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
379 .cra_blocksize = DES_BLOCK_SIZE,
380 .cra_ctxsize = sizeof(struct des_sparc64_ctx),
381 .cra_alignmask = 7,
382 .cra_module = THIS_MODULE,
383 .cra_u = {
384 .cipher = {
385 .cia_min_keysize = DES_KEY_SIZE,
386 .cia_max_keysize = DES_KEY_SIZE,
387 .cia_setkey = des_set_key,
388 .cia_encrypt = sparc_des_encrypt,
389 .cia_decrypt = sparc_des_decrypt
390 }
391 }
392}, {
393 .cra_name = "ecb(des)",
394 .cra_driver_name = "ecb-des-sparc64",
395 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
396 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
397 .cra_blocksize = DES_BLOCK_SIZE,
398 .cra_ctxsize = sizeof(struct des_sparc64_ctx),
399 .cra_alignmask = 7,
400 .cra_type = &crypto_blkcipher_type,
401 .cra_module = THIS_MODULE,
402 .cra_u = {
403 .blkcipher = {
404 .min_keysize = DES_KEY_SIZE,
405 .max_keysize = DES_KEY_SIZE,
406 .setkey = des_set_key,
407 .encrypt = ecb_encrypt,
408 .decrypt = ecb_decrypt,
409 },
410 },
411}, {
412 .cra_name = "cbc(des)",
413 .cra_driver_name = "cbc-des-sparc64",
414 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
415 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
416 .cra_blocksize = DES_BLOCK_SIZE,
417 .cra_ctxsize = sizeof(struct des_sparc64_ctx),
418 .cra_alignmask = 7,
419 .cra_type = &crypto_blkcipher_type,
420 .cra_module = THIS_MODULE,
421 .cra_u = {
422 .blkcipher = {
423 .min_keysize = DES_KEY_SIZE,
424 .max_keysize = DES_KEY_SIZE,
425 .ivsize = DES_BLOCK_SIZE,
426 .setkey = des_set_key,
427 .encrypt = cbc_encrypt,
428 .decrypt = cbc_decrypt,
429 },
430 },
431}, {
432 .cra_name = "des3_ede",
433 .cra_driver_name = "des3_ede-sparc64",
434 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
435 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
436 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
437 .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
438 .cra_alignmask = 7,
439 .cra_module = THIS_MODULE,
440 .cra_u = {
441 .cipher = {
442 .cia_min_keysize = DES3_EDE_KEY_SIZE,
443 .cia_max_keysize = DES3_EDE_KEY_SIZE,
444 .cia_setkey = des3_ede_set_key,
445 .cia_encrypt = sparc_des3_ede_encrypt,
446 .cia_decrypt = sparc_des3_ede_decrypt
447 }
448 }
449}, {
450 .cra_name = "ecb(des3_ede)",
451 .cra_driver_name = "ecb-des3_ede-sparc64",
452 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
453 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
454 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
455 .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
456 .cra_alignmask = 7,
457 .cra_type = &crypto_blkcipher_type,
458 .cra_module = THIS_MODULE,
459 .cra_u = {
460 .blkcipher = {
461 .min_keysize = DES3_EDE_KEY_SIZE,
462 .max_keysize = DES3_EDE_KEY_SIZE,
463 .setkey = des3_ede_set_key,
464 .encrypt = ecb3_encrypt,
465 .decrypt = ecb3_decrypt,
466 },
467 },
468}, {
469 .cra_name = "cbc(des3_ede)",
470 .cra_driver_name = "cbc-des3_ede-sparc64",
471 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
472 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
473 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
474 .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
475 .cra_alignmask = 7,
476 .cra_type = &crypto_blkcipher_type,
477 .cra_module = THIS_MODULE,
478 .cra_u = {
479 .blkcipher = {
480 .min_keysize = DES3_EDE_KEY_SIZE,
481 .max_keysize = DES3_EDE_KEY_SIZE,
482 .ivsize = DES3_EDE_BLOCK_SIZE,
483 .setkey = des3_ede_set_key,
484 .encrypt = cbc3_encrypt,
485 .decrypt = cbc3_decrypt,
486 },
487 },
488} };
489
490static bool __init sparc64_has_des_opcode(void)
491{
492 unsigned long cfr;
493
494 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
495 return false;
496
497 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
498 if (!(cfr & CFR_DES))
499 return false;
500
501 return true;
502}
503
504static int __init des_sparc64_mod_init(void)
505{
506 if (sparc64_has_des_opcode()) {
507 pr_info("Using sparc64 des opcodes optimized DES implementation\n");
508 return crypto_register_algs(algs, ARRAY_SIZE(algs));
509 }
510 pr_info("sparc64 des opcodes not available.\n");
511 return -ENODEV;
512}
513
514static void __exit des_sparc64_mod_fini(void)
515{
516 crypto_unregister_algs(algs, ARRAY_SIZE(algs));
517}
518
519module_init(des_sparc64_mod_init);
520module_exit(des_sparc64_mod_fini);
521
522MODULE_LICENSE("GPL");
523MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
524
525MODULE_ALIAS_CRYPTO("des");
526MODULE_ALIAS_CRYPTO("des3_ede");
527
528#include "crop_devid.c"