~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/sparc/crypto/camellia_glue.c

Version: ~ [ linux-5.8-rc3 ] ~ [ linux-5.7.5 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.48 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.129 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.185 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.228 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.228 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.85 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /* Glue code for CAMELLIA encryption optimized for sparc64 crypto opcodes.
  2  *
  3  * Copyright (C) 2012 David S. Miller <davem@davemloft.net>
  4  */
  5 
  6 #define pr_fmt(fmt)     KBUILD_MODNAME ": " fmt
  7 
  8 #include <linux/crypto.h>
  9 #include <linux/init.h>
 10 #include <linux/module.h>
 11 #include <linux/mm.h>
 12 #include <linux/types.h>
 13 #include <crypto/algapi.h>
 14 
 15 #include <asm/fpumacro.h>
 16 #include <asm/pstate.h>
 17 #include <asm/elf.h>
 18 
 19 #include "opcodes.h"
 20 
 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
 25 
 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)];
 29         int key_len;
 30 };
 31 
 32 extern void camellia_sparc64_key_expand(const u32 *in_key, u64 *encrypt_key,
 33                                         unsigned int key_len, u64 *decrypt_key);
 34 
 35 static int camellia_set_key(struct crypto_tfm *tfm, const u8 *_in_key,
 36                             unsigned int key_len)
 37 {
 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;
 41 
 42         if (key_len != 16 && key_len != 24 && key_len != 32) {
 43                 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
 44                 return -EINVAL;
 45         }
 46 
 47         ctx->key_len = key_len;
 48 
 49         camellia_sparc64_key_expand(in_key, &ctx->encrypt_key[0],
 50                                     key_len, &ctx->decrypt_key[0]);
 51         return 0;
 52 }
 53 
 54 extern void camellia_sparc64_crypt(const u64 *key, const u32 *input,
 55                                    u32 *output, unsigned int key_len);
 56 
 57 static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 58 {
 59         struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
 60 
 61         camellia_sparc64_crypt(&ctx->encrypt_key[0],
 62                                (const u32 *) src,
 63                                (u32 *) dst, ctx->key_len);
 64 }
 65 
 66 static void camellia_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
 67 {
 68         struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
 69 
 70         camellia_sparc64_crypt(&ctx->decrypt_key[0],
 71                                (const u32 *) src,
 72                                (u32 *) dst, ctx->key_len);
 73 }
 74 
 75 extern void camellia_sparc64_load_keys(const u64 *key, unsigned int key_len);
 76 
 77 typedef void ecb_crypt_op(const u64 *input, u64 *output, unsigned int len,
 78                           const u64 *key);
 79 
 80 extern ecb_crypt_op camellia_sparc64_ecb_crypt_3_grand_rounds;
 81 extern ecb_crypt_op camellia_sparc64_ecb_crypt_4_grand_rounds;
 82 
 83 #define CAMELLIA_BLOCK_MASK     (~(CAMELLIA_BLOCK_SIZE - 1))
 84 
 85 static int __ecb_crypt(struct blkcipher_desc *desc,
 86                        struct scatterlist *dst, struct scatterlist *src,
 87                        unsigned int nbytes, bool encrypt)
 88 {
 89         struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
 90         struct blkcipher_walk walk;
 91         ecb_crypt_op *op;
 92         const u64 *key;
 93         int err;
 94 
 95         op = camellia_sparc64_ecb_crypt_3_grand_rounds;
 96         if (ctx->key_len != 16)
 97                 op = camellia_sparc64_ecb_crypt_4_grand_rounds;
 98 
 99         blkcipher_walk_init(&walk, dst, src, nbytes);
100         err = blkcipher_walk_virt(desc, &walk);
101         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
102 
103         if (encrypt)
104                 key = &ctx->encrypt_key[0];
105         else
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;
110 
111                 if (likely(block_len)) {
112                         const u64 *src64;
113                         u64 *dst64;
114 
115                         src64 = (const u64 *)walk.src.virt.addr;
116                         dst64 = (u64 *) walk.dst.virt.addr;
117                         op(src64, dst64, block_len, key);
118                 }
119                 nbytes &= CAMELLIA_BLOCK_SIZE - 1;
120                 err = blkcipher_walk_done(desc, &walk, nbytes);
121         }
122         fprs_write(0);
123         return err;
124 }
125 
126 static int ecb_encrypt(struct blkcipher_desc *desc,
127                        struct scatterlist *dst, struct scatterlist *src,
128                        unsigned int nbytes)
129 {
130         return __ecb_crypt(desc, dst, src, nbytes, true);
131 }
132 
133 static int ecb_decrypt(struct blkcipher_desc *desc,
134                        struct scatterlist *dst, struct scatterlist *src,
135                        unsigned int nbytes)
136 {
137         return __ecb_crypt(desc, dst, src, nbytes, false);
138 }
139 
140 typedef void cbc_crypt_op(const u64 *input, u64 *output, unsigned int len,
141                           const u64 *key, u64 *iv);
142 
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;
147 
148 static int cbc_encrypt(struct blkcipher_desc *desc,
149                        struct scatterlist *dst, struct scatterlist *src,
150                        unsigned int nbytes)
151 {
152         struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
153         struct blkcipher_walk walk;
154         cbc_crypt_op *op;
155         const u64 *key;
156         int err;
157 
158         op = camellia_sparc64_cbc_encrypt_3_grand_rounds;
159         if (ctx->key_len != 16)
160                 op = camellia_sparc64_cbc_encrypt_4_grand_rounds;
161 
162         blkcipher_walk_init(&walk, dst, src, nbytes);
163         err = blkcipher_walk_virt(desc, &walk);
164         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
165 
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;
170 
171                 if (likely(block_len)) {
172                         const u64 *src64;
173                         u64 *dst64;
174 
175                         src64 = (const u64 *)walk.src.virt.addr;
176                         dst64 = (u64 *) walk.dst.virt.addr;
177                         op(src64, dst64, block_len, key,
178                            (u64 *) walk.iv);
179                 }
180                 nbytes &= CAMELLIA_BLOCK_SIZE - 1;
181                 err = blkcipher_walk_done(desc, &walk, nbytes);
182         }
183         fprs_write(0);
184         return err;
185 }
186 
187 static int cbc_decrypt(struct blkcipher_desc *desc,
188                        struct scatterlist *dst, struct scatterlist *src,
189                        unsigned int nbytes)
190 {
191         struct camellia_sparc64_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
192         struct blkcipher_walk walk;
193         cbc_crypt_op *op;
194         const u64 *key;
195         int err;
196 
197         op = camellia_sparc64_cbc_decrypt_3_grand_rounds;
198         if (ctx->key_len != 16)
199                 op = camellia_sparc64_cbc_decrypt_4_grand_rounds;
200 
201         blkcipher_walk_init(&walk, dst, src, nbytes);
202         err = blkcipher_walk_virt(desc, &walk);
203         desc->flags &= ~CRYPTO_TFM_REQ_MAY_SLEEP;
204 
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;
209 
210                 if (likely(block_len)) {
211                         const u64 *src64;
212                         u64 *dst64;
213 
214                         src64 = (const u64 *)walk.src.virt.addr;
215                         dst64 = (u64 *) walk.dst.virt.addr;
216                         op(src64, dst64, block_len, key,
217                            (u64 *) walk.iv);
218                 }
219                 nbytes &= CAMELLIA_BLOCK_SIZE - 1;
220                 err = blkcipher_walk_done(desc, &walk, nbytes);
221         }
222         fprs_write(0);
223         return err;
224 }
225 
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),
233         .cra_alignmask          = 3,
234         .cra_module             = THIS_MODULE,
235         .cra_u  = {
236                 .cipher = {
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
242                 }
243         }
244 }, {
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),
251         .cra_alignmask          = 7,
252         .cra_type               = &crypto_blkcipher_type,
253         .cra_module             = THIS_MODULE,
254         .cra_u = {
255                 .blkcipher = {
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,
261                 },
262         },
263 }, {
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),
270         .cra_alignmask          = 7,
271         .cra_type               = &crypto_blkcipher_type,
272         .cra_module             = THIS_MODULE,
273         .cra_u = {
274                 .blkcipher = {
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,
281                 },
282         },
283 }
284 };
285 
286 static bool __init sparc64_has_camellia_opcode(void)
287 {
288         unsigned long cfr;
289 
290         if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
291                 return false;
292 
293         __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
294         if (!(cfr & CFR_CAMELLIA))
295                 return false;
296 
297         return true;
298 }
299 
300 static int __init camellia_sparc64_mod_init(void)
301 {
302         int i;
303 
304         for (i = 0; i < ARRAY_SIZE(algs); i++)
305                 INIT_LIST_HEAD(&algs[i].cra_list);
306 
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));
310         }
311         pr_info("sparc64 camellia opcodes not available.\n");
312         return -ENODEV;
313 }
314 
315 static void __exit camellia_sparc64_mod_fini(void)
316 {
317         crypto_unregister_algs(algs, ARRAY_SIZE(algs));
318 }
319 
320 module_init(camellia_sparc64_mod_init);
321 module_exit(camellia_sparc64_mod_fini);
322 
323 MODULE_LICENSE("GPL");
324 MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
325 
326 MODULE_ALIAS_CRYPTO("aes");
327 
328 #include "crop_devid.c"
329 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp