120a884f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+ 2c1e26e1eSJan Glauber /* 3c1e26e1eSJan Glauber * Cryptographic API. 4c1e26e1eSJan Glauber * 5c1e26e1eSJan Glauber * s390 implementation of the DES Cipher Algorithm. 6c1e26e1eSJan Glauber * 70200f3ecSGerald Schaefer * Copyright IBM Corp. 2003, 2011 886aa9fc2SJan Glauber * Author(s): Thomas Spatzier 986aa9fc2SJan Glauber * Jan Glauber (jan.glauber@de.ibm.com) 10c1e26e1eSJan Glauber */ 11a9e62fadSHerbert Xu 12c1e26e1eSJan Glauber #include <linux/init.h> 13c1e26e1eSJan Glauber #include <linux/module.h> 14d05377c1SHendrik Brueckner #include <linux/cpufeature.h> 151efbd15cSJan Glauber #include <linux/crypto.h> 16f3d3584fSMatthew Rosato #include <linux/fips.h> 171efbd15cSJan Glauber #include <crypto/algapi.h> 181efbd15cSJan Glauber #include <crypto/des.h> 19c7d4d259SMartin Schwidefsky #include <asm/cpacf.h> 20c1e26e1eSJan Glauber 2198971f84SJan Glauber #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) 22c1e26e1eSJan Glauber 230200f3ecSGerald Schaefer static u8 *ctrblk; 24ee97dc7dSHarald Freudenberger static DEFINE_SPINLOCK(ctrblk_lock); 250200f3ecSGerald Schaefer 2669c0e360SMartin Schwidefsky static cpacf_mask_t km_functions, kmc_functions, kmctr_functions; 2769c0e360SMartin Schwidefsky 2898971f84SJan Glauber struct s390_des_ctx { 29c1e26e1eSJan Glauber u8 iv[DES_BLOCK_SIZE]; 3098971f84SJan Glauber u8 key[DES3_KEY_SIZE]; 31c1e26e1eSJan Glauber }; 32c1e26e1eSJan Glauber 336c2bb98bSHerbert Xu static int des_setkey(struct crypto_tfm *tfm, const u8 *key, 3498971f84SJan Glauber unsigned int key_len) 35c1e26e1eSJan Glauber { 3698971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 371efbd15cSJan Glauber u32 tmp[DES_EXPKEY_WORDS]; 38c1e26e1eSJan Glauber 391efbd15cSJan Glauber /* check for weak keys */ 4069c0e360SMartin Schwidefsky if (!des_ekey(tmp, key) && 41231baecdSEric Biggers (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { 4269c0e360SMartin Schwidefsky tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; 431efbd15cSJan Glauber return -EINVAL; 441efbd15cSJan Glauber } 451efbd15cSJan Glauber 4698971f84SJan Glauber memcpy(ctx->key, key, key_len); 471efbd15cSJan Glauber return 0; 48c1e26e1eSJan Glauber } 49c1e26e1eSJan Glauber 506c2bb98bSHerbert Xu static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 51c1e26e1eSJan Glauber { 5298971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 53c1e26e1eSJan Glauber 54edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE); 55c1e26e1eSJan Glauber } 56c1e26e1eSJan Glauber 576c2bb98bSHerbert Xu static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 58c1e26e1eSJan Glauber { 5998971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 60c1e26e1eSJan Glauber 61edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT, 62edc63a37SMartin Schwidefsky ctx->key, out, in, DES_BLOCK_SIZE); 63b8dc6038SJan Glauber } 64b8dc6038SJan Glauber 65c1e26e1eSJan Glauber static struct crypto_alg des_alg = { 66c1e26e1eSJan Glauber .cra_name = "des", 6765b75c36SHerbert Xu .cra_driver_name = "des-s390", 68c7d4d259SMartin Schwidefsky .cra_priority = 300, 69c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 70c1e26e1eSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 7198971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 72c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 73c1357833SJan Glauber .cra_u = { 74c1357833SJan Glauber .cipher = { 75c1e26e1eSJan Glauber .cia_min_keysize = DES_KEY_SIZE, 76c1e26e1eSJan Glauber .cia_max_keysize = DES_KEY_SIZE, 77c1e26e1eSJan Glauber .cia_setkey = des_setkey, 78c1e26e1eSJan Glauber .cia_encrypt = des_encrypt, 79b8dc6038SJan Glauber .cia_decrypt = des_decrypt, 80c1357833SJan Glauber } 81c1357833SJan Glauber } 82c1e26e1eSJan Glauber }; 83c1e26e1eSJan Glauber 847bac4f5bSMartin Schwidefsky static int ecb_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, 85adc3fcf1SHarald Freudenberger struct blkcipher_walk *walk) 86a9e62fadSHerbert Xu { 87adc3fcf1SHarald Freudenberger struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 887bac4f5bSMartin Schwidefsky unsigned int nbytes, n; 897bac4f5bSMartin Schwidefsky int ret; 907bac4f5bSMartin Schwidefsky 917bac4f5bSMartin Schwidefsky ret = blkcipher_walk_virt(desc, walk); 927bac4f5bSMartin Schwidefsky while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 937bac4f5bSMartin Schwidefsky /* only use complete blocks */ 947bac4f5bSMartin Schwidefsky n = nbytes & ~(DES_BLOCK_SIZE - 1); 957bac4f5bSMartin Schwidefsky cpacf_km(fc, ctx->key, walk->dst.virt.addr, 967bac4f5bSMartin Schwidefsky walk->src.virt.addr, n); 977bac4f5bSMartin Schwidefsky ret = blkcipher_walk_done(desc, walk, nbytes - n); 987bac4f5bSMartin Schwidefsky } 997bac4f5bSMartin Schwidefsky return ret; 1007bac4f5bSMartin Schwidefsky } 1017bac4f5bSMartin Schwidefsky 1027bac4f5bSMartin Schwidefsky static int cbc_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, 1037bac4f5bSMartin Schwidefsky struct blkcipher_walk *walk) 1047bac4f5bSMartin Schwidefsky { 1057bac4f5bSMartin Schwidefsky struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 1067bac4f5bSMartin Schwidefsky unsigned int nbytes, n; 1077bac4f5bSMartin Schwidefsky int ret; 108adc3fcf1SHarald Freudenberger struct { 109adc3fcf1SHarald Freudenberger u8 iv[DES_BLOCK_SIZE]; 110adc3fcf1SHarald Freudenberger u8 key[DES3_KEY_SIZE]; 111adc3fcf1SHarald Freudenberger } param; 112a9e62fadSHerbert Xu 1137bac4f5bSMartin Schwidefsky ret = blkcipher_walk_virt(desc, walk); 114adc3fcf1SHarald Freudenberger memcpy(param.iv, walk->iv, DES_BLOCK_SIZE); 115adc3fcf1SHarald Freudenberger memcpy(param.key, ctx->key, DES3_KEY_SIZE); 1167bac4f5bSMartin Schwidefsky while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 117a9e62fadSHerbert Xu /* only use complete blocks */ 1187bac4f5bSMartin Schwidefsky n = nbytes & ~(DES_BLOCK_SIZE - 1); 1197bac4f5bSMartin Schwidefsky cpacf_kmc(fc, ¶m, walk->dst.virt.addr, 1207bac4f5bSMartin Schwidefsky walk->src.virt.addr, n); 1217bac4f5bSMartin Schwidefsky ret = blkcipher_walk_done(desc, walk, nbytes - n); 1227bac4f5bSMartin Schwidefsky } 123adc3fcf1SHarald Freudenberger memcpy(walk->iv, param.iv, DES_BLOCK_SIZE); 124a9e62fadSHerbert Xu return ret; 125a9e62fadSHerbert Xu } 126a9e62fadSHerbert Xu 127a9e62fadSHerbert Xu static int ecb_des_encrypt(struct blkcipher_desc *desc, 128a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 129a9e62fadSHerbert Xu unsigned int nbytes) 130a9e62fadSHerbert Xu { 131a9e62fadSHerbert Xu struct blkcipher_walk walk; 132a9e62fadSHerbert Xu 133a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 1347bac4f5bSMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA, &walk); 135a9e62fadSHerbert Xu } 136a9e62fadSHerbert Xu 137a9e62fadSHerbert Xu static int ecb_des_decrypt(struct blkcipher_desc *desc, 138a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 139a9e62fadSHerbert Xu unsigned int nbytes) 140a9e62fadSHerbert Xu { 141a9e62fadSHerbert Xu struct blkcipher_walk walk; 142a9e62fadSHerbert Xu 143a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 1447bac4f5bSMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA | CPACF_DECRYPT, &walk); 145a9e62fadSHerbert Xu } 146a9e62fadSHerbert Xu 147a9e62fadSHerbert Xu static struct crypto_alg ecb_des_alg = { 148a9e62fadSHerbert Xu .cra_name = "ecb(des)", 149a9e62fadSHerbert Xu .cra_driver_name = "ecb-des-s390", 150c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ecb */ 151a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 152a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 15398971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 154a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 155a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 156a9e62fadSHerbert Xu .cra_u = { 157a9e62fadSHerbert Xu .blkcipher = { 158a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 159a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 160a9e62fadSHerbert Xu .setkey = des_setkey, 161a9e62fadSHerbert Xu .encrypt = ecb_des_encrypt, 162a9e62fadSHerbert Xu .decrypt = ecb_des_decrypt, 163a9e62fadSHerbert Xu } 164a9e62fadSHerbert Xu } 165a9e62fadSHerbert Xu }; 166a9e62fadSHerbert Xu 167a9e62fadSHerbert Xu static int cbc_des_encrypt(struct blkcipher_desc *desc, 168a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 169a9e62fadSHerbert Xu unsigned int nbytes) 170a9e62fadSHerbert Xu { 171a9e62fadSHerbert Xu struct blkcipher_walk walk; 172a9e62fadSHerbert Xu 173a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 174edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA, &walk); 175a9e62fadSHerbert Xu } 176a9e62fadSHerbert Xu 177a9e62fadSHerbert Xu static int cbc_des_decrypt(struct blkcipher_desc *desc, 178a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 179a9e62fadSHerbert Xu unsigned int nbytes) 180a9e62fadSHerbert Xu { 181a9e62fadSHerbert Xu struct blkcipher_walk walk; 182a9e62fadSHerbert Xu 183a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 184edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA | CPACF_DECRYPT, &walk); 185a9e62fadSHerbert Xu } 186a9e62fadSHerbert Xu 187a9e62fadSHerbert Xu static struct crypto_alg cbc_des_alg = { 188a9e62fadSHerbert Xu .cra_name = "cbc(des)", 189a9e62fadSHerbert Xu .cra_driver_name = "cbc-des-s390", 190c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + cbc */ 191a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 192a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 19398971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 194a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 195a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 196a9e62fadSHerbert Xu .cra_u = { 197a9e62fadSHerbert Xu .blkcipher = { 198a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 199a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 200a9e62fadSHerbert Xu .ivsize = DES_BLOCK_SIZE, 201a9e62fadSHerbert Xu .setkey = des_setkey, 202a9e62fadSHerbert Xu .encrypt = cbc_des_encrypt, 203a9e62fadSHerbert Xu .decrypt = cbc_des_decrypt, 204a9e62fadSHerbert Xu } 205a9e62fadSHerbert Xu } 206a9e62fadSHerbert Xu }; 207a9e62fadSHerbert Xu 208c1e26e1eSJan Glauber /* 209c1e26e1eSJan Glauber * RFC2451: 210c1e26e1eSJan Glauber * 211c1e26e1eSJan Glauber * For DES-EDE3, there is no known need to reject weak or 212c1e26e1eSJan Glauber * complementation keys. Any weakness is obviated by the use of 213c1e26e1eSJan Glauber * multiple keys. 214c1e26e1eSJan Glauber * 215c1e26e1eSJan Glauber * However, if the first two or last two independent 64-bit keys are 216c1e26e1eSJan Glauber * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the 217c1e26e1eSJan Glauber * same as DES. Implementers MUST reject keys that exhibit this 218c1e26e1eSJan Glauber * property. 219c1e26e1eSJan Glauber * 220f3d3584fSMatthew Rosato * In fips mode additinally check for all 3 keys are unique. 221f3d3584fSMatthew Rosato * 222c1e26e1eSJan Glauber */ 22398971f84SJan Glauber static int des3_setkey(struct crypto_tfm *tfm, const u8 *key, 22498971f84SJan Glauber unsigned int key_len) 225c1e26e1eSJan Glauber { 22698971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 22755902d85SHerbert Xu int err; 228c1e26e1eSJan Glauber 22955902d85SHerbert Xu err = __des3_verify_key(&tfm->crt_flags, key); 23055902d85SHerbert Xu if (unlikely(err)) 23155902d85SHerbert Xu return err; 232f3d3584fSMatthew Rosato 23398971f84SJan Glauber memcpy(ctx->key, key, key_len); 234c1e26e1eSJan Glauber return 0; 235c1e26e1eSJan Glauber } 236c1e26e1eSJan Glauber 23798971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 238c1e26e1eSJan Glauber { 23998971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 240c1e26e1eSJan Glauber 241edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE); 242c1e26e1eSJan Glauber } 243c1e26e1eSJan Glauber 24498971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 245c1e26e1eSJan Glauber { 24698971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 247c1e26e1eSJan Glauber 248edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT, 249edc63a37SMartin Schwidefsky ctx->key, dst, src, DES_BLOCK_SIZE); 250c1e26e1eSJan Glauber } 251c1e26e1eSJan Glauber 25298971f84SJan Glauber static struct crypto_alg des3_alg = { 253c1e26e1eSJan Glauber .cra_name = "des3_ede", 25465b75c36SHerbert Xu .cra_driver_name = "des3_ede-s390", 255c7d4d259SMartin Schwidefsky .cra_priority = 300, 256c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2571efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 25898971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 259c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 260c1357833SJan Glauber .cra_u = { 261c1357833SJan Glauber .cipher = { 26298971f84SJan Glauber .cia_min_keysize = DES3_KEY_SIZE, 26398971f84SJan Glauber .cia_max_keysize = DES3_KEY_SIZE, 26498971f84SJan Glauber .cia_setkey = des3_setkey, 26598971f84SJan Glauber .cia_encrypt = des3_encrypt, 26698971f84SJan Glauber .cia_decrypt = des3_decrypt, 267c1357833SJan Glauber } 268c1357833SJan Glauber } 269c1e26e1eSJan Glauber }; 270c1e26e1eSJan Glauber 27198971f84SJan Glauber static int ecb_des3_encrypt(struct blkcipher_desc *desc, 27298971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 27398971f84SJan Glauber unsigned int nbytes) 274a9e62fadSHerbert Xu { 275a9e62fadSHerbert Xu struct blkcipher_walk walk; 276a9e62fadSHerbert Xu 277a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 2787bac4f5bSMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192, &walk); 279a9e62fadSHerbert Xu } 280a9e62fadSHerbert Xu 28198971f84SJan Glauber static int ecb_des3_decrypt(struct blkcipher_desc *desc, 28298971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 28398971f84SJan Glauber unsigned int nbytes) 284a9e62fadSHerbert Xu { 285a9e62fadSHerbert Xu struct blkcipher_walk walk; 286a9e62fadSHerbert Xu 287a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 288edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192 | CPACF_DECRYPT, 2897bac4f5bSMartin Schwidefsky &walk); 290a9e62fadSHerbert Xu } 291a9e62fadSHerbert Xu 29298971f84SJan Glauber static struct crypto_alg ecb_des3_alg = { 293a9e62fadSHerbert Xu .cra_name = "ecb(des3_ede)", 294a9e62fadSHerbert Xu .cra_driver_name = "ecb-des3_ede-s390", 295c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ecb */ 296a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 2971efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 29898971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 299a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 300a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 301a9e62fadSHerbert Xu .cra_u = { 302a9e62fadSHerbert Xu .blkcipher = { 30398971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 30498971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 30598971f84SJan Glauber .setkey = des3_setkey, 30698971f84SJan Glauber .encrypt = ecb_des3_encrypt, 30798971f84SJan Glauber .decrypt = ecb_des3_decrypt, 308a9e62fadSHerbert Xu } 309a9e62fadSHerbert Xu } 310a9e62fadSHerbert Xu }; 311a9e62fadSHerbert Xu 31298971f84SJan Glauber static int cbc_des3_encrypt(struct blkcipher_desc *desc, 31398971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 31498971f84SJan Glauber unsigned int nbytes) 315a9e62fadSHerbert Xu { 316a9e62fadSHerbert Xu struct blkcipher_walk walk; 317a9e62fadSHerbert Xu 318a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 319edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192, &walk); 320a9e62fadSHerbert Xu } 321a9e62fadSHerbert Xu 32298971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc, 32398971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 32498971f84SJan Glauber unsigned int nbytes) 325a9e62fadSHerbert Xu { 326a9e62fadSHerbert Xu struct blkcipher_walk walk; 327a9e62fadSHerbert Xu 328a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 329edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192 | CPACF_DECRYPT, 330edc63a37SMartin Schwidefsky &walk); 331a9e62fadSHerbert Xu } 332a9e62fadSHerbert Xu 33398971f84SJan Glauber static struct crypto_alg cbc_des3_alg = { 334a9e62fadSHerbert Xu .cra_name = "cbc(des3_ede)", 335a9e62fadSHerbert Xu .cra_driver_name = "cbc-des3_ede-s390", 336c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + cbc */ 337a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3381efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 33998971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 340a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 341a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 342a9e62fadSHerbert Xu .cra_u = { 343a9e62fadSHerbert Xu .blkcipher = { 34498971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 34598971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 3461efbd15cSJan Glauber .ivsize = DES_BLOCK_SIZE, 34798971f84SJan Glauber .setkey = des3_setkey, 34898971f84SJan Glauber .encrypt = cbc_des3_encrypt, 34998971f84SJan Glauber .decrypt = cbc_des3_decrypt, 350a9e62fadSHerbert Xu } 351a9e62fadSHerbert Xu } 352a9e62fadSHerbert Xu }; 353a9e62fadSHerbert Xu 3547bac4f5bSMartin Schwidefsky static unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes) 355ee97dc7dSHarald Freudenberger { 356ee97dc7dSHarald Freudenberger unsigned int i, n; 357ee97dc7dSHarald Freudenberger 358ee97dc7dSHarald Freudenberger /* align to block size, max. PAGE_SIZE */ 359ee97dc7dSHarald Freudenberger n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); 3607bac4f5bSMartin Schwidefsky memcpy(ctrptr, iv, DES_BLOCK_SIZE); 3617bac4f5bSMartin Schwidefsky for (i = (n / DES_BLOCK_SIZE) - 1; i > 0; i--) { 3627bac4f5bSMartin Schwidefsky memcpy(ctrptr + DES_BLOCK_SIZE, ctrptr, DES_BLOCK_SIZE); 3637bac4f5bSMartin Schwidefsky crypto_inc(ctrptr + DES_BLOCK_SIZE, DES_BLOCK_SIZE); 3647bac4f5bSMartin Schwidefsky ctrptr += DES_BLOCK_SIZE; 365ee97dc7dSHarald Freudenberger } 366ee97dc7dSHarald Freudenberger return n; 367ee97dc7dSHarald Freudenberger } 368ee97dc7dSHarald Freudenberger 3697bac4f5bSMartin Schwidefsky static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, 370ee97dc7dSHarald Freudenberger struct blkcipher_walk *walk) 3710200f3ecSGerald Schaefer { 3727bac4f5bSMartin Schwidefsky struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 3737bac4f5bSMartin Schwidefsky u8 buf[DES_BLOCK_SIZE], *ctrptr; 374ee97dc7dSHarald Freudenberger unsigned int n, nbytes; 3757bac4f5bSMartin Schwidefsky int ret, locked; 3760200f3ecSGerald Schaefer 3777bac4f5bSMartin Schwidefsky locked = spin_trylock(&ctrblk_lock); 378ee97dc7dSHarald Freudenberger 3797bac4f5bSMartin Schwidefsky ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); 3800200f3ecSGerald Schaefer while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 381ee97dc7dSHarald Freudenberger n = DES_BLOCK_SIZE; 3827bac4f5bSMartin Schwidefsky if (nbytes >= 2*DES_BLOCK_SIZE && locked) 3837bac4f5bSMartin Schwidefsky n = __ctrblk_init(ctrblk, walk->iv, nbytes); 3847bac4f5bSMartin Schwidefsky ctrptr = (n > DES_BLOCK_SIZE) ? ctrblk : walk->iv; 3857bac4f5bSMartin Schwidefsky cpacf_kmctr(fc, ctx->key, walk->dst.virt.addr, 3867bac4f5bSMartin Schwidefsky walk->src.virt.addr, n, ctrptr); 3877bac4f5bSMartin Schwidefsky if (ctrptr == ctrblk) 3887bac4f5bSMartin Schwidefsky memcpy(walk->iv, ctrptr + n - DES_BLOCK_SIZE, 3890200f3ecSGerald Schaefer DES_BLOCK_SIZE); 3907bac4f5bSMartin Schwidefsky crypto_inc(walk->iv, DES_BLOCK_SIZE); 3917bac4f5bSMartin Schwidefsky ret = blkcipher_walk_done(desc, walk, nbytes - n); 3920200f3ecSGerald Schaefer } 3937bac4f5bSMartin Schwidefsky if (locked) 394ee97dc7dSHarald Freudenberger spin_unlock(&ctrblk_lock); 3950200f3ecSGerald Schaefer /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ 3960200f3ecSGerald Schaefer if (nbytes) { 3977bac4f5bSMartin Schwidefsky cpacf_kmctr(fc, ctx->key, buf, walk->src.virt.addr, 3987bac4f5bSMartin Schwidefsky DES_BLOCK_SIZE, walk->iv); 3997bac4f5bSMartin Schwidefsky memcpy(walk->dst.virt.addr, buf, nbytes); 4007bac4f5bSMartin Schwidefsky crypto_inc(walk->iv, DES_BLOCK_SIZE); 4010200f3ecSGerald Schaefer ret = blkcipher_walk_done(desc, walk, 0); 4020200f3ecSGerald Schaefer } 4030200f3ecSGerald Schaefer return ret; 4040200f3ecSGerald Schaefer } 4050200f3ecSGerald Schaefer 4060200f3ecSGerald Schaefer static int ctr_des_encrypt(struct blkcipher_desc *desc, 4070200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4080200f3ecSGerald Schaefer unsigned int nbytes) 4090200f3ecSGerald Schaefer { 4100200f3ecSGerald Schaefer struct blkcipher_walk walk; 4110200f3ecSGerald Schaefer 4120200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4137bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA, &walk); 4140200f3ecSGerald Schaefer } 4150200f3ecSGerald Schaefer 4160200f3ecSGerald Schaefer static int ctr_des_decrypt(struct blkcipher_desc *desc, 4170200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4180200f3ecSGerald Schaefer unsigned int nbytes) 4190200f3ecSGerald Schaefer { 4200200f3ecSGerald Schaefer struct blkcipher_walk walk; 4210200f3ecSGerald Schaefer 4220200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4237bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA | CPACF_DECRYPT, &walk); 4240200f3ecSGerald Schaefer } 4250200f3ecSGerald Schaefer 4260200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = { 4270200f3ecSGerald Schaefer .cra_name = "ctr(des)", 4280200f3ecSGerald Schaefer .cra_driver_name = "ctr-des-s390", 429c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ctr */ 4300200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 4310200f3ecSGerald Schaefer .cra_blocksize = 1, 4320200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 4330200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 4340200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 4350200f3ecSGerald Schaefer .cra_u = { 4360200f3ecSGerald Schaefer .blkcipher = { 4370200f3ecSGerald Schaefer .min_keysize = DES_KEY_SIZE, 4380200f3ecSGerald Schaefer .max_keysize = DES_KEY_SIZE, 4390200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4400200f3ecSGerald Schaefer .setkey = des_setkey, 4410200f3ecSGerald Schaefer .encrypt = ctr_des_encrypt, 4420200f3ecSGerald Schaefer .decrypt = ctr_des_decrypt, 4430200f3ecSGerald Schaefer } 4440200f3ecSGerald Schaefer } 4450200f3ecSGerald Schaefer }; 4460200f3ecSGerald Schaefer 4470200f3ecSGerald Schaefer static int ctr_des3_encrypt(struct blkcipher_desc *desc, 4480200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4490200f3ecSGerald Schaefer unsigned int nbytes) 4500200f3ecSGerald Schaefer { 4510200f3ecSGerald Schaefer struct blkcipher_walk walk; 4520200f3ecSGerald Schaefer 4530200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4547bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192, &walk); 4550200f3ecSGerald Schaefer } 4560200f3ecSGerald Schaefer 4570200f3ecSGerald Schaefer static int ctr_des3_decrypt(struct blkcipher_desc *desc, 4580200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4590200f3ecSGerald Schaefer unsigned int nbytes) 4600200f3ecSGerald Schaefer { 4610200f3ecSGerald Schaefer struct blkcipher_walk walk; 4620200f3ecSGerald Schaefer 4630200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 464edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192 | CPACF_DECRYPT, 4657bac4f5bSMartin Schwidefsky &walk); 4660200f3ecSGerald Schaefer } 4670200f3ecSGerald Schaefer 4680200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = { 4690200f3ecSGerald Schaefer .cra_name = "ctr(des3_ede)", 4700200f3ecSGerald Schaefer .cra_driver_name = "ctr-des3_ede-s390", 471c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ede */ 4720200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 4730200f3ecSGerald Schaefer .cra_blocksize = 1, 4740200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 4750200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 4760200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 4770200f3ecSGerald Schaefer .cra_u = { 4780200f3ecSGerald Schaefer .blkcipher = { 4790200f3ecSGerald Schaefer .min_keysize = DES3_KEY_SIZE, 4800200f3ecSGerald Schaefer .max_keysize = DES3_KEY_SIZE, 4810200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4820200f3ecSGerald Schaefer .setkey = des3_setkey, 4830200f3ecSGerald Schaefer .encrypt = ctr_des3_encrypt, 4840200f3ecSGerald Schaefer .decrypt = ctr_des3_decrypt, 4850200f3ecSGerald Schaefer } 4860200f3ecSGerald Schaefer } 4870200f3ecSGerald Schaefer }; 4880200f3ecSGerald Schaefer 489d863d594SMartin Schwidefsky static struct crypto_alg *des_s390_algs_ptr[8]; 490d863d594SMartin Schwidefsky static int des_s390_algs_num; 491d863d594SMartin Schwidefsky 492d863d594SMartin Schwidefsky static int des_s390_register_alg(struct crypto_alg *alg) 493d863d594SMartin Schwidefsky { 494d863d594SMartin Schwidefsky int ret; 495d863d594SMartin Schwidefsky 496d863d594SMartin Schwidefsky ret = crypto_register_alg(alg); 497d863d594SMartin Schwidefsky if (!ret) 498d863d594SMartin Schwidefsky des_s390_algs_ptr[des_s390_algs_num++] = alg; 499d863d594SMartin Schwidefsky return ret; 500d863d594SMartin Schwidefsky } 501d863d594SMartin Schwidefsky 502d863d594SMartin Schwidefsky static void des_s390_exit(void) 503d863d594SMartin Schwidefsky { 504d863d594SMartin Schwidefsky while (des_s390_algs_num--) 505d863d594SMartin Schwidefsky crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]); 506d863d594SMartin Schwidefsky if (ctrblk) 507d863d594SMartin Schwidefsky free_page((unsigned long) ctrblk); 508d863d594SMartin Schwidefsky } 509d863d594SMartin Schwidefsky 51098971f84SJan Glauber static int __init des_s390_init(void) 511c1e26e1eSJan Glauber { 51280d663a4SJan Glauber int ret; 513c1e26e1eSJan Glauber 51469c0e360SMartin Schwidefsky /* Query available functions for KM, KMC and KMCTR */ 51569c0e360SMartin Schwidefsky cpacf_query(CPACF_KM, &km_functions); 51669c0e360SMartin Schwidefsky cpacf_query(CPACF_KMC, &kmc_functions); 51769c0e360SMartin Schwidefsky cpacf_query(CPACF_KMCTR, &kmctr_functions); 518c1e26e1eSJan Glauber 51969c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) { 520d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des_alg); 521a9e62fadSHerbert Xu if (ret) 522d863d594SMartin Schwidefsky goto out_err; 523d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des_alg); 524a9e62fadSHerbert Xu if (ret) 525d863d594SMartin Schwidefsky goto out_err; 52669c0e360SMartin Schwidefsky } 52769c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) { 528d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des_alg); 529a9e62fadSHerbert Xu if (ret) 530d863d594SMartin Schwidefsky goto out_err; 53169c0e360SMartin Schwidefsky } 53269c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) { 533d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des3_alg); 534a9e62fadSHerbert Xu if (ret) 535d863d594SMartin Schwidefsky goto out_err; 536d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des3_alg); 537a9e62fadSHerbert Xu if (ret) 538d863d594SMartin Schwidefsky goto out_err; 53969c0e360SMartin Schwidefsky } 54069c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) { 541d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des3_alg); 542a9e62fadSHerbert Xu if (ret) 543d863d594SMartin Schwidefsky goto out_err; 54469c0e360SMartin Schwidefsky } 5450200f3ecSGerald Schaefer 54669c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) || 54769c0e360SMartin Schwidefsky cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 5480200f3ecSGerald Schaefer ctrblk = (u8 *) __get_free_page(GFP_KERNEL); 5490200f3ecSGerald Schaefer if (!ctrblk) { 5500200f3ecSGerald Schaefer ret = -ENOMEM; 551d863d594SMartin Schwidefsky goto out_err; 5520200f3ecSGerald Schaefer } 55369c0e360SMartin Schwidefsky } 55469c0e360SMartin Schwidefsky 55569c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) { 556d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des_alg); 557d863d594SMartin Schwidefsky if (ret) 558d863d594SMartin Schwidefsky goto out_err; 55969c0e360SMartin Schwidefsky } 56069c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 561d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des3_alg); 562d863d594SMartin Schwidefsky if (ret) 563d863d594SMartin Schwidefsky goto out_err; 5640200f3ecSGerald Schaefer } 565d863d594SMartin Schwidefsky 566d863d594SMartin Schwidefsky return 0; 567d863d594SMartin Schwidefsky out_err: 568d863d594SMartin Schwidefsky des_s390_exit(); 569a9e62fadSHerbert Xu return ret; 570c1e26e1eSJan Glauber } 571c1e26e1eSJan Glauber 572d05377c1SHendrik Brueckner module_cpu_feature_match(MSA, des_s390_init); 5731efbd15cSJan Glauber module_exit(des_s390_exit); 574c1e26e1eSJan Glauber 5755d26a105SKees Cook MODULE_ALIAS_CRYPTO("des"); 5765d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede"); 577c1e26e1eSJan Glauber 578c1e26e1eSJan Glauber MODULE_LICENSE("GPL"); 579c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); 580