18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* Glue code for DES encryption optimized for sparc64 crypto opcodes. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2012 David S. Miller <davem@davemloft.net> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/crypto.h> 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/mm.h> 138c2ecf20Sopenharmony_ci#include <linux/types.h> 148c2ecf20Sopenharmony_ci#include <crypto/algapi.h> 158c2ecf20Sopenharmony_ci#include <crypto/internal/des.h> 168c2ecf20Sopenharmony_ci#include <crypto/internal/skcipher.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <asm/fpumacro.h> 198c2ecf20Sopenharmony_ci#include <asm/pstate.h> 208c2ecf20Sopenharmony_ci#include <asm/elf.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#include "opcodes.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cistruct des_sparc64_ctx { 258c2ecf20Sopenharmony_ci u64 encrypt_expkey[DES_EXPKEY_WORDS / 2]; 268c2ecf20Sopenharmony_ci u64 decrypt_expkey[DES_EXPKEY_WORDS / 2]; 278c2ecf20Sopenharmony_ci}; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_cistruct des3_ede_sparc64_ctx { 308c2ecf20Sopenharmony_ci u64 encrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2]; 318c2ecf20Sopenharmony_ci u64 decrypt_expkey[DES3_EDE_EXPKEY_WORDS / 2]; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic void encrypt_to_decrypt(u64 *d, const u64 *e) 358c2ecf20Sopenharmony_ci{ 368c2ecf20Sopenharmony_ci const u64 *s = e + (DES_EXPKEY_WORDS / 2) - 1; 378c2ecf20Sopenharmony_ci int i; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci for (i = 0; i < DES_EXPKEY_WORDS / 2; i++) 408c2ecf20Sopenharmony_ci *d++ = *s--; 418c2ecf20Sopenharmony_ci} 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ciextern void des_sparc64_key_expand(const u32 *input_key, u64 *key); 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic int des_set_key(struct crypto_tfm *tfm, const u8 *key, 468c2ecf20Sopenharmony_ci unsigned int keylen) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci struct des_sparc64_ctx *dctx = crypto_tfm_ctx(tfm); 498c2ecf20Sopenharmony_ci int err; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci /* Even though we have special instructions for key expansion, 528c2ecf20Sopenharmony_ci * we call des_verify_key() so that we don't have to write our own 538c2ecf20Sopenharmony_ci * weak key detection code. 548c2ecf20Sopenharmony_ci */ 558c2ecf20Sopenharmony_ci err = crypto_des_verify_key(tfm, key); 568c2ecf20Sopenharmony_ci if (err) 578c2ecf20Sopenharmony_ci return err; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci des_sparc64_key_expand((const u32 *) key, &dctx->encrypt_expkey[0]); 608c2ecf20Sopenharmony_ci encrypt_to_decrypt(&dctx->decrypt_expkey[0], &dctx->encrypt_expkey[0]); 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci return 0; 638c2ecf20Sopenharmony_ci} 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_cistatic int des_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *key, 668c2ecf20Sopenharmony_ci unsigned int keylen) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci return des_set_key(crypto_skcipher_tfm(tfm), key, keylen); 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciextern void des_sparc64_crypt(const u64 *key, const u64 *input, 728c2ecf20Sopenharmony_ci u64 *output); 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic void sparc_des_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 778c2ecf20Sopenharmony_ci const u64 *K = ctx->encrypt_expkey; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 808c2ecf20Sopenharmony_ci} 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_cistatic void sparc_des_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 838c2ecf20Sopenharmony_ci{ 848c2ecf20Sopenharmony_ci struct des_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 858c2ecf20Sopenharmony_ci const u64 *K = ctx->decrypt_expkey; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci des_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ciextern void des_sparc64_load_keys(const u64 *key); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ciextern void des_sparc64_ecb_crypt(const u64 *input, u64 *output, 938c2ecf20Sopenharmony_ci unsigned int len); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_cistatic int __ecb_crypt(struct skcipher_request *req, bool encrypt) 968c2ecf20Sopenharmony_ci{ 978c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 988c2ecf20Sopenharmony_ci const struct des_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 998c2ecf20Sopenharmony_ci struct skcipher_walk walk; 1008c2ecf20Sopenharmony_ci unsigned int nbytes; 1018c2ecf20Sopenharmony_ci int err; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 1048c2ecf20Sopenharmony_ci if (err) 1058c2ecf20Sopenharmony_ci return err; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (encrypt) 1088c2ecf20Sopenharmony_ci des_sparc64_load_keys(&ctx->encrypt_expkey[0]); 1098c2ecf20Sopenharmony_ci else 1108c2ecf20Sopenharmony_ci des_sparc64_load_keys(&ctx->decrypt_expkey[0]); 1118c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 1128c2ecf20Sopenharmony_ci des_sparc64_ecb_crypt(walk.src.virt.addr, walk.dst.virt.addr, 1138c2ecf20Sopenharmony_ci round_down(nbytes, DES_BLOCK_SIZE)); 1148c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci fprs_write(0); 1178c2ecf20Sopenharmony_ci return err; 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic int ecb_encrypt(struct skcipher_request *req) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci return __ecb_crypt(req, true); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic int ecb_decrypt(struct skcipher_request *req) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci return __ecb_crypt(req, false); 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ciextern void des_sparc64_cbc_encrypt(const u64 *input, u64 *output, 1318c2ecf20Sopenharmony_ci unsigned int len, u64 *iv); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ciextern void des_sparc64_cbc_decrypt(const u64 *input, u64 *output, 1348c2ecf20Sopenharmony_ci unsigned int len, u64 *iv); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic int __cbc_crypt(struct skcipher_request *req, bool encrypt) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 1398c2ecf20Sopenharmony_ci const struct des_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 1408c2ecf20Sopenharmony_ci struct skcipher_walk walk; 1418c2ecf20Sopenharmony_ci unsigned int nbytes; 1428c2ecf20Sopenharmony_ci int err; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 1458c2ecf20Sopenharmony_ci if (err) 1468c2ecf20Sopenharmony_ci return err; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci if (encrypt) 1498c2ecf20Sopenharmony_ci des_sparc64_load_keys(&ctx->encrypt_expkey[0]); 1508c2ecf20Sopenharmony_ci else 1518c2ecf20Sopenharmony_ci des_sparc64_load_keys(&ctx->decrypt_expkey[0]); 1528c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 1538c2ecf20Sopenharmony_ci if (encrypt) 1548c2ecf20Sopenharmony_ci des_sparc64_cbc_encrypt(walk.src.virt.addr, 1558c2ecf20Sopenharmony_ci walk.dst.virt.addr, 1568c2ecf20Sopenharmony_ci round_down(nbytes, 1578c2ecf20Sopenharmony_ci DES_BLOCK_SIZE), 1588c2ecf20Sopenharmony_ci walk.iv); 1598c2ecf20Sopenharmony_ci else 1608c2ecf20Sopenharmony_ci des_sparc64_cbc_decrypt(walk.src.virt.addr, 1618c2ecf20Sopenharmony_ci walk.dst.virt.addr, 1628c2ecf20Sopenharmony_ci round_down(nbytes, 1638c2ecf20Sopenharmony_ci DES_BLOCK_SIZE), 1648c2ecf20Sopenharmony_ci walk.iv); 1658c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci fprs_write(0); 1688c2ecf20Sopenharmony_ci return err; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_cistatic int cbc_encrypt(struct skcipher_request *req) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci return __cbc_crypt(req, true); 1748c2ecf20Sopenharmony_ci} 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_cistatic int cbc_decrypt(struct skcipher_request *req) 1778c2ecf20Sopenharmony_ci{ 1788c2ecf20Sopenharmony_ci return __cbc_crypt(req, false); 1798c2ecf20Sopenharmony_ci} 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_cistatic int des3_ede_set_key(struct crypto_tfm *tfm, const u8 *key, 1828c2ecf20Sopenharmony_ci unsigned int keylen) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct des3_ede_sparc64_ctx *dctx = crypto_tfm_ctx(tfm); 1858c2ecf20Sopenharmony_ci u64 k1[DES_EXPKEY_WORDS / 2]; 1868c2ecf20Sopenharmony_ci u64 k2[DES_EXPKEY_WORDS / 2]; 1878c2ecf20Sopenharmony_ci u64 k3[DES_EXPKEY_WORDS / 2]; 1888c2ecf20Sopenharmony_ci int err; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci err = crypto_des3_ede_verify_key(tfm, key); 1918c2ecf20Sopenharmony_ci if (err) 1928c2ecf20Sopenharmony_ci return err; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci des_sparc64_key_expand((const u32 *)key, k1); 1958c2ecf20Sopenharmony_ci key += DES_KEY_SIZE; 1968c2ecf20Sopenharmony_ci des_sparc64_key_expand((const u32 *)key, k2); 1978c2ecf20Sopenharmony_ci key += DES_KEY_SIZE; 1988c2ecf20Sopenharmony_ci des_sparc64_key_expand((const u32 *)key, k3); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci memcpy(&dctx->encrypt_expkey[0], &k1[0], sizeof(k1)); 2018c2ecf20Sopenharmony_ci encrypt_to_decrypt(&dctx->encrypt_expkey[DES_EXPKEY_WORDS / 2], &k2[0]); 2028c2ecf20Sopenharmony_ci memcpy(&dctx->encrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2], 2038c2ecf20Sopenharmony_ci &k3[0], sizeof(k3)); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci encrypt_to_decrypt(&dctx->decrypt_expkey[0], &k3[0]); 2068c2ecf20Sopenharmony_ci memcpy(&dctx->decrypt_expkey[DES_EXPKEY_WORDS / 2], 2078c2ecf20Sopenharmony_ci &k2[0], sizeof(k2)); 2088c2ecf20Sopenharmony_ci encrypt_to_decrypt(&dctx->decrypt_expkey[(DES_EXPKEY_WORDS / 2) * 2], 2098c2ecf20Sopenharmony_ci &k1[0]); 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci return 0; 2128c2ecf20Sopenharmony_ci} 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cistatic int des3_ede_set_key_skcipher(struct crypto_skcipher *tfm, const u8 *key, 2158c2ecf20Sopenharmony_ci unsigned int keylen) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci return des3_ede_set_key(crypto_skcipher_tfm(tfm), key, keylen); 2188c2ecf20Sopenharmony_ci} 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ciextern void des3_ede_sparc64_crypt(const u64 *key, const u64 *input, 2218c2ecf20Sopenharmony_ci u64 *output); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic void sparc_des3_ede_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 2268c2ecf20Sopenharmony_ci const u64 *K = ctx->encrypt_expkey; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_cistatic void sparc_des3_ede_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 2328c2ecf20Sopenharmony_ci{ 2338c2ecf20Sopenharmony_ci struct des3_ede_sparc64_ctx *ctx = crypto_tfm_ctx(tfm); 2348c2ecf20Sopenharmony_ci const u64 *K = ctx->decrypt_expkey; 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci des3_ede_sparc64_crypt(K, (const u64 *) src, (u64 *) dst); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ciextern void des3_ede_sparc64_load_keys(const u64 *key); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ciextern void des3_ede_sparc64_ecb_crypt(const u64 *expkey, const u64 *input, 2428c2ecf20Sopenharmony_ci u64 *output, unsigned int len); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_cistatic int __ecb3_crypt(struct skcipher_request *req, bool encrypt) 2458c2ecf20Sopenharmony_ci{ 2468c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2478c2ecf20Sopenharmony_ci const struct des3_ede_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 2488c2ecf20Sopenharmony_ci struct skcipher_walk walk; 2498c2ecf20Sopenharmony_ci const u64 *K; 2508c2ecf20Sopenharmony_ci unsigned int nbytes; 2518c2ecf20Sopenharmony_ci int err; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 2548c2ecf20Sopenharmony_ci if (err) 2558c2ecf20Sopenharmony_ci return err; 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci if (encrypt) 2588c2ecf20Sopenharmony_ci K = &ctx->encrypt_expkey[0]; 2598c2ecf20Sopenharmony_ci else 2608c2ecf20Sopenharmony_ci K = &ctx->decrypt_expkey[0]; 2618c2ecf20Sopenharmony_ci des3_ede_sparc64_load_keys(K); 2628c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 2638c2ecf20Sopenharmony_ci des3_ede_sparc64_ecb_crypt(K, walk.src.virt.addr, 2648c2ecf20Sopenharmony_ci walk.dst.virt.addr, 2658c2ecf20Sopenharmony_ci round_down(nbytes, DES_BLOCK_SIZE)); 2668c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 2678c2ecf20Sopenharmony_ci } 2688c2ecf20Sopenharmony_ci fprs_write(0); 2698c2ecf20Sopenharmony_ci return err; 2708c2ecf20Sopenharmony_ci} 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_cistatic int ecb3_encrypt(struct skcipher_request *req) 2738c2ecf20Sopenharmony_ci{ 2748c2ecf20Sopenharmony_ci return __ecb3_crypt(req, true); 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic int ecb3_decrypt(struct skcipher_request *req) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci return __ecb3_crypt(req, false); 2808c2ecf20Sopenharmony_ci} 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ciextern void des3_ede_sparc64_cbc_encrypt(const u64 *expkey, const u64 *input, 2838c2ecf20Sopenharmony_ci u64 *output, unsigned int len, 2848c2ecf20Sopenharmony_ci u64 *iv); 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ciextern void des3_ede_sparc64_cbc_decrypt(const u64 *expkey, const u64 *input, 2878c2ecf20Sopenharmony_ci u64 *output, unsigned int len, 2888c2ecf20Sopenharmony_ci u64 *iv); 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_cistatic int __cbc3_crypt(struct skcipher_request *req, bool encrypt) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 2938c2ecf20Sopenharmony_ci const struct des3_ede_sparc64_ctx *ctx = crypto_skcipher_ctx(tfm); 2948c2ecf20Sopenharmony_ci struct skcipher_walk walk; 2958c2ecf20Sopenharmony_ci const u64 *K; 2968c2ecf20Sopenharmony_ci unsigned int nbytes; 2978c2ecf20Sopenharmony_ci int err; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci err = skcipher_walk_virt(&walk, req, true); 3008c2ecf20Sopenharmony_ci if (err) 3018c2ecf20Sopenharmony_ci return err; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci if (encrypt) 3048c2ecf20Sopenharmony_ci K = &ctx->encrypt_expkey[0]; 3058c2ecf20Sopenharmony_ci else 3068c2ecf20Sopenharmony_ci K = &ctx->decrypt_expkey[0]; 3078c2ecf20Sopenharmony_ci des3_ede_sparc64_load_keys(K); 3088c2ecf20Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 3098c2ecf20Sopenharmony_ci if (encrypt) 3108c2ecf20Sopenharmony_ci des3_ede_sparc64_cbc_encrypt(K, walk.src.virt.addr, 3118c2ecf20Sopenharmony_ci walk.dst.virt.addr, 3128c2ecf20Sopenharmony_ci round_down(nbytes, 3138c2ecf20Sopenharmony_ci DES_BLOCK_SIZE), 3148c2ecf20Sopenharmony_ci walk.iv); 3158c2ecf20Sopenharmony_ci else 3168c2ecf20Sopenharmony_ci des3_ede_sparc64_cbc_decrypt(K, walk.src.virt.addr, 3178c2ecf20Sopenharmony_ci walk.dst.virt.addr, 3188c2ecf20Sopenharmony_ci round_down(nbytes, 3198c2ecf20Sopenharmony_ci DES_BLOCK_SIZE), 3208c2ecf20Sopenharmony_ci walk.iv); 3218c2ecf20Sopenharmony_ci err = skcipher_walk_done(&walk, nbytes % DES_BLOCK_SIZE); 3228c2ecf20Sopenharmony_ci } 3238c2ecf20Sopenharmony_ci fprs_write(0); 3248c2ecf20Sopenharmony_ci return err; 3258c2ecf20Sopenharmony_ci} 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_cistatic int cbc3_encrypt(struct skcipher_request *req) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci return __cbc3_crypt(req, true); 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic int cbc3_decrypt(struct skcipher_request *req) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci return __cbc3_crypt(req, false); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_cistatic struct crypto_alg cipher_algs[] = { 3388c2ecf20Sopenharmony_ci { 3398c2ecf20Sopenharmony_ci .cra_name = "des", 3408c2ecf20Sopenharmony_ci .cra_driver_name = "des-sparc64", 3418c2ecf20Sopenharmony_ci .cra_priority = SPARC_CR_OPCODE_PRIORITY, 3428c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 3438c2ecf20Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 3448c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct des_sparc64_ctx), 3458c2ecf20Sopenharmony_ci .cra_alignmask = 7, 3468c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 3478c2ecf20Sopenharmony_ci .cra_u = { 3488c2ecf20Sopenharmony_ci .cipher = { 3498c2ecf20Sopenharmony_ci .cia_min_keysize = DES_KEY_SIZE, 3508c2ecf20Sopenharmony_ci .cia_max_keysize = DES_KEY_SIZE, 3518c2ecf20Sopenharmony_ci .cia_setkey = des_set_key, 3528c2ecf20Sopenharmony_ci .cia_encrypt = sparc_des_encrypt, 3538c2ecf20Sopenharmony_ci .cia_decrypt = sparc_des_decrypt 3548c2ecf20Sopenharmony_ci } 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci }, { 3578c2ecf20Sopenharmony_ci .cra_name = "des3_ede", 3588c2ecf20Sopenharmony_ci .cra_driver_name = "des3_ede-sparc64", 3598c2ecf20Sopenharmony_ci .cra_priority = SPARC_CR_OPCODE_PRIORITY, 3608c2ecf20Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 3618c2ecf20Sopenharmony_ci .cra_blocksize = DES3_EDE_BLOCK_SIZE, 3628c2ecf20Sopenharmony_ci .cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx), 3638c2ecf20Sopenharmony_ci .cra_alignmask = 7, 3648c2ecf20Sopenharmony_ci .cra_module = THIS_MODULE, 3658c2ecf20Sopenharmony_ci .cra_u = { 3668c2ecf20Sopenharmony_ci .cipher = { 3678c2ecf20Sopenharmony_ci .cia_min_keysize = DES3_EDE_KEY_SIZE, 3688c2ecf20Sopenharmony_ci .cia_max_keysize = DES3_EDE_KEY_SIZE, 3698c2ecf20Sopenharmony_ci .cia_setkey = des3_ede_set_key, 3708c2ecf20Sopenharmony_ci .cia_encrypt = sparc_des3_ede_encrypt, 3718c2ecf20Sopenharmony_ci .cia_decrypt = sparc_des3_ede_decrypt 3728c2ecf20Sopenharmony_ci } 3738c2ecf20Sopenharmony_ci } 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci}; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_cistatic struct skcipher_alg skcipher_algs[] = { 3788c2ecf20Sopenharmony_ci { 3798c2ecf20Sopenharmony_ci .base.cra_name = "ecb(des)", 3808c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-des-sparc64", 3818c2ecf20Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 3828c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 3838c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des_sparc64_ctx), 3848c2ecf20Sopenharmony_ci .base.cra_alignmask = 7, 3858c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 3868c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 3878c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 3888c2ecf20Sopenharmony_ci .setkey = des_set_key_skcipher, 3898c2ecf20Sopenharmony_ci .encrypt = ecb_encrypt, 3908c2ecf20Sopenharmony_ci .decrypt = ecb_decrypt, 3918c2ecf20Sopenharmony_ci }, { 3928c2ecf20Sopenharmony_ci .base.cra_name = "cbc(des)", 3938c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-des-sparc64", 3948c2ecf20Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 3958c2ecf20Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 3968c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des_sparc64_ctx), 3978c2ecf20Sopenharmony_ci .base.cra_alignmask = 7, 3988c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 3998c2ecf20Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 4008c2ecf20Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 4018c2ecf20Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 4028c2ecf20Sopenharmony_ci .setkey = des_set_key_skcipher, 4038c2ecf20Sopenharmony_ci .encrypt = cbc_encrypt, 4048c2ecf20Sopenharmony_ci .decrypt = cbc_decrypt, 4058c2ecf20Sopenharmony_ci }, { 4068c2ecf20Sopenharmony_ci .base.cra_name = "ecb(des3_ede)", 4078c2ecf20Sopenharmony_ci .base.cra_driver_name = "ecb-des3_ede-sparc64", 4088c2ecf20Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 4098c2ecf20Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 4108c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx), 4118c2ecf20Sopenharmony_ci .base.cra_alignmask = 7, 4128c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 4138c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 4148c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 4158c2ecf20Sopenharmony_ci .setkey = des3_ede_set_key_skcipher, 4168c2ecf20Sopenharmony_ci .encrypt = ecb3_encrypt, 4178c2ecf20Sopenharmony_ci .decrypt = ecb3_decrypt, 4188c2ecf20Sopenharmony_ci }, { 4198c2ecf20Sopenharmony_ci .base.cra_name = "cbc(des3_ede)", 4208c2ecf20Sopenharmony_ci .base.cra_driver_name = "cbc-des3_ede-sparc64", 4218c2ecf20Sopenharmony_ci .base.cra_priority = SPARC_CR_OPCODE_PRIORITY, 4228c2ecf20Sopenharmony_ci .base.cra_blocksize = DES3_EDE_BLOCK_SIZE, 4238c2ecf20Sopenharmony_ci .base.cra_ctxsize = sizeof(struct des3_ede_sparc64_ctx), 4248c2ecf20Sopenharmony_ci .base.cra_alignmask = 7, 4258c2ecf20Sopenharmony_ci .base.cra_module = THIS_MODULE, 4268c2ecf20Sopenharmony_ci .min_keysize = DES3_EDE_KEY_SIZE, 4278c2ecf20Sopenharmony_ci .max_keysize = DES3_EDE_KEY_SIZE, 4288c2ecf20Sopenharmony_ci .ivsize = DES3_EDE_BLOCK_SIZE, 4298c2ecf20Sopenharmony_ci .setkey = des3_ede_set_key_skcipher, 4308c2ecf20Sopenharmony_ci .encrypt = cbc3_encrypt, 4318c2ecf20Sopenharmony_ci .decrypt = cbc3_decrypt, 4328c2ecf20Sopenharmony_ci } 4338c2ecf20Sopenharmony_ci}; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic bool __init sparc64_has_des_opcode(void) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci unsigned long cfr; 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci if (!(sparc64_elf_hwcap & HWCAP_SPARC_CRYPTO)) 4408c2ecf20Sopenharmony_ci return false; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci __asm__ __volatile__("rd %%asr26, %0" : "=r" (cfr)); 4438c2ecf20Sopenharmony_ci if (!(cfr & CFR_DES)) 4448c2ecf20Sopenharmony_ci return false; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci return true; 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_cistatic int __init des_sparc64_mod_init(void) 4508c2ecf20Sopenharmony_ci{ 4518c2ecf20Sopenharmony_ci int err; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci if (!sparc64_has_des_opcode()) { 4548c2ecf20Sopenharmony_ci pr_info("sparc64 des opcodes not available.\n"); 4558c2ecf20Sopenharmony_ci return -ENODEV; 4568c2ecf20Sopenharmony_ci } 4578c2ecf20Sopenharmony_ci pr_info("Using sparc64 des opcodes optimized DES implementation\n"); 4588c2ecf20Sopenharmony_ci err = crypto_register_algs(cipher_algs, ARRAY_SIZE(cipher_algs)); 4598c2ecf20Sopenharmony_ci if (err) 4608c2ecf20Sopenharmony_ci return err; 4618c2ecf20Sopenharmony_ci err = crypto_register_skciphers(skcipher_algs, 4628c2ecf20Sopenharmony_ci ARRAY_SIZE(skcipher_algs)); 4638c2ecf20Sopenharmony_ci if (err) 4648c2ecf20Sopenharmony_ci crypto_unregister_algs(cipher_algs, ARRAY_SIZE(cipher_algs)); 4658c2ecf20Sopenharmony_ci return err; 4668c2ecf20Sopenharmony_ci} 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_cistatic void __exit des_sparc64_mod_fini(void) 4698c2ecf20Sopenharmony_ci{ 4708c2ecf20Sopenharmony_ci crypto_unregister_algs(cipher_algs, ARRAY_SIZE(cipher_algs)); 4718c2ecf20Sopenharmony_ci crypto_unregister_skciphers(skcipher_algs, ARRAY_SIZE(skcipher_algs)); 4728c2ecf20Sopenharmony_ci} 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cimodule_init(des_sparc64_mod_init); 4758c2ecf20Sopenharmony_cimodule_exit(des_sparc64_mod_fini); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 4788c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms, sparc64 des opcode accelerated"); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("des"); 4818c2ecf20Sopenharmony_ciMODULE_ALIAS_CRYPTO("des3_ede"); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci#include "crop_devid.c" 484