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 3098971f84SJan Glauber struct s390_des_ctx { 31c1e26e1eSJan Glauber u8 iv[DES_BLOCK_SIZE]; 3298971f84SJan Glauber u8 key[DES3_KEY_SIZE]; 33c1e26e1eSJan Glauber }; 34c1e26e1eSJan Glauber 356c2bb98bSHerbert Xu static int des_setkey(struct crypto_tfm *tfm, const u8 *key, 3698971f84SJan Glauber unsigned int key_len) 37c1e26e1eSJan Glauber { 3898971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 39560c06aeSHerbert Xu u32 *flags = &tfm->crt_flags; 401efbd15cSJan Glauber u32 tmp[DES_EXPKEY_WORDS]; 41c1e26e1eSJan Glauber 421efbd15cSJan Glauber /* check for weak keys */ 431efbd15cSJan Glauber if (!des_ekey(tmp, key) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) { 441efbd15cSJan Glauber *flags |= CRYPTO_TFM_RES_WEAK_KEY; 451efbd15cSJan Glauber return -EINVAL; 461efbd15cSJan Glauber } 471efbd15cSJan Glauber 4898971f84SJan Glauber memcpy(ctx->key, key, key_len); 491efbd15cSJan Glauber return 0; 50c1e26e1eSJan Glauber } 51c1e26e1eSJan Glauber 526c2bb98bSHerbert Xu static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 53c1e26e1eSJan Glauber { 5498971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 55c1e26e1eSJan Glauber 56edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE); 57c1e26e1eSJan Glauber } 58c1e26e1eSJan Glauber 596c2bb98bSHerbert Xu static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 60c1e26e1eSJan Glauber { 6198971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 62c1e26e1eSJan Glauber 63edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT, 64edc63a37SMartin Schwidefsky ctx->key, out, in, DES_BLOCK_SIZE); 65b8dc6038SJan Glauber } 66b8dc6038SJan Glauber 67c1e26e1eSJan Glauber static struct crypto_alg des_alg = { 68c1e26e1eSJan Glauber .cra_name = "des", 6965b75c36SHerbert Xu .cra_driver_name = "des-s390", 70c7d4d259SMartin Schwidefsky .cra_priority = 300, 71c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 72c1e26e1eSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 7398971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 74c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 75c1357833SJan Glauber .cra_u = { 76c1357833SJan Glauber .cipher = { 77c1e26e1eSJan Glauber .cia_min_keysize = DES_KEY_SIZE, 78c1e26e1eSJan Glauber .cia_max_keysize = DES_KEY_SIZE, 79c1e26e1eSJan Glauber .cia_setkey = des_setkey, 80c1e26e1eSJan Glauber .cia_encrypt = des_encrypt, 81b8dc6038SJan Glauber .cia_decrypt = des_decrypt, 82c1357833SJan Glauber } 83c1357833SJan Glauber } 84c1e26e1eSJan Glauber }; 85c1e26e1eSJan Glauber 86a9e62fadSHerbert Xu static int ecb_desall_crypt(struct blkcipher_desc *desc, long func, 8798971f84SJan Glauber u8 *key, struct blkcipher_walk *walk) 88a9e62fadSHerbert Xu { 89a9e62fadSHerbert Xu int ret = blkcipher_walk_virt(desc, walk); 90a9e62fadSHerbert Xu unsigned int nbytes; 91a9e62fadSHerbert Xu 92a9e62fadSHerbert Xu while ((nbytes = walk->nbytes)) { 93a9e62fadSHerbert Xu /* only use complete blocks */ 94a9e62fadSHerbert Xu unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1); 95a9e62fadSHerbert Xu u8 *out = walk->dst.virt.addr; 96a9e62fadSHerbert Xu u8 *in = walk->src.virt.addr; 97a9e62fadSHerbert Xu 98c7d4d259SMartin Schwidefsky ret = cpacf_km(func, key, out, in, n); 9936eb2caaSJan Glauber if (ret < 0 || ret != n) 10036eb2caaSJan Glauber return -EIO; 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 131c7d4d259SMartin Schwidefsky ret = cpacf_kmc(func, ¶m, out, in, n); 13236eb2caaSJan Glauber if (ret < 0 || ret != n) 13336eb2caaSJan Glauber return -EIO; 134a9e62fadSHerbert Xu 135a9e62fadSHerbert Xu nbytes &= DES_BLOCK_SIZE - 1; 136a9e62fadSHerbert Xu ret = blkcipher_walk_done(desc, walk, nbytes); 137a9e62fadSHerbert Xu } while ((nbytes = walk->nbytes)); 138adc3fcf1SHarald Freudenberger memcpy(walk->iv, param.iv, DES_BLOCK_SIZE); 139a9e62fadSHerbert Xu 140a9e62fadSHerbert Xu out: 141a9e62fadSHerbert Xu return ret; 142a9e62fadSHerbert Xu } 143a9e62fadSHerbert Xu 144a9e62fadSHerbert Xu static int ecb_des_encrypt(struct blkcipher_desc *desc, 145a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 146a9e62fadSHerbert Xu unsigned int nbytes) 147a9e62fadSHerbert Xu { 14898971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 149a9e62fadSHerbert Xu struct blkcipher_walk walk; 150a9e62fadSHerbert Xu 151a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 152edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA, ctx->key, &walk); 153a9e62fadSHerbert Xu } 154a9e62fadSHerbert Xu 155a9e62fadSHerbert Xu static int ecb_des_decrypt(struct blkcipher_desc *desc, 156a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 157a9e62fadSHerbert Xu unsigned int nbytes) 158a9e62fadSHerbert Xu { 15998971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 160a9e62fadSHerbert Xu struct blkcipher_walk walk; 161a9e62fadSHerbert Xu 162a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 163edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_DEA | CPACF_DECRYPT, 164edc63a37SMartin Schwidefsky ctx->key, &walk); 165a9e62fadSHerbert Xu } 166a9e62fadSHerbert Xu 167a9e62fadSHerbert Xu static struct crypto_alg ecb_des_alg = { 168a9e62fadSHerbert Xu .cra_name = "ecb(des)", 169a9e62fadSHerbert Xu .cra_driver_name = "ecb-des-s390", 170c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ecb */ 171a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 172a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 17398971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 174a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 175a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 176a9e62fadSHerbert Xu .cra_u = { 177a9e62fadSHerbert Xu .blkcipher = { 178a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 179a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 180a9e62fadSHerbert Xu .setkey = des_setkey, 181a9e62fadSHerbert Xu .encrypt = ecb_des_encrypt, 182a9e62fadSHerbert Xu .decrypt = ecb_des_decrypt, 183a9e62fadSHerbert Xu } 184a9e62fadSHerbert Xu } 185a9e62fadSHerbert Xu }; 186a9e62fadSHerbert Xu 187a9e62fadSHerbert Xu static int cbc_des_encrypt(struct blkcipher_desc *desc, 188a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 189a9e62fadSHerbert Xu unsigned int nbytes) 190a9e62fadSHerbert Xu { 191a9e62fadSHerbert Xu struct blkcipher_walk walk; 192a9e62fadSHerbert Xu 193a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 194edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA, &walk); 195a9e62fadSHerbert Xu } 196a9e62fadSHerbert Xu 197a9e62fadSHerbert Xu static int cbc_des_decrypt(struct blkcipher_desc *desc, 198a9e62fadSHerbert Xu struct scatterlist *dst, struct scatterlist *src, 199a9e62fadSHerbert Xu unsigned int nbytes) 200a9e62fadSHerbert Xu { 201a9e62fadSHerbert Xu struct blkcipher_walk walk; 202a9e62fadSHerbert Xu 203a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 204edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_DEA | CPACF_DECRYPT, &walk); 205a9e62fadSHerbert Xu } 206a9e62fadSHerbert Xu 207a9e62fadSHerbert Xu static struct crypto_alg cbc_des_alg = { 208a9e62fadSHerbert Xu .cra_name = "cbc(des)", 209a9e62fadSHerbert Xu .cra_driver_name = "cbc-des-s390", 210c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + cbc */ 211a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 212a9e62fadSHerbert Xu .cra_blocksize = DES_BLOCK_SIZE, 21398971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 214a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 215a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 216a9e62fadSHerbert Xu .cra_u = { 217a9e62fadSHerbert Xu .blkcipher = { 218a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 219a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 220a9e62fadSHerbert Xu .ivsize = DES_BLOCK_SIZE, 221a9e62fadSHerbert Xu .setkey = des_setkey, 222a9e62fadSHerbert Xu .encrypt = cbc_des_encrypt, 223a9e62fadSHerbert Xu .decrypt = cbc_des_decrypt, 224a9e62fadSHerbert Xu } 225a9e62fadSHerbert Xu } 226a9e62fadSHerbert Xu }; 227a9e62fadSHerbert Xu 228c1e26e1eSJan Glauber /* 229c1e26e1eSJan Glauber * RFC2451: 230c1e26e1eSJan Glauber * 231c1e26e1eSJan Glauber * For DES-EDE3, there is no known need to reject weak or 232c1e26e1eSJan Glauber * complementation keys. Any weakness is obviated by the use of 233c1e26e1eSJan Glauber * multiple keys. 234c1e26e1eSJan Glauber * 235c1e26e1eSJan Glauber * However, if the first two or last two independent 64-bit keys are 236c1e26e1eSJan Glauber * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the 237c1e26e1eSJan Glauber * same as DES. Implementers MUST reject keys that exhibit this 238c1e26e1eSJan Glauber * property. 239c1e26e1eSJan Glauber * 240c1e26e1eSJan Glauber */ 24198971f84SJan Glauber static int des3_setkey(struct crypto_tfm *tfm, const u8 *key, 24298971f84SJan Glauber unsigned int key_len) 243c1e26e1eSJan Glauber { 24498971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 245560c06aeSHerbert Xu u32 *flags = &tfm->crt_flags; 246c1e26e1eSJan Glauber 247fed28611SDaniel Borkmann if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && 248fed28611SDaniel Borkmann crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], 24903b56ce5SJarod Wilson DES_KEY_SIZE)) && 25003b56ce5SJarod Wilson (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) { 25103b56ce5SJarod Wilson *flags |= CRYPTO_TFM_RES_WEAK_KEY; 252c1e26e1eSJan Glauber return -EINVAL; 253c1e26e1eSJan Glauber } 25498971f84SJan Glauber memcpy(ctx->key, key, key_len); 255c1e26e1eSJan Glauber return 0; 256c1e26e1eSJan Glauber } 257c1e26e1eSJan Glauber 25898971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 259c1e26e1eSJan Glauber { 26098971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 261c1e26e1eSJan Glauber 262edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE); 263c1e26e1eSJan Glauber } 264c1e26e1eSJan Glauber 26598971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 266c1e26e1eSJan Glauber { 26798971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 268c1e26e1eSJan Glauber 269edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT, 270edc63a37SMartin Schwidefsky ctx->key, dst, src, DES_BLOCK_SIZE); 271c1e26e1eSJan Glauber } 272c1e26e1eSJan Glauber 27398971f84SJan Glauber static struct crypto_alg des3_alg = { 274c1e26e1eSJan Glauber .cra_name = "des3_ede", 27565b75c36SHerbert Xu .cra_driver_name = "des3_ede-s390", 276c7d4d259SMartin Schwidefsky .cra_priority = 300, 277c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2781efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 27998971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 280c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 281c1357833SJan Glauber .cra_u = { 282c1357833SJan Glauber .cipher = { 28398971f84SJan Glauber .cia_min_keysize = DES3_KEY_SIZE, 28498971f84SJan Glauber .cia_max_keysize = DES3_KEY_SIZE, 28598971f84SJan Glauber .cia_setkey = des3_setkey, 28698971f84SJan Glauber .cia_encrypt = des3_encrypt, 28798971f84SJan Glauber .cia_decrypt = des3_decrypt, 288c1357833SJan Glauber } 289c1357833SJan Glauber } 290c1e26e1eSJan Glauber }; 291c1e26e1eSJan Glauber 29298971f84SJan Glauber static int ecb_des3_encrypt(struct blkcipher_desc *desc, 29398971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 29498971f84SJan Glauber unsigned int nbytes) 295a9e62fadSHerbert Xu { 29698971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 297a9e62fadSHerbert Xu struct blkcipher_walk walk; 298a9e62fadSHerbert Xu 299a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 300edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192, ctx->key, &walk); 301a9e62fadSHerbert Xu } 302a9e62fadSHerbert Xu 30398971f84SJan Glauber static int ecb_des3_decrypt(struct blkcipher_desc *desc, 30498971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 30598971f84SJan Glauber unsigned int nbytes) 306a9e62fadSHerbert Xu { 30798971f84SJan Glauber struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 308a9e62fadSHerbert Xu struct blkcipher_walk walk; 309a9e62fadSHerbert Xu 310a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 311edc63a37SMartin Schwidefsky return ecb_desall_crypt(desc, CPACF_KM_TDEA_192 | CPACF_DECRYPT, 312edc63a37SMartin Schwidefsky ctx->key, &walk); 313a9e62fadSHerbert Xu } 314a9e62fadSHerbert Xu 31598971f84SJan Glauber static struct crypto_alg ecb_des3_alg = { 316a9e62fadSHerbert Xu .cra_name = "ecb(des3_ede)", 317a9e62fadSHerbert Xu .cra_driver_name = "ecb-des3_ede-s390", 318c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ecb */ 319a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3201efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 32198971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 322a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 323a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 324a9e62fadSHerbert Xu .cra_u = { 325a9e62fadSHerbert Xu .blkcipher = { 32698971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 32798971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 32898971f84SJan Glauber .setkey = des3_setkey, 32998971f84SJan Glauber .encrypt = ecb_des3_encrypt, 33098971f84SJan Glauber .decrypt = ecb_des3_decrypt, 331a9e62fadSHerbert Xu } 332a9e62fadSHerbert Xu } 333a9e62fadSHerbert Xu }; 334a9e62fadSHerbert Xu 33598971f84SJan Glauber static int cbc_des3_encrypt(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, &walk); 343a9e62fadSHerbert Xu } 344a9e62fadSHerbert Xu 34598971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc, 34698971f84SJan Glauber struct scatterlist *dst, struct scatterlist *src, 34798971f84SJan Glauber unsigned int nbytes) 348a9e62fadSHerbert Xu { 349a9e62fadSHerbert Xu struct blkcipher_walk walk; 350a9e62fadSHerbert Xu 351a9e62fadSHerbert Xu blkcipher_walk_init(&walk, dst, src, nbytes); 352edc63a37SMartin Schwidefsky return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192 | CPACF_DECRYPT, 353edc63a37SMartin Schwidefsky &walk); 354a9e62fadSHerbert Xu } 355a9e62fadSHerbert Xu 35698971f84SJan Glauber static struct crypto_alg cbc_des3_alg = { 357a9e62fadSHerbert Xu .cra_name = "cbc(des3_ede)", 358a9e62fadSHerbert Xu .cra_driver_name = "cbc-des3_ede-s390", 359c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + cbc */ 360a9e62fadSHerbert Xu .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 3611efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 36298971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 363a9e62fadSHerbert Xu .cra_type = &crypto_blkcipher_type, 364a9e62fadSHerbert Xu .cra_module = THIS_MODULE, 365a9e62fadSHerbert Xu .cra_u = { 366a9e62fadSHerbert Xu .blkcipher = { 36798971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 36898971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 3691efbd15cSJan Glauber .ivsize = DES_BLOCK_SIZE, 37098971f84SJan Glauber .setkey = des3_setkey, 37198971f84SJan Glauber .encrypt = cbc_des3_encrypt, 37298971f84SJan Glauber .decrypt = cbc_des3_decrypt, 373a9e62fadSHerbert Xu } 374a9e62fadSHerbert Xu } 375a9e62fadSHerbert Xu }; 376a9e62fadSHerbert Xu 377ee97dc7dSHarald Freudenberger static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes) 378ee97dc7dSHarald Freudenberger { 379ee97dc7dSHarald Freudenberger unsigned int i, n; 380ee97dc7dSHarald Freudenberger 381ee97dc7dSHarald Freudenberger /* align to block size, max. PAGE_SIZE */ 382ee97dc7dSHarald Freudenberger n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); 383ee97dc7dSHarald Freudenberger for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) { 384ee97dc7dSHarald Freudenberger memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE); 385ee97dc7dSHarald Freudenberger crypto_inc(ctrptr + i, DES_BLOCK_SIZE); 386ee97dc7dSHarald Freudenberger } 387ee97dc7dSHarald Freudenberger return n; 388ee97dc7dSHarald Freudenberger } 389ee97dc7dSHarald Freudenberger 3900200f3ecSGerald Schaefer static int ctr_desall_crypt(struct blkcipher_desc *desc, long func, 391ee97dc7dSHarald Freudenberger struct s390_des_ctx *ctx, 392ee97dc7dSHarald Freudenberger struct blkcipher_walk *walk) 3930200f3ecSGerald Schaefer { 3940200f3ecSGerald Schaefer int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE); 395ee97dc7dSHarald Freudenberger unsigned int n, nbytes; 396ee97dc7dSHarald Freudenberger u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE]; 397ee97dc7dSHarald Freudenberger u8 *out, *in, *ctrptr = ctrbuf; 3980200f3ecSGerald Schaefer 399ee97dc7dSHarald Freudenberger if (!walk->nbytes) 400ee97dc7dSHarald Freudenberger return ret; 401ee97dc7dSHarald Freudenberger 402ee97dc7dSHarald Freudenberger if (spin_trylock(&ctrblk_lock)) 403ee97dc7dSHarald Freudenberger ctrptr = ctrblk; 404ee97dc7dSHarald Freudenberger 405ee97dc7dSHarald Freudenberger memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE); 4060200f3ecSGerald Schaefer while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) { 4070200f3ecSGerald Schaefer out = walk->dst.virt.addr; 4080200f3ecSGerald Schaefer in = walk->src.virt.addr; 4090200f3ecSGerald Schaefer while (nbytes >= DES_BLOCK_SIZE) { 410ee97dc7dSHarald Freudenberger if (ctrptr == ctrblk) 411ee97dc7dSHarald Freudenberger n = __ctrblk_init(ctrptr, nbytes); 412ee97dc7dSHarald Freudenberger else 413ee97dc7dSHarald Freudenberger n = DES_BLOCK_SIZE; 414c7d4d259SMartin Schwidefsky ret = cpacf_kmctr(func, ctx->key, out, in, n, ctrptr); 415ee97dc7dSHarald Freudenberger if (ret < 0 || ret != n) { 416ee97dc7dSHarald Freudenberger if (ctrptr == ctrblk) 417ee97dc7dSHarald Freudenberger spin_unlock(&ctrblk_lock); 41836eb2caaSJan Glauber return -EIO; 419ee97dc7dSHarald Freudenberger } 4200200f3ecSGerald Schaefer if (n > DES_BLOCK_SIZE) 421ee97dc7dSHarald Freudenberger memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE, 4220200f3ecSGerald Schaefer DES_BLOCK_SIZE); 423ee97dc7dSHarald Freudenberger crypto_inc(ctrptr, DES_BLOCK_SIZE); 4240200f3ecSGerald Schaefer out += n; 4250200f3ecSGerald Schaefer in += n; 4260200f3ecSGerald Schaefer nbytes -= n; 4270200f3ecSGerald Schaefer } 4280200f3ecSGerald Schaefer ret = blkcipher_walk_done(desc, walk, nbytes); 4290200f3ecSGerald Schaefer } 430ee97dc7dSHarald Freudenberger if (ctrptr == ctrblk) { 431ee97dc7dSHarald Freudenberger if (nbytes) 432ee97dc7dSHarald Freudenberger memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE); 433ee97dc7dSHarald Freudenberger else 434ee97dc7dSHarald Freudenberger memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE); 435ee97dc7dSHarald Freudenberger spin_unlock(&ctrblk_lock); 4363901c112SHarald Freudenberger } else { 4373901c112SHarald Freudenberger if (!nbytes) 4383901c112SHarald Freudenberger memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE); 439ee97dc7dSHarald Freudenberger } 4400200f3ecSGerald Schaefer /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ 4410200f3ecSGerald Schaefer if (nbytes) { 4420200f3ecSGerald Schaefer out = walk->dst.virt.addr; 4430200f3ecSGerald Schaefer in = walk->src.virt.addr; 444c7d4d259SMartin Schwidefsky ret = cpacf_kmctr(func, ctx->key, buf, in, 445ee97dc7dSHarald Freudenberger DES_BLOCK_SIZE, ctrbuf); 44636eb2caaSJan Glauber if (ret < 0 || ret != DES_BLOCK_SIZE) 44736eb2caaSJan Glauber return -EIO; 4480200f3ecSGerald Schaefer memcpy(out, buf, nbytes); 449ee97dc7dSHarald Freudenberger crypto_inc(ctrbuf, DES_BLOCK_SIZE); 4500200f3ecSGerald Schaefer ret = blkcipher_walk_done(desc, walk, 0); 451ee97dc7dSHarald Freudenberger memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE); 4520200f3ecSGerald Schaefer } 4530200f3ecSGerald Schaefer return ret; 4540200f3ecSGerald Schaefer } 4550200f3ecSGerald Schaefer 4560200f3ecSGerald Schaefer static int ctr_des_encrypt(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, ctx, &walk); 4650200f3ecSGerald Schaefer } 4660200f3ecSGerald Schaefer 4670200f3ecSGerald Schaefer static int ctr_des_decrypt(struct blkcipher_desc *desc, 4680200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 4690200f3ecSGerald Schaefer unsigned int nbytes) 4700200f3ecSGerald Schaefer { 4710200f3ecSGerald Schaefer struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 4720200f3ecSGerald Schaefer struct blkcipher_walk walk; 4730200f3ecSGerald Schaefer 4740200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 475edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_DEA | CPACF_DECRYPT, 476edc63a37SMartin Schwidefsky ctx, &walk); 4770200f3ecSGerald Schaefer } 4780200f3ecSGerald Schaefer 4790200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = { 4800200f3ecSGerald Schaefer .cra_name = "ctr(des)", 4810200f3ecSGerald Schaefer .cra_driver_name = "ctr-des-s390", 482c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des + ctr */ 4830200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 4840200f3ecSGerald Schaefer .cra_blocksize = 1, 4850200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 4860200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 4870200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 4880200f3ecSGerald Schaefer .cra_u = { 4890200f3ecSGerald Schaefer .blkcipher = { 4900200f3ecSGerald Schaefer .min_keysize = DES_KEY_SIZE, 4910200f3ecSGerald Schaefer .max_keysize = DES_KEY_SIZE, 4920200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 4930200f3ecSGerald Schaefer .setkey = des_setkey, 4940200f3ecSGerald Schaefer .encrypt = ctr_des_encrypt, 4950200f3ecSGerald Schaefer .decrypt = ctr_des_decrypt, 4960200f3ecSGerald Schaefer } 4970200f3ecSGerald Schaefer } 4980200f3ecSGerald Schaefer }; 4990200f3ecSGerald Schaefer 5000200f3ecSGerald Schaefer static int ctr_des3_encrypt(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, ctx, &walk); 5090200f3ecSGerald Schaefer } 5100200f3ecSGerald Schaefer 5110200f3ecSGerald Schaefer static int ctr_des3_decrypt(struct blkcipher_desc *desc, 5120200f3ecSGerald Schaefer struct scatterlist *dst, struct scatterlist *src, 5130200f3ecSGerald Schaefer unsigned int nbytes) 5140200f3ecSGerald Schaefer { 5150200f3ecSGerald Schaefer struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm); 5160200f3ecSGerald Schaefer struct blkcipher_walk walk; 5170200f3ecSGerald Schaefer 5180200f3ecSGerald Schaefer blkcipher_walk_init(&walk, dst, src, nbytes); 519edc63a37SMartin Schwidefsky return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192 | CPACF_DECRYPT, 520edc63a37SMartin Schwidefsky ctx, &walk); 5210200f3ecSGerald Schaefer } 5220200f3ecSGerald Schaefer 5230200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = { 5240200f3ecSGerald Schaefer .cra_name = "ctr(des3_ede)", 5250200f3ecSGerald Schaefer .cra_driver_name = "ctr-des3_ede-s390", 526c7d4d259SMartin Schwidefsky .cra_priority = 400, /* combo: des3 + ede */ 5270200f3ecSGerald Schaefer .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER, 5280200f3ecSGerald Schaefer .cra_blocksize = 1, 5290200f3ecSGerald Schaefer .cra_ctxsize = sizeof(struct s390_des_ctx), 5300200f3ecSGerald Schaefer .cra_type = &crypto_blkcipher_type, 5310200f3ecSGerald Schaefer .cra_module = THIS_MODULE, 5320200f3ecSGerald Schaefer .cra_u = { 5330200f3ecSGerald Schaefer .blkcipher = { 5340200f3ecSGerald Schaefer .min_keysize = DES3_KEY_SIZE, 5350200f3ecSGerald Schaefer .max_keysize = DES3_KEY_SIZE, 5360200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 5370200f3ecSGerald Schaefer .setkey = des3_setkey, 5380200f3ecSGerald Schaefer .encrypt = ctr_des3_encrypt, 5390200f3ecSGerald Schaefer .decrypt = ctr_des3_decrypt, 5400200f3ecSGerald Schaefer } 5410200f3ecSGerald Schaefer } 5420200f3ecSGerald Schaefer }; 5430200f3ecSGerald Schaefer 54498971f84SJan Glauber static int __init des_s390_init(void) 545c1e26e1eSJan Glauber { 54680d663a4SJan Glauber int ret; 547c1e26e1eSJan Glauber 548edc63a37SMartin Schwidefsky if (!cpacf_query(CPACF_KM, CPACF_KM_DEA) || 549edc63a37SMartin Schwidefsky !cpacf_query(CPACF_KM, CPACF_KM_TDEA_192)) 55086aa9fc2SJan Glauber return -EOPNOTSUPP; 551c1e26e1eSJan Glauber 552a9e62fadSHerbert Xu ret = crypto_register_alg(&des_alg); 553a9e62fadSHerbert Xu if (ret) 554a9e62fadSHerbert Xu goto des_err; 555a9e62fadSHerbert Xu ret = crypto_register_alg(&ecb_des_alg); 556a9e62fadSHerbert Xu if (ret) 557a9e62fadSHerbert Xu goto ecb_des_err; 558a9e62fadSHerbert Xu ret = crypto_register_alg(&cbc_des_alg); 559a9e62fadSHerbert Xu if (ret) 560a9e62fadSHerbert Xu goto cbc_des_err; 56198971f84SJan Glauber ret = crypto_register_alg(&des3_alg); 562a9e62fadSHerbert Xu if (ret) 56398971f84SJan Glauber goto des3_err; 56498971f84SJan Glauber ret = crypto_register_alg(&ecb_des3_alg); 565a9e62fadSHerbert Xu if (ret) 56698971f84SJan Glauber goto ecb_des3_err; 56798971f84SJan Glauber ret = crypto_register_alg(&cbc_des3_alg); 568a9e62fadSHerbert Xu if (ret) 56998971f84SJan Glauber goto cbc_des3_err; 5700200f3ecSGerald Schaefer 571edc63a37SMartin Schwidefsky if (cpacf_query(CPACF_KMCTR, CPACF_KMCTR_DEA) && 572edc63a37SMartin Schwidefsky cpacf_query(CPACF_KMCTR, CPACF_KMCTR_TDEA_192)) { 5730200f3ecSGerald Schaefer ret = crypto_register_alg(&ctr_des_alg); 5740200f3ecSGerald Schaefer if (ret) 5750200f3ecSGerald Schaefer goto ctr_des_err; 5760200f3ecSGerald Schaefer ret = crypto_register_alg(&ctr_des3_alg); 5770200f3ecSGerald Schaefer if (ret) 5780200f3ecSGerald Schaefer goto ctr_des3_err; 5790200f3ecSGerald Schaefer ctrblk = (u8 *) __get_free_page(GFP_KERNEL); 5800200f3ecSGerald Schaefer if (!ctrblk) { 5810200f3ecSGerald Schaefer ret = -ENOMEM; 5820200f3ecSGerald Schaefer goto ctr_mem_err; 5830200f3ecSGerald Schaefer } 5840200f3ecSGerald Schaefer } 585a9e62fadSHerbert Xu out: 586a9e62fadSHerbert Xu return ret; 587a9e62fadSHerbert Xu 5880200f3ecSGerald Schaefer ctr_mem_err: 5890200f3ecSGerald Schaefer crypto_unregister_alg(&ctr_des3_alg); 5900200f3ecSGerald Schaefer ctr_des3_err: 5910200f3ecSGerald Schaefer crypto_unregister_alg(&ctr_des_alg); 5920200f3ecSGerald Schaefer ctr_des_err: 5930200f3ecSGerald Schaefer crypto_unregister_alg(&cbc_des3_alg); 59498971f84SJan Glauber cbc_des3_err: 59598971f84SJan Glauber crypto_unregister_alg(&ecb_des3_alg); 59698971f84SJan Glauber ecb_des3_err: 59798971f84SJan Glauber crypto_unregister_alg(&des3_alg); 59898971f84SJan Glauber des3_err: 599a9e62fadSHerbert Xu crypto_unregister_alg(&cbc_des_alg); 600a9e62fadSHerbert Xu cbc_des_err: 601a9e62fadSHerbert Xu crypto_unregister_alg(&ecb_des_alg); 602a9e62fadSHerbert Xu ecb_des_err: 603c1e26e1eSJan Glauber crypto_unregister_alg(&des_alg); 604a9e62fadSHerbert Xu des_err: 605a9e62fadSHerbert Xu goto out; 606c1e26e1eSJan Glauber } 607c1e26e1eSJan Glauber 6081efbd15cSJan Glauber static void __exit des_s390_exit(void) 609c1e26e1eSJan Glauber { 6100200f3ecSGerald Schaefer if (ctrblk) { 6110200f3ecSGerald Schaefer crypto_unregister_alg(&ctr_des_alg); 6120200f3ecSGerald Schaefer crypto_unregister_alg(&ctr_des3_alg); 6130200f3ecSGerald Schaefer free_page((unsigned long) ctrblk); 6140200f3ecSGerald Schaefer } 61598971f84SJan Glauber crypto_unregister_alg(&cbc_des3_alg); 61698971f84SJan Glauber crypto_unregister_alg(&ecb_des3_alg); 61798971f84SJan Glauber crypto_unregister_alg(&des3_alg); 618a9e62fadSHerbert Xu crypto_unregister_alg(&cbc_des_alg); 619a9e62fadSHerbert Xu crypto_unregister_alg(&ecb_des_alg); 620c1e26e1eSJan Glauber crypto_unregister_alg(&des_alg); 621c1e26e1eSJan Glauber } 622c1e26e1eSJan Glauber 623d05377c1SHendrik Brueckner module_cpu_feature_match(MSA, des_s390_init); 6241efbd15cSJan Glauber module_exit(des_s390_exit); 625c1e26e1eSJan Glauber 6265d26a105SKees Cook MODULE_ALIAS_CRYPTO("des"); 6275d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede"); 628c1e26e1eSJan Glauber 629c1e26e1eSJan Glauber MODULE_LICENSE("GPL"); 630c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); 631