162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Cryptographic API. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * s390 implementation of the DES Cipher Algorithm. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright IBM Corp. 2003, 2011 862306a36Sopenharmony_ci * Author(s): Thomas Spatzier 962306a36Sopenharmony_ci * Jan Glauber (jan.glauber@de.ibm.com) 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/init.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/cpufeature.h> 1562306a36Sopenharmony_ci#include <linux/crypto.h> 1662306a36Sopenharmony_ci#include <linux/fips.h> 1762306a36Sopenharmony_ci#include <linux/mutex.h> 1862306a36Sopenharmony_ci#include <crypto/algapi.h> 1962306a36Sopenharmony_ci#include <crypto/internal/des.h> 2062306a36Sopenharmony_ci#include <crypto/internal/skcipher.h> 2162306a36Sopenharmony_ci#include <asm/cpacf.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#define DES3_KEY_SIZE (3 * DES_KEY_SIZE) 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistatic u8 *ctrblk; 2662306a36Sopenharmony_cistatic DEFINE_MUTEX(ctrblk_lock); 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic cpacf_mask_t km_functions, kmc_functions, kmctr_functions; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct s390_des_ctx { 3162306a36Sopenharmony_ci u8 iv[DES_BLOCK_SIZE]; 3262306a36Sopenharmony_ci u8 key[DES3_KEY_SIZE]; 3362306a36Sopenharmony_ci}; 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistatic int des_setkey(struct crypto_tfm *tfm, const u8 *key, 3662306a36Sopenharmony_ci unsigned int key_len) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 3962306a36Sopenharmony_ci int err; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci err = crypto_des_verify_key(tfm, key); 4262306a36Sopenharmony_ci if (err) 4362306a36Sopenharmony_ci return err; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci memcpy(ctx->key, key, key_len); 4662306a36Sopenharmony_ci return 0; 4762306a36Sopenharmony_ci} 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic int des_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key, 5062306a36Sopenharmony_ci unsigned int key_len) 5162306a36Sopenharmony_ci{ 5262306a36Sopenharmony_ci return des_setkey(crypto_skcipher_tfm(tfm), key, key_len); 5362306a36Sopenharmony_ci} 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_cistatic void s390_des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 5662306a36Sopenharmony_ci{ 5762306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE); 6062306a36Sopenharmony_ci} 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistatic void s390_des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 6362306a36Sopenharmony_ci{ 6462306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT, 6762306a36Sopenharmony_ci ctx->key, out, in, DES_BLOCK_SIZE); 6862306a36Sopenharmony_ci} 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic struct crypto_alg des_alg = { 7162306a36Sopenharmony_ci .cra_name = "des", 7262306a36Sopenharmony_ci .cra_driver_name = "des-s390", 7362306a36Sopenharmony_ci .cra_priority = 300, 7462306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 7562306a36Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 7662306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct s390_des_ctx), 7762306a36Sopenharmony_ci .cra_module = THIS_MODULE, 7862306a36Sopenharmony_ci .cra_u = { 7962306a36Sopenharmony_ci .cipher = { 8062306a36Sopenharmony_ci .cia_min_keysize = DES_KEY_SIZE, 8162306a36Sopenharmony_ci .cia_max_keysize = DES_KEY_SIZE, 8262306a36Sopenharmony_ci .cia_setkey = des_setkey, 8362306a36Sopenharmony_ci .cia_encrypt = s390_des_encrypt, 8462306a36Sopenharmony_ci .cia_decrypt = s390_des_decrypt, 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci } 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_cistatic int ecb_desall_crypt(struct skcipher_request *req, unsigned long fc) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 9262306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm); 9362306a36Sopenharmony_ci struct skcipher_walk walk; 9462306a36Sopenharmony_ci unsigned int nbytes, n; 9562306a36Sopenharmony_ci int ret; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci ret = skcipher_walk_virt(&walk, req, false); 9862306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 9962306a36Sopenharmony_ci /* only use complete blocks */ 10062306a36Sopenharmony_ci n = nbytes & ~(DES_BLOCK_SIZE - 1); 10162306a36Sopenharmony_ci cpacf_km(fc, ctx->key, walk.dst.virt.addr, 10262306a36Sopenharmony_ci walk.src.virt.addr, n); 10362306a36Sopenharmony_ci ret = skcipher_walk_done(&walk, nbytes - n); 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci return ret; 10662306a36Sopenharmony_ci} 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic int cbc_desall_crypt(struct skcipher_request *req, unsigned long fc) 10962306a36Sopenharmony_ci{ 11062306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 11162306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm); 11262306a36Sopenharmony_ci struct skcipher_walk walk; 11362306a36Sopenharmony_ci unsigned int nbytes, n; 11462306a36Sopenharmony_ci int ret; 11562306a36Sopenharmony_ci struct { 11662306a36Sopenharmony_ci u8 iv[DES_BLOCK_SIZE]; 11762306a36Sopenharmony_ci u8 key[DES3_KEY_SIZE]; 11862306a36Sopenharmony_ci } param; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci ret = skcipher_walk_virt(&walk, req, false); 12162306a36Sopenharmony_ci if (ret) 12262306a36Sopenharmony_ci return ret; 12362306a36Sopenharmony_ci memcpy(param.iv, walk.iv, DES_BLOCK_SIZE); 12462306a36Sopenharmony_ci memcpy(param.key, ctx->key, DES3_KEY_SIZE); 12562306a36Sopenharmony_ci while ((nbytes = walk.nbytes) != 0) { 12662306a36Sopenharmony_ci /* only use complete blocks */ 12762306a36Sopenharmony_ci n = nbytes & ~(DES_BLOCK_SIZE - 1); 12862306a36Sopenharmony_ci cpacf_kmc(fc, ¶m, walk.dst.virt.addr, 12962306a36Sopenharmony_ci walk.src.virt.addr, n); 13062306a36Sopenharmony_ci memcpy(walk.iv, param.iv, DES_BLOCK_SIZE); 13162306a36Sopenharmony_ci ret = skcipher_walk_done(&walk, nbytes - n); 13262306a36Sopenharmony_ci } 13362306a36Sopenharmony_ci return ret; 13462306a36Sopenharmony_ci} 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic int ecb_des_encrypt(struct skcipher_request *req) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci return ecb_desall_crypt(req, CPACF_KM_DEA); 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic int ecb_des_decrypt(struct skcipher_request *req) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci return ecb_desall_crypt(req, CPACF_KM_DEA | CPACF_DECRYPT); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic struct skcipher_alg ecb_des_alg = { 14762306a36Sopenharmony_ci .base.cra_name = "ecb(des)", 14862306a36Sopenharmony_ci .base.cra_driver_name = "ecb-des-s390", 14962306a36Sopenharmony_ci .base.cra_priority = 400, /* combo: des + ecb */ 15062306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 15162306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct s390_des_ctx), 15262306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 15362306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 15462306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 15562306a36Sopenharmony_ci .setkey = des_setkey_skcipher, 15662306a36Sopenharmony_ci .encrypt = ecb_des_encrypt, 15762306a36Sopenharmony_ci .decrypt = ecb_des_decrypt, 15862306a36Sopenharmony_ci}; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic int cbc_des_encrypt(struct skcipher_request *req) 16162306a36Sopenharmony_ci{ 16262306a36Sopenharmony_ci return cbc_desall_crypt(req, CPACF_KMC_DEA); 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic int cbc_des_decrypt(struct skcipher_request *req) 16662306a36Sopenharmony_ci{ 16762306a36Sopenharmony_ci return cbc_desall_crypt(req, CPACF_KMC_DEA | CPACF_DECRYPT); 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic struct skcipher_alg cbc_des_alg = { 17162306a36Sopenharmony_ci .base.cra_name = "cbc(des)", 17262306a36Sopenharmony_ci .base.cra_driver_name = "cbc-des-s390", 17362306a36Sopenharmony_ci .base.cra_priority = 400, /* combo: des + cbc */ 17462306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 17562306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct s390_des_ctx), 17662306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 17762306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 17862306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 17962306a36Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 18062306a36Sopenharmony_ci .setkey = des_setkey_skcipher, 18162306a36Sopenharmony_ci .encrypt = cbc_des_encrypt, 18262306a36Sopenharmony_ci .decrypt = cbc_des_decrypt, 18362306a36Sopenharmony_ci}; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci/* 18662306a36Sopenharmony_ci * RFC2451: 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * For DES-EDE3, there is no known need to reject weak or 18962306a36Sopenharmony_ci * complementation keys. Any weakness is obviated by the use of 19062306a36Sopenharmony_ci * multiple keys. 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * However, if the first two or last two independent 64-bit keys are 19362306a36Sopenharmony_ci * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the 19462306a36Sopenharmony_ci * same as DES. Implementers MUST reject keys that exhibit this 19562306a36Sopenharmony_ci * property. 19662306a36Sopenharmony_ci * 19762306a36Sopenharmony_ci * In fips mode additionally check for all 3 keys are unique. 19862306a36Sopenharmony_ci * 19962306a36Sopenharmony_ci */ 20062306a36Sopenharmony_cistatic int des3_setkey(struct crypto_tfm *tfm, const u8 *key, 20162306a36Sopenharmony_ci unsigned int key_len) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 20462306a36Sopenharmony_ci int err; 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci err = crypto_des3_ede_verify_key(tfm, key); 20762306a36Sopenharmony_ci if (err) 20862306a36Sopenharmony_ci return err; 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_ci memcpy(ctx->key, key, key_len); 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic int des3_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key, 21562306a36Sopenharmony_ci unsigned int key_len) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci return des3_setkey(crypto_skcipher_tfm(tfm), key, key_len); 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_cistatic void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 22162306a36Sopenharmony_ci{ 22262306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE); 22562306a36Sopenharmony_ci} 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_cistatic void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT, 23262306a36Sopenharmony_ci ctx->key, dst, src, DES_BLOCK_SIZE); 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic struct crypto_alg des3_alg = { 23662306a36Sopenharmony_ci .cra_name = "des3_ede", 23762306a36Sopenharmony_ci .cra_driver_name = "des3_ede-s390", 23862306a36Sopenharmony_ci .cra_priority = 300, 23962306a36Sopenharmony_ci .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 24062306a36Sopenharmony_ci .cra_blocksize = DES_BLOCK_SIZE, 24162306a36Sopenharmony_ci .cra_ctxsize = sizeof(struct s390_des_ctx), 24262306a36Sopenharmony_ci .cra_module = THIS_MODULE, 24362306a36Sopenharmony_ci .cra_u = { 24462306a36Sopenharmony_ci .cipher = { 24562306a36Sopenharmony_ci .cia_min_keysize = DES3_KEY_SIZE, 24662306a36Sopenharmony_ci .cia_max_keysize = DES3_KEY_SIZE, 24762306a36Sopenharmony_ci .cia_setkey = des3_setkey, 24862306a36Sopenharmony_ci .cia_encrypt = des3_encrypt, 24962306a36Sopenharmony_ci .cia_decrypt = des3_decrypt, 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci}; 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic int ecb_des3_encrypt(struct skcipher_request *req) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci return ecb_desall_crypt(req, CPACF_KM_TDEA_192); 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cistatic int ecb_des3_decrypt(struct skcipher_request *req) 26062306a36Sopenharmony_ci{ 26162306a36Sopenharmony_ci return ecb_desall_crypt(req, CPACF_KM_TDEA_192 | CPACF_DECRYPT); 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistatic struct skcipher_alg ecb_des3_alg = { 26562306a36Sopenharmony_ci .base.cra_name = "ecb(des3_ede)", 26662306a36Sopenharmony_ci .base.cra_driver_name = "ecb-des3_ede-s390", 26762306a36Sopenharmony_ci .base.cra_priority = 400, /* combo: des3 + ecb */ 26862306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 26962306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct s390_des_ctx), 27062306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 27162306a36Sopenharmony_ci .min_keysize = DES3_KEY_SIZE, 27262306a36Sopenharmony_ci .max_keysize = DES3_KEY_SIZE, 27362306a36Sopenharmony_ci .setkey = des3_setkey_skcipher, 27462306a36Sopenharmony_ci .encrypt = ecb_des3_encrypt, 27562306a36Sopenharmony_ci .decrypt = ecb_des3_decrypt, 27662306a36Sopenharmony_ci}; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_cistatic int cbc_des3_encrypt(struct skcipher_request *req) 27962306a36Sopenharmony_ci{ 28062306a36Sopenharmony_ci return cbc_desall_crypt(req, CPACF_KMC_TDEA_192); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_cistatic int cbc_des3_decrypt(struct skcipher_request *req) 28462306a36Sopenharmony_ci{ 28562306a36Sopenharmony_ci return cbc_desall_crypt(req, CPACF_KMC_TDEA_192 | CPACF_DECRYPT); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_cistatic struct skcipher_alg cbc_des3_alg = { 28962306a36Sopenharmony_ci .base.cra_name = "cbc(des3_ede)", 29062306a36Sopenharmony_ci .base.cra_driver_name = "cbc-des3_ede-s390", 29162306a36Sopenharmony_ci .base.cra_priority = 400, /* combo: des3 + cbc */ 29262306a36Sopenharmony_ci .base.cra_blocksize = DES_BLOCK_SIZE, 29362306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct s390_des_ctx), 29462306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 29562306a36Sopenharmony_ci .min_keysize = DES3_KEY_SIZE, 29662306a36Sopenharmony_ci .max_keysize = DES3_KEY_SIZE, 29762306a36Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 29862306a36Sopenharmony_ci .setkey = des3_setkey_skcipher, 29962306a36Sopenharmony_ci .encrypt = cbc_des3_encrypt, 30062306a36Sopenharmony_ci .decrypt = cbc_des3_decrypt, 30162306a36Sopenharmony_ci}; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci unsigned int i, n; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci /* align to block size, max. PAGE_SIZE */ 30862306a36Sopenharmony_ci n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); 30962306a36Sopenharmony_ci memcpy(ctrptr, iv, DES_BLOCK_SIZE); 31062306a36Sopenharmony_ci for (i = (n / DES_BLOCK_SIZE) - 1; i > 0; i--) { 31162306a36Sopenharmony_ci memcpy(ctrptr + DES_BLOCK_SIZE, ctrptr, DES_BLOCK_SIZE); 31262306a36Sopenharmony_ci crypto_inc(ctrptr + DES_BLOCK_SIZE, DES_BLOCK_SIZE); 31362306a36Sopenharmony_ci ctrptr += DES_BLOCK_SIZE; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci return n; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic int ctr_desall_crypt(struct skcipher_request *req, unsigned long fc) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 32162306a36Sopenharmony_ci struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm); 32262306a36Sopenharmony_ci u8 buf[DES_BLOCK_SIZE], *ctrptr; 32362306a36Sopenharmony_ci struct skcipher_walk walk; 32462306a36Sopenharmony_ci unsigned int n, nbytes; 32562306a36Sopenharmony_ci int ret, locked; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci locked = mutex_trylock(&ctrblk_lock); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci ret = skcipher_walk_virt(&walk, req, false); 33062306a36Sopenharmony_ci while ((nbytes = walk.nbytes) >= DES_BLOCK_SIZE) { 33162306a36Sopenharmony_ci n = DES_BLOCK_SIZE; 33262306a36Sopenharmony_ci if (nbytes >= 2*DES_BLOCK_SIZE && locked) 33362306a36Sopenharmony_ci n = __ctrblk_init(ctrblk, walk.iv, nbytes); 33462306a36Sopenharmony_ci ctrptr = (n > DES_BLOCK_SIZE) ? ctrblk : walk.iv; 33562306a36Sopenharmony_ci cpacf_kmctr(fc, ctx->key, walk.dst.virt.addr, 33662306a36Sopenharmony_ci walk.src.virt.addr, n, ctrptr); 33762306a36Sopenharmony_ci if (ctrptr == ctrblk) 33862306a36Sopenharmony_ci memcpy(walk.iv, ctrptr + n - DES_BLOCK_SIZE, 33962306a36Sopenharmony_ci DES_BLOCK_SIZE); 34062306a36Sopenharmony_ci crypto_inc(walk.iv, DES_BLOCK_SIZE); 34162306a36Sopenharmony_ci ret = skcipher_walk_done(&walk, nbytes - n); 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci if (locked) 34462306a36Sopenharmony_ci mutex_unlock(&ctrblk_lock); 34562306a36Sopenharmony_ci /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ 34662306a36Sopenharmony_ci if (nbytes) { 34762306a36Sopenharmony_ci cpacf_kmctr(fc, ctx->key, buf, walk.src.virt.addr, 34862306a36Sopenharmony_ci DES_BLOCK_SIZE, walk.iv); 34962306a36Sopenharmony_ci memcpy(walk.dst.virt.addr, buf, nbytes); 35062306a36Sopenharmony_ci crypto_inc(walk.iv, DES_BLOCK_SIZE); 35162306a36Sopenharmony_ci ret = skcipher_walk_done(&walk, 0); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci return ret; 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic int ctr_des_crypt(struct skcipher_request *req) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci return ctr_desall_crypt(req, CPACF_KMCTR_DEA); 35962306a36Sopenharmony_ci} 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic struct skcipher_alg ctr_des_alg = { 36262306a36Sopenharmony_ci .base.cra_name = "ctr(des)", 36362306a36Sopenharmony_ci .base.cra_driver_name = "ctr-des-s390", 36462306a36Sopenharmony_ci .base.cra_priority = 400, /* combo: des + ctr */ 36562306a36Sopenharmony_ci .base.cra_blocksize = 1, 36662306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct s390_des_ctx), 36762306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 36862306a36Sopenharmony_ci .min_keysize = DES_KEY_SIZE, 36962306a36Sopenharmony_ci .max_keysize = DES_KEY_SIZE, 37062306a36Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 37162306a36Sopenharmony_ci .setkey = des_setkey_skcipher, 37262306a36Sopenharmony_ci .encrypt = ctr_des_crypt, 37362306a36Sopenharmony_ci .decrypt = ctr_des_crypt, 37462306a36Sopenharmony_ci .chunksize = DES_BLOCK_SIZE, 37562306a36Sopenharmony_ci}; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_cistatic int ctr_des3_crypt(struct skcipher_request *req) 37862306a36Sopenharmony_ci{ 37962306a36Sopenharmony_ci return ctr_desall_crypt(req, CPACF_KMCTR_TDEA_192); 38062306a36Sopenharmony_ci} 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic struct skcipher_alg ctr_des3_alg = { 38362306a36Sopenharmony_ci .base.cra_name = "ctr(des3_ede)", 38462306a36Sopenharmony_ci .base.cra_driver_name = "ctr-des3_ede-s390", 38562306a36Sopenharmony_ci .base.cra_priority = 400, /* combo: des3 + ede */ 38662306a36Sopenharmony_ci .base.cra_blocksize = 1, 38762306a36Sopenharmony_ci .base.cra_ctxsize = sizeof(struct s390_des_ctx), 38862306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 38962306a36Sopenharmony_ci .min_keysize = DES3_KEY_SIZE, 39062306a36Sopenharmony_ci .max_keysize = DES3_KEY_SIZE, 39162306a36Sopenharmony_ci .ivsize = DES_BLOCK_SIZE, 39262306a36Sopenharmony_ci .setkey = des3_setkey_skcipher, 39362306a36Sopenharmony_ci .encrypt = ctr_des3_crypt, 39462306a36Sopenharmony_ci .decrypt = ctr_des3_crypt, 39562306a36Sopenharmony_ci .chunksize = DES_BLOCK_SIZE, 39662306a36Sopenharmony_ci}; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic struct crypto_alg *des_s390_algs_ptr[2]; 39962306a36Sopenharmony_cistatic int des_s390_algs_num; 40062306a36Sopenharmony_cistatic struct skcipher_alg *des_s390_skciphers_ptr[6]; 40162306a36Sopenharmony_cistatic int des_s390_skciphers_num; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic int des_s390_register_alg(struct crypto_alg *alg) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci int ret; 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci ret = crypto_register_alg(alg); 40862306a36Sopenharmony_ci if (!ret) 40962306a36Sopenharmony_ci des_s390_algs_ptr[des_s390_algs_num++] = alg; 41062306a36Sopenharmony_ci return ret; 41162306a36Sopenharmony_ci} 41262306a36Sopenharmony_ci 41362306a36Sopenharmony_cistatic int des_s390_register_skcipher(struct skcipher_alg *alg) 41462306a36Sopenharmony_ci{ 41562306a36Sopenharmony_ci int ret; 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_ci ret = crypto_register_skcipher(alg); 41862306a36Sopenharmony_ci if (!ret) 41962306a36Sopenharmony_ci des_s390_skciphers_ptr[des_s390_skciphers_num++] = alg; 42062306a36Sopenharmony_ci return ret; 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_cistatic void des_s390_exit(void) 42462306a36Sopenharmony_ci{ 42562306a36Sopenharmony_ci while (des_s390_algs_num--) 42662306a36Sopenharmony_ci crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]); 42762306a36Sopenharmony_ci while (des_s390_skciphers_num--) 42862306a36Sopenharmony_ci crypto_unregister_skcipher(des_s390_skciphers_ptr[des_s390_skciphers_num]); 42962306a36Sopenharmony_ci if (ctrblk) 43062306a36Sopenharmony_ci free_page((unsigned long) ctrblk); 43162306a36Sopenharmony_ci} 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cistatic int __init des_s390_init(void) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci int ret; 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* Query available functions for KM, KMC and KMCTR */ 43862306a36Sopenharmony_ci cpacf_query(CPACF_KM, &km_functions); 43962306a36Sopenharmony_ci cpacf_query(CPACF_KMC, &kmc_functions); 44062306a36Sopenharmony_ci cpacf_query(CPACF_KMCTR, &kmctr_functions); 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) { 44362306a36Sopenharmony_ci ret = des_s390_register_alg(&des_alg); 44462306a36Sopenharmony_ci if (ret) 44562306a36Sopenharmony_ci goto out_err; 44662306a36Sopenharmony_ci ret = des_s390_register_skcipher(&ecb_des_alg); 44762306a36Sopenharmony_ci if (ret) 44862306a36Sopenharmony_ci goto out_err; 44962306a36Sopenharmony_ci } 45062306a36Sopenharmony_ci if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) { 45162306a36Sopenharmony_ci ret = des_s390_register_skcipher(&cbc_des_alg); 45262306a36Sopenharmony_ci if (ret) 45362306a36Sopenharmony_ci goto out_err; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) { 45662306a36Sopenharmony_ci ret = des_s390_register_alg(&des3_alg); 45762306a36Sopenharmony_ci if (ret) 45862306a36Sopenharmony_ci goto out_err; 45962306a36Sopenharmony_ci ret = des_s390_register_skcipher(&ecb_des3_alg); 46062306a36Sopenharmony_ci if (ret) 46162306a36Sopenharmony_ci goto out_err; 46262306a36Sopenharmony_ci } 46362306a36Sopenharmony_ci if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) { 46462306a36Sopenharmony_ci ret = des_s390_register_skcipher(&cbc_des3_alg); 46562306a36Sopenharmony_ci if (ret) 46662306a36Sopenharmony_ci goto out_err; 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_ci if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) || 47062306a36Sopenharmony_ci cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 47162306a36Sopenharmony_ci ctrblk = (u8 *) __get_free_page(GFP_KERNEL); 47262306a36Sopenharmony_ci if (!ctrblk) { 47362306a36Sopenharmony_ci ret = -ENOMEM; 47462306a36Sopenharmony_ci goto out_err; 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) { 47962306a36Sopenharmony_ci ret = des_s390_register_skcipher(&ctr_des_alg); 48062306a36Sopenharmony_ci if (ret) 48162306a36Sopenharmony_ci goto out_err; 48262306a36Sopenharmony_ci } 48362306a36Sopenharmony_ci if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 48462306a36Sopenharmony_ci ret = des_s390_register_skcipher(&ctr_des3_alg); 48562306a36Sopenharmony_ci if (ret) 48662306a36Sopenharmony_ci goto out_err; 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci return 0; 49062306a36Sopenharmony_ciout_err: 49162306a36Sopenharmony_ci des_s390_exit(); 49262306a36Sopenharmony_ci return ret; 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cimodule_cpu_feature_match(S390_CPU_FEATURE_MSA, des_s390_init); 49662306a36Sopenharmony_cimodule_exit(des_s390_exit); 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des"); 49962306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("des3_ede"); 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 50262306a36Sopenharmony_ciMODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); 503