1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Glue code for CAMELLIA encryption optimized for sparc64 crypto opcodes.
4 * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
7 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
9 #include <linux/crypto.h>
10 #include <linux/init.h>
11 #include <linux/module.h>
13 #include <linux/types.h>
14 #include <crypto/algapi.h>
15 #include <crypto/internal/skcipher.h>
17 #include <asm/fpumacro.h>
18 #include <asm/pstate.h>
23 #define CAMELLIA_MIN_KEY_SIZE 16
24 #define CAMELLIA_MAX_KEY_SIZE 32
25 #define CAMELLIA_BLOCK_SIZE 16
26 #define CAMELLIA_TABLE_BYTE_LEN 272
28 struct camellia_sparc64_ctx
{
29 u64 encrypt_key
[CAMELLIA_TABLE_BYTE_LEN
/ sizeof(u64
)];
30 u64 decrypt_key
[CAMELLIA_TABLE_BYTE_LEN
/ sizeof(u64
)];
34 extern void camellia_sparc64_key_expand(const u32
*in_key
, u64
*encrypt_key
,
35 unsigned int key_len
, u64
*decrypt_key
);
37 static int camellia_set_key(struct crypto_tfm
*tfm
, const u8
*_in_key
,
40 struct camellia_sparc64_ctx
*ctx
= crypto_tfm_ctx(tfm
);
41 const u32
*in_key
= (const u32
*) _in_key
;
43 if (key_len
!= 16 && key_len
!= 24 && key_len
!= 32)
46 ctx
->key_len
= key_len
;
48 camellia_sparc64_key_expand(in_key
, &ctx
->encrypt_key
[0],
49 key_len
, &ctx
->decrypt_key
[0]);
53 static int camellia_set_key_skcipher(struct crypto_skcipher
*tfm
,
54 const u8
*in_key
, unsigned int key_len
)
56 return camellia_set_key(crypto_skcipher_tfm(tfm
), in_key
, key_len
);
59 extern void camellia_sparc64_crypt(const u64
*key
, const u32
*input
,
60 u32
*output
, unsigned int key_len
);
62 static void camellia_encrypt(struct crypto_tfm
*tfm
, u8
*dst
, const u8
*src
)
64 struct camellia_sparc64_ctx
*ctx
= crypto_tfm_ctx(tfm
);
66 camellia_sparc64_crypt(&ctx
->encrypt_key
[0],
68 (u32
*) dst
, ctx
->key_len
);
71 static void camellia_decrypt(struct crypto_tfm
*tfm
, u8
*dst
, const u8
*src
)
73 struct camellia_sparc64_ctx
*ctx
= crypto_tfm_ctx(tfm
);
75 camellia_sparc64_crypt(&ctx
->decrypt_key
[0],
77 (u32
*) dst
, ctx
->key_len
);
80 extern void camellia_sparc64_load_keys(const u64
*key
, unsigned int key_len
);
82 typedef void ecb_crypt_op(const u64
*input
, u64
*output
, unsigned int len
,
85 extern ecb_crypt_op camellia_sparc64_ecb_crypt_3_grand_rounds
;
86 extern ecb_crypt_op camellia_sparc64_ecb_crypt_4_grand_rounds
;
88 static int __ecb_crypt(struct skcipher_request
*req
, bool encrypt
)
90 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
91 const struct camellia_sparc64_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
92 struct skcipher_walk walk
;
98 op
= camellia_sparc64_ecb_crypt_3_grand_rounds
;
99 if (ctx
->key_len
!= 16)
100 op
= camellia_sparc64_ecb_crypt_4_grand_rounds
;
102 err
= skcipher_walk_virt(&walk
, req
, true);
107 key
= &ctx
->encrypt_key
[0];
109 key
= &ctx
->decrypt_key
[0];
110 camellia_sparc64_load_keys(key
, ctx
->key_len
);
111 while ((nbytes
= walk
.nbytes
) != 0) {
112 op(walk
.src
.virt
.addr
, walk
.dst
.virt
.addr
,
113 round_down(nbytes
, CAMELLIA_BLOCK_SIZE
), key
);
114 err
= skcipher_walk_done(&walk
, nbytes
% CAMELLIA_BLOCK_SIZE
);
120 static int ecb_encrypt(struct skcipher_request
*req
)
122 return __ecb_crypt(req
, true);
125 static int ecb_decrypt(struct skcipher_request
*req
)
127 return __ecb_crypt(req
, false);
130 typedef void cbc_crypt_op(const u64
*input
, u64
*output
, unsigned int len
,
131 const u64
*key
, u64
*iv
);
133 extern cbc_crypt_op camellia_sparc64_cbc_encrypt_3_grand_rounds
;
134 extern cbc_crypt_op camellia_sparc64_cbc_encrypt_4_grand_rounds
;
135 extern cbc_crypt_op camellia_sparc64_cbc_decrypt_3_grand_rounds
;
136 extern cbc_crypt_op camellia_sparc64_cbc_decrypt_4_grand_rounds
;
138 static int cbc_encrypt(struct skcipher_request
*req
)
140 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
141 const struct camellia_sparc64_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
142 struct skcipher_walk walk
;
148 op
= camellia_sparc64_cbc_encrypt_3_grand_rounds
;
149 if (ctx
->key_len
!= 16)
150 op
= camellia_sparc64_cbc_encrypt_4_grand_rounds
;
152 err
= skcipher_walk_virt(&walk
, req
, true);
156 key
= &ctx
->encrypt_key
[0];
157 camellia_sparc64_load_keys(key
, ctx
->key_len
);
158 while ((nbytes
= walk
.nbytes
) != 0) {
159 op(walk
.src
.virt
.addr
, walk
.dst
.virt
.addr
,
160 round_down(nbytes
, CAMELLIA_BLOCK_SIZE
), key
, walk
.iv
);
161 err
= skcipher_walk_done(&walk
, nbytes
% CAMELLIA_BLOCK_SIZE
);
167 static int cbc_decrypt(struct skcipher_request
*req
)
169 struct crypto_skcipher
*tfm
= crypto_skcipher_reqtfm(req
);
170 const struct camellia_sparc64_ctx
*ctx
= crypto_skcipher_ctx(tfm
);
171 struct skcipher_walk walk
;
177 op
= camellia_sparc64_cbc_decrypt_3_grand_rounds
;
178 if (ctx
->key_len
!= 16)
179 op
= camellia_sparc64_cbc_decrypt_4_grand_rounds
;
181 err
= skcipher_walk_virt(&walk
, req
, true);
185 key
= &ctx
->decrypt_key
[0];
186 camellia_sparc64_load_keys(key
, ctx
->key_len
);
187 while ((nbytes
= walk
.nbytes
) != 0) {
188 op(walk
.src
.virt
.addr
, walk
.dst
.virt
.addr
,
189 round_down(nbytes
, CAMELLIA_BLOCK_SIZE
), key
, walk
.iv
);
190 err
= skcipher_walk_done(&walk
, nbytes
% CAMELLIA_BLOCK_SIZE
);
196 static struct crypto_alg cipher_alg
= {
197 .cra_name
= "camellia",
198 .cra_driver_name
= "camellia-sparc64",
199 .cra_priority
= SPARC_CR_OPCODE_PRIORITY
,
200 .cra_flags
= CRYPTO_ALG_TYPE_CIPHER
,
201 .cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
202 .cra_ctxsize
= sizeof(struct camellia_sparc64_ctx
),
204 .cra_module
= THIS_MODULE
,
207 .cia_min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
208 .cia_max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
209 .cia_setkey
= camellia_set_key
,
210 .cia_encrypt
= camellia_encrypt
,
211 .cia_decrypt
= camellia_decrypt
216 static struct skcipher_alg skcipher_algs
[] = {
218 .base
.cra_name
= "ecb(camellia)",
219 .base
.cra_driver_name
= "ecb-camellia-sparc64",
220 .base
.cra_priority
= SPARC_CR_OPCODE_PRIORITY
,
221 .base
.cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
222 .base
.cra_ctxsize
= sizeof(struct camellia_sparc64_ctx
),
223 .base
.cra_alignmask
= 7,
224 .base
.cra_module
= THIS_MODULE
,
225 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
226 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
227 .setkey
= camellia_set_key_skcipher
,
228 .encrypt
= ecb_encrypt
,
229 .decrypt
= ecb_decrypt
,
231 .base
.cra_name
= "cbc(camellia)",
232 .base
.cra_driver_name
= "cbc-camellia-sparc64",
233 .base
.cra_priority
= SPARC_CR_OPCODE_PRIORITY
,
234 .base
.cra_blocksize
= CAMELLIA_BLOCK_SIZE
,
235 .base
.cra_ctxsize
= sizeof(struct camellia_sparc64_ctx
),
236 .base
.cra_alignmask
= 7,
237 .base
.cra_module
= THIS_MODULE
,
238 .min_keysize
= CAMELLIA_MIN_KEY_SIZE
,
239 .max_keysize
= CAMELLIA_MAX_KEY_SIZE
,
240 .ivsize
= CAMELLIA_BLOCK_SIZE
,
241 .setkey
= camellia_set_key_skcipher
,
242 .encrypt
= cbc_encrypt
,
243 .decrypt
= cbc_decrypt
,
247 static bool __init
sparc64_has_camellia_opcode(void)
251 if (!(sparc64_elf_hwcap
& HWCAP_SPARC_CRYPTO
))
254 __asm__
__volatile__("rd %%asr26, %0" : "=r" (cfr
));
255 if (!(cfr
& CFR_CAMELLIA
))
261 static int __init
camellia_sparc64_mod_init(void)
265 if (!sparc64_has_camellia_opcode()) {
266 pr_info("sparc64 camellia opcodes not available.\n");
269 pr_info("Using sparc64 camellia opcodes optimized CAMELLIA implementation\n");
270 err
= crypto_register_alg(&cipher_alg
);
273 err
= crypto_register_skciphers(skcipher_algs
,
274 ARRAY_SIZE(skcipher_algs
));
276 crypto_unregister_alg(&cipher_alg
);
280 static void __exit
camellia_sparc64_mod_fini(void)
282 crypto_unregister_alg(&cipher_alg
);
283 crypto_unregister_skciphers(skcipher_algs
, ARRAY_SIZE(skcipher_algs
));
286 module_init(camellia_sparc64_mod_init
);
287 module_exit(camellia_sparc64_mod_fini
);
289 MODULE_LICENSE("GPL");
290 MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
292 MODULE_ALIAS_CRYPTO("camellia");
294 #include "crop_devid.c"