blob: 77d2ad6e899ef86953e8c2e851a09c3577230164 [file] [log] [blame]
David S. Millerc5aac2d2012-08-25 22:37:23 -07001/* Glue code for DES encryption optimized for sparc64 crypto opcodes.
2 *
3 * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
4 */
5
6#include <linux/crypto.h>
7#include <linux/init.h>
8#include <linux/module.h>
9#include <linux/mm.h>
10#include <linux/types.h>
11#include <crypto/algapi.h>
12#include <crypto/des.h>
13
14#include <asm/fpumacro.h>
15#include <asm/pstate.h>
16#include <asm/elf.h>
17
David S. Miller10803622012-09-15 09:06:30 -070018#include "opcodes.h"
19
David S. Millerc5aac2d2012-08-25 22:37:23 -070020struct des_sparc64_ctx {
21 u64 encrypt_expkey[DES_EXPKEY_WORDS / 2];
22 u64 decrypt_expkey[DES_EXPKEY_WORDS / 2];
23};
24
25struct des3_ede_sparc64_ctx {
26 u64 encrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
27 u64 decrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2];
28};
29
30static void encrypt_to_decrypt(u64 *d, const u64 *e)
31{
32 const u64 *s = e + (DES_EXPKEY_WORDS / 2) - 1;
33 int i;
34
35 for (i = 0; i < DES_EXPKEY_WORDS / 2; i++)
36 *d++ = *s--;
37}
38
39extern void des_sparc64_key_expand(const u32 *input_key, u64 *key);
40
41static int des_set_key(struct crypto_tfm *tfm, const u8 *key,
42 unsigned int keylen)
43{
44 struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
45 u32 *flags = &tfm->crt_flags;
46 u32 tmp[DES_EXPKEY_WORDS];
47 int ret;
48
49 /* Even though we have special instructions for key expansion,
50 * we call des_ekey() so that we don't have to write our own
51 * weak key detection code.
52 */
53 ret = des_ekey(tmp, key);
54 if (unlikely(ret == 0) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
55 *flags |= CRYPTO_TFM_RES_WEAK_KEY;
56 return -EINVAL;
57 }
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
65extern void des_sparc64_crypt(const u64 *key, const u64 *input,
66 u64 *output);
67
68static void des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
69{
70 struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
71 const u64 *K = ctx->encrypt_expkey;
72
73 des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
74}
75
76static void des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
77{
78 struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
79 const u64 *K = ctx->decrypt_expkey;
80
81 des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
82}
83
84extern void des_sparc64_load_keys(const u64 *key);
85
86extern void des_sparc64_ecb_crypt(const u64 *input, u64 *output,
87 unsigned int len);
88
89#define DES_BLOCK_MASK (~(DES_BLOCK_SIZE - 1))
90
91static int __ecb_crypt(struct blkcipher_desc *desc,
92 struct scatterlist *dst, struct scatterlist *src,
93 unsigned int nbytes, bool encrypt)
94{
95 struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
96 struct blkcipher_walk walk;
97 int err;
98
99 blkcipher_walk_init(&walk, dst, src, nbytes);
100 err = blkcipher_walk_virt(desc, &walk);
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
149 des_sparc64_load_keys(&ctx->encrypt_expkey[0]);
150 while ((nbytes = walk.nbytes)) {
151 unsigned int block_len = nbytes & DES_BLOCK_MASK;
152
153 if (likely(block_len)) {
154 des_sparc64_cbc_encrypt((const u64 *)walk.src.virt.addr,
155 (u64 *) walk.dst.virt.addr,
156 block_len, (u64 *) walk.iv);
157 }
158 nbytes &= DES_BLOCK_SIZE - 1;
159 err = blkcipher_walk_done(desc, &walk, nbytes);
160 }
161 fprs_write(0);
162 return err;
163}
164
165extern void des_sparc64_cbc_decrypt(const u64 *input, u64 *output,
166 unsigned int len, u64 *iv);
167
168static int cbc_decrypt(struct blkcipher_desc *desc,
169 struct scatterlist *dst, struct scatterlist *src,
170 unsigned int nbytes)
171{
172 struct des_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
173 struct blkcipher_walk walk;
174 int err;
175
176 blkcipher_walk_init(&walk, dst, src, nbytes);
177 err = blkcipher_walk_virt(desc, &walk);
178
179 des_sparc64_load_keys(&ctx->decrypt_expkey[0]);
180 while ((nbytes = walk.nbytes)) {
181 unsigned int block_len = nbytes & DES_BLOCK_MASK;
182
183 if (likely(block_len)) {
184 des_sparc64_cbc_decrypt((const u64 *)walk.src.virt.addr,
185 (u64 *) walk.dst.virt.addr,
186 block_len, (u64 *) walk.iv);
187 }
188 nbytes &= DES_BLOCK_SIZE - 1;
189 err = blkcipher_walk_done(desc, &walk, nbytes);
190 }
191 fprs_write(0);
192 return err;
193}
194
195static int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key,
196 unsigned int keylen)
197{
198 struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm);
199 const u32 *K = (const u32 *)key;
200 u32 *flags = &tfm->crt_flags;
201 u64 k1[DES_EXPKEY_WORDS / 2];
202 u64 k2[DES_EXPKEY_WORDS / 2];
203 u64 k3[DES_EXPKEY_WORDS / 2];
204
205 if (unlikely(!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
206 !((K[2] ^ K[4]) | (K[3] ^ K[5]))) &&
207 (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
208 *flags |= CRYPTO_TFM_RES_WEAK_KEY;
209 return -EINVAL;
210 }
211
212 des_sparc64_key_expand((const u32 *)key, k1);
213 key += DES_KEY_SIZE;
214 des_sparc64_key_expand((const u32 *)key, k2);
215 key += DES_KEY_SIZE;
216 des_sparc64_key_expand((const u32 *)key, k3);
217
218 memcpy(&dctx->encrypt_expkey[0], &k1[0], sizeof(k1));
219 encrypt_to_decrypt(&dctx->encrypt_expkey[DES_EXPKEY_WORDS / 2], &k2[0]);
220 memcpy(&dctx->encrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
221 &k3[0], sizeof(k3));
222
223 encrypt_to_decrypt(&dctx->decrypt_expkey[0], &k3[0]);
224 memcpy(&dctx->decrypt_expkey[DES_EXPKEY_WORDS / 2],
225 &k2[0], sizeof(k2));
226 encrypt_to_decrypt(&dctx->decrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2],
227 &k1[0]);
228
229 return 0;
230}
231
232extern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input,
233 u64 *output);
234
235static void des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
236{
237 struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
238 const u64 *K = ctx->encrypt_expkey;
239
240 des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
241}
242
243static void des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
244{
245 struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
246 const u64 *K = ctx->decrypt_expkey;
247
248 des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst);
249}
250
251extern void des3_ede_sparc64_load_keys(const u64 *key);
252
253extern void des3_ede_sparc64_ecb_crypt(const u64 *expkey, const u64 *input,
254 u64 *output, unsigned int len);
255
256static int __ecb3_crypt(struct blkcipher_desc *desc,
257 struct scatterlist *dst, struct scatterlist *src,
258 unsigned int nbytes, bool encrypt)
259{
260 struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
261 struct blkcipher_walk walk;
262 const u64 *K;
263 int err;
264
265 blkcipher_walk_init(&walk, dst, src, nbytes);
266 err = blkcipher_walk_virt(desc, &walk);
267
268 if (encrypt)
269 K = &ctx->encrypt_expkey[0];
270 else
271 K = &ctx->decrypt_expkey[0];
272 des3_ede_sparc64_load_keys(K);
273 while ((nbytes = walk.nbytes)) {
274 unsigned int block_len = nbytes & DES_BLOCK_MASK;
275
276 if (likely(block_len)) {
277 const u64 *src64 = (const u64 *)walk.src.virt.addr;
278 des3_ede_sparc64_ecb_crypt(K, src64,
279 (u64 *) walk.dst.virt.addr,
280 block_len);
281 }
282 nbytes &= DES_BLOCK_SIZE - 1;
283 err = blkcipher_walk_done(desc, &walk, nbytes);
284 }
285 fprs_write(0);
286 return err;
287}
288
289static int ecb3_encrypt(struct blkcipher_desc *desc,
290 struct scatterlist *dst, struct scatterlist *src,
291 unsigned int nbytes)
292{
293 return __ecb3_crypt(desc, dst, src, nbytes, true);
294}
295
296static int ecb3_decrypt(struct blkcipher_desc *desc,
297 struct scatterlist *dst, struct scatterlist *src,
298 unsigned int nbytes)
299{
300 return __ecb3_crypt(desc, dst, src, nbytes, false);
301}
302
303extern void des3_ede_sparc64_cbc_encrypt(const u64 *expkey, const u64 *input,
304 u64 *output, unsigned int len,
305 u64 *iv);
306
307static int cbc3_encrypt(struct blkcipher_desc *desc,
308 struct scatterlist *dst, struct scatterlist *src,
309 unsigned int nbytes)
310{
311 struct des3_ede_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
312 struct blkcipher_walk walk;
313 const u64 *K;
314 int err;
315
316 blkcipher_walk_init(&walk, dst, src, nbytes);
317 err = blkcipher_walk_virt(desc, &walk);
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
354 K = &ctx->decrypt_expkey[0];
355 des3_ede_sparc64_load_keys(K);
356 while ((nbytes = walk.nbytes)) {
357 unsigned int block_len = nbytes & DES_BLOCK_MASK;
358
359 if (likely(block_len)) {
360 const u64 *src64 = (const u64 *)walk.src.virt.addr;
361 des3_ede_sparc64_cbc_decrypt(K, src64,
362 (u64 *) walk.dst.virt.addr,
363 block_len,
364 (u64 *) walk.iv);
365 }
366 nbytes &= DES_BLOCK_SIZE - 1;
367 err = blkcipher_walk_done(desc, &walk, nbytes);
368 }
369 fprs_write(0);
370 return err;
371}
372
373static struct crypto_alg algs[] = { {
374 .cra_name = "des",
375 .cra_driver_name = "des-sparc64",
David S. Miller10803622012-09-15 09:06:30 -0700376 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
David S. Millerc5aac2d2012-08-25 22:37:23 -0700377 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
378 .cra_blocksize = DES_BLOCK_SIZE,
379 .cra_ctxsize = sizeof(struct des_sparc64_ctx),
380 .cra_alignmask = 7,
381 .cra_module = THIS_MODULE,
382 .cra_u = {
383 .cipher = {
384 .cia_min_keysize = DES_KEY_SIZE,
385 .cia_max_keysize = DES_KEY_SIZE,
386 .cia_setkey = des_set_key,
387 .cia_encrypt = des_encrypt,
388 .cia_decrypt = des_decrypt
389 }
390 }
391}, {
392 .cra_name = "ecb(des)",
393 .cra_driver_name = "ecb-des-sparc64",
David S. Miller10803622012-09-15 09:06:30 -0700394 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
David S. Millerc5aac2d2012-08-25 22:37:23 -0700395 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
396 .cra_blocksize = DES_BLOCK_SIZE,
397 .cra_ctxsize = sizeof(struct des_sparc64_ctx),
398 .cra_alignmask = 7,
399 .cra_type = &crypto_blkcipher_type,
400 .cra_module = THIS_MODULE,
401 .cra_u = {
402 .blkcipher = {
403 .min_keysize = DES_KEY_SIZE,
404 .max_keysize = DES_KEY_SIZE,
405 .setkey = des_set_key,
406 .encrypt = ecb_encrypt,
407 .decrypt = ecb_decrypt,
408 },
409 },
410}, {
411 .cra_name = "cbc(des)",
412 .cra_driver_name = "cbc-des-sparc64",
David S. Miller10803622012-09-15 09:06:30 -0700413 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
David S. Millerc5aac2d2012-08-25 22:37:23 -0700414 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
415 .cra_blocksize = DES_BLOCK_SIZE,
416 .cra_ctxsize = sizeof(struct des_sparc64_ctx),
417 .cra_alignmask = 7,
418 .cra_type = &crypto_blkcipher_type,
419 .cra_module = THIS_MODULE,
420 .cra_u = {
421 .blkcipher = {
422 .min_keysize = DES_KEY_SIZE,
423 .max_keysize = DES_KEY_SIZE,
424 .setkey = des_set_key,
425 .encrypt = cbc_encrypt,
426 .decrypt = cbc_decrypt,
427 },
428 },
429}, {
430 .cra_name = "des3_ede",
431 .cra_driver_name = "des3_ede-sparc64",
David S. Miller10803622012-09-15 09:06:30 -0700432 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
David S. Millerc5aac2d2012-08-25 22:37:23 -0700433 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
434 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
435 .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
436 .cra_alignmask = 7,
437 .cra_module = THIS_MODULE,
438 .cra_u = {
439 .cipher = {
440 .cia_min_keysize = DES3_EDE_KEY_SIZE,
441 .cia_max_keysize = DES3_EDE_KEY_SIZE,
442 .cia_setkey = des3_ede_set_key,
443 .cia_encrypt = des3_ede_encrypt,
444 .cia_decrypt = des3_ede_decrypt
445 }
446 }
447}, {
448 .cra_name = "ecb(des3_ede)",
449 .cra_driver_name = "ecb-des3_ede-sparc64",
David S. Miller10803622012-09-15 09:06:30 -0700450 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
David S. Millerc5aac2d2012-08-25 22:37:23 -0700451 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
452 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
453 .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
454 .cra_alignmask = 7,
455 .cra_type = &crypto_blkcipher_type,
456 .cra_module = THIS_MODULE,
457 .cra_u = {
458 .blkcipher = {
459 .min_keysize = DES3_EDE_KEY_SIZE,
460 .max_keysize = DES3_EDE_KEY_SIZE,
461 .setkey = des3_ede_set_key,
462 .encrypt = ecb3_encrypt,
463 .decrypt = ecb3_decrypt,
464 },
465 },
466}, {
467 .cra_name = "cbc(des3_ede)",
468 .cra_driver_name = "cbc-des3_ede-sparc64",
David S. Miller10803622012-09-15 09:06:30 -0700469 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
David S. Millerc5aac2d2012-08-25 22:37:23 -0700470 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
471 .cra_blocksize = DES3_EDE_BLOCK_SIZE,
472 .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx),
473 .cra_alignmask = 7,
474 .cra_type = &crypto_blkcipher_type,
475 .cra_module = THIS_MODULE,
476 .cra_u = {
477 .blkcipher = {
478 .min_keysize = DES3_EDE_KEY_SIZE,
479 .max_keysize = DES3_EDE_KEY_SIZE,
480 .setkey = des3_ede_set_key,
481 .encrypt = cbc3_encrypt,
482 .decrypt = cbc3_decrypt,
483 },
484 },
485} };
486
487static bool __init sparc64_has_des_opcode(void)
488{
489 unsigned long cfr;
490
491 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
492 return false;
493
494 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
495 if (!(cfr & CFR_DES))
496 return false;
497
498 return true;
499}
500
501static int __init des_sparc64_mod_init(void)
502{
503 int i;
504
505 for (i = 0; i < ARRAY_SIZE(algs); i++)
506 INIT_LIST_HEAD(&algs[i].cra_list);
507
508 if (sparc64_has_des_opcode()) {
509 pr_info("Using sparc64 des opcodes optimized DES implementation\n");
510 return crypto_register_algs(algs, ARRAY_SIZE(algs));
511 }
512 pr_info("sparc64 des opcodes not available.\n");
513 return -ENODEV;
514}
515
516static void __exit des_sparc64_mod_fini(void)
517{
518 crypto_unregister_algs(algs, ARRAY_SIZE(algs));
519}
520
521module_init(des_sparc64_mod_init);
522module_exit(des_sparc64_mod_fini);
523
524MODULE_LICENSE("GPL");
525MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated");
526
527MODULE_ALIAS("des");