1c1e26e1eSJan Glauber /* 2c1e26e1eSJan Glauber * Cryptographic API. 3c1e26e1eSJan Glauber * 4c1e26e1eSJan Glauber * s390 implementation of the DES Cipher Algorithm. 5c1e26e1eSJan Glauber * 60200f3ecSGerald Schaefer * Copyright IBM Corp. 2003, 2011 786aa9fc2SJan Glauber * Author(s): Thomas Spatzier 886aa9fc2SJan Glauber * Jan Glauber (jan.glauber@de.ibm.com) 9c1e26e1eSJan Glauber * 10c1e26e1eSJan Glauber * This program is free software; you can redistribute it and/or modify 11c1e26e1eSJan Glauber * it under the terms of the GNU General Public License as published by 12c1e26e1eSJan Glauber * the Free Software Foundation; either version 2 of the License, or 13c1e26e1eSJan Glauber * (at your option) any later version. 14c1e26e1eSJan Glauber * 15c1e26e1eSJan Glauber */ 16a9e62fadSHerbert Xu 17c1e26e1eSJan Glauber #include <linux/init.h> 18c1e26e1eSJan Glauber #include <linux/module.h> 19d05377c1SHendrik Brueckner #include <linux/cpufeature.h> 201efbd15cSJan Glauber #include <linux/crypto.h> 211efbd15cSJan Glauber #include <crypto/algapi.h> 221efbd15cSJan Glauber #include <crypto/des.h> 23c7d4d259SMartin Schwidefsky #include <asm/cpacf.h> 24c1e26e1eSJan Glauber 2598971f84SJan Glauber #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) 26c1e26e1eSJan Glauber 270200f3ecSGerald Schaefer static u8 *ctrblk; 28ee97dc7dSHarald Freudenberger static DEFINE_SPINLOCK(ctrblk_lock); 290200f3ecSGerald Schaefer 3069c0e360SMartin Schwidefsky static cpacf_mask_t km_functions, kmc_functions, kmctr_functions; 3169c0e360SMartin Schwidefsky 3298971f84SJan Glauber struct s390_des_ctx { 33c1e26e1eSJan Glauber u8 iv[DES_BLOCK_SIZE]; 3498971f84SJan Glauber u8 key[DES3_KEY_SIZE]; 35c1e26e1eSJan Glauber }; 36c1e26e1eSJan Glauber 376c2bb98bSHerbert Xu static int des_setkey(struct crypto_tfm *tfm, const u8 *key, 3898971f84SJan Glauber unsigned int key_len) 39c1e26e1eSJan Glauber { 4098971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 411efbd15cSJan Glauber u32 tmp[DES_EXPKEY_WORDS]; 42c1e26e1eSJan Glauber 431efbd15cSJan Glauber /* check for weak keys */ 4469c0e360SMartin Schwidefsky if (!des_ekey(tmp, key) && 4569c0e360SMartin Schwidefsky (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) { 4669c0e360SMartin Schwidefsky tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; 471efbd15cSJan Glauber return -EINVAL; 481efbd15cSJan Glauber } 491efbd15cSJan Glauber 5098971f84SJan Glauber memcpy(ctx->key, key, key_len); 511efbd15cSJan Glauber return 0; 52c1e26e1eSJan Glauber } 53c1e26e1eSJan Glauber 546c2bb98bSHerbert Xu static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 55c1e26e1eSJan Glauber { 5698971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 57c1e26e1eSJan Glauber 58edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE); 59c1e26e1eSJan Glauber } 60c1e26e1eSJan Glauber 616c2bb98bSHerbert Xu static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 62c1e26e1eSJan Glauber { 6398971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 64c1e26e1eSJan Glauber 65edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT, 66edc63a37SMartin Schwidefsky ctx->key, out, in, DES_BLOCK_SIZE); 67b8dc6038SJan Glauber } 68b8dc6038SJan Glauber 69c1e26e1eSJan Glauber static struct crypto_alg des_alg = { 70c1e26e1eSJan Glauber .cra_name = "des", 7165b75c36SHerbert Xu .cra_driver_name = "des-s390", 72c7d4d259SMartin Schwidefsky .cra_priority = 300, 73c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 74c1e26e1eSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 7598971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 76c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 77c1357833SJan Glauber .cra_u = { 78c1357833SJan Glauber .cipher = { 79c1e26e1eSJan Glauber .cia_min_keysize = DES_KEY_SIZE, 80c1e26e1eSJan Glauber .cia_max_keysize = DES_KEY_SIZE, 81c1e26e1eSJan Glauber .cia_setkey = des_setkey, 82c1e26e1eSJan Glauber .cia_encrypt = des_encrypt, 83b8dc6038SJan Glauber .cia_decrypt = des_decrypt, 84c1357833SJan Glauber } 85c1357833SJan Glauber } 86c1e26e1eSJan Glauber }; 87c1e26e1eSJan Glauber 887bac4f5bSMartin Schwidefsky static int ecb_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, 89adc3fcf1SHarald Freudenberger struct blkcipher_walk *walk) 90a9e62fadSHerbert Xu { 91adc3fcf1SHarald Freudenberger struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 927bac4f5bSMartin Schwidefsky unsigned int nbytes, n; 937bac4f5bSMartin Schwidefsky int ret; 947bac4f5bSMartin Schwidefsky 957bac4f5bSMartin Schwidefsky ret = blkcipher_walk_virt(desc, walk); 967bac4f5bSMartin Schwidefsky while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 977bac4f5bSMartin Schwidefsky /* only use complete blocks */ 987bac4f5bSMartin Schwidefsky n = nbytes & ~(DES_BLOCK_SIZE - 1); 997bac4f5bSMartin Schwidefsky cpacf_km(fc, ctx->key, walk->dst.virt.addr, 1007bac4f5bSMartin Schwidefsky walk->src.virt.addr, n); 1017bac4f5bSMartin Schwidefsky ret = blkcipher_walk_done(desc, walk, nbytes - n); 1027bac4f5bSMartin Schwidefsky } 1037bac4f5bSMartin Schwidefsky return ret; 1047bac4f5bSMartin Schwidefsky } 1057bac4f5bSMartin Schwidefsky 1067bac4f5bSMartin Schwidefsky static int cbc_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, 1077bac4f5bSMartin Schwidefsky struct blkcipher_walk *walk) 1087bac4f5bSMartin Schwidefsky { 1097bac4f5bSMartin Schwidefsky struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 1107bac4f5bSMartin Schwidefsky unsigned int nbytes, n; 1117bac4f5bSMartin Schwidefsky int ret; 112adc3fcf1SHarald Freudenberger struct { 113adc3fcf1SHarald Freudenberger u8 iv[DES_BLOCK_SIZE]; 114adc3fcf1SHarald Freudenberger u8 key[DES3_KEY_SIZE]; 115adc3fcf1SHarald Freudenberger } param; 116a9e62fadSHerbert Xu 1177bac4f5bSMartin Schwidefsky ret = blkcipher_walk_virt(desc, walk); 118adc3fcf1SHarald Freudenberger memcpy(param.iv, walk->iv, DES_BLOCK_SIZE); 119adc3fcf1SHarald Freudenberger memcpy(param.key, ctx->key, DES3_KEY_SIZE); 1207bac4f5bSMartin Schwidefsky while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 121a9e62fadSHerbert Xu /* only use complete blocks */ 1227bac4f5bSMartin Schwidefsky n = nbytes & ~(DES_BLOCK_SIZE - 1); 1237bac4f5bSMartin Schwidefsky cpacf_kmc(fc, ¶m, walk->dst.virt.addr, 1247bac4f5bSMartin Schwidefsky walk->src.virt.addr, n); 1257bac4f5bSMartin Schwidefsky ret = blkcipher_walk_done(desc, walk, nbytes - n); 1267bac4f5bSMartin Schwidefsky } 127adc3fcf1SHarald Freudenberger memcpy(walk->iv, param.iv, DES_BLOCK_SIZE); 128a9e62fadSHerbert Xu return ret; 129a9e62fadSHerbert Xu } 130a9e62fadSHerbert Xu 131a9e62fadSHerbert Xu static int ecb_des_encrypt(struct blkcipher_desc *desc, 132a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 133a9e62fadSHerbert Xu unsigned int nbytes) 134a9e62fadSHerbert Xu { 135a9e62fadSHerbert Xu struct blkcipher_walk walk; 136a9e62fadSHerbert Xu 137a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 1387bac4f5bSMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA, &walk); 139a9e62fadSHerbert Xu } 140a9e62fadSHerbert Xu 141a9e62fadSHerbert Xu static int ecb_des_decrypt(struct blkcipher_desc *desc, 142a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 143a9e62fadSHerbert Xu unsigned int nbytes) 144a9e62fadSHerbert Xu { 145a9e62fadSHerbert Xu struct blkcipher_walk walk; 146a9e62fadSHerbert Xu 147a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 1487bac4f5bSMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA | CPACF_DECRYPT, &walk); 149a9e62fadSHerbert Xu } 150a9e62fadSHerbert Xu 151a9e62fadSHerbert Xu static struct crypto_alg ecb_des_alg = { 152a9e62fadSHerbert Xu .cra_name = "ecb(des)", 153a9e62fadSHerbert Xu .cra_driver_name = "ecb-des-s390", 154c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ecb */ 155a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 156a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 15798971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 158a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 159a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 160a9e62fadSHerbert Xu .cra_u = { 161a9e62fadSHerbert Xu .blkcipher = { 162a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 163a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 164a9e62fadSHerbert Xu .setkey = des_setkey, 165a9e62fadSHerbert Xu .encrypt = ecb_des_encrypt, 166a9e62fadSHerbert Xu .decrypt = ecb_des_decrypt, 167a9e62fadSHerbert Xu } 168a9e62fadSHerbert Xu } 169a9e62fadSHerbert Xu }; 170a9e62fadSHerbert Xu 171a9e62fadSHerbert Xu static int cbc_des_encrypt(struct blkcipher_desc *desc, 172a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 173a9e62fadSHerbert Xu unsigned int nbytes) 174a9e62fadSHerbert Xu { 175a9e62fadSHerbert Xu struct blkcipher_walk walk; 176a9e62fadSHerbert Xu 177a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 178edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA, &walk); 179a9e62fadSHerbert Xu } 180a9e62fadSHerbert Xu 181a9e62fadSHerbert Xu static int cbc_des_decrypt(struct blkcipher_desc *desc, 182a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 183a9e62fadSHerbert Xu unsigned int nbytes) 184a9e62fadSHerbert Xu { 185a9e62fadSHerbert Xu struct blkcipher_walk walk; 186a9e62fadSHerbert Xu 187a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 188edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA | CPACF_DECRYPT, &walk); 189a9e62fadSHerbert Xu } 190a9e62fadSHerbert Xu 191a9e62fadSHerbert Xu static struct crypto_alg cbc_des_alg = { 192a9e62fadSHerbert Xu .cra_name = "cbc(des)", 193a9e62fadSHerbert Xu .cra_driver_name = "cbc-des-s390", 194c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + cbc */ 195a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 196a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 19798971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 198a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 199a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 200a9e62fadSHerbert Xu .cra_u = { 201a9e62fadSHerbert Xu .blkcipher = { 202a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 203a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 204a9e62fadSHerbert Xu .ivsize = DES_BLOCK_SIZE, 205a9e62fadSHerbert Xu .setkey = des_setkey, 206a9e62fadSHerbert Xu .encrypt = cbc_des_encrypt, 207a9e62fadSHerbert Xu .decrypt = cbc_des_decrypt, 208a9e62fadSHerbert Xu } 209a9e62fadSHerbert Xu } 210a9e62fadSHerbert Xu }; 211a9e62fadSHerbert Xu 212c1e26e1eSJan Glauber /* 213c1e26e1eSJan Glauber * RFC2451: 214c1e26e1eSJan Glauber * 215c1e26e1eSJan Glauber * For DES-EDE3, there is no known need to reject weak or 216c1e26e1eSJan Glauber * complementation keys. Any weakness is obviated by the use of 217c1e26e1eSJan Glauber * multiple keys. 218c1e26e1eSJan Glauber * 219c1e26e1eSJan Glauber * However, if the first two or last two independent 64-bit keys are 220c1e26e1eSJan Glauber * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the 221c1e26e1eSJan Glauber * same as DES. Implementers MUST reject keys that exhibit this 222c1e26e1eSJan Glauber * property. 223c1e26e1eSJan Glauber * 224c1e26e1eSJan Glauber */ 22598971f84SJan Glauber static int des3_setkey(struct crypto_tfm *tfm, const u8 *key, 22698971f84SJan Glauber unsigned int key_len) 227c1e26e1eSJan Glauber { 22898971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 229c1e26e1eSJan Glauber 230fed28611SDaniel Borkmann if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && 231fed28611SDaniel Borkmann crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], 23203b56ce5SJarod Wilson DES_KEY_SIZE)) && 23369c0e360SMartin Schwidefsky (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) { 23469c0e360SMartin Schwidefsky tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; 235c1e26e1eSJan Glauber return -EINVAL; 236c1e26e1eSJan Glauber } 23798971f84SJan Glauber memcpy(ctx->key, key, key_len); 238c1e26e1eSJan Glauber return 0; 239c1e26e1eSJan Glauber } 240c1e26e1eSJan Glauber 24198971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 242c1e26e1eSJan Glauber { 24398971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 244c1e26e1eSJan Glauber 245edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE); 246c1e26e1eSJan Glauber } 247c1e26e1eSJan Glauber 24898971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 249c1e26e1eSJan Glauber { 25098971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 251c1e26e1eSJan Glauber 252edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT, 253edc63a37SMartin Schwidefsky ctx->key, dst, src, DES_BLOCK_SIZE); 254c1e26e1eSJan Glauber } 255c1e26e1eSJan Glauber 25698971f84SJan Glauber static struct crypto_alg des3_alg = { 257c1e26e1eSJan Glauber .cra_name = "des3_ede", 25865b75c36SHerbert Xu .cra_driver_name = "des3_ede-s390", 259c7d4d259SMartin Schwidefsky .cra_priority = 300, 260c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2611efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 26298971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 263c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 264c1357833SJan Glauber .cra_u = { 265c1357833SJan Glauber .cipher = { 26698971f84SJan Glauber .cia_min_keysize = DES3_KEY_SIZE, 26798971f84SJan Glauber .cia_max_keysize = DES3_KEY_SIZE, 26898971f84SJan Glauber .cia_setkey = des3_setkey, 26998971f84SJan Glauber .cia_encrypt = des3_encrypt, 27098971f84SJan Glauber .cia_decrypt = des3_decrypt, 271c1357833SJan Glauber } 272c1357833SJan Glauber } 273c1e26e1eSJan Glauber }; 274c1e26e1eSJan Glauber 27598971f84SJan Glauber static int ecb_des3_encrypt(struct blkcipher_desc *desc, 27698971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 27798971f84SJan Glauber unsigned int nbytes) 278a9e62fadSHerbert Xu { 279a9e62fadSHerbert Xu struct blkcipher_walk walk; 280a9e62fadSHerbert Xu 281a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 2827bac4f5bSMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192, &walk); 283a9e62fadSHerbert Xu } 284a9e62fadSHerbert Xu 28598971f84SJan Glauber static int ecb_des3_decrypt(struct blkcipher_desc *desc, 28698971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 28798971f84SJan Glauber unsigned int nbytes) 288a9e62fadSHerbert Xu { 289a9e62fadSHerbert Xu struct blkcipher_walk walk; 290a9e62fadSHerbert Xu 291a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 292edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192 | CPACF_DECRYPT, 2937bac4f5bSMartin Schwidefsky &walk); 294a9e62fadSHerbert Xu } 295a9e62fadSHerbert Xu 29698971f84SJan Glauber static struct crypto_alg ecb_des3_alg = { 297a9e62fadSHerbert Xu .cra_name = "ecb(des3_ede)", 298a9e62fadSHerbert Xu .cra_driver_name = "ecb-des3_ede-s390", 299c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ecb */ 300a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3011efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 30298971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 303a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 304a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 305a9e62fadSHerbert Xu .cra_u = { 306a9e62fadSHerbert Xu .blkcipher = { 30798971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 30898971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 30998971f84SJan Glauber .setkey = des3_setkey, 31098971f84SJan Glauber .encrypt = ecb_des3_encrypt, 31198971f84SJan Glauber .decrypt = ecb_des3_decrypt, 312a9e62fadSHerbert Xu } 313a9e62fadSHerbert Xu } 314a9e62fadSHerbert Xu }; 315a9e62fadSHerbert Xu 31698971f84SJan Glauber static int cbc_des3_encrypt(struct blkcipher_desc *desc, 31798971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 31898971f84SJan Glauber unsigned int nbytes) 319a9e62fadSHerbert Xu { 320a9e62fadSHerbert Xu struct blkcipher_walk walk; 321a9e62fadSHerbert Xu 322a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 323edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192, &walk); 324a9e62fadSHerbert Xu } 325a9e62fadSHerbert Xu 32698971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc, 32798971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 32898971f84SJan Glauber unsigned int nbytes) 329a9e62fadSHerbert Xu { 330a9e62fadSHerbert Xu struct blkcipher_walk walk; 331a9e62fadSHerbert Xu 332a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 333edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192 | CPACF_DECRYPT, 334edc63a37SMartin Schwidefsky &walk); 335a9e62fadSHerbert Xu } 336a9e62fadSHerbert Xu 33798971f84SJan Glauber static struct crypto_alg cbc_des3_alg = { 338a9e62fadSHerbert Xu .cra_name = "cbc(des3_ede)", 339a9e62fadSHerbert Xu .cra_driver_name = "cbc-des3_ede-s390", 340c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + cbc */ 341a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3421efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 34398971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 344a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 345a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 346a9e62fadSHerbert Xu .cra_u = { 347a9e62fadSHerbert Xu .blkcipher = { 34898971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 34998971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 3501efbd15cSJan Glauber .ivsize = DES_BLOCK_SIZE, 35198971f84SJan Glauber .setkey = des3_setkey, 35298971f84SJan Glauber .encrypt = cbc_des3_encrypt, 35398971f84SJan Glauber .decrypt = cbc_des3_decrypt, 354a9e62fadSHerbert Xu } 355a9e62fadSHerbert Xu } 356a9e62fadSHerbert Xu }; 357a9e62fadSHerbert Xu 3587bac4f5bSMartin Schwidefsky static unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes) 359ee97dc7dSHarald Freudenberger { 360ee97dc7dSHarald Freudenberger unsigned int i, n; 361ee97dc7dSHarald Freudenberger 362ee97dc7dSHarald Freudenberger /* align to block size, max. PAGE_SIZE */ 363ee97dc7dSHarald Freudenberger n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); 3647bac4f5bSMartin Schwidefsky memcpy(ctrptr, iv, DES_BLOCK_SIZE); 3657bac4f5bSMartin Schwidefsky for (i = (n / DES_BLOCK_SIZE) - 1; i > 0; i--) { 3667bac4f5bSMartin Schwidefsky memcpy(ctrptr + DES_BLOCK_SIZE, ctrptr, DES_BLOCK_SIZE); 3677bac4f5bSMartin Schwidefsky crypto_inc(ctrptr + DES_BLOCK_SIZE, DES_BLOCK_SIZE); 3687bac4f5bSMartin Schwidefsky ctrptr += DES_BLOCK_SIZE; 369ee97dc7dSHarald Freudenberger } 370ee97dc7dSHarald Freudenberger return n; 371ee97dc7dSHarald Freudenberger } 372ee97dc7dSHarald Freudenberger 3737bac4f5bSMartin Schwidefsky static int ctr_desall_crypt(struct blkcipher_desc *desc, unsigned long fc, 374ee97dc7dSHarald Freudenberger struct blkcipher_walk *walk) 3750200f3ecSGerald Schaefer { 3767bac4f5bSMartin Schwidefsky struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 3777bac4f5bSMartin Schwidefsky u8 buf[DES_BLOCK_SIZE], *ctrptr; 378ee97dc7dSHarald Freudenberger unsigned int n, nbytes; 3797bac4f5bSMartin Schwidefsky int ret, locked; 3800200f3ecSGerald Schaefer 3817bac4f5bSMartin Schwidefsky locked = spin_trylock(&ctrblk_lock); 382ee97dc7dSHarald Freudenberger 3837bac4f5bSMartin Schwidefsky ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); 3840200f3ecSGerald Schaefer while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 385ee97dc7dSHarald Freudenberger n = DES_BLOCK_SIZE; 3867bac4f5bSMartin Schwidefsky if (nbytes >= 2*DES_BLOCK_SIZE && locked) 3877bac4f5bSMartin Schwidefsky n = __ctrblk_init(ctrblk, walk->iv, nbytes); 3887bac4f5bSMartin Schwidefsky ctrptr = (n > DES_BLOCK_SIZE) ? ctrblk : walk->iv; 3897bac4f5bSMartin Schwidefsky cpacf_kmctr(fc, ctx->key, walk->dst.virt.addr, 3907bac4f5bSMartin Schwidefsky walk->src.virt.addr, n, ctrptr); 3917bac4f5bSMartin Schwidefsky if (ctrptr == ctrblk) 3927bac4f5bSMartin Schwidefsky memcpy(walk->iv, ctrptr + n - DES_BLOCK_SIZE, 3930200f3ecSGerald Schaefer DES_BLOCK_SIZE); 3947bac4f5bSMartin Schwidefsky crypto_inc(walk->iv, DES_BLOCK_SIZE); 3957bac4f5bSMartin Schwidefsky ret = blkcipher_walk_done(desc, walk, nbytes - n); 3960200f3ecSGerald Schaefer } 3977bac4f5bSMartin Schwidefsky if (locked) 398ee97dc7dSHarald Freudenberger spin_unlock(&ctrblk_lock); 3990200f3ecSGerald Schaefer /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ 4000200f3ecSGerald Schaefer if (nbytes) { 4017bac4f5bSMartin Schwidefsky cpacf_kmctr(fc, ctx->key, buf, walk->src.virt.addr, 4027bac4f5bSMartin Schwidefsky DES_BLOCK_SIZE, walk->iv); 4037bac4f5bSMartin Schwidefsky memcpy(walk->dst.virt.addr, buf, nbytes); 4047bac4f5bSMartin Schwidefsky crypto_inc(walk->iv, DES_BLOCK_SIZE); 4050200f3ecSGerald Schaefer ret = blkcipher_walk_done(desc, walk, 0); 4060200f3ecSGerald Schaefer } 4070200f3ecSGerald Schaefer return ret; 4080200f3ecSGerald Schaefer } 4090200f3ecSGerald Schaefer 4100200f3ecSGerald Schaefer static int ctr_des_encrypt(struct blkcipher_desc *desc, 4110200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4120200f3ecSGerald Schaefer unsigned int nbytes) 4130200f3ecSGerald Schaefer { 4140200f3ecSGerald Schaefer struct blkcipher_walk walk; 4150200f3ecSGerald Schaefer 4160200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4177bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA, &walk); 4180200f3ecSGerald Schaefer } 4190200f3ecSGerald Schaefer 4200200f3ecSGerald Schaefer static int ctr_des_decrypt(struct blkcipher_desc *desc, 4210200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4220200f3ecSGerald Schaefer unsigned int nbytes) 4230200f3ecSGerald Schaefer { 4240200f3ecSGerald Schaefer struct blkcipher_walk walk; 4250200f3ecSGerald Schaefer 4260200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4277bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA | CPACF_DECRYPT, &walk); 4280200f3ecSGerald Schaefer } 4290200f3ecSGerald Schaefer 4300200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = { 4310200f3ecSGerald Schaefer .cra_name = "ctr(des)", 4320200f3ecSGerald Schaefer .cra_driver_name = "ctr-des-s390", 433c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ctr */ 4340200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 4350200f3ecSGerald Schaefer .cra_blocksize = 1, 4360200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 4370200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 4380200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 4390200f3ecSGerald Schaefer .cra_u = { 4400200f3ecSGerald Schaefer .blkcipher = { 4410200f3ecSGerald Schaefer .min_keysize = DES_KEY_SIZE, 4420200f3ecSGerald Schaefer .max_keysize = DES_KEY_SIZE, 4430200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4440200f3ecSGerald Schaefer .setkey = des_setkey, 4450200f3ecSGerald Schaefer .encrypt = ctr_des_encrypt, 4460200f3ecSGerald Schaefer .decrypt = ctr_des_decrypt, 4470200f3ecSGerald Schaefer } 4480200f3ecSGerald Schaefer } 4490200f3ecSGerald Schaefer }; 4500200f3ecSGerald Schaefer 4510200f3ecSGerald Schaefer static int ctr_des3_encrypt(struct blkcipher_desc *desc, 4520200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4530200f3ecSGerald Schaefer unsigned int nbytes) 4540200f3ecSGerald Schaefer { 4550200f3ecSGerald Schaefer struct blkcipher_walk walk; 4560200f3ecSGerald Schaefer 4570200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 4587bac4f5bSMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192, &walk); 4590200f3ecSGerald Schaefer } 4600200f3ecSGerald Schaefer 4610200f3ecSGerald Schaefer static int ctr_des3_decrypt(struct blkcipher_desc *desc, 4620200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4630200f3ecSGerald Schaefer unsigned int nbytes) 4640200f3ecSGerald Schaefer { 4650200f3ecSGerald Schaefer struct blkcipher_walk walk; 4660200f3ecSGerald Schaefer 4670200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 468edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192 | CPACF_DECRYPT, 4697bac4f5bSMartin Schwidefsky &walk); 4700200f3ecSGerald Schaefer } 4710200f3ecSGerald Schaefer 4720200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = { 4730200f3ecSGerald Schaefer .cra_name = "ctr(des3_ede)", 4740200f3ecSGerald Schaefer .cra_driver_name = "ctr-des3_ede-s390", 475c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ede */ 4760200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 4770200f3ecSGerald Schaefer .cra_blocksize = 1, 4780200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 4790200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 4800200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 4810200f3ecSGerald Schaefer .cra_u = { 4820200f3ecSGerald Schaefer .blkcipher = { 4830200f3ecSGerald Schaefer .min_keysize = DES3_KEY_SIZE, 4840200f3ecSGerald Schaefer .max_keysize = DES3_KEY_SIZE, 4850200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4860200f3ecSGerald Schaefer .setkey = des3_setkey, 4870200f3ecSGerald Schaefer .encrypt = ctr_des3_encrypt, 4880200f3ecSGerald Schaefer .decrypt = ctr_des3_decrypt, 4890200f3ecSGerald Schaefer } 4900200f3ecSGerald Schaefer } 4910200f3ecSGerald Schaefer }; 4920200f3ecSGerald Schaefer 493d863d594SMartin Schwidefsky static struct crypto_alg *des_s390_algs_ptr[8]; 494d863d594SMartin Schwidefsky static int des_s390_algs_num; 495d863d594SMartin Schwidefsky 496d863d594SMartin Schwidefsky static int des_s390_register_alg(struct crypto_alg *alg) 497d863d594SMartin Schwidefsky { 498d863d594SMartin Schwidefsky int ret; 499d863d594SMartin Schwidefsky 500d863d594SMartin Schwidefsky ret = crypto_register_alg(alg); 501d863d594SMartin Schwidefsky if (!ret) 502d863d594SMartin Schwidefsky des_s390_algs_ptr[des_s390_algs_num++] = alg; 503d863d594SMartin Schwidefsky return ret; 504d863d594SMartin Schwidefsky } 505d863d594SMartin Schwidefsky 506d863d594SMartin Schwidefsky static void des_s390_exit(void) 507d863d594SMartin Schwidefsky { 508d863d594SMartin Schwidefsky while (des_s390_algs_num--) 509d863d594SMartin Schwidefsky crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]); 510d863d594SMartin Schwidefsky if (ctrblk) 511d863d594SMartin Schwidefsky free_page((unsigned long) ctrblk); 512d863d594SMartin Schwidefsky } 513d863d594SMartin Schwidefsky 51498971f84SJan Glauber static int __init des_s390_init(void) 515c1e26e1eSJan Glauber { 51680d663a4SJan Glauber int ret; 517c1e26e1eSJan Glauber 51869c0e360SMartin Schwidefsky /* Query available functions for KM, KMC and KMCTR */ 51969c0e360SMartin Schwidefsky cpacf_query(CPACF_KM, &km_functions); 52069c0e360SMartin Schwidefsky cpacf_query(CPACF_KMC, &kmc_functions); 52169c0e360SMartin Schwidefsky cpacf_query(CPACF_KMCTR, &kmctr_functions); 522c1e26e1eSJan Glauber 52369c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) { 524d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des_alg); 525a9e62fadSHerbert Xu if (ret) 526d863d594SMartin Schwidefsky goto out_err; 527d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des_alg); 528a9e62fadSHerbert Xu if (ret) 529d863d594SMartin Schwidefsky goto out_err; 53069c0e360SMartin Schwidefsky } 53169c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) { 532d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des_alg); 533a9e62fadSHerbert Xu if (ret) 534d863d594SMartin Schwidefsky goto out_err; 53569c0e360SMartin Schwidefsky } 53669c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) { 537d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des3_alg); 538a9e62fadSHerbert Xu if (ret) 539d863d594SMartin Schwidefsky goto out_err; 540d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des3_alg); 541a9e62fadSHerbert Xu if (ret) 542d863d594SMartin Schwidefsky goto out_err; 54369c0e360SMartin Schwidefsky } 54469c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) { 545d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des3_alg); 546a9e62fadSHerbert Xu if (ret) 547d863d594SMartin Schwidefsky goto out_err; 54869c0e360SMartin Schwidefsky } 5490200f3ecSGerald Schaefer 55069c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) || 55169c0e360SMartin Schwidefsky cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 5520200f3ecSGerald Schaefer ctrblk = (u8 *) __get_free_page(GFP_KERNEL); 5530200f3ecSGerald Schaefer if (!ctrblk) { 5540200f3ecSGerald Schaefer ret = -ENOMEM; 555d863d594SMartin Schwidefsky goto out_err; 5560200f3ecSGerald Schaefer } 55769c0e360SMartin Schwidefsky } 55869c0e360SMartin Schwidefsky 55969c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) { 560d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des_alg); 561d863d594SMartin Schwidefsky if (ret) 562d863d594SMartin Schwidefsky goto out_err; 56369c0e360SMartin Schwidefsky } 56469c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 565d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des3_alg); 566d863d594SMartin Schwidefsky if (ret) 567d863d594SMartin Schwidefsky goto out_err; 5680200f3ecSGerald Schaefer } 569d863d594SMartin Schwidefsky 570d863d594SMartin Schwidefsky return 0; 571d863d594SMartin Schwidefsky out_err: 572d863d594SMartin Schwidefsky des_s390_exit(); 573a9e62fadSHerbert Xu return ret; 574c1e26e1eSJan Glauber } 575c1e26e1eSJan Glauber 576d05377c1SHendrik Brueckner module_cpu_feature_match(MSA, des_s390_init); 5771efbd15cSJan Glauber module_exit(des_s390_exit); 578c1e26e1eSJan Glauber 5795d26a105SKees Cook MODULE_ALIAS_CRYPTO("des"); 5805d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede"); 581c1e26e1eSJan Glauber 582c1e26e1eSJan Glauber MODULE_LICENSE("GPL"); 583c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); 584