1 /* Glue code for CAMELLIA encryption optimized for sparc64 crypto opcodes.
3 * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8 #include <linux/crypto.h>
9 #include <linux/init.h>
10 #include <linux/module.h>
12 #include <linux/types.h>
13 #include <crypto/algapi.h>
15 #include <asm/fpumacro.h>
16 #include <asm/pstate.h>
21 #define CAMELLIA_MIN_KEY_SIZE 16
22 #define CAMELLIA_MAX_KEY_SIZE 32
23 #define CAMELLIA_BLOCK_SIZE 16
24 #define CAMELLIA_TABLE_BYTE_LEN 272
26 struct camellia_sparc64_ctx
{
27 u64 encrypt_key
[CAMELLIA_TABLE_BYTE_LEN
/ sizeof(u64
)];
28 u64 decrypt_key
[CAMELLIA_TABLE_BYTE_LEN
/ sizeof(u64
)];
32 extern void camellia_sparc64_key_expand(const u32
*in_key
, u64
*encrypt_key
,
33 unsigned int key_len
, u64
*decrypt_key
);
35 static int camellia_set_key(struct crypto_tfm
*tfm
, const u8
*_in_key
,
38 struct camellia_sparc64_ctx
*ctx
= crypto_tfm_ctx(tfm
);
39 const u32
*in_key
= (const u32
*) _in_key
;
40 u32
*flags
= &tfm
->crt_flags
;
42 if (key_len
!= 16 && key_len
!= 24 && key_len
!= 32) {
43 *flags
|= CRYPTO_TFM_RES_BAD_KEY_LEN
;
47 ctx
->key_len
= key_len
;
49 camellia_sparc64_key_expand(in_key
, &ctx
->encrypt_key
[0],
50 key_len
, &ctx
->decrypt_key
[0]);
54 extern void camellia_sparc64_crypt(const u64
*key
, const u32
*input
,
55 u32
*output
, unsigned int key_len
);
57 static void camellia_encrypt(struct crypto_tfm
*tfm
, u8
*dst
, const u8
*src
)
59 struct camellia_sparc64_ctx
*ctx
= crypto_tfm_ctx(tfm
);
61 camellia_sparc64_crypt(&ctx
->encrypt_key
[0],
63 (u32
*) dst
, ctx
->key_len
);
66 static void camellia_decrypt(struct crypto_tfm
*tfm
, u8
*dst
, const u8
*src
)
68 struct camellia_sparc64_ctx
*ctx
= crypto_tfm_ctx(tfm
);
70 camellia_sparc64_crypt(&ctx
->decrypt_key
[0],
72 (u32
*) dst
, ctx
->key_len
);
75 extern void camellia_sparc64_load_keys(const u64
*key
, unsigned int key_len
);
77 typedef void ecb_crypt_op(const u64
*input
, u64
*output
, unsigned int len
,
80 extern ecb_crypt_op camellia_sparc64_ecb_crypt_3_grand_rounds
;
81 extern ecb_crypt_op camellia_sparc64_ecb_crypt_4_grand_rounds
;
83 #define CAMELLIA_BLOCK_MASK (~(CAMELLIA_BLOCK_SIZE - 1))
85 static int __ecb_crypt(struct blkcipher_desc
*desc
,
86 struct scatterlist
*dst
, struct scatterlist
*src
,
87 unsigned int nbytes
, bool encrypt
)
89 struct camellia_sparc64_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
90 struct blkcipher_walk walk
;
95 op
= camellia_sparc64_ecb_crypt_3_grand_rounds
;
96 if (ctx
->key_len
!= 16)
97 op
= camellia_sparc64_ecb_crypt_4_grand_rounds
;
99 blkcipher_walk_init(&walk
, dst
, src
, nbytes
);
100 err
= blkcipher_walk_virt(desc
, &walk
);
101 desc
->flags
&= ~CRYPTO_TFM_REQ_MAY_SLEEP
;
104 key
= &ctx
->encrypt_key
[0];
106 key
= &ctx
->decrypt_key
[0];
107 camellia_sparc64_load_keys(key
, ctx
->key_len
);
108 while ((nbytes
= walk
.nbytes
)) {
109 unsigned int block_len
= nbytes
& CAMELLIA_BLOCK_MASK
;
111 if (likely(block_len
)) {
115 src64
= (const u64
*)walk
.src
.virt
.addr
;
116 dst64
= (u64
*) walk
.dst
.virt
.addr
;
117 op(src64
, dst64
, block_len
, key
);
119 nbytes
&= CAMELLIA_BLOCK_SIZE
- 1;
120 err
= blkcipher_walk_done(desc
, &walk
, nbytes
);
126 static int ecb_encrypt(struct blkcipher_desc
*desc
,
127 struct scatterlist
*dst
, struct scatterlist
*src
,
130 return __ecb_crypt(desc
, dst
, src
, nbytes
, true);
133 static int ecb_decrypt(struct blkcipher_desc
*desc
,
134 struct scatterlist
*dst
, struct scatterlist
*src
,
137 return __ecb_crypt(desc
, dst
, src
, nbytes
, false);
140 typedef void cbc_crypt_op(const u64
*input
, u64
*output
, unsigned int len
,
141 const u64
*key
, u64
*iv
);
143 extern cbc_crypt_op camellia_sparc64_cbc_encrypt_3_grand_rounds
;
144 extern cbc_crypt_op camellia_sparc64_cbc_encrypt_4_grand_rounds
;
145 extern cbc_crypt_op camellia_sparc64_cbc_decrypt_3_grand_rounds
;
146 extern cbc_crypt_op camellia_sparc64_cbc_decrypt_4_grand_rounds
;
148 static int cbc_encrypt(struct blkcipher_desc
*desc
,
149 struct scatterlist
*dst
, struct scatterlist
*src
,
152 struct camellia_sparc64_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
153 struct blkcipher_walk walk
;
158 op
= camellia_sparc64_cbc_encrypt_3_grand_rounds
;
159 if (ctx
->key_len
!= 16)
160 op
= camellia_sparc64_cbc_encrypt_4_grand_rounds
;
162 blkcipher_walk_init(&walk
, dst
, src
, nbytes
);
163 err
= blkcipher_walk_virt(desc
, &walk
);
164 desc
->flags
&= ~CRYPTO_TFM_REQ_MAY_SLEEP
;
166 key
= &ctx
->encrypt_key
[0];
167 camellia_sparc64_load_keys(key
, ctx
->key_len
);
168 while ((nbytes
= walk
.nbytes
)) {
169 unsigned int block_len
= nbytes
& CAMELLIA_BLOCK_MASK
;
171 if (likely(block_len
)) {
175 src64
= (const u64
*)walk
.src
.virt
.addr
;
176 dst64
= (u64
*) walk
.dst
.virt
.addr
;
177 op(src64
, dst64
, block_len
, key
,
180 nbytes
&= CAMELLIA_BLOCK_SIZE
- 1;
181 err
= blkcipher_walk_done(desc
, &walk
, nbytes
);
187 static int cbc_decrypt(struct blkcipher_desc
*desc
,
188 struct scatterlist
*dst
, struct scatterlist
*src
,
191 struct camellia_sparc64_ctx
*ctx
= crypto_blkcipher_ctx(desc
->tfm
);
192 struct blkcipher_walk walk
;
197 op
= camellia_sparc64_cbc_decrypt_3_grand_rounds
;
198 if (ctx
->key_len
!= 16)
199 op
= camellia_sparc64_cbc_decrypt_4_grand_rounds
;
201 blkcipher_walk_init(&walk
, dst
, src
, nbytes
);
202 err
= blkcipher_walk_virt(desc
, &walk
);
203 desc
->flags
&= ~CRYPTO_TFM_REQ_MAY_SLEEP
;
205 key
= &ctx
->decrypt_key
[0];
206 camellia_sparc64_load_keys(key
, ctx
->key_len
);
207 while ((nbytes
= walk
.nbytes
)) {
208 unsigned int block_len
= nbytes
& CAMELLIA_BLOCK_MASK
;
210 if (likely(block_len
)) {
214 src64
= (const u64
*)walk
.src
.virt
.addr
;
215 dst64
= (u64
*) walk
.dst
.virt
.addr
;
216 op(src64
, dst64
, block_len
, key
,
219 nbytes
&= CAMELLIA_BLOCK_SIZE
- 1;
220 err
= blkcipher_walk_done(desc
, &walk
, nbytes
);
226 static struct crypto_alg algs
[] = { {
227 .cra_name
= "camellia",
228 .cra_driver_name
= "camellia-sparc64",
229 .cra_priority
= SPARC_CR_OPCODE_PRIORITY
,
230 .cra_flags
= CRYPTO_ALG_TYPE_CIPHER
,
231 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
232 .cra_ctxsize
= sizeof(struct camellia_sparc64_ctx
),
234 .cra_module
= THIS_MODULE
,
237 .cia_min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
238 .cia_max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
239 .cia_setkey
= camellia_set_key
,
240 .cia_encrypt
= camellia_encrypt
,
241 .cia_decrypt
= camellia_decrypt
245 .cra_name
= "ecb(camellia)",
246 .cra_driver_name
= "ecb-camellia-sparc64",
247 .cra_priority
= SPARC_CR_OPCODE_PRIORITY
,
248 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
249 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
250 .cra_ctxsize
= sizeof(struct camellia_sparc64_ctx
),
252 .cra_type
= &crypto_blkcipher_type
,
253 .cra_module
= THIS_MODULE
,
256 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
257 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
258 .setkey
= camellia_set_key
,
259 .encrypt
= ecb_encrypt
,
260 .decrypt
= ecb_decrypt
,
264 .cra_name
= "cbc(camellia)",
265 .cra_driver_name
= "cbc-camellia-sparc64",
266 .cra_priority
= SPARC_CR_OPCODE_PRIORITY
,
267 .cra_flags
= CRYPTO_ALG_TYPE_BLKCIPHER
,
268 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
269 .cra_ctxsize
= sizeof(struct camellia_sparc64_ctx
),
271 .cra_type
= &crypto_blkcipher_type
,
272 .cra_module
= THIS_MODULE
,
275 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
276 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
277 .ivsize
= CAMELLIA_BLOCK_SIZE
,
278 .setkey
= camellia_set_key
,
279 .encrypt
= cbc_encrypt
,
280 .decrypt
= cbc_decrypt
,
286 static bool __init
sparc64_has_camellia_opcode(void)
290 if (!(sparc64_elf_hwcap
& HWCAP_SPARC_CRYPTO
))
293 __asm__
__volatile__("rd %%asr26, %0" : "=r" (cfr
));
294 if (!(cfr
& CFR_CAMELLIA
))
300 static int __init
camellia_sparc64_mod_init(void)
304 for (i
= 0; i
< ARRAY_SIZE(algs
); i
++)
305 INIT_LIST_HEAD(&algs
[i
].cra_list
);
307 if (sparc64_has_camellia_opcode()) {
308 pr_info("Using sparc64 camellia opcodes optimized CAMELLIA implementation\n");
309 return crypto_register_algs(algs
, ARRAY_SIZE(algs
));
311 pr_info("sparc64 camellia opcodes not available.\n");
315 static void __exit
camellia_sparc64_mod_fini(void)
317 crypto_unregister_algs(algs
, ARRAY_SIZE(algs
));
320 module_init(camellia_sparc64_mod_init
);
321 module_exit(camellia_sparc64_mod_fini
);
323 MODULE_LICENSE("GPL");
324 MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
326 MODULE_ALIAS_CRYPTO("camellia");
328 #include "crop_devid.c"