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); 227c1e26e1eSJan Glauber 228fed28611SDaniel Borkmann if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && 229fed28611SDaniel Borkmann crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], 23003b56ce5SJarod Wilson DES_KEY_SIZE)) && 231231baecdSEric Biggers (tfm->crt_flags & CRYPTO_TFM_REQ_FORBID_WEAK_KEYS)) { 23269c0e360SMartin Schwidefsky tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; 233c1e26e1eSJan Glauber return -EINVAL; 234c1e26e1eSJan Glauber } 235f3d3584fSMatthew Rosato 236f3d3584fSMatthew Rosato /* in fips mode, ensure k1 != k2 and k2 != k3 and k1 != k3 */ 237f3d3584fSMatthew Rosato if (fips_enabled && 238f3d3584fSMatthew Rosato !(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && 239f3d3584fSMatthew Rosato crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], 240f3d3584fSMatthew Rosato DES_KEY_SIZE) && 241f3d3584fSMatthew Rosato crypto_memneq(key, &key[DES_KEY_SIZE * 2], DES_KEY_SIZE))) { 242f3d3584fSMatthew Rosato tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; 243f3d3584fSMatthew Rosato return -EINVAL; 244f3d3584fSMatthew Rosato } 245f3d3584fSMatthew Rosato 24698971f84SJan Glauber memcpy(ctx->key, key, key_len); 247c1e26e1eSJan Glauber return 0; 248c1e26e1eSJan Glauber } 249c1e26e1eSJan Glauber 25098971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 251c1e26e1eSJan Glauber { 25298971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 253c1e26e1eSJan Glauber 254edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE); 255c1e26e1eSJan Glauber } 256c1e26e1eSJan Glauber 25798971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 258c1e26e1eSJan Glauber { 25998971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 260c1e26e1eSJan Glauber 261edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT, 262edc63a37SMartin Schwidefsky ctx->key, dst, src, DES_BLOCK_SIZE); 263c1e26e1eSJan Glauber } 264c1e26e1eSJan Glauber 26598971f84SJan Glauber static struct crypto_alg des3_alg = { 266c1e26e1eSJan Glauber .cra_name = "des3_ede", 26765b75c36SHerbert Xu .cra_driver_name = "des3_ede-s390", 268c7d4d259SMartin Schwidefsky .cra_priority = 300, 269c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2701efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 27198971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 272c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 273c1357833SJan Glauber .cra_u = { 274c1357833SJan Glauber .cipher = { 27598971f84SJan Glauber .cia_min_keysize = DES3_KEY_SIZE, 27698971f84SJan Glauber .cia_max_keysize = DES3_KEY_SIZE, 27798971f84SJan Glauber .cia_setkey = des3_setkey, 27898971f84SJan Glauber .cia_encrypt = des3_encrypt, 27998971f84SJan Glauber .cia_decrypt = des3_decrypt, 280c1357833SJan Glauber } 281c1357833SJan Glauber } 282c1e26e1eSJan Glauber }; 283c1e26e1eSJan Glauber 28498971f84SJan Glauber static int ecb_des3_encrypt(struct blkcipher_desc *desc, 28598971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 28698971f84SJan Glauber unsigned int nbytes) 287a9e62fadSHerbert Xu { 288a9e62fadSHerbert Xu struct blkcipher_walk walk; 289a9e62fadSHerbert Xu 290a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 2917bac4f5bSMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192, &walk); 292a9e62fadSHerbert Xu } 293a9e62fadSHerbert Xu 29498971f84SJan Glauber static int ecb_des3_decrypt(struct blkcipher_desc *desc, 29598971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 29698971f84SJan Glauber unsigned int nbytes) 297a9e62fadSHerbert Xu { 298a9e62fadSHerbert Xu struct blkcipher_walk walk; 299a9e62fadSHerbert Xu 300a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 301edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192 | CPACF_DECRYPT, 3027bac4f5bSMartin Schwidefsky &walk); 303a9e62fadSHerbert Xu } 304a9e62fadSHerbert Xu 30598971f84SJan Glauber static struct crypto_alg ecb_des3_alg = { 306a9e62fadSHerbert Xu .cra_name = "ecb(des3_ede)", 307a9e62fadSHerbert Xu .cra_driver_name = "ecb-des3_ede-s390", 308c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ecb */ 309a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3101efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 31198971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 312a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 313a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 314a9e62fadSHerbert Xu .cra_u = { 315a9e62fadSHerbert Xu .blkcipher = { 31698971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 31798971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 31898971f84SJan Glauber .setkey = des3_setkey, 31998971f84SJan Glauber .encrypt = ecb_des3_encrypt, 32098971f84SJan Glauber .decrypt = ecb_des3_decrypt, 321a9e62fadSHerbert Xu } 322a9e62fadSHerbert Xu } 323a9e62fadSHerbert Xu }; 324a9e62fadSHerbert Xu 32598971f84SJan Glauber static int cbc_des3_encrypt(struct blkcipher_desc *desc, 32698971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 32798971f84SJan Glauber unsigned int nbytes) 328a9e62fadSHerbert Xu { 329a9e62fadSHerbert Xu struct blkcipher_walk walk; 330a9e62fadSHerbert Xu 331a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 332edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192, &walk); 333a9e62fadSHerbert Xu } 334a9e62fadSHerbert Xu 33598971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc, 33698971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 33798971f84SJan Glauber unsigned int nbytes) 338a9e62fadSHerbert Xu { 339a9e62fadSHerbert Xu struct blkcipher_walk walk; 340a9e62fadSHerbert Xu 341a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 342edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192 | CPACF_DECRYPT, 343edc63a37SMartin Schwidefsky &walk); 344a9e62fadSHerbert Xu } 345a9e62fadSHerbert Xu 34698971f84SJan Glauber static struct crypto_alg cbc_des3_alg = { 347a9e62fadSHerbert Xu .cra_name = "cbc(des3_ede)", 348a9e62fadSHerbert Xu .cra_driver_name = "cbc-des3_ede-s390", 349c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + cbc */ 350a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3511efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 35298971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 353a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 354a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 355a9e62fadSHerbert Xu .cra_u = { 356a9e62fadSHerbert Xu .blkcipher = { 35798971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 35898971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 3591efbd15cSJan Glauber .ivsize = DES_BLOCK_SIZE, 36098971f84SJan Glauber .setkey = des3_setkey, 36198971f84SJan Glauber .encrypt = cbc_des3_encrypt, 36298971f84SJan Glauber .decrypt = cbc_des3_decrypt, 363a9e62fadSHerbert Xu } 364a9e62fadSHerbert Xu } 365a9e62fadSHerbert Xu }; 366a9e62fadSHerbert Xu 3677bac4f5bSMartin Schwidefsky static unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes) 368ee97dc7dSHarald Freudenberger { 369ee97dc7dSHarald Freudenberger unsigned int i, n; 370ee97dc7dSHarald Freudenberger 371ee97dc7dSHarald Freudenberger /* align to block size, max. PAGE_SIZE */ 372ee97dc7dSHarald Freudenberger n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); 3737bac4f5bSMartin Schwidefsky memcpy(ctrptr, iv, DES_BLOCK_SIZE); 3747bac4f5bSMartin Schwidefsky for (i = (n / DES_BLOCK_SIZE) - 1; i > 0; i--) { 3757bac4f5bSMartin Schwidefsky memcpy(ctrptr + DES_BLOCK_SIZE, ctrptr, DES_BLOCK_SIZE); 3767bac4f5bSMartin Schwidefsky crypto_inc(ctrptr + DES_BLOCK_SIZE, DES_BLOCK_SIZE); 3777bac4f5bSMartin Schwidefsky ctrptr += DES_BLOCK_SIZE; 378ee97dc7dSHarald Freudenberger } 379ee97dc7dSHarald Freudenberger return n; 380ee97dc7dSHarald Freudenberger } 381ee97dc7dSHarald Freudenberger 3827bac4f5bSMartin Schwidefsky static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, 383ee97dc7dSHarald Freudenberger struct blkcipher_walk *walk) 3840200f3ecSGerald Schaefer { 3857bac4f5bSMartin Schwidefsky struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 3867bac4f5bSMartin Schwidefsky u8 buf[DES_BLOCK_SIZE], *ctrptr; 387ee97dc7dSHarald Freudenberger unsigned int n, nbytes; 3887bac4f5bSMartin Schwidefsky int ret, locked; 3890200f3ecSGerald Schaefer 3907bac4f5bSMartin Schwidefsky locked = spin_trylock(&ctrblk_lock); 391ee97dc7dSHarald Freudenberger 3927bac4f5bSMartin Schwidefsky ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); 3930200f3ecSGerald Schaefer while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 394ee97dc7dSHarald Freudenberger n = DES_BLOCK_SIZE; 3957bac4f5bSMartin Schwidefsky if (nbytes >= 2*DES_BLOCK_SIZE && locked) 3967bac4f5bSMartin Schwidefsky n = __ctrblk_init(ctrblk, walk->iv, nbytes); 3977bac4f5bSMartin Schwidefsky ctrptr = (n > DES_BLOCK_SIZE) ? ctrblk : walk->iv; 3987bac4f5bSMartin Schwidefsky cpacf_kmctr(fc, ctx->key, walk->dst.virt.addr, 3997bac4f5bSMartin Schwidefsky walk->src.virt.addr, n, ctrptr); 4007bac4f5bSMartin Schwidefsky if (ctrptr == ctrblk) 4017bac4f5bSMartin Schwidefsky memcpy(walk->iv, ctrptr + n - DES_BLOCK_SIZE, 4020200f3ecSGerald Schaefer DES_BLOCK_SIZE); 4037bac4f5bSMartin Schwidefsky crypto_inc(walk->iv, DES_BLOCK_SIZE); 4047bac4f5bSMartin Schwidefsky ret = blkcipher_walk_done(desc, walk, nbytes - n); 4050200f3ecSGerald Schaefer } 4067bac4f5bSMartin Schwidefsky if (locked) 407ee97dc7dSHarald Freudenberger spin_unlock(&ctrblk_lock); 4080200f3ecSGerald Schaefer /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ 4090200f3ecSGerald Schaefer if (nbytes) { 4107bac4f5bSMartin Schwidefsky cpacf_kmctr(fc, ctx->key, buf, walk->src.virt.addr, 4117bac4f5bSMartin Schwidefsky DES_BLOCK_SIZE, walk->iv); 4127bac4f5bSMartin Schwidefsky memcpy(walk->dst.virt.addr, buf, nbytes); 4137bac4f5bSMartin Schwidefsky crypto_inc(walk->iv, DES_BLOCK_SIZE); 4140200f3ecSGerald Schaefer ret = blkcipher_walk_done(desc, walk, 0); 4150200f3ecSGerald Schaefer } 4160200f3ecSGerald Schaefer return ret; 4170200f3ecSGerald Schaefer } 4180200f3ecSGerald Schaefer 4190200f3ecSGerald Schaefer static int ctr_des_encrypt(struct blkcipher_desc *desc, 4200200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4210200f3ecSGerald Schaefer unsigned int nbytes) 4220200f3ecSGerald Schaefer { 4230200f3ecSGerald Schaefer struct blkcipher_walk walk; 4240200f3ecSGerald Schaefer 4250200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4267bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA, &walk); 4270200f3ecSGerald Schaefer } 4280200f3ecSGerald Schaefer 4290200f3ecSGerald Schaefer static int ctr_des_decrypt(struct blkcipher_desc *desc, 4300200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4310200f3ecSGerald Schaefer unsigned int nbytes) 4320200f3ecSGerald Schaefer { 4330200f3ecSGerald Schaefer struct blkcipher_walk walk; 4340200f3ecSGerald Schaefer 4350200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4367bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA | CPACF_DECRYPT, &walk); 4370200f3ecSGerald Schaefer } 4380200f3ecSGerald Schaefer 4390200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = { 4400200f3ecSGerald Schaefer .cra_name = "ctr(des)", 4410200f3ecSGerald Schaefer .cra_driver_name = "ctr-des-s390", 442c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ctr */ 4430200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 4440200f3ecSGerald Schaefer .cra_blocksize = 1, 4450200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 4460200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 4470200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 4480200f3ecSGerald Schaefer .cra_u = { 4490200f3ecSGerald Schaefer .blkcipher = { 4500200f3ecSGerald Schaefer .min_keysize = DES_KEY_SIZE, 4510200f3ecSGerald Schaefer .max_keysize = DES_KEY_SIZE, 4520200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4530200f3ecSGerald Schaefer .setkey = des_setkey, 4540200f3ecSGerald Schaefer .encrypt = ctr_des_encrypt, 4550200f3ecSGerald Schaefer .decrypt = ctr_des_decrypt, 4560200f3ecSGerald Schaefer } 4570200f3ecSGerald Schaefer } 4580200f3ecSGerald Schaefer }; 4590200f3ecSGerald Schaefer 4600200f3ecSGerald Schaefer static int ctr_des3_encrypt(struct blkcipher_desc *desc, 4610200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4620200f3ecSGerald Schaefer unsigned int nbytes) 4630200f3ecSGerald Schaefer { 4640200f3ecSGerald Schaefer struct blkcipher_walk walk; 4650200f3ecSGerald Schaefer 4660200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4677bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192, &walk); 4680200f3ecSGerald Schaefer } 4690200f3ecSGerald Schaefer 4700200f3ecSGerald Schaefer static int ctr_des3_decrypt(struct blkcipher_desc *desc, 4710200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4720200f3ecSGerald Schaefer unsigned int nbytes) 4730200f3ecSGerald Schaefer { 4740200f3ecSGerald Schaefer struct blkcipher_walk walk; 4750200f3ecSGerald Schaefer 4760200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 477edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192 | CPACF_DECRYPT, 4787bac4f5bSMartin Schwidefsky &walk); 4790200f3ecSGerald Schaefer } 4800200f3ecSGerald Schaefer 4810200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = { 4820200f3ecSGerald Schaefer .cra_name = "ctr(des3_ede)", 4830200f3ecSGerald Schaefer .cra_driver_name = "ctr-des3_ede-s390", 484c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ede */ 4850200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 4860200f3ecSGerald Schaefer .cra_blocksize = 1, 4870200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 4880200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 4890200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 4900200f3ecSGerald Schaefer .cra_u = { 4910200f3ecSGerald Schaefer .blkcipher = { 4920200f3ecSGerald Schaefer .min_keysize = DES3_KEY_SIZE, 4930200f3ecSGerald Schaefer .max_keysize = DES3_KEY_SIZE, 4940200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4950200f3ecSGerald Schaefer .setkey = des3_setkey, 4960200f3ecSGerald Schaefer .encrypt = ctr_des3_encrypt, 4970200f3ecSGerald Schaefer .decrypt = ctr_des3_decrypt, 4980200f3ecSGerald Schaefer } 4990200f3ecSGerald Schaefer } 5000200f3ecSGerald Schaefer }; 5010200f3ecSGerald Schaefer 502d863d594SMartin Schwidefsky static struct crypto_alg *des_s390_algs_ptr[8]; 503d863d594SMartin Schwidefsky static int des_s390_algs_num; 504d863d594SMartin Schwidefsky 505d863d594SMartin Schwidefsky static int des_s390_register_alg(struct crypto_alg *alg) 506d863d594SMartin Schwidefsky { 507d863d594SMartin Schwidefsky int ret; 508d863d594SMartin Schwidefsky 509d863d594SMartin Schwidefsky ret = crypto_register_alg(alg); 510d863d594SMartin Schwidefsky if (!ret) 511d863d594SMartin Schwidefsky des_s390_algs_ptr[des_s390_algs_num++] = alg; 512d863d594SMartin Schwidefsky return ret; 513d863d594SMartin Schwidefsky } 514d863d594SMartin Schwidefsky 515d863d594SMartin Schwidefsky static void des_s390_exit(void) 516d863d594SMartin Schwidefsky { 517d863d594SMartin Schwidefsky while (des_s390_algs_num--) 518d863d594SMartin Schwidefsky crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]); 519d863d594SMartin Schwidefsky if (ctrblk) 520d863d594SMartin Schwidefsky free_page((unsigned long) ctrblk); 521d863d594SMartin Schwidefsky } 522d863d594SMartin Schwidefsky 52398971f84SJan Glauber static int __init des_s390_init(void) 524c1e26e1eSJan Glauber { 52580d663a4SJan Glauber int ret; 526c1e26e1eSJan Glauber 52769c0e360SMartin Schwidefsky /* Query available functions for KM, KMC and KMCTR */ 52869c0e360SMartin Schwidefsky cpacf_query(CPACF_KM, &km_functions); 52969c0e360SMartin Schwidefsky cpacf_query(CPACF_KMC, &kmc_functions); 53069c0e360SMartin Schwidefsky cpacf_query(CPACF_KMCTR, &kmctr_functions); 531c1e26e1eSJan Glauber 53269c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) { 533d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des_alg); 534a9e62fadSHerbert Xu if (ret) 535d863d594SMartin Schwidefsky goto out_err; 536d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des_alg); 537a9e62fadSHerbert Xu if (ret) 538d863d594SMartin Schwidefsky goto out_err; 53969c0e360SMartin Schwidefsky } 54069c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) { 541d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des_alg); 542a9e62fadSHerbert Xu if (ret) 543d863d594SMartin Schwidefsky goto out_err; 54469c0e360SMartin Schwidefsky } 54569c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) { 546d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des3_alg); 547a9e62fadSHerbert Xu if (ret) 548d863d594SMartin Schwidefsky goto out_err; 549d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des3_alg); 550a9e62fadSHerbert Xu if (ret) 551d863d594SMartin Schwidefsky goto out_err; 55269c0e360SMartin Schwidefsky } 55369c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) { 554d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des3_alg); 555a9e62fadSHerbert Xu if (ret) 556d863d594SMartin Schwidefsky goto out_err; 55769c0e360SMartin Schwidefsky } 5580200f3ecSGerald Schaefer 55969c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) || 56069c0e360SMartin Schwidefsky cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 5610200f3ecSGerald Schaefer ctrblk = (u8 *) __get_free_page(GFP_KERNEL); 5620200f3ecSGerald Schaefer if (!ctrblk) { 5630200f3ecSGerald Schaefer ret = -ENOMEM; 564d863d594SMartin Schwidefsky goto out_err; 5650200f3ecSGerald Schaefer } 56669c0e360SMartin Schwidefsky } 56769c0e360SMartin Schwidefsky 56869c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) { 569d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des_alg); 570d863d594SMartin Schwidefsky if (ret) 571d863d594SMartin Schwidefsky goto out_err; 57269c0e360SMartin Schwidefsky } 57369c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 574d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des3_alg); 575d863d594SMartin Schwidefsky if (ret) 576d863d594SMartin Schwidefsky goto out_err; 5770200f3ecSGerald Schaefer } 578d863d594SMartin Schwidefsky 579d863d594SMartin Schwidefsky return 0; 580d863d594SMartin Schwidefsky out_err: 581d863d594SMartin Schwidefsky des_s390_exit(); 582a9e62fadSHerbert Xu return ret; 583c1e26e1eSJan Glauber } 584c1e26e1eSJan Glauber 585d05377c1SHendrik Brueckner module_cpu_feature_match(MSA, des_s390_init); 5861efbd15cSJan Glauber module_exit(des_s390_exit); 587c1e26e1eSJan Glauber 5885d26a105SKees Cook MODULE_ALIAS_CRYPTO("des"); 5895d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede"); 590c1e26e1eSJan Glauber 591c1e26e1eSJan Glauber MODULE_LICENSE("GPL"); 592c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); 593