120a884f5SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+ 2c1e26e1eSJan Glauber /* 3c1e26e1eSJan Glauber * Cryptographic API. 4c1e26e1eSJan Glauber * 5c1e26e1eSJan Glauber * s390 implementation of the DES Cipher Algorithm. 6c1e26e1eSJan Glauber * 70200f3ecSGerald Schaefer * Copyright IBM Corp. 2003, 2011 886aa9fc2SJan Glauber * Author(s): Thomas Spatzier 986aa9fc2SJan Glauber * Jan Glauber (jan.glauber@de.ibm.com) 10c1e26e1eSJan Glauber */ 11a9e62fadSHerbert Xu 12c1e26e1eSJan Glauber #include <linux/init.h> 13c1e26e1eSJan Glauber #include <linux/module.h> 14d05377c1SHendrik Brueckner #include <linux/cpufeature.h> 151efbd15cSJan Glauber #include <linux/crypto.h> 16f3d3584fSMatthew Rosato #include <linux/fips.h> 171c2c7029SHarald Freudenberger #include <linux/mutex.h> 181efbd15cSJan Glauber #include <crypto/algapi.h> 194e2c8208SArd Biesheuvel #include <crypto/internal/des.h> 20fabdf253SEric Biggers #include <crypto/internal/skcipher.h> 21c7d4d259SMartin Schwidefsky #include <asm/cpacf.h> 22c1e26e1eSJan Glauber 2398971f84SJan Glauber #define DES3_KEY_SIZE (3 * DES_KEY_SIZE) 24c1e26e1eSJan Glauber 250200f3ecSGerald Schaefer static u8 *ctrblk; 261c2c7029SHarald Freudenberger static DEFINE_MUTEX(ctrblk_lock); 270200f3ecSGerald Schaefer 2869c0e360SMartin Schwidefsky static cpacf_mask_t km_functions, kmc_functions, kmctr_functions; 2969c0e360SMartin Schwidefsky 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); 394e2c8208SArd Biesheuvel int err; 40c1e26e1eSJan Glauber 414e2c8208SArd Biesheuvel err = crypto_des_verify_key(tfm, key); 424e2c8208SArd Biesheuvel if (err) 434e2c8208SArd Biesheuvel return err; 441efbd15cSJan Glauber 4598971f84SJan Glauber memcpy(ctx->key, key, key_len); 461efbd15cSJan Glauber return 0; 47c1e26e1eSJan Glauber } 48c1e26e1eSJan Glauber 49fabdf253SEric Biggers static int des_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key, 50fabdf253SEric Biggers unsigned int key_len) 51fabdf253SEric Biggers { 52fabdf253SEric Biggers return des_setkey(crypto_skcipher_tfm(tfm), key, key_len); 53fabdf253SEric Biggers } 54fabdf253SEric Biggers 554e2c8208SArd Biesheuvel static void s390_des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 56c1e26e1eSJan Glauber { 5798971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 58c1e26e1eSJan Glauber 59edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE); 60c1e26e1eSJan Glauber } 61c1e26e1eSJan Glauber 624e2c8208SArd Biesheuvel static void s390_des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in) 63c1e26e1eSJan Glauber { 6498971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 65c1e26e1eSJan Glauber 66edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT, 67edc63a37SMartin Schwidefsky ctx->key, out, in, DES_BLOCK_SIZE); 68b8dc6038SJan Glauber } 69b8dc6038SJan Glauber 70c1e26e1eSJan Glauber static struct crypto_alg des_alg = { 71c1e26e1eSJan Glauber .cra_name = "des", 7265b75c36SHerbert Xu .cra_driver_name = "des-s390", 73c7d4d259SMartin Schwidefsky .cra_priority = 300, 74c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 75c1e26e1eSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 7698971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 77c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 78c1357833SJan Glauber .cra_u = { 79c1357833SJan Glauber .cipher = { 80c1e26e1eSJan Glauber .cia_min_keysize = DES_KEY_SIZE, 81c1e26e1eSJan Glauber .cia_max_keysize = DES_KEY_SIZE, 82c1e26e1eSJan Glauber .cia_setkey = des_setkey, 834e2c8208SArd Biesheuvel .cia_encrypt = s390_des_encrypt, 844e2c8208SArd Biesheuvel .cia_decrypt = s390_des_decrypt, 85c1357833SJan Glauber } 86c1357833SJan Glauber } 87c1e26e1eSJan Glauber }; 88c1e26e1eSJan Glauber 89fabdf253SEric Biggers static int ecb_desall_crypt(struct skcipher_request *req, unsigned long fc) 90a9e62fadSHerbert Xu { 91fabdf253SEric Biggers struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 92fabdf253SEric Biggers struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm); 93fabdf253SEric Biggers struct skcipher_walk walk; 947bac4f5bSMartin Schwidefsky unsigned int nbytes, n; 957bac4f5bSMartin Schwidefsky int ret; 967bac4f5bSMartin Schwidefsky 97fabdf253SEric Biggers ret = skcipher_walk_virt(&walk, req, false); 98fabdf253SEric Biggers while ((nbytes = walk.nbytes) != 0) { 997bac4f5bSMartin Schwidefsky /* only use complete blocks */ 1007bac4f5bSMartin Schwidefsky n = nbytes & ~(DES_BLOCK_SIZE - 1); 101fabdf253SEric Biggers cpacf_km(fc, ctx->key, walk.dst.virt.addr, 102fabdf253SEric Biggers walk.src.virt.addr, n); 103fabdf253SEric Biggers ret = skcipher_walk_done(&walk, nbytes - n); 1047bac4f5bSMartin Schwidefsky } 1057bac4f5bSMartin Schwidefsky return ret; 1067bac4f5bSMartin Schwidefsky } 1077bac4f5bSMartin Schwidefsky 108fabdf253SEric Biggers static int cbc_desall_crypt(struct skcipher_request *req, unsigned long fc) 1097bac4f5bSMartin Schwidefsky { 110fabdf253SEric Biggers struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 111fabdf253SEric Biggers struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm); 112fabdf253SEric Biggers struct skcipher_walk walk; 1137bac4f5bSMartin Schwidefsky unsigned int nbytes, n; 1147bac4f5bSMartin Schwidefsky int ret; 115adc3fcf1SHarald Freudenberger struct { 116adc3fcf1SHarald Freudenberger u8 iv[DES_BLOCK_SIZE]; 117adc3fcf1SHarald Freudenberger u8 key[DES3_KEY_SIZE]; 118adc3fcf1SHarald Freudenberger } param; 119a9e62fadSHerbert Xu 120fabdf253SEric Biggers ret = skcipher_walk_virt(&walk, req, false); 121fabdf253SEric Biggers if (ret) 122fabdf253SEric Biggers return ret; 123fabdf253SEric Biggers memcpy(param.iv, walk.iv, DES_BLOCK_SIZE); 124adc3fcf1SHarald Freudenberger memcpy(param.key, ctx->key, DES3_KEY_SIZE); 125fabdf253SEric Biggers while ((nbytes = walk.nbytes) != 0) { 126a9e62fadSHerbert Xu /* only use complete blocks */ 1277bac4f5bSMartin Schwidefsky n = nbytes & ~(DES_BLOCK_SIZE - 1); 128fabdf253SEric Biggers cpacf_kmc(fc, ¶m, walk.dst.virt.addr, 129fabdf253SEric Biggers walk.src.virt.addr, n); 130fabdf253SEric Biggers memcpy(walk.iv, param.iv, DES_BLOCK_SIZE); 131fabdf253SEric Biggers ret = skcipher_walk_done(&walk, nbytes - n); 1327bac4f5bSMartin Schwidefsky } 133a9e62fadSHerbert Xu return ret; 134a9e62fadSHerbert Xu } 135a9e62fadSHerbert Xu 136fabdf253SEric Biggers static int ecb_des_encrypt(struct skcipher_request *req) 137a9e62fadSHerbert Xu { 138fabdf253SEric Biggers return ecb_desall_crypt(req, CPACF_KM_DEA); 139a9e62fadSHerbert Xu } 140a9e62fadSHerbert Xu 141fabdf253SEric Biggers static int ecb_des_decrypt(struct skcipher_request *req) 142a9e62fadSHerbert Xu { 143fabdf253SEric Biggers return ecb_desall_crypt(req, CPACF_KM_DEA | CPACF_DECRYPT); 144a9e62fadSHerbert Xu } 145a9e62fadSHerbert Xu 146fabdf253SEric Biggers static struct skcipher_alg ecb_des_alg = { 147fabdf253SEric Biggers .base.cra_name = "ecb(des)", 148fabdf253SEric Biggers .base.cra_driver_name = "ecb-des-s390", 149fabdf253SEric Biggers .base.cra_priority = 400, /* combo: des + ecb */ 150fabdf253SEric Biggers .base.cra_blocksize = DES_BLOCK_SIZE, 151fabdf253SEric Biggers .base.cra_ctxsize = sizeof(struct s390_des_ctx), 152fabdf253SEric Biggers .base.cra_module = THIS_MODULE, 153a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 154a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 155fabdf253SEric Biggers .setkey = des_setkey_skcipher, 156a9e62fadSHerbert Xu .encrypt = ecb_des_encrypt, 157a9e62fadSHerbert Xu .decrypt = ecb_des_decrypt, 158a9e62fadSHerbert Xu }; 159a9e62fadSHerbert Xu 160fabdf253SEric Biggers static int cbc_des_encrypt(struct skcipher_request *req) 161a9e62fadSHerbert Xu { 162fabdf253SEric Biggers return cbc_desall_crypt(req, CPACF_KMC_DEA); 163a9e62fadSHerbert Xu } 164a9e62fadSHerbert Xu 165fabdf253SEric Biggers static int cbc_des_decrypt(struct skcipher_request *req) 166a9e62fadSHerbert Xu { 167fabdf253SEric Biggers return cbc_desall_crypt(req, CPACF_KMC_DEA | CPACF_DECRYPT); 168a9e62fadSHerbert Xu } 169a9e62fadSHerbert Xu 170fabdf253SEric Biggers static struct skcipher_alg cbc_des_alg = { 171fabdf253SEric Biggers .base.cra_name = "cbc(des)", 172fabdf253SEric Biggers .base.cra_driver_name = "cbc-des-s390", 173fabdf253SEric Biggers .base.cra_priority = 400, /* combo: des + cbc */ 174fabdf253SEric Biggers .base.cra_blocksize = DES_BLOCK_SIZE, 175fabdf253SEric Biggers .base.cra_ctxsize = sizeof(struct s390_des_ctx), 176fabdf253SEric Biggers .base.cra_module = THIS_MODULE, 177a9e62fadSHerbert Xu .min_keysize = DES_KEY_SIZE, 178a9e62fadSHerbert Xu .max_keysize = DES_KEY_SIZE, 179a9e62fadSHerbert Xu .ivsize = DES_BLOCK_SIZE, 180fabdf253SEric Biggers .setkey = des_setkey_skcipher, 181a9e62fadSHerbert Xu .encrypt = cbc_des_encrypt, 182a9e62fadSHerbert Xu .decrypt = cbc_des_decrypt, 183a9e62fadSHerbert Xu }; 184a9e62fadSHerbert Xu 185c1e26e1eSJan Glauber /* 186c1e26e1eSJan Glauber * RFC2451: 187c1e26e1eSJan Glauber * 188c1e26e1eSJan Glauber * For DES-EDE3, there is no known need to reject weak or 189c1e26e1eSJan Glauber * complementation keys. Any weakness is obviated by the use of 190c1e26e1eSJan Glauber * multiple keys. 191c1e26e1eSJan Glauber * 192c1e26e1eSJan Glauber * However, if the first two or last two independent 64-bit keys are 193c1e26e1eSJan Glauber * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the 194c1e26e1eSJan Glauber * same as DES. Implementers MUST reject keys that exhibit this 195c1e26e1eSJan Glauber * property. 196c1e26e1eSJan Glauber * 197f3d3584fSMatthew Rosato * In fips mode additinally check for all 3 keys are unique. 198f3d3584fSMatthew Rosato * 199c1e26e1eSJan Glauber */ 20098971f84SJan Glauber static int des3_setkey(struct crypto_tfm *tfm, const u8 *key, 20198971f84SJan Glauber unsigned int key_len) 202c1e26e1eSJan Glauber { 20398971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 20455902d85SHerbert Xu int err; 205c1e26e1eSJan Glauber 2064e2c8208SArd Biesheuvel err = crypto_des3_ede_verify_key(tfm, key); 2074e2c8208SArd Biesheuvel if (err) 20855902d85SHerbert Xu return err; 209f3d3584fSMatthew Rosato 21098971f84SJan Glauber memcpy(ctx->key, key, key_len); 211c1e26e1eSJan Glauber return 0; 212c1e26e1eSJan Glauber } 213c1e26e1eSJan Glauber 214fabdf253SEric Biggers static int des3_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key, 215fabdf253SEric Biggers unsigned int key_len) 216fabdf253SEric Biggers { 217fabdf253SEric Biggers return des3_setkey(crypto_skcipher_tfm(tfm), key, key_len); 218fabdf253SEric Biggers } 219fabdf253SEric Biggers 22098971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 221c1e26e1eSJan Glauber { 22298971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 223c1e26e1eSJan Glauber 224edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE); 225c1e26e1eSJan Glauber } 226c1e26e1eSJan Glauber 22798971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) 228c1e26e1eSJan Glauber { 22998971f84SJan Glauber struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm); 230c1e26e1eSJan Glauber 231edc63a37SMartin Schwidefsky cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT, 232edc63a37SMartin Schwidefsky ctx->key, dst, src, DES_BLOCK_SIZE); 233c1e26e1eSJan Glauber } 234c1e26e1eSJan Glauber 23598971f84SJan Glauber static struct crypto_alg des3_alg = { 236c1e26e1eSJan Glauber .cra_name = "des3_ede", 23765b75c36SHerbert Xu .cra_driver_name = "des3_ede-s390", 238c7d4d259SMartin Schwidefsky .cra_priority = 300, 239c1e26e1eSJan Glauber .cra_flags = CRYPTO_ALG_TYPE_CIPHER, 2401efbd15cSJan Glauber .cra_blocksize = DES_BLOCK_SIZE, 24198971f84SJan Glauber .cra_ctxsize = sizeof(struct s390_des_ctx), 242c1e26e1eSJan Glauber .cra_module = THIS_MODULE, 243c1357833SJan Glauber .cra_u = { 244c1357833SJan Glauber .cipher = { 24598971f84SJan Glauber .cia_min_keysize = DES3_KEY_SIZE, 24698971f84SJan Glauber .cia_max_keysize = DES3_KEY_SIZE, 24798971f84SJan Glauber .cia_setkey = des3_setkey, 24898971f84SJan Glauber .cia_encrypt = des3_encrypt, 24998971f84SJan Glauber .cia_decrypt = des3_decrypt, 250c1357833SJan Glauber } 251c1357833SJan Glauber } 252c1e26e1eSJan Glauber }; 253c1e26e1eSJan Glauber 254fabdf253SEric Biggers static int ecb_des3_encrypt(struct skcipher_request *req) 255a9e62fadSHerbert Xu { 256fabdf253SEric Biggers return ecb_desall_crypt(req, CPACF_KM_TDEA_192); 257a9e62fadSHerbert Xu } 258a9e62fadSHerbert Xu 259fabdf253SEric Biggers static int ecb_des3_decrypt(struct skcipher_request *req) 260a9e62fadSHerbert Xu { 261fabdf253SEric Biggers return ecb_desall_crypt(req, CPACF_KM_TDEA_192 | CPACF_DECRYPT); 262a9e62fadSHerbert Xu } 263a9e62fadSHerbert Xu 264fabdf253SEric Biggers static struct skcipher_alg ecb_des3_alg = { 265fabdf253SEric Biggers .base.cra_name = "ecb(des3_ede)", 266fabdf253SEric Biggers .base.cra_driver_name = "ecb-des3_ede-s390", 267fabdf253SEric Biggers .base.cra_priority = 400, /* combo: des3 + ecb */ 268fabdf253SEric Biggers .base.cra_blocksize = DES_BLOCK_SIZE, 269fabdf253SEric Biggers .base.cra_ctxsize = sizeof(struct s390_des_ctx), 270fabdf253SEric Biggers .base.cra_module = THIS_MODULE, 27198971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 27298971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 273fabdf253SEric Biggers .setkey = des3_setkey_skcipher, 27498971f84SJan Glauber .encrypt = ecb_des3_encrypt, 27598971f84SJan Glauber .decrypt = ecb_des3_decrypt, 276a9e62fadSHerbert Xu }; 277a9e62fadSHerbert Xu 278fabdf253SEric Biggers static int cbc_des3_encrypt(struct skcipher_request *req) 279a9e62fadSHerbert Xu { 280fabdf253SEric Biggers return cbc_desall_crypt(req, CPACF_KMC_TDEA_192); 281a9e62fadSHerbert Xu } 282a9e62fadSHerbert Xu 283fabdf253SEric Biggers static int cbc_des3_decrypt(struct skcipher_request *req) 284a9e62fadSHerbert Xu { 285fabdf253SEric Biggers return cbc_desall_crypt(req, CPACF_KMC_TDEA_192 | CPACF_DECRYPT); 286a9e62fadSHerbert Xu } 287a9e62fadSHerbert Xu 288fabdf253SEric Biggers static struct skcipher_alg cbc_des3_alg = { 289fabdf253SEric Biggers .base.cra_name = "cbc(des3_ede)", 290fabdf253SEric Biggers .base.cra_driver_name = "cbc-des3_ede-s390", 291fabdf253SEric Biggers .base.cra_priority = 400, /* combo: des3 + cbc */ 292fabdf253SEric Biggers .base.cra_blocksize = DES_BLOCK_SIZE, 293fabdf253SEric Biggers .base.cra_ctxsize = sizeof(struct s390_des_ctx), 294fabdf253SEric Biggers .base.cra_module = THIS_MODULE, 29598971f84SJan Glauber .min_keysize = DES3_KEY_SIZE, 29698971f84SJan Glauber .max_keysize = DES3_KEY_SIZE, 2971efbd15cSJan Glauber .ivsize = DES_BLOCK_SIZE, 298fabdf253SEric Biggers .setkey = des3_setkey_skcipher, 29998971f84SJan Glauber .encrypt = cbc_des3_encrypt, 30098971f84SJan Glauber .decrypt = cbc_des3_decrypt, 301a9e62fadSHerbert Xu }; 302a9e62fadSHerbert Xu 3037bac4f5bSMartin Schwidefsky static unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes) 304ee97dc7dSHarald Freudenberger { 305ee97dc7dSHarald Freudenberger unsigned int i, n; 306ee97dc7dSHarald Freudenberger 307ee97dc7dSHarald Freudenberger /* align to block size, max. PAGE_SIZE */ 308ee97dc7dSHarald Freudenberger n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1); 3097bac4f5bSMartin Schwidefsky memcpy(ctrptr, iv, DES_BLOCK_SIZE); 3107bac4f5bSMartin Schwidefsky for (i = (n / DES_BLOCK_SIZE) - 1; i > 0; i--) { 3117bac4f5bSMartin Schwidefsky memcpy(ctrptr + DES_BLOCK_SIZE, ctrptr, DES_BLOCK_SIZE); 3127bac4f5bSMartin Schwidefsky crypto_inc(ctrptr + DES_BLOCK_SIZE, DES_BLOCK_SIZE); 3137bac4f5bSMartin Schwidefsky ctrptr += DES_BLOCK_SIZE; 314ee97dc7dSHarald Freudenberger } 315ee97dc7dSHarald Freudenberger return n; 316ee97dc7dSHarald Freudenberger } 317ee97dc7dSHarald Freudenberger 318fabdf253SEric Biggers static int ctr_desall_crypt(struct skcipher_request *req, unsigned long fc) 3190200f3ecSGerald Schaefer { 320fabdf253SEric Biggers struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req); 321fabdf253SEric Biggers struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm); 3227bac4f5bSMartin Schwidefsky u8 buf[DES_BLOCK_SIZE], *ctrptr; 323fabdf253SEric Biggers struct skcipher_walk walk; 324ee97dc7dSHarald Freudenberger unsigned int n, nbytes; 3257bac4f5bSMartin Schwidefsky int ret, locked; 3260200f3ecSGerald Schaefer 3271c2c7029SHarald Freudenberger locked = mutex_trylock(&ctrblk_lock); 328ee97dc7dSHarald Freudenberger 329fabdf253SEric Biggers ret = skcipher_walk_virt(&walk, req, false); 330fabdf253SEric Biggers while ((nbytes = walk.nbytes) >= DES_BLOCK_SIZE) { 331ee97dc7dSHarald Freudenberger n = DES_BLOCK_SIZE; 3327bac4f5bSMartin Schwidefsky if (nbytes >= 2*DES_BLOCK_SIZE && locked) 333fabdf253SEric Biggers n = __ctrblk_init(ctrblk, walk.iv, nbytes); 334fabdf253SEric Biggers ctrptr = (n > DES_BLOCK_SIZE) ? ctrblk : walk.iv; 335fabdf253SEric Biggers cpacf_kmctr(fc, ctx->key, walk.dst.virt.addr, 336fabdf253SEric Biggers walk.src.virt.addr, n, ctrptr); 3377bac4f5bSMartin Schwidefsky if (ctrptr == ctrblk) 338fabdf253SEric Biggers memcpy(walk.iv, ctrptr + n - DES_BLOCK_SIZE, 3390200f3ecSGerald Schaefer DES_BLOCK_SIZE); 340fabdf253SEric Biggers crypto_inc(walk.iv, DES_BLOCK_SIZE); 341fabdf253SEric Biggers ret = skcipher_walk_done(&walk, nbytes - n); 3420200f3ecSGerald Schaefer } 3437bac4f5bSMartin Schwidefsky if (locked) 3441c2c7029SHarald Freudenberger mutex_unlock(&ctrblk_lock); 3450200f3ecSGerald Schaefer /* final block may be < DES_BLOCK_SIZE, copy only nbytes */ 3460200f3ecSGerald Schaefer if (nbytes) { 347fabdf253SEric Biggers cpacf_kmctr(fc, ctx->key, buf, walk.src.virt.addr, 348fabdf253SEric Biggers DES_BLOCK_SIZE, walk.iv); 349fabdf253SEric Biggers memcpy(walk.dst.virt.addr, buf, nbytes); 350fabdf253SEric Biggers crypto_inc(walk.iv, DES_BLOCK_SIZE); 351fabdf253SEric Biggers ret = skcipher_walk_done(&walk, 0); 3520200f3ecSGerald Schaefer } 3530200f3ecSGerald Schaefer return ret; 3540200f3ecSGerald Schaefer } 3550200f3ecSGerald Schaefer 356fabdf253SEric Biggers static int ctr_des_crypt(struct skcipher_request *req) 3570200f3ecSGerald Schaefer { 358fabdf253SEric Biggers return ctr_desall_crypt(req, CPACF_KMCTR_DEA); 3590200f3ecSGerald Schaefer } 3600200f3ecSGerald Schaefer 361fabdf253SEric Biggers static struct skcipher_alg ctr_des_alg = { 362fabdf253SEric Biggers .base.cra_name = "ctr(des)", 363fabdf253SEric Biggers .base.cra_driver_name = "ctr-des-s390", 364fabdf253SEric Biggers .base.cra_priority = 400, /* combo: des + ctr */ 365fabdf253SEric Biggers .base.cra_blocksize = 1, 366fabdf253SEric Biggers .base.cra_ctxsize = sizeof(struct s390_des_ctx), 367fabdf253SEric Biggers .base.cra_module = THIS_MODULE, 3680200f3ecSGerald Schaefer .min_keysize = DES_KEY_SIZE, 3690200f3ecSGerald Schaefer .max_keysize = DES_KEY_SIZE, 3700200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 371fabdf253SEric Biggers .setkey = des_setkey_skcipher, 372fabdf253SEric Biggers .encrypt = ctr_des_crypt, 373fabdf253SEric Biggers .decrypt = ctr_des_crypt, 374fabdf253SEric Biggers .chunksize = DES_BLOCK_SIZE, 3750200f3ecSGerald Schaefer }; 3760200f3ecSGerald Schaefer 377fabdf253SEric Biggers static int ctr_des3_crypt(struct skcipher_request *req) 3780200f3ecSGerald Schaefer { 379fabdf253SEric Biggers return ctr_desall_crypt(req, CPACF_KMCTR_TDEA_192); 3800200f3ecSGerald Schaefer } 3810200f3ecSGerald Schaefer 382fabdf253SEric Biggers static struct skcipher_alg ctr_des3_alg = { 383fabdf253SEric Biggers .base.cra_name = "ctr(des3_ede)", 384fabdf253SEric Biggers .base.cra_driver_name = "ctr-des3_ede-s390", 385fabdf253SEric Biggers .base.cra_priority = 400, /* combo: des3 + ede */ 386fabdf253SEric Biggers .base.cra_blocksize = 1, 387fabdf253SEric Biggers .base.cra_ctxsize = sizeof(struct s390_des_ctx), 388fabdf253SEric Biggers .base.cra_module = THIS_MODULE, 3890200f3ecSGerald Schaefer .min_keysize = DES3_KEY_SIZE, 3900200f3ecSGerald Schaefer .max_keysize = DES3_KEY_SIZE, 3910200f3ecSGerald Schaefer .ivsize = DES_BLOCK_SIZE, 392fabdf253SEric Biggers .setkey = des3_setkey_skcipher, 393fabdf253SEric Biggers .encrypt = ctr_des3_crypt, 394fabdf253SEric Biggers .decrypt = ctr_des3_crypt, 395fabdf253SEric Biggers .chunksize = DES_BLOCK_SIZE, 3960200f3ecSGerald Schaefer }; 3970200f3ecSGerald Schaefer 398fabdf253SEric Biggers static struct crypto_alg *des_s390_algs_ptr[2]; 399d863d594SMartin Schwidefsky static int des_s390_algs_num; 400fabdf253SEric Biggers static struct skcipher_alg *des_s390_skciphers_ptr[6]; 401fabdf253SEric Biggers static int des_s390_skciphers_num; 402d863d594SMartin Schwidefsky 403d863d594SMartin Schwidefsky static int des_s390_register_alg(struct crypto_alg *alg) 404d863d594SMartin Schwidefsky { 405d863d594SMartin Schwidefsky int ret; 406d863d594SMartin Schwidefsky 407d863d594SMartin Schwidefsky ret = crypto_register_alg(alg); 408d863d594SMartin Schwidefsky if (!ret) 409d863d594SMartin Schwidefsky des_s390_algs_ptr[des_s390_algs_num++] = alg; 410d863d594SMartin Schwidefsky return ret; 411d863d594SMartin Schwidefsky } 412d863d594SMartin Schwidefsky 413fabdf253SEric Biggers static int des_s390_register_skcipher(struct skcipher_alg *alg) 414fabdf253SEric Biggers { 415fabdf253SEric Biggers int ret; 416fabdf253SEric Biggers 417fabdf253SEric Biggers ret = crypto_register_skcipher(alg); 418fabdf253SEric Biggers if (!ret) 419fabdf253SEric Biggers des_s390_skciphers_ptr[des_s390_skciphers_num++] = alg; 420fabdf253SEric Biggers return ret; 421fabdf253SEric Biggers } 422fabdf253SEric Biggers 423d863d594SMartin Schwidefsky static void des_s390_exit(void) 424d863d594SMartin Schwidefsky { 425d863d594SMartin Schwidefsky while (des_s390_algs_num--) 426d863d594SMartin Schwidefsky crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]); 427fabdf253SEric Biggers while (des_s390_skciphers_num--) 428fabdf253SEric Biggers crypto_unregister_skcipher(des_s390_skciphers_ptr[des_s390_skciphers_num]); 429d863d594SMartin Schwidefsky if (ctrblk) 430d863d594SMartin Schwidefsky free_page((unsigned long) ctrblk); 431d863d594SMartin Schwidefsky } 432d863d594SMartin Schwidefsky 43398971f84SJan Glauber static int __init des_s390_init(void) 434c1e26e1eSJan Glauber { 43580d663a4SJan Glauber int ret; 436c1e26e1eSJan Glauber 43769c0e360SMartin Schwidefsky /* Query available functions for KM, KMC and KMCTR */ 43869c0e360SMartin Schwidefsky cpacf_query(CPACF_KM, &km_functions); 43969c0e360SMartin Schwidefsky cpacf_query(CPACF_KMC, &kmc_functions); 44069c0e360SMartin Schwidefsky cpacf_query(CPACF_KMCTR, &kmctr_functions); 441c1e26e1eSJan Glauber 44269c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) { 443d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des_alg); 444a9e62fadSHerbert Xu if (ret) 445d863d594SMartin Schwidefsky goto out_err; 446fabdf253SEric Biggers ret = des_s390_register_skcipher(&ecb_des_alg); 447a9e62fadSHerbert Xu if (ret) 448d863d594SMartin Schwidefsky goto out_err; 44969c0e360SMartin Schwidefsky } 45069c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) { 451fabdf253SEric Biggers ret = des_s390_register_skcipher(&cbc_des_alg); 452a9e62fadSHerbert Xu if (ret) 453d863d594SMartin Schwidefsky goto out_err; 45469c0e360SMartin Schwidefsky } 45569c0e360SMartin Schwidefsky if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) { 456d863d594SMartin Schwidefsky ret = des_s390_register_alg(&des3_alg); 457a9e62fadSHerbert Xu if (ret) 458d863d594SMartin Schwidefsky goto out_err; 459fabdf253SEric Biggers ret = des_s390_register_skcipher(&ecb_des3_alg); 460a9e62fadSHerbert Xu if (ret) 461d863d594SMartin Schwidefsky goto out_err; 46269c0e360SMartin Schwidefsky } 46369c0e360SMartin Schwidefsky if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) { 464fabdf253SEric Biggers ret = des_s390_register_skcipher(&cbc_des3_alg); 465a9e62fadSHerbert Xu if (ret) 466d863d594SMartin Schwidefsky goto out_err; 46769c0e360SMartin Schwidefsky } 4680200f3ecSGerald Schaefer 46969c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) || 47069c0e360SMartin Schwidefsky cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 4710200f3ecSGerald Schaefer ctrblk = (u8 *) __get_free_page(GFP_KERNEL); 4720200f3ecSGerald Schaefer if (!ctrblk) { 4730200f3ecSGerald Schaefer ret = -ENOMEM; 474d863d594SMartin Schwidefsky goto out_err; 4750200f3ecSGerald Schaefer } 47669c0e360SMartin Schwidefsky } 47769c0e360SMartin Schwidefsky 47869c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) { 479fabdf253SEric Biggers ret = des_s390_register_skcipher(&ctr_des_alg); 480d863d594SMartin Schwidefsky if (ret) 481d863d594SMartin Schwidefsky goto out_err; 48269c0e360SMartin Schwidefsky } 48369c0e360SMartin Schwidefsky if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) { 484fabdf253SEric Biggers ret = des_s390_register_skcipher(&ctr_des3_alg); 485d863d594SMartin Schwidefsky if (ret) 486d863d594SMartin Schwidefsky goto out_err; 4870200f3ecSGerald Schaefer } 488d863d594SMartin Schwidefsky 489d863d594SMartin Schwidefsky return 0; 490d863d594SMartin Schwidefsky out_err: 491d863d594SMartin Schwidefsky des_s390_exit(); 492a9e62fadSHerbert Xu return ret; 493c1e26e1eSJan Glauber } 494c1e26e1eSJan Glauber 495d05377c1SHendrik Brueckner module_cpu_feature_match(MSA, des_s390_init); 4961efbd15cSJan Glauber module_exit(des_s390_exit); 497c1e26e1eSJan Glauber 4985d26a105SKees Cook MODULE_ALIAS_CRYPTO("des"); 4995d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede"); 500c1e26e1eSJan Glauber 501c1e26e1eSJan Glauber MODULE_LICENSE("GPL"); 502c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); 503