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 88a9e62fadSHerbert Xu static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, 8998971f84SJan Glauber u8 *key, struct blkcipher_walk *walk) 90a9e62fadSHerbert Xu { 91a9e62fadSHerbert Xu int ret = blkcipher_walk_virt(desc, walk); 92a9e62fadSHerbert Xu unsigned int nbytes; 93a9e62fadSHerbert Xu 94a9e62fadSHerbert Xu while ((nbytes = walk->nbytes)) { 95a9e62fadSHerbert Xu /* only use complete blocks */ 96a9e62fadSHerbert Xu unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); 97a9e62fadSHerbert Xu u8 *out = walk->dst.virt.addr; 98a9e62fadSHerbert Xu u8 *in = walk->src.virt.addr; 99a9e62fadSHerbert Xu 1000177db01SMartin Schwidefsky cpacf_km(func, key, out, in, n); 101a9e62fadSHerbert Xu 102a9e62fadSHerbert Xu nbytes &= DES_BLOCK_SIZE - 1; 103a9e62fadSHerbert Xu ret = blkcipher_walk_done(desc, walk, nbytes); 104a9e62fadSHerbert Xu } 105a9e62fadSHerbert Xu 106a9e62fadSHerbert Xu return ret; 107a9e62fadSHerbert Xu } 108a9e62fadSHerbert Xu 109a9e62fadSHerbert Xu static int cbc_desall_crypt(struct blkcipher_desc *desc, long func, 110adc3fcf1SHarald Freudenberger struct blkcipher_walk *walk) 111a9e62fadSHerbert Xu { 112adc3fcf1SHarald Freudenberger struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 113a9e62fadSHerbert Xu int ret = blkcipher_walk_virt(desc, walk); 114a9e62fadSHerbert Xu unsigned int nbytes = walk->nbytes; 115adc3fcf1SHarald Freudenberger struct { 116adc3fcf1SHarald Freudenberger u8 iv[DES_BLOCK_SIZE]; 117adc3fcf1SHarald Freudenberger u8 key[DES3_KEY_SIZE]; 118adc3fcf1SHarald Freudenberger } param; 119a9e62fadSHerbert Xu 120a9e62fadSHerbert Xu if (!nbytes) 121a9e62fadSHerbert Xu goto out; 122a9e62fadSHerbert Xu 123adc3fcf1SHarald Freudenberger memcpy(param.iv, walk->iv, DES_BLOCK_SIZE); 124adc3fcf1SHarald Freudenberger memcpy(param.key, ctx->key, DES3_KEY_SIZE); 125a9e62fadSHerbert Xu do { 126a9e62fadSHerbert Xu /* only use complete blocks */ 127a9e62fadSHerbert Xu unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); 128a9e62fadSHerbert Xu u8 *out = walk->dst.virt.addr; 129a9e62fadSHerbert Xu u8 *in = walk->src.virt.addr; 130a9e62fadSHerbert Xu 1310177db01SMartin Schwidefsky cpacf_kmc(func, ¶m, out, in, n); 132a9e62fadSHerbert Xu 133a9e62fadSHerbert Xu nbytes &= DES_BLOCK_SIZE - 1; 134a9e62fadSHerbert Xu ret = blkcipher_walk_done(desc, walk, nbytes); 135a9e62fadSHerbert Xu } while ((nbytes = walk->nbytes)); 136adc3fcf1SHarald Freudenberger memcpy(walk->iv, param.iv, DES_BLOCK_SIZE); 137a9e62fadSHerbert Xu 138a9e62fadSHerbert Xu out: 139a9e62fadSHerbert Xu return ret; 140a9e62fadSHerbert Xu } 141a9e62fadSHerbert Xu 142a9e62fadSHerbert Xu static int ecb_des_encrypt(struct blkcipher_desc *desc, 143a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 144a9e62fadSHerbert Xu unsigned int nbytes) 145a9e62fadSHerbert Xu { 14698971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 147a9e62fadSHerbert Xu struct blkcipher_walk walk; 148a9e62fadSHerbert Xu 149a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 150edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA, ctx->key, &walk); 151a9e62fadSHerbert Xu } 152a9e62fadSHerbert Xu 153a9e62fadSHerbert Xu static int ecb_des_decrypt(struct blkcipher_desc *desc, 154a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 155a9e62fadSHerbert Xu unsigned int nbytes) 156a9e62fadSHerbert Xu { 15798971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 158a9e62fadSHerbert Xu struct blkcipher_walk walk; 159a9e62fadSHerbert Xu 160a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 161edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA | CPACF_DECRYPT, 162edc63a37SMartin Schwidefsky ctx->key, &walk); 163a9e62fadSHerbert Xu } 164a9e62fadSHerbert Xu 165a9e62fadSHerbert Xu static struct crypto_alg ecb_des_alg = { 166a9e62fadSHerbert Xu .cra_name = "ecb(des)", 167a9e62fadSHerbert Xu .cra_driver_name = "ecb-des-s390", 168c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ecb */ 169a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 170a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 17198971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 172a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 173a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 174a9e62fadSHerbert Xu .cra_u = { 175a9e62fadSHerbert Xu .blkcipher = { 176a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 177a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 178a9e62fadSHerbert Xu .setkey = des_setkey, 179a9e62fadSHerbert Xu .encrypt = ecb_des_encrypt, 180a9e62fadSHerbert Xu .decrypt = ecb_des_decrypt, 181a9e62fadSHerbert Xu } 182a9e62fadSHerbert Xu } 183a9e62fadSHerbert Xu }; 184a9e62fadSHerbert Xu 185a9e62fadSHerbert Xu static int cbc_des_encrypt(struct blkcipher_desc *desc, 186a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 187a9e62fadSHerbert Xu unsigned int nbytes) 188a9e62fadSHerbert Xu { 189a9e62fadSHerbert Xu struct blkcipher_walk walk; 190a9e62fadSHerbert Xu 191a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 192edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA, &walk); 193a9e62fadSHerbert Xu } 194a9e62fadSHerbert Xu 195a9e62fadSHerbert Xu static int cbc_des_decrypt(struct blkcipher_desc *desc, 196a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 197a9e62fadSHerbert Xu unsigned int nbytes) 198a9e62fadSHerbert Xu { 199a9e62fadSHerbert Xu struct blkcipher_walk walk; 200a9e62fadSHerbert Xu 201a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 202edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA | CPACF_DECRYPT, &walk); 203a9e62fadSHerbert Xu } 204a9e62fadSHerbert Xu 205a9e62fadSHerbert Xu static struct crypto_alg cbc_des_alg = { 206a9e62fadSHerbert Xu .cra_name = "cbc(des)", 207a9e62fadSHerbert Xu .cra_driver_name = "cbc-des-s390", 208c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + cbc */ 209a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 210a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 21198971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 212a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 213a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 214a9e62fadSHerbert Xu .cra_u = { 215a9e62fadSHerbert Xu .blkcipher = { 216a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 217a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 218a9e62fadSHerbert Xu .ivsize = DES_BLOCK_SIZE, 219a9e62fadSHerbert Xu .setkey = des_setkey, 220a9e62fadSHerbert Xu .encrypt = cbc_des_encrypt, 221a9e62fadSHerbert Xu .decrypt = cbc_des_decrypt, 222a9e62fadSHerbert Xu } 223a9e62fadSHerbert Xu } 224a9e62fadSHerbert Xu }; 225a9e62fadSHerbert Xu 226c1e26e1eSJan Glauber /* 227c1e26e1eSJan Glauber * RFC2451: 228c1e26e1eSJan Glauber * 229c1e26e1eSJan Glauber * For DES-EDE3, there is no known need to reject weak or 230c1e26e1eSJan Glauber * complementation keys. Any weakness is obviated by the use of 231c1e26e1eSJan Glauber * multiple keys. 232c1e26e1eSJan Glauber * 233c1e26e1eSJan Glauber * However, if the first two or last two independent 64-bit keys are 234c1e26e1eSJan Glauber * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the 235c1e26e1eSJan Glauber * same as DES. Implementers MUST reject keys that exhibit this 236c1e26e1eSJan Glauber * property. 237c1e26e1eSJan Glauber * 238c1e26e1eSJan Glauber */ 23998971f84SJan Glauber static int des3_setkey(struct crypto_tfm *tfm, const u8 *key, 24098971f84SJan Glauber unsigned int key_len) 241c1e26e1eSJan Glauber { 24298971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 243c1e26e1eSJan Glauber 244fed28611SDaniel Borkmann if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && 245fed28611SDaniel Borkmann crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], 24603b56ce5SJarod Wilson DES_KEY_SIZE)) && 24769c0e360SMartin Schwidefsky (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) { 24869c0e360SMartin Schwidefsky tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY; 249c1e26e1eSJan Glauber return -EINVAL; 250c1e26e1eSJan Glauber } 25198971f84SJan Glauber memcpy(ctx->key, key, key_len); 252c1e26e1eSJan Glauber return 0; 253c1e26e1eSJan Glauber } 254c1e26e1eSJan Glauber 25598971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 256c1e26e1eSJan Glauber { 25798971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 258c1e26e1eSJan Glauber 259edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE); 260c1e26e1eSJan Glauber } 261c1e26e1eSJan Glauber 26298971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 263c1e26e1eSJan Glauber { 26498971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 265c1e26e1eSJan Glauber 266edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT, 267edc63a37SMartin Schwidefsky ctx->key, dst, src, DES_BLOCK_SIZE); 268c1e26e1eSJan Glauber } 269c1e26e1eSJan Glauber 27098971f84SJan Glauber static struct crypto_alg des3_alg = { 271c1e26e1eSJan Glauber .cra_name = "des3_ede", 27265b75c36SHerbert Xu .cra_driver_name = "des3_ede-s390", 273c7d4d259SMartin Schwidefsky .cra_priority = 300, 274c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2751efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 27698971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 277c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 278c1357833SJan Glauber .cra_u = { 279c1357833SJan Glauber .cipher = { 28098971f84SJan Glauber .cia_min_keysize = DES3_KEY_SIZE, 28198971f84SJan Glauber .cia_max_keysize = DES3_KEY_SIZE, 28298971f84SJan Glauber .cia_setkey = des3_setkey, 28398971f84SJan Glauber .cia_encrypt = des3_encrypt, 28498971f84SJan Glauber .cia_decrypt = des3_decrypt, 285c1357833SJan Glauber } 286c1357833SJan Glauber } 287c1e26e1eSJan Glauber }; 288c1e26e1eSJan Glauber 28998971f84SJan Glauber static int ecb_des3_encrypt(struct blkcipher_desc *desc, 29098971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 29198971f84SJan Glauber unsigned int nbytes) 292a9e62fadSHerbert Xu { 29398971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 294a9e62fadSHerbert Xu struct blkcipher_walk walk; 295a9e62fadSHerbert Xu 296a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 297edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192, ctx->key, &walk); 298a9e62fadSHerbert Xu } 299a9e62fadSHerbert Xu 30098971f84SJan Glauber static int ecb_des3_decrypt(struct blkcipher_desc *desc, 30198971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 30298971f84SJan Glauber unsigned int nbytes) 303a9e62fadSHerbert Xu { 30498971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 305a9e62fadSHerbert Xu struct blkcipher_walk walk; 306a9e62fadSHerbert Xu 307a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 308edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192 | CPACF_DECRYPT, 309edc63a37SMartin Schwidefsky ctx->key, &walk); 310a9e62fadSHerbert Xu } 311a9e62fadSHerbert Xu 31298971f84SJan Glauber static struct crypto_alg ecb_des3_alg = { 313a9e62fadSHerbert Xu .cra_name = "ecb(des3_ede)", 314a9e62fadSHerbert Xu .cra_driver_name = "ecb-des3_ede-s390", 315c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ecb */ 316a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3171efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 31898971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 319a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 320a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 321a9e62fadSHerbert Xu .cra_u = { 322a9e62fadSHerbert Xu .blkcipher = { 32398971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 32498971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 32598971f84SJan Glauber .setkey = des3_setkey, 32698971f84SJan Glauber .encrypt = ecb_des3_encrypt, 32798971f84SJan Glauber .decrypt = ecb_des3_decrypt, 328a9e62fadSHerbert Xu } 329a9e62fadSHerbert Xu } 330a9e62fadSHerbert Xu }; 331a9e62fadSHerbert Xu 33298971f84SJan Glauber static int cbc_des3_encrypt(struct blkcipher_desc *desc, 33398971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 33498971f84SJan Glauber unsigned int nbytes) 335a9e62fadSHerbert Xu { 336a9e62fadSHerbert Xu struct blkcipher_walk walk; 337a9e62fadSHerbert Xu 338a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 339edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192, &walk); 340a9e62fadSHerbert Xu } 341a9e62fadSHerbert Xu 34298971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc, 34398971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 34498971f84SJan Glauber unsigned int nbytes) 345a9e62fadSHerbert Xu { 346a9e62fadSHerbert Xu struct blkcipher_walk walk; 347a9e62fadSHerbert Xu 348a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 349edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192 | CPACF_DECRYPT, 350edc63a37SMartin Schwidefsky &walk); 351a9e62fadSHerbert Xu } 352a9e62fadSHerbert Xu 35398971f84SJan Glauber static struct crypto_alg cbc_des3_alg = { 354a9e62fadSHerbert Xu .cra_name = "cbc(des3_ede)", 355a9e62fadSHerbert Xu .cra_driver_name = "cbc-des3_ede-s390", 356c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + cbc */ 357a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3581efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 35998971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 360a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 361a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 362a9e62fadSHerbert Xu .cra_u = { 363a9e62fadSHerbert Xu .blkcipher = { 36498971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 36598971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 3661efbd15cSJan Glauber .ivsize = DES_BLOCK_SIZE, 36798971f84SJan Glauber .setkey = des3_setkey, 36898971f84SJan Glauber .encrypt = cbc_des3_encrypt, 36998971f84SJan Glauber .decrypt = cbc_des3_decrypt, 370a9e62fadSHerbert Xu } 371a9e62fadSHerbert Xu } 372a9e62fadSHerbert Xu }; 373a9e62fadSHerbert Xu 374ee97dc7dSHarald Freudenberger static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes) 375ee97dc7dSHarald Freudenberger { 376ee97dc7dSHarald Freudenberger unsigned int i, n; 377ee97dc7dSHarald Freudenberger 378ee97dc7dSHarald Freudenberger /* align to block size, max. PAGE_SIZE */ 379ee97dc7dSHarald Freudenberger n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); 380ee97dc7dSHarald Freudenberger for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) { 381ee97dc7dSHarald Freudenberger memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE); 382ee97dc7dSHarald Freudenberger crypto_inc(ctrptr + i, DES_BLOCK_SIZE); 383ee97dc7dSHarald Freudenberger } 384ee97dc7dSHarald Freudenberger return n; 385ee97dc7dSHarald Freudenberger } 386ee97dc7dSHarald Freudenberger 3870200f3ecSGerald Schaefer static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, 388ee97dc7dSHarald Freudenberger struct s390_des_ctx *ctx, 389ee97dc7dSHarald Freudenberger struct blkcipher_walk *walk) 3900200f3ecSGerald Schaefer { 3910200f3ecSGerald Schaefer int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); 392ee97dc7dSHarald Freudenberger unsigned int n, nbytes; 393ee97dc7dSHarald Freudenberger u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE]; 394ee97dc7dSHarald Freudenberger u8 *out, *in, *ctrptr = ctrbuf; 3950200f3ecSGerald Schaefer 396ee97dc7dSHarald Freudenberger if (!walk->nbytes) 397ee97dc7dSHarald Freudenberger return ret; 398ee97dc7dSHarald Freudenberger 399ee97dc7dSHarald Freudenberger if (spin_trylock(&ctrblk_lock)) 400ee97dc7dSHarald Freudenberger ctrptr = ctrblk; 401ee97dc7dSHarald Freudenberger 402ee97dc7dSHarald Freudenberger memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE); 4030200f3ecSGerald Schaefer while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 4040200f3ecSGerald Schaefer out = walk->dst.virt.addr; 4050200f3ecSGerald Schaefer in = walk->src.virt.addr; 4060200f3ecSGerald Schaefer while (nbytes >= DES_BLOCK_SIZE) { 407ee97dc7dSHarald Freudenberger if (ctrptr == ctrblk) 408ee97dc7dSHarald Freudenberger n = __ctrblk_init(ctrptr, nbytes); 409ee97dc7dSHarald Freudenberger else 410ee97dc7dSHarald Freudenberger n = DES_BLOCK_SIZE; 4110177db01SMartin Schwidefsky cpacf_kmctr(func, ctx->key, out, in, n, ctrptr); 4120200f3ecSGerald Schaefer if (n > DES_BLOCK_SIZE) 413ee97dc7dSHarald Freudenberger memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE, 4140200f3ecSGerald Schaefer DES_BLOCK_SIZE); 415ee97dc7dSHarald Freudenberger crypto_inc(ctrptr, DES_BLOCK_SIZE); 4160200f3ecSGerald Schaefer out += n; 4170200f3ecSGerald Schaefer in += n; 4180200f3ecSGerald Schaefer nbytes -= n; 4190200f3ecSGerald Schaefer } 4200200f3ecSGerald Schaefer ret = blkcipher_walk_done(desc, walk, nbytes); 4210200f3ecSGerald Schaefer } 422ee97dc7dSHarald Freudenberger if (ctrptr == ctrblk) { 423ee97dc7dSHarald Freudenberger if (nbytes) 424ee97dc7dSHarald Freudenberger memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE); 425ee97dc7dSHarald Freudenberger else 426ee97dc7dSHarald Freudenberger memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE); 427ee97dc7dSHarald Freudenberger spin_unlock(&ctrblk_lock); 4283901c112SHarald Freudenberger } else { 4293901c112SHarald Freudenberger if (!nbytes) 4303901c112SHarald Freudenberger memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE); 431ee97dc7dSHarald Freudenberger } 4320200f3ecSGerald Schaefer /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ 4330200f3ecSGerald Schaefer if (nbytes) { 4340200f3ecSGerald Schaefer out = walk->dst.virt.addr; 4350200f3ecSGerald Schaefer in = walk->src.virt.addr; 4360177db01SMartin Schwidefsky cpacf_kmctr(func, ctx->key, buf, in, DES_BLOCK_SIZE, ctrbuf); 4370200f3ecSGerald Schaefer memcpy(out, buf, nbytes); 438ee97dc7dSHarald Freudenberger crypto_inc(ctrbuf, DES_BLOCK_SIZE); 4390200f3ecSGerald Schaefer ret = blkcipher_walk_done(desc, walk, 0); 440ee97dc7dSHarald Freudenberger memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE); 4410200f3ecSGerald Schaefer } 4420200f3ecSGerald Schaefer return ret; 4430200f3ecSGerald Schaefer } 4440200f3ecSGerald Schaefer 4450200f3ecSGerald Schaefer static int ctr_des_encrypt(struct blkcipher_desc *desc, 4460200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4470200f3ecSGerald Schaefer unsigned int nbytes) 4480200f3ecSGerald Schaefer { 4490200f3ecSGerald Schaefer struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 4500200f3ecSGerald Schaefer struct blkcipher_walk walk; 4510200f3ecSGerald Schaefer 4520200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 453edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA, ctx, &walk); 4540200f3ecSGerald Schaefer } 4550200f3ecSGerald Schaefer 4560200f3ecSGerald Schaefer static int ctr_des_decrypt(struct blkcipher_desc *desc, 4570200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4580200f3ecSGerald Schaefer unsigned int nbytes) 4590200f3ecSGerald Schaefer { 4600200f3ecSGerald Schaefer struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 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_DEA | CPACF_DECRYPT, 465edc63a37SMartin Schwidefsky ctx, &walk); 4660200f3ecSGerald Schaefer } 4670200f3ecSGerald Schaefer 4680200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = { 4690200f3ecSGerald Schaefer .cra_name = "ctr(des)", 4700200f3ecSGerald Schaefer .cra_driver_name = "ctr-des-s390", 471c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ctr */ 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 = DES_KEY_SIZE, 4800200f3ecSGerald Schaefer .max_keysize = DES_KEY_SIZE, 4810200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4820200f3ecSGerald Schaefer .setkey = des_setkey, 4830200f3ecSGerald Schaefer .encrypt = ctr_des_encrypt, 4840200f3ecSGerald Schaefer .decrypt = ctr_des_decrypt, 4850200f3ecSGerald Schaefer } 4860200f3ecSGerald Schaefer } 4870200f3ecSGerald Schaefer }; 4880200f3ecSGerald Schaefer 4890200f3ecSGerald Schaefer static int ctr_des3_encrypt(struct blkcipher_desc *desc, 4900200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4910200f3ecSGerald Schaefer unsigned int nbytes) 4920200f3ecSGerald Schaefer { 4930200f3ecSGerald Schaefer struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 4940200f3ecSGerald Schaefer struct blkcipher_walk walk; 4950200f3ecSGerald Schaefer 4960200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 497edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192, ctx, &walk); 4980200f3ecSGerald Schaefer } 4990200f3ecSGerald Schaefer 5000200f3ecSGerald Schaefer static int ctr_des3_decrypt(struct blkcipher_desc *desc, 5010200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 5020200f3ecSGerald Schaefer unsigned int nbytes) 5030200f3ecSGerald Schaefer { 5040200f3ecSGerald Schaefer struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 5050200f3ecSGerald Schaefer struct blkcipher_walk walk; 5060200f3ecSGerald Schaefer 5070200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 508edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192 | CPACF_DECRYPT, 509edc63a37SMartin Schwidefsky ctx, &walk); 5100200f3ecSGerald Schaefer } 5110200f3ecSGerald Schaefer 5120200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = { 5130200f3ecSGerald Schaefer .cra_name = "ctr(des3_ede)", 5140200f3ecSGerald Schaefer .cra_driver_name = "ctr-des3_ede-s390", 515c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ede */ 5160200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 5170200f3ecSGerald Schaefer .cra_blocksize = 1, 5180200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 5190200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 5200200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 5210200f3ecSGerald Schaefer .cra_u = { 5220200f3ecSGerald Schaefer .blkcipher = { 5230200f3ecSGerald Schaefer .min_keysize = DES3_KEY_SIZE, 5240200f3ecSGerald Schaefer .max_keysize = DES3_KEY_SIZE, 5250200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 5260200f3ecSGerald Schaefer .setkey = des3_setkey, 5270200f3ecSGerald Schaefer .encrypt = ctr_des3_encrypt, 5280200f3ecSGerald Schaefer .decrypt = ctr_des3_decrypt, 5290200f3ecSGerald Schaefer } 5300200f3ecSGerald Schaefer } 5310200f3ecSGerald Schaefer }; 5320200f3ecSGerald Schaefer 533d863d594SMartin Schwidefsky static struct crypto_alg *des_s390_algs_ptr[8]; 534d863d594SMartin Schwidefsky static int des_s390_algs_num; 535d863d594SMartin Schwidefsky 536d863d594SMartin Schwidefsky static int des_s390_register_alg(struct crypto_alg *alg) 537d863d594SMartin Schwidefsky { 538d863d594SMartin Schwidefsky int ret; 539d863d594SMartin Schwidefsky 540d863d594SMartin Schwidefsky ret = crypto_register_alg(alg); 541d863d594SMartin Schwidefsky if (!ret) 542d863d594SMartin Schwidefsky des_s390_algs_ptr[des_s390_algs_num++] = alg; 543d863d594SMartin Schwidefsky return ret; 544d863d594SMartin Schwidefsky } 545d863d594SMartin Schwidefsky 546d863d594SMartin Schwidefsky static void des_s390_exit(void) 547d863d594SMartin Schwidefsky { 548d863d594SMartin Schwidefsky while (des_s390_algs_num--) 549d863d594SMartin Schwidefsky crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]); 550d863d594SMartin Schwidefsky if (ctrblk) 551d863d594SMartin Schwidefsky free_page((unsigned long) ctrblk); 552d863d594SMartin Schwidefsky } 553d863d594SMartin Schwidefsky 55498971f84SJan Glauber static int __init des_s390_init(void) 555c1e26e1eSJan Glauber { 55680d663a4SJan Glauber int ret; 557c1e26e1eSJan Glauber 55869c0e360SMartin Schwidefsky /* Query available functions for KM, KMC and KMCTR */ 55969c0e360SMartin Schwidefsky cpacf_query(CPACF_KM, &km_functions); 56069c0e360SMartin Schwidefsky cpacf_query(CPACF_KMC, &kmc_functions); 56169c0e360SMartin Schwidefsky cpacf_query(CPACF_KMCTR, &kmctr_functions); 562c1e26e1eSJan Glauber 56369c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) { 564d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des_alg); 565a9e62fadSHerbert Xu if (ret) 566d863d594SMartin Schwidefsky goto out_err; 567d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des_alg); 568a9e62fadSHerbert Xu if (ret) 569d863d594SMartin Schwidefsky goto out_err; 57069c0e360SMartin Schwidefsky } 57169c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) { 572d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des_alg); 573a9e62fadSHerbert Xu if (ret) 574d863d594SMartin Schwidefsky goto out_err; 57569c0e360SMartin Schwidefsky } 57669c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) { 577d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des3_alg); 578a9e62fadSHerbert Xu if (ret) 579d863d594SMartin Schwidefsky goto out_err; 580d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ecb_des3_alg); 581a9e62fadSHerbert Xu if (ret) 582d863d594SMartin Schwidefsky goto out_err; 58369c0e360SMartin Schwidefsky } 58469c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) { 585d863d594SMartin Schwidefsky ret = des_s390_register_alg(&cbc_des3_alg); 586a9e62fadSHerbert Xu if (ret) 587d863d594SMartin Schwidefsky goto out_err; 58869c0e360SMartin Schwidefsky } 5890200f3ecSGerald Schaefer 59069c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) || 59169c0e360SMartin Schwidefsky cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 5920200f3ecSGerald Schaefer ctrblk = (u8 *) __get_free_page(GFP_KERNEL); 5930200f3ecSGerald Schaefer if (!ctrblk) { 5940200f3ecSGerald Schaefer ret = -ENOMEM; 595d863d594SMartin Schwidefsky goto out_err; 5960200f3ecSGerald Schaefer } 59769c0e360SMartin Schwidefsky } 59869c0e360SMartin Schwidefsky 59969c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) { 600d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des_alg); 601d863d594SMartin Schwidefsky if (ret) 602d863d594SMartin Schwidefsky goto out_err; 60369c0e360SMartin Schwidefsky } 60469c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 605d863d594SMartin Schwidefsky ret = des_s390_register_alg(&ctr_des3_alg); 606d863d594SMartin Schwidefsky if (ret) 607d863d594SMartin Schwidefsky goto out_err; 6080200f3ecSGerald Schaefer } 609d863d594SMartin Schwidefsky 610d863d594SMartin Schwidefsky return 0; 611d863d594SMartin Schwidefsky out_err: 612d863d594SMartin Schwidefsky des_s390_exit(); 613a9e62fadSHerbert Xu return ret; 614c1e26e1eSJan Glauber } 615c1e26e1eSJan Glauber 616d05377c1SHendrik Brueckner module_cpu_feature_match(MSA, des_s390_init); 6171efbd15cSJan Glauber module_exit(des_s390_exit); 618c1e26e1eSJan Glauber 6195d26a105SKees Cook MODULE_ALIAS_CRYPTO("des"); 6205d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede"); 621c1e26e1eSJan Glauber 622c1e26e1eSJan Glauber MODULE_LICENSE("GPL"); 623c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); 624