0001
0002
0003
0004
0005
0006
0007 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0008
0009 #include <linux/crypto.h>
0010 #include <linux/init.h>
0011 #include <linux/module.h>
0012 #include <linux/mm.h>
0013 #include <linux/types.h>
0014 #include <crypto/algapi.h>
0015 #include <crypto/internal/skcipher.h>
0016
0017 #include <asm/fpumacro.h>
0018 #include <asm/pstate.h>
0019 #include <asm/elf.h>
0020
0021 #include "opcodes.h"
0022
0023 #define CAMELLIA_MIN_KEY_SIZE 16
0024 #define CAMELLIA_MAX_KEY_SIZE 32
0025 #define CAMELLIA_BLOCK_SIZE 16
0026 #define CAMELLIA_TABLE_BYTE_LEN 272
0027
0028 struct camellia_sparc64_ctx {
0029 u64 encrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
0030 u64 decrypt_key[CAMELLIA_TABLE_BYTE_LEN / sizeof(u64)];
0031 int key_len;
0032 };
0033
0034 extern void camellia_sparc64_key_expand(const u32 *in_key, u64 *encrypt_key,
0035 unsigned int key_len, u64 *decrypt_key);
0036
0037 static int camellia_set_key(struct crypto_tfm *tfm, const u8 *_in_key,
0038 unsigned int key_len)
0039 {
0040 struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
0041 const u32 *in_key = (const u32 *) _in_key;
0042
0043 if (key_len != 16 && key_len != 24 && key_len != 32)
0044 return -EINVAL;
0045
0046 ctx->key_len = key_len;
0047
0048 camellia_sparc64_key_expand(in_key, &ctx->encrypt_key[0],
0049 key_len, &ctx->decrypt_key[0]);
0050 return 0;
0051 }
0052
0053 static int camellia_set_key_skcipher(struct crypto_skcipher *tfm,
0054 const u8 *in_key, unsigned int key_len)
0055 {
0056 return camellia_set_key(crypto_skcipher_tfm(tfm), in_key, key_len);
0057 }
0058
0059 extern void camellia_sparc64_crypt(const u64 *key, const u32 *input,
0060 u32 *output, unsigned int key_len);
0061
0062 static void camellia_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
0063 {
0064 struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
0065
0066 camellia_sparc64_crypt(&ctx->encrypt_key[0],
0067 (const u32 *) src,
0068 (u32 *) dst, ctx->key_len);
0069 }
0070
0071 static void camellia_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
0072 {
0073 struct camellia_sparc64_ctx *ctx = crypto_tfm_ctx(tfm);
0074
0075 camellia_sparc64_crypt(&ctx->decrypt_key[0],
0076 (const u32 *) src,
0077 (u32 *) dst, ctx->key_len);
0078 }
0079
0080 extern void camellia_sparc64_load_keys(const u64 *key, unsigned int key_len);
0081
0082 typedef void ecb_crypt_op(const u64 *input, u64 *output, unsigned int len,
0083 const u64 *key);
0084
0085 extern ecb_crypt_op camellia_sparc64_ecb_crypt_3_grand_rounds;
0086 extern ecb_crypt_op camellia_sparc64_ecb_crypt_4_grand_rounds;
0087
0088 static int __ecb_crypt(struct skcipher_request *req, bool encrypt)
0089 {
0090 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0091 const struct camellia_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm);
0092 struct skcipher_walk walk;
0093 ecb_crypt_op *op;
0094 const u64 *key;
0095 unsigned int nbytes;
0096 int err;
0097
0098 op = camellia_sparc64_ecb_crypt_3_grand_rounds;
0099 if (ctx->key_len != 16)
0100 op = camellia_sparc64_ecb_crypt_4_grand_rounds;
0101
0102 err = skcipher_walk_virt(&walk, req, true);
0103 if (err)
0104 return err;
0105
0106 if (encrypt)
0107 key = &ctx->encrypt_key[0];
0108 else
0109 key = &ctx->decrypt_key[0];
0110 camellia_sparc64_load_keys(key, ctx->key_len);
0111 while ((nbytes = walk.nbytes) != 0) {
0112 op(walk.src.virt.addr, walk.dst.virt.addr,
0113 round_down(nbytes, CAMELLIA_BLOCK_SIZE), key);
0114 err = skcipher_walk_done(&walk, nbytes % CAMELLIA_BLOCK_SIZE);
0115 }
0116 fprs_write(0);
0117 return err;
0118 }
0119
0120 static int ecb_encrypt(struct skcipher_request *req)
0121 {
0122 return __ecb_crypt(req, true);
0123 }
0124
0125 static int ecb_decrypt(struct skcipher_request *req)
0126 {
0127 return __ecb_crypt(req, false);
0128 }
0129
0130 typedef void cbc_crypt_op(const u64 *input, u64 *output, unsigned int len,
0131 const u64 *key, u64 *iv);
0132
0133 extern cbc_crypt_op camellia_sparc64_cbc_encrypt_3_grand_rounds;
0134 extern cbc_crypt_op camellia_sparc64_cbc_encrypt_4_grand_rounds;
0135 extern cbc_crypt_op camellia_sparc64_cbc_decrypt_3_grand_rounds;
0136 extern cbc_crypt_op camellia_sparc64_cbc_decrypt_4_grand_rounds;
0137
0138 static int cbc_encrypt(struct skcipher_request *req)
0139 {
0140 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0141 const struct camellia_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm);
0142 struct skcipher_walk walk;
0143 cbc_crypt_op *op;
0144 const u64 *key;
0145 unsigned int nbytes;
0146 int err;
0147
0148 op = camellia_sparc64_cbc_encrypt_3_grand_rounds;
0149 if (ctx->key_len != 16)
0150 op = camellia_sparc64_cbc_encrypt_4_grand_rounds;
0151
0152 err = skcipher_walk_virt(&walk, req, true);
0153 if (err)
0154 return err;
0155
0156 key = &ctx->encrypt_key[0];
0157 camellia_sparc64_load_keys(key, ctx->key_len);
0158 while ((nbytes = walk.nbytes) != 0) {
0159 op(walk.src.virt.addr, walk.dst.virt.addr,
0160 round_down(nbytes, CAMELLIA_BLOCK_SIZE), key, walk.iv);
0161 err = skcipher_walk_done(&walk, nbytes % CAMELLIA_BLOCK_SIZE);
0162 }
0163 fprs_write(0);
0164 return err;
0165 }
0166
0167 static int cbc_decrypt(struct skcipher_request *req)
0168 {
0169 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0170 const struct camellia_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm);
0171 struct skcipher_walk walk;
0172 cbc_crypt_op *op;
0173 const u64 *key;
0174 unsigned int nbytes;
0175 int err;
0176
0177 op = camellia_sparc64_cbc_decrypt_3_grand_rounds;
0178 if (ctx->key_len != 16)
0179 op = camellia_sparc64_cbc_decrypt_4_grand_rounds;
0180
0181 err = skcipher_walk_virt(&walk, req, true);
0182 if (err)
0183 return err;
0184
0185 key = &ctx->decrypt_key[0];
0186 camellia_sparc64_load_keys(key, ctx->key_len);
0187 while ((nbytes = walk.nbytes) != 0) {
0188 op(walk.src.virt.addr, walk.dst.virt.addr,
0189 round_down(nbytes, CAMELLIA_BLOCK_SIZE), key, walk.iv);
0190 err = skcipher_walk_done(&walk, nbytes % CAMELLIA_BLOCK_SIZE);
0191 }
0192 fprs_write(0);
0193 return err;
0194 }
0195
0196 static struct crypto_alg cipher_alg = {
0197 .cra_name = "camellia",
0198 .cra_driver_name = "camellia-sparc64",
0199 .cra_priority = SPARC_CR_OPCODE_PRIORITY,
0200 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
0201 .cra_blocksize = CAMELLIA_BLOCK_SIZE,
0202 .cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
0203 .cra_alignmask = 3,
0204 .cra_module = THIS_MODULE,
0205 .cra_u = {
0206 .cipher = {
0207 .cia_min_keysize = CAMELLIA_MIN_KEY_SIZE,
0208 .cia_max_keysize = CAMELLIA_MAX_KEY_SIZE,
0209 .cia_setkey = camellia_set_key,
0210 .cia_encrypt = camellia_encrypt,
0211 .cia_decrypt = camellia_decrypt
0212 }
0213 }
0214 };
0215
0216 static struct skcipher_alg skcipher_algs[] = {
0217 {
0218 .base.cra_name = "ecb(camellia)",
0219 .base.cra_driver_name = "ecb-camellia-sparc64",
0220 .base.cra_priority = SPARC_CR_OPCODE_PRIORITY,
0221 .base.cra_blocksize = CAMELLIA_BLOCK_SIZE,
0222 .base.cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
0223 .base.cra_alignmask = 7,
0224 .base.cra_module = THIS_MODULE,
0225 .min_keysize = CAMELLIA_MIN_KEY_SIZE,
0226 .max_keysize = CAMELLIA_MAX_KEY_SIZE,
0227 .setkey = camellia_set_key_skcipher,
0228 .encrypt = ecb_encrypt,
0229 .decrypt = ecb_decrypt,
0230 }, {
0231 .base.cra_name = "cbc(camellia)",
0232 .base.cra_driver_name = "cbc-camellia-sparc64",
0233 .base.cra_priority = SPARC_CR_OPCODE_PRIORITY,
0234 .base.cra_blocksize = CAMELLIA_BLOCK_SIZE,
0235 .base.cra_ctxsize = sizeof(struct camellia_sparc64_ctx),
0236 .base.cra_alignmask = 7,
0237 .base.cra_module = THIS_MODULE,
0238 .min_keysize = CAMELLIA_MIN_KEY_SIZE,
0239 .max_keysize = CAMELLIA_MAX_KEY_SIZE,
0240 .ivsize = CAMELLIA_BLOCK_SIZE,
0241 .setkey = camellia_set_key_skcipher,
0242 .encrypt = cbc_encrypt,
0243 .decrypt = cbc_decrypt,
0244 }
0245 };
0246
0247 static bool __init sparc64_has_camellia_opcode(void)
0248 {
0249 unsigned long cfr;
0250
0251 if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO))
0252 return false;
0253
0254 __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr));
0255 if (!(cfr & CFR_CAMELLIA))
0256 return false;
0257
0258 return true;
0259 }
0260
0261 static int __init camellia_sparc64_mod_init(void)
0262 {
0263 int err;
0264
0265 if (!sparc64_has_camellia_opcode()) {
0266 pr_info("sparc64 camellia opcodes not available.\n");
0267 return -ENODEV;
0268 }
0269 pr_info("Using sparc64 camellia opcodes optimized CAMELLIA implementation\n");
0270 err = crypto_register_alg(&cipher_alg);
0271 if (err)
0272 return err;
0273 err = crypto_register_skciphers(skcipher_algs,
0274 ARRAY_SIZE(skcipher_algs));
0275 if (err)
0276 crypto_unregister_alg(&cipher_alg);
0277 return err;
0278 }
0279
0280 static void __exit camellia_sparc64_mod_fini(void)
0281 {
0282 crypto_unregister_alg(&cipher_alg);
0283 crypto_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs));
0284 }
0285
0286 module_init(camellia_sparc64_mod_init);
0287 module_exit(camellia_sparc64_mod_fini);
0288
0289 MODULE_LICENSE("GPL");
0290 MODULE_DESCRIPTION("Camellia Cipher Algorithm, sparc64 camellia opcode accelerated");
0291
0292 MODULE_ALIAS_CRYPTO("camellia");
0293
0294 #include "crop_devid.c"