162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* Glue code for DES encryption optimized for sparc64 crypto opcodes. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2012 David S. Miller <davem@davemloft.net> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#include <linux/crypto.h> 1062306a36Sopenharmony_ci#include <linux/init.h> 1162306a36Sopenharmony_ci#include <linux/module.h> 1262306a36Sopenharmony_ci#include <linux/mm.h> 1362306a36Sopenharmony_ci#include <linux/types.h> 1462306a36Sopenharmony_ci#include <crypto/algapi.h> 1562306a36Sopenharmony_ci#include <crypto/internal/des.h> 1662306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include <asm/fpumacro.h> 1962306a36Sopenharmony_ci#include <asm/pstate.h> 2062306a36Sopenharmony_ci#include <asm/elf.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "opcodes.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_cistruct des_sparc64_ctx { 2562306a36Sopenharmony_ci u64 encrypt_expkey[DES_EXPKEY_WORDS / 2]; 2662306a36Sopenharmony_ci u64 decrypt_expkey[DES_EXPKEY_WORDS / 2]; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistruct des3_ede_sparc64_ctx { 3062306a36Sopenharmony_ci u64 encrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2]; 3162306a36Sopenharmony_ci u64 decrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2]; 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_cistatic void encrypt_to_decrypt(u64 *d, const u64 *e) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci const u64 *s = e + (DES_EXPKEY_WORDS / 2) - 1; 3762306a36Sopenharmony_ci int i; 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci for (i = 0; i < DES_EXPKEY_WORDS / 2; i++) 4062306a36Sopenharmony_ci *d++ = *s--; 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ciextern void des_sparc64_key_expand(const u32 *input_key, u64 *key); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic int des_set_key(struct crypto_tfm *tfm, const u8 *key, 4662306a36Sopenharmony_ci unsigned int keylen) 4762306a36Sopenharmony_ci{ 4862306a36Sopenharmony_ci struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm); 4962306a36Sopenharmony_ci int err; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* Even though we have special instructions for key expansion, 5262306a36Sopenharmony_ci * we call des_verify_key() so that we don't have to write our own 5362306a36Sopenharmony_ci * weak key detection code. 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci err = crypto_des_verify_key(tfm, key); 5662306a36Sopenharmony_ci if (err) 5762306a36Sopenharmony_ci return err; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci des_sparc64_key_expand((const u32 *) key, &dctx->encrypt_expkey[0]); 6062306a36Sopenharmony_ci encrypt_to_decrypt(&dctx->decrypt_expkey[0], &dctx->encrypt_expkey[0]); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci return 0; 6362306a36Sopenharmony_ci} 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_cistatic int des_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *key, 6662306a36Sopenharmony_ci unsigned int keylen) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci return des_set_key(crypto_skcipher_tfm(tfm), key, keylen); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ciextern void des_sparc64_crypt(const u64 *key, const u64 *input, 7262306a36Sopenharmony_ci u64 *output); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void sparc_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 7762306a36Sopenharmony_ci const u64 *K = ctx->encrypt_expkey; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistatic void sparc_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 8362306a36Sopenharmony_ci{ 8462306a36Sopenharmony_ci struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 8562306a36Sopenharmony_ci const u64 *K = ctx->decrypt_expkey; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 8862306a36Sopenharmony_ci} 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ciextern void des_sparc64_load_keys(const u64 *key); 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ciextern void des_sparc64_ecb_crypt(const u64 *input, u64 *output, 9362306a36Sopenharmony_ci unsigned int len); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic int __ecb_crypt(struct skcipher_request *req, bool encrypt) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 9862306a36Sopenharmony_ci const struct des_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 9962306a36Sopenharmony_ci struct skcipher_walk walk; 10062306a36Sopenharmony_ci unsigned int nbytes; 10162306a36Sopenharmony_ci int err; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 10462306a36Sopenharmony_ci if (err) 10562306a36Sopenharmony_ci return err; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci if (encrypt) 10862306a36Sopenharmony_ci des_sparc64_load_keys(&ctx->encrypt_expkey[0]); 10962306a36Sopenharmony_ci else 11062306a36Sopenharmony_ci des_sparc64_load_keys(&ctx->decrypt_expkey[0]); 11162306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 11262306a36Sopenharmony_ci des_sparc64_ecb_crypt(walk.src.virt.addr, walk.dst.virt.addr, 11362306a36Sopenharmony_ci round_down(nbytes, DES_BLOCK_SIZE)); 11462306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 11562306a36Sopenharmony_ci } 11662306a36Sopenharmony_ci fprs_write(0); 11762306a36Sopenharmony_ci return err; 11862306a36Sopenharmony_ci} 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_cistatic int ecb_encrypt(struct skcipher_request *req) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci return __ecb_crypt(req, true); 12362306a36Sopenharmony_ci} 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic int ecb_decrypt(struct skcipher_request *req) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci return __ecb_crypt(req, false); 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ciextern void des_sparc64_cbc_encrypt(const u64 *input, u64 *output, 13162306a36Sopenharmony_ci unsigned int len, u64 *iv); 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ciextern void des_sparc64_cbc_decrypt(const u64 *input, u64 *output, 13462306a36Sopenharmony_ci unsigned int len, u64 *iv); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic int __cbc_crypt(struct skcipher_request *req, bool encrypt) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 13962306a36Sopenharmony_ci const struct des_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 14062306a36Sopenharmony_ci struct skcipher_walk walk; 14162306a36Sopenharmony_ci unsigned int nbytes; 14262306a36Sopenharmony_ci int err; 14362306a36Sopenharmony_ci 14462306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 14562306a36Sopenharmony_ci if (err) 14662306a36Sopenharmony_ci return err; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci if (encrypt) 14962306a36Sopenharmony_ci des_sparc64_load_keys(&ctx->encrypt_expkey[0]); 15062306a36Sopenharmony_ci else 15162306a36Sopenharmony_ci des_sparc64_load_keys(&ctx->decrypt_expkey[0]); 15262306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 15362306a36Sopenharmony_ci if (encrypt) 15462306a36Sopenharmony_ci des_sparc64_cbc_encrypt(walk.src.virt.addr, 15562306a36Sopenharmony_ci walk.dst.virt.addr, 15662306a36Sopenharmony_ci round_down(nbytes, 15762306a36Sopenharmony_ci DES_BLOCK_SIZE), 15862306a36Sopenharmony_ci walk.iv); 15962306a36Sopenharmony_ci else 16062306a36Sopenharmony_ci des_sparc64_cbc_decrypt(walk.src.virt.addr, 16162306a36Sopenharmony_ci walk.dst.virt.addr, 16262306a36Sopenharmony_ci round_down(nbytes, 16362306a36Sopenharmony_ci DES_BLOCK_SIZE), 16462306a36Sopenharmony_ci walk.iv); 16562306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci fprs_write(0); 16862306a36Sopenharmony_ci return err; 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic int cbc_encrypt(struct skcipher_request *req) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci return __cbc_crypt(req, true); 17462306a36Sopenharmony_ci} 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic int cbc_decrypt(struct skcipher_request *req) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci return __cbc_crypt(req, false); 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key, 18262306a36Sopenharmony_ci unsigned int keylen) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm); 18562306a36Sopenharmony_ci u64 k1[DES_EXPKEY_WORDS / 2]; 18662306a36Sopenharmony_ci u64 k2[DES_EXPKEY_WORDS / 2]; 18762306a36Sopenharmony_ci u64 k3[DES_EXPKEY_WORDS / 2]; 18862306a36Sopenharmony_ci int err; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci err = crypto_des3_ede_verify_key(tfm, key); 19162306a36Sopenharmony_ci if (err) 19262306a36Sopenharmony_ci return err; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci des_sparc64_key_expand((const u32 *)key, k1); 19562306a36Sopenharmony_ci key += DES_KEY_SIZE; 19662306a36Sopenharmony_ci des_sparc64_key_expand((const u32 *)key, k2); 19762306a36Sopenharmony_ci key += DES_KEY_SIZE; 19862306a36Sopenharmony_ci des_sparc64_key_expand((const u32 *)key, k3); 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci memcpy(&dctx->encrypt_expkey[0], &k1[0], sizeof(k1)); 20162306a36Sopenharmony_ci encrypt_to_decrypt(&dctx->encrypt_expkey[DES_EXPKEY_WORDS / 2], &k2[0]); 20262306a36Sopenharmony_ci memcpy(&dctx->encrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2], 20362306a36Sopenharmony_ci &k3[0], sizeof(k3)); 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci encrypt_to_decrypt(&dctx->decrypt_expkey[0], &k3[0]); 20662306a36Sopenharmony_ci memcpy(&dctx->decrypt_expkey[DES_EXPKEY_WORDS / 2], 20762306a36Sopenharmony_ci &k2[0], sizeof(k2)); 20862306a36Sopenharmony_ci encrypt_to_decrypt(&dctx->decrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2], 20962306a36Sopenharmony_ci &k1[0]); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic int des3_ede_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *key, 21562306a36Sopenharmony_ci unsigned int keylen) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci return des3_ede_set_key(crypto_skcipher_tfm(tfm), key, keylen); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ciextern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input, 22162306a36Sopenharmony_ci u64 *output); 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cistatic void sparc_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 22662306a36Sopenharmony_ci const u64 *K = ctx->encrypt_expkey; 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic void sparc_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 23462306a36Sopenharmony_ci const u64 *K = ctx->decrypt_expkey; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ciextern void des3_ede_sparc64_load_keys(const u64 *key); 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ciextern void des3_ede_sparc64_ecb_crypt(const u64 *expkey, const u64 *input, 24262306a36Sopenharmony_ci u64 *output, unsigned int len); 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic int __ecb3_crypt(struct skcipher_request *req, bool encrypt) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 24762306a36Sopenharmony_ci const struct des3_ede_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 24862306a36Sopenharmony_ci struct skcipher_walk walk; 24962306a36Sopenharmony_ci const u64 *K; 25062306a36Sopenharmony_ci unsigned int nbytes; 25162306a36Sopenharmony_ci int err; 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 25462306a36Sopenharmony_ci if (err) 25562306a36Sopenharmony_ci return err; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci if (encrypt) 25862306a36Sopenharmony_ci K = &ctx->encrypt_expkey[0]; 25962306a36Sopenharmony_ci else 26062306a36Sopenharmony_ci K = &ctx->decrypt_expkey[0]; 26162306a36Sopenharmony_ci des3_ede_sparc64_load_keys(K); 26262306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 26362306a36Sopenharmony_ci des3_ede_sparc64_ecb_crypt(K, walk.src.virt.addr, 26462306a36Sopenharmony_ci walk.dst.virt.addr, 26562306a36Sopenharmony_ci round_down(nbytes, DES_BLOCK_SIZE)); 26662306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 26762306a36Sopenharmony_ci } 26862306a36Sopenharmony_ci fprs_write(0); 26962306a36Sopenharmony_ci return err; 27062306a36Sopenharmony_ci} 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_cistatic int ecb3_encrypt(struct skcipher_request *req) 27362306a36Sopenharmony_ci{ 27462306a36Sopenharmony_ci return __ecb3_crypt(req, true); 27562306a36Sopenharmony_ci} 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_cistatic int ecb3_decrypt(struct skcipher_request *req) 27862306a36Sopenharmony_ci{ 27962306a36Sopenharmony_ci return __ecb3_crypt(req, false); 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ciextern void des3_ede_sparc64_cbc_encrypt(const u64 *expkey, const u64 *input, 28362306a36Sopenharmony_ci u64 *output, unsigned int len, 28462306a36Sopenharmony_ci u64 *iv); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ciextern void des3_ede_sparc64_cbc_decrypt(const u64 *expkey, const u64 *input, 28762306a36Sopenharmony_ci u64 *output, unsigned int len, 28862306a36Sopenharmony_ci u64 *iv); 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic int __cbc3_crypt(struct skcipher_request *req, bool encrypt) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 29362306a36Sopenharmony_ci const struct des3_ede_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 29462306a36Sopenharmony_ci struct skcipher_walk walk; 29562306a36Sopenharmony_ci const u64 *K; 29662306a36Sopenharmony_ci unsigned int nbytes; 29762306a36Sopenharmony_ci int err; 29862306a36Sopenharmony_ci 29962306a36Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 30062306a36Sopenharmony_ci if (err) 30162306a36Sopenharmony_ci return err; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (encrypt) 30462306a36Sopenharmony_ci K = &ctx->encrypt_expkey[0]; 30562306a36Sopenharmony_ci else 30662306a36Sopenharmony_ci K = &ctx->decrypt_expkey[0]; 30762306a36Sopenharmony_ci des3_ede_sparc64_load_keys(K); 30862306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 30962306a36Sopenharmony_ci if (encrypt) 31062306a36Sopenharmony_ci des3_ede_sparc64_cbc_encrypt(K, walk.src.virt.addr, 31162306a36Sopenharmony_ci walk.dst.virt.addr, 31262306a36Sopenharmony_ci round_down(nbytes, 31362306a36Sopenharmony_ci DES_BLOCK_SIZE), 31462306a36Sopenharmony_ci walk.iv); 31562306a36Sopenharmony_ci else 31662306a36Sopenharmony_ci des3_ede_sparc64_cbc_decrypt(K, walk.src.virt.addr, 31762306a36Sopenharmony_ci walk.dst.virt.addr, 31862306a36Sopenharmony_ci round_down(nbytes, 31962306a36Sopenharmony_ci DES_BLOCK_SIZE), 32062306a36Sopenharmony_ci walk.iv); 32162306a36Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci fprs_write(0); 32462306a36Sopenharmony_ci return err; 32562306a36Sopenharmony_ci} 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_cistatic int cbc3_encrypt(struct skcipher_request *req) 32862306a36Sopenharmony_ci{ 32962306a36Sopenharmony_ci return __cbc3_crypt(req, true); 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic int cbc3_decrypt(struct skcipher_request *req) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci return __cbc3_crypt(req, false); 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_cistatic struct crypto_alg cipher_algs[] = { 33862306a36Sopenharmony_ci { 33962306a36Sopenharmony_ci .cra_name = "des", 34062306a36Sopenharmony_ci .cra_driver_name = "des-sparc64", 34162306a36Sopenharmony_ci .cra_priority = SPARC_CR_OPCODE_PRIORITY, 34262306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 34362306a36Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 34462306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct des_sparc64_ctx), 34562306a36Sopenharmony_ci .cra_alignmask = 7, 34662306a36Sopenharmony_ci .cra_module = THIS_MODULE, 34762306a36Sopenharmony_ci .cra_u = { 34862306a36Sopenharmony_ci .cipher = { 34962306a36Sopenharmony_ci .cia_min_keysize = DES_KEY_SIZE, 35062306a36Sopenharmony_ci .cia_max_keysize = DES_KEY_SIZE, 35162306a36Sopenharmony_ci .cia_setkey = des_set_key, 35262306a36Sopenharmony_ci .cia_encrypt = sparc_des_encrypt, 35362306a36Sopenharmony_ci .cia_decrypt = sparc_des_decrypt 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci }, { 35762306a36Sopenharmony_ci .cra_name = "des3_ede", 35862306a36Sopenharmony_ci .cra_driver_name = "des3_ede-sparc64", 35962306a36Sopenharmony_ci .cra_priority = SPARC_CR_OPCODE_PRIORITY, 36062306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 36162306a36Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 36262306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx), 36362306a36Sopenharmony_ci .cra_alignmask = 7, 36462306a36Sopenharmony_ci .cra_module = THIS_MODULE, 36562306a36Sopenharmony_ci .cra_u = { 36662306a36Sopenharmony_ci .cipher = { 36762306a36Sopenharmony_ci .cia_min_keysize = DES3_EDE_KEY_SIZE, 36862306a36Sopenharmony_ci .cia_max_keysize = DES3_EDE_KEY_SIZE, 36962306a36Sopenharmony_ci .cia_setkey = des3_ede_set_key, 37062306a36Sopenharmony_ci .cia_encrypt = sparc_des3_ede_encrypt, 37162306a36Sopenharmony_ci .cia_decrypt = sparc_des3_ede_decrypt 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci } 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic struct skcipher_alg skcipher_algs[] = { 37862306a36Sopenharmony_ci { 37962306a36Sopenharmony_ci .base.cra_name = "ecb(des)", 38062306a36Sopenharmony_ci .base.cra_driver_name = "ecb-des-sparc64", 38162306a36Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 38262306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 38362306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des_sparc64_ctx), 38462306a36Sopenharmony_ci .base.cra_alignmask = 7, 38562306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 38662306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 38762306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 38862306a36Sopenharmony_ci .setkey = des_set_key_skcipher, 38962306a36Sopenharmony_ci .encrypt = ecb_encrypt, 39062306a36Sopenharmony_ci .decrypt = ecb_decrypt, 39162306a36Sopenharmony_ci }, { 39262306a36Sopenharmony_ci .base.cra_name = "cbc(des)", 39362306a36Sopenharmony_ci .base.cra_driver_name = "cbc-des-sparc64", 39462306a36Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 39562306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 39662306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des_sparc64_ctx), 39762306a36Sopenharmony_ci .base.cra_alignmask = 7, 39862306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 39962306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 40062306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 40162306a36Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 40262306a36Sopenharmony_ci .setkey = des_set_key_skcipher, 40362306a36Sopenharmony_ci .encrypt = cbc_encrypt, 40462306a36Sopenharmony_ci .decrypt = cbc_decrypt, 40562306a36Sopenharmony_ci }, { 40662306a36Sopenharmony_ci .base.cra_name = "ecb(des3_ede)", 40762306a36Sopenharmony_ci .base.cra_driver_name = "ecb-des3_ede-sparc64", 40862306a36Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 40962306a36Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 41062306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx), 41162306a36Sopenharmony_ci .base.cra_alignmask = 7, 41262306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 41362306a36Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 41462306a36Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 41562306a36Sopenharmony_ci .setkey = des3_ede_set_key_skcipher, 41662306a36Sopenharmony_ci .encrypt = ecb3_encrypt, 41762306a36Sopenharmony_ci .decrypt = ecb3_decrypt, 41862306a36Sopenharmony_ci }, { 41962306a36Sopenharmony_ci .base.cra_name = "cbc(des3_ede)", 42062306a36Sopenharmony_ci .base.cra_driver_name = "cbc-des3_ede-sparc64", 42162306a36Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 42262306a36Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 42362306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx), 42462306a36Sopenharmony_ci .base.cra_alignmask = 7, 42562306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 42662306a36Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 42762306a36Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 42862306a36Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 42962306a36Sopenharmony_ci .setkey = des3_ede_set_key_skcipher, 43062306a36Sopenharmony_ci .encrypt = cbc3_encrypt, 43162306a36Sopenharmony_ci .decrypt = cbc3_decrypt, 43262306a36Sopenharmony_ci } 43362306a36Sopenharmony_ci}; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_cistatic bool __init sparc64_has_des_opcode(void) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci unsigned long cfr; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 44062306a36Sopenharmony_ci return false; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 44362306a36Sopenharmony_ci if (!(cfr & CFR_DES)) 44462306a36Sopenharmony_ci return false; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci return true; 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic int __init des_sparc64_mod_init(void) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci int err; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (!sparc64_has_des_opcode()) { 45462306a36Sopenharmony_ci pr_info("sparc64 des opcodes not available.\n"); 45562306a36Sopenharmony_ci return -ENODEV; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci pr_info("Using sparc64 des opcodes optimized DES implementation\n"); 45862306a36Sopenharmony_ci err = crypto_register_algs(cipher_algs, ARRAY_SIZE(cipher_algs)); 45962306a36Sopenharmony_ci if (err) 46062306a36Sopenharmony_ci return err; 46162306a36Sopenharmony_ci err = crypto_register_skciphers(skcipher_algs, 46262306a36Sopenharmony_ci ARRAY_SIZE(skcipher_algs)); 46362306a36Sopenharmony_ci if (err) 46462306a36Sopenharmony_ci crypto_unregister_algs(cipher_algs, ARRAY_SIZE(cipher_algs)); 46562306a36Sopenharmony_ci return err; 46662306a36Sopenharmony_ci} 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_cistatic void __exit des_sparc64_mod_fini(void) 46962306a36Sopenharmony_ci{ 47062306a36Sopenharmony_ci crypto_unregister_algs(cipher_algs, ARRAY_SIZE(cipher_algs)); 47162306a36Sopenharmony_ci crypto_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs)); 47262306a36Sopenharmony_ci} 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_cimodule_init(des_sparc64_mod_init); 47562306a36Sopenharmony_cimodule_exit(des_sparc64_mod_fini); 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 47862306a36Sopenharmony_ciMODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated"); 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des"); 48162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des3_ede"); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci#include "crop_devid.c" 484