0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <linux/init.h>
0013 #include <linux/module.h>
0014 #include <linux/cpufeature.h>
0015 #include <linux/crypto.h>
0016 #include <linux/fips.h>
0017 #include <linux/mutex.h>
0018 #include <crypto/algapi.h>
0019 #include <crypto/internal/des.h>
0020 #include <crypto/internal/skcipher.h>
0021 #include <asm/cpacf.h>
0022
0023 #define DES3_KEY_SIZE (3 * DES_KEY_SIZE)
0024
0025 static u8 *ctrblk;
0026 static DEFINE_MUTEX(ctrblk_lock);
0027
0028 static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
0029
0030 struct s390_des_ctx {
0031 u8 iv[DES_BLOCK_SIZE];
0032 u8 key[DES3_KEY_SIZE];
0033 };
0034
0035 static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
0036 unsigned int key_len)
0037 {
0038 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
0039 int err;
0040
0041 err = crypto_des_verify_key(tfm, key);
0042 if (err)
0043 return err;
0044
0045 memcpy(ctx->key, key, key_len);
0046 return 0;
0047 }
0048
0049 static int des_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key,
0050 unsigned int key_len)
0051 {
0052 return des_setkey(crypto_skcipher_tfm(tfm), key, key_len);
0053 }
0054
0055 static void s390_des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
0056 {
0057 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
0058
0059 cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE);
0060 }
0061
0062 static void s390_des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
0063 {
0064 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
0065
0066 cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT,
0067 ctx->key, out, in, DES_BLOCK_SIZE);
0068 }
0069
0070 static struct crypto_alg des_alg = {
0071 .cra_name = "des",
0072 .cra_driver_name = "des-s390",
0073 .cra_priority = 300,
0074 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
0075 .cra_blocksize = DES_BLOCK_SIZE,
0076 .cra_ctxsize = sizeof(struct s390_des_ctx),
0077 .cra_module = THIS_MODULE,
0078 .cra_u = {
0079 .cipher = {
0080 .cia_min_keysize = DES_KEY_SIZE,
0081 .cia_max_keysize = DES_KEY_SIZE,
0082 .cia_setkey = des_setkey,
0083 .cia_encrypt = s390_des_encrypt,
0084 .cia_decrypt = s390_des_decrypt,
0085 }
0086 }
0087 };
0088
0089 static int ecb_desall_crypt(struct skcipher_request *req, unsigned long fc)
0090 {
0091 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0092 struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm);
0093 struct skcipher_walk walk;
0094 unsigned int nbytes, n;
0095 int ret;
0096
0097 ret = skcipher_walk_virt(&walk, req, false);
0098 while ((nbytes = walk.nbytes) != 0) {
0099
0100 n = nbytes & ~(DES_BLOCK_SIZE - 1);
0101 cpacf_km(fc, ctx->key, walk.dst.virt.addr,
0102 walk.src.virt.addr, n);
0103 ret = skcipher_walk_done(&walk, nbytes - n);
0104 }
0105 return ret;
0106 }
0107
0108 static int cbc_desall_crypt(struct skcipher_request *req, unsigned long fc)
0109 {
0110 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0111 struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm);
0112 struct skcipher_walk walk;
0113 unsigned int nbytes, n;
0114 int ret;
0115 struct {
0116 u8 iv[DES_BLOCK_SIZE];
0117 u8 key[DES3_KEY_SIZE];
0118 } param;
0119
0120 ret = skcipher_walk_virt(&walk, req, false);
0121 if (ret)
0122 return ret;
0123 memcpy(param.iv, walk.iv, DES_BLOCK_SIZE);
0124 memcpy(param.key, ctx->key, DES3_KEY_SIZE);
0125 while ((nbytes = walk.nbytes) != 0) {
0126
0127 n = nbytes & ~(DES_BLOCK_SIZE - 1);
0128 cpacf_kmc(fc, ¶m, walk.dst.virt.addr,
0129 walk.src.virt.addr, n);
0130 memcpy(walk.iv, param.iv, DES_BLOCK_SIZE);
0131 ret = skcipher_walk_done(&walk, nbytes - n);
0132 }
0133 return ret;
0134 }
0135
0136 static int ecb_des_encrypt(struct skcipher_request *req)
0137 {
0138 return ecb_desall_crypt(req, CPACF_KM_DEA);
0139 }
0140
0141 static int ecb_des_decrypt(struct skcipher_request *req)
0142 {
0143 return ecb_desall_crypt(req, CPACF_KM_DEA | CPACF_DECRYPT);
0144 }
0145
0146 static struct skcipher_alg ecb_des_alg = {
0147 .base.cra_name = "ecb(des)",
0148 .base.cra_driver_name = "ecb-des-s390",
0149 .base.cra_priority = 400,
0150 .base.cra_blocksize = DES_BLOCK_SIZE,
0151 .base.cra_ctxsize = sizeof(struct s390_des_ctx),
0152 .base.cra_module = THIS_MODULE,
0153 .min_keysize = DES_KEY_SIZE,
0154 .max_keysize = DES_KEY_SIZE,
0155 .setkey = des_setkey_skcipher,
0156 .encrypt = ecb_des_encrypt,
0157 .decrypt = ecb_des_decrypt,
0158 };
0159
0160 static int cbc_des_encrypt(struct skcipher_request *req)
0161 {
0162 return cbc_desall_crypt(req, CPACF_KMC_DEA);
0163 }
0164
0165 static int cbc_des_decrypt(struct skcipher_request *req)
0166 {
0167 return cbc_desall_crypt(req, CPACF_KMC_DEA | CPACF_DECRYPT);
0168 }
0169
0170 static struct skcipher_alg cbc_des_alg = {
0171 .base.cra_name = "cbc(des)",
0172 .base.cra_driver_name = "cbc-des-s390",
0173 .base.cra_priority = 400,
0174 .base.cra_blocksize = DES_BLOCK_SIZE,
0175 .base.cra_ctxsize = sizeof(struct s390_des_ctx),
0176 .base.cra_module = THIS_MODULE,
0177 .min_keysize = DES_KEY_SIZE,
0178 .max_keysize = DES_KEY_SIZE,
0179 .ivsize = DES_BLOCK_SIZE,
0180 .setkey = des_setkey_skcipher,
0181 .encrypt = cbc_des_encrypt,
0182 .decrypt = cbc_des_decrypt,
0183 };
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 static int des3_setkey(struct crypto_tfm *tfm, const u8 *key,
0201 unsigned int key_len)
0202 {
0203 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
0204 int err;
0205
0206 err = crypto_des3_ede_verify_key(tfm, key);
0207 if (err)
0208 return err;
0209
0210 memcpy(ctx->key, key, key_len);
0211 return 0;
0212 }
0213
0214 static int des3_setkey_skcipher(struct crypto_skcipher *tfm, const u8 *key,
0215 unsigned int key_len)
0216 {
0217 return des3_setkey(crypto_skcipher_tfm(tfm), key, key_len);
0218 }
0219
0220 static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
0221 {
0222 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
0223
0224 cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE);
0225 }
0226
0227 static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
0228 {
0229 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
0230
0231 cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT,
0232 ctx->key, dst, src, DES_BLOCK_SIZE);
0233 }
0234
0235 static struct crypto_alg des3_alg = {
0236 .cra_name = "des3_ede",
0237 .cra_driver_name = "des3_ede-s390",
0238 .cra_priority = 300,
0239 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
0240 .cra_blocksize = DES_BLOCK_SIZE,
0241 .cra_ctxsize = sizeof(struct s390_des_ctx),
0242 .cra_module = THIS_MODULE,
0243 .cra_u = {
0244 .cipher = {
0245 .cia_min_keysize = DES3_KEY_SIZE,
0246 .cia_max_keysize = DES3_KEY_SIZE,
0247 .cia_setkey = des3_setkey,
0248 .cia_encrypt = des3_encrypt,
0249 .cia_decrypt = des3_decrypt,
0250 }
0251 }
0252 };
0253
0254 static int ecb_des3_encrypt(struct skcipher_request *req)
0255 {
0256 return ecb_desall_crypt(req, CPACF_KM_TDEA_192);
0257 }
0258
0259 static int ecb_des3_decrypt(struct skcipher_request *req)
0260 {
0261 return ecb_desall_crypt(req, CPACF_KM_TDEA_192 | CPACF_DECRYPT);
0262 }
0263
0264 static struct skcipher_alg ecb_des3_alg = {
0265 .base.cra_name = "ecb(des3_ede)",
0266 .base.cra_driver_name = "ecb-des3_ede-s390",
0267 .base.cra_priority = 400,
0268 .base.cra_blocksize = DES_BLOCK_SIZE,
0269 .base.cra_ctxsize = sizeof(struct s390_des_ctx),
0270 .base.cra_module = THIS_MODULE,
0271 .min_keysize = DES3_KEY_SIZE,
0272 .max_keysize = DES3_KEY_SIZE,
0273 .setkey = des3_setkey_skcipher,
0274 .encrypt = ecb_des3_encrypt,
0275 .decrypt = ecb_des3_decrypt,
0276 };
0277
0278 static int cbc_des3_encrypt(struct skcipher_request *req)
0279 {
0280 return cbc_desall_crypt(req, CPACF_KMC_TDEA_192);
0281 }
0282
0283 static int cbc_des3_decrypt(struct skcipher_request *req)
0284 {
0285 return cbc_desall_crypt(req, CPACF_KMC_TDEA_192 | CPACF_DECRYPT);
0286 }
0287
0288 static struct skcipher_alg cbc_des3_alg = {
0289 .base.cra_name = "cbc(des3_ede)",
0290 .base.cra_driver_name = "cbc-des3_ede-s390",
0291 .base.cra_priority = 400,
0292 .base.cra_blocksize = DES_BLOCK_SIZE,
0293 .base.cra_ctxsize = sizeof(struct s390_des_ctx),
0294 .base.cra_module = THIS_MODULE,
0295 .min_keysize = DES3_KEY_SIZE,
0296 .max_keysize = DES3_KEY_SIZE,
0297 .ivsize = DES_BLOCK_SIZE,
0298 .setkey = des3_setkey_skcipher,
0299 .encrypt = cbc_des3_encrypt,
0300 .decrypt = cbc_des3_decrypt,
0301 };
0302
0303 static unsigned int __ctrblk_init(u8 *ctrptr, u8 *iv, unsigned int nbytes)
0304 {
0305 unsigned int i, n;
0306
0307
0308 n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1);
0309 memcpy(ctrptr, iv, DES_BLOCK_SIZE);
0310 for (i = (n / DES_BLOCK_SIZE) - 1; i > 0; i--) {
0311 memcpy(ctrptr + DES_BLOCK_SIZE, ctrptr, DES_BLOCK_SIZE);
0312 crypto_inc(ctrptr + DES_BLOCK_SIZE, DES_BLOCK_SIZE);
0313 ctrptr += DES_BLOCK_SIZE;
0314 }
0315 return n;
0316 }
0317
0318 static int ctr_desall_crypt(struct skcipher_request *req, unsigned long fc)
0319 {
0320 struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(req);
0321 struct s390_des_ctx *ctx = crypto_skcipher_ctx(tfm);
0322 u8 buf[DES_BLOCK_SIZE], *ctrptr;
0323 struct skcipher_walk walk;
0324 unsigned int n, nbytes;
0325 int ret, locked;
0326
0327 locked = mutex_trylock(&ctrblk_lock);
0328
0329 ret = skcipher_walk_virt(&walk, req, false);
0330 while ((nbytes = walk.nbytes) >= DES_BLOCK_SIZE) {
0331 n = DES_BLOCK_SIZE;
0332 if (nbytes >= 2*DES_BLOCK_SIZE && locked)
0333 n = __ctrblk_init(ctrblk, walk.iv, nbytes);
0334 ctrptr = (n > DES_BLOCK_SIZE) ? ctrblk : walk.iv;
0335 cpacf_kmctr(fc, ctx->key, walk.dst.virt.addr,
0336 walk.src.virt.addr, n, ctrptr);
0337 if (ctrptr == ctrblk)
0338 memcpy(walk.iv, ctrptr + n - DES_BLOCK_SIZE,
0339 DES_BLOCK_SIZE);
0340 crypto_inc(walk.iv, DES_BLOCK_SIZE);
0341 ret = skcipher_walk_done(&walk, nbytes - n);
0342 }
0343 if (locked)
0344 mutex_unlock(&ctrblk_lock);
0345
0346 if (nbytes) {
0347 cpacf_kmctr(fc, ctx->key, buf, walk.src.virt.addr,
0348 DES_BLOCK_SIZE, walk.iv);
0349 memcpy(walk.dst.virt.addr, buf, nbytes);
0350 crypto_inc(walk.iv, DES_BLOCK_SIZE);
0351 ret = skcipher_walk_done(&walk, 0);
0352 }
0353 return ret;
0354 }
0355
0356 static int ctr_des_crypt(struct skcipher_request *req)
0357 {
0358 return ctr_desall_crypt(req, CPACF_KMCTR_DEA);
0359 }
0360
0361 static struct skcipher_alg ctr_des_alg = {
0362 .base.cra_name = "ctr(des)",
0363 .base.cra_driver_name = "ctr-des-s390",
0364 .base.cra_priority = 400,
0365 .base.cra_blocksize = 1,
0366 .base.cra_ctxsize = sizeof(struct s390_des_ctx),
0367 .base.cra_module = THIS_MODULE,
0368 .min_keysize = DES_KEY_SIZE,
0369 .max_keysize = DES_KEY_SIZE,
0370 .ivsize = DES_BLOCK_SIZE,
0371 .setkey = des_setkey_skcipher,
0372 .encrypt = ctr_des_crypt,
0373 .decrypt = ctr_des_crypt,
0374 .chunksize = DES_BLOCK_SIZE,
0375 };
0376
0377 static int ctr_des3_crypt(struct skcipher_request *req)
0378 {
0379 return ctr_desall_crypt(req, CPACF_KMCTR_TDEA_192);
0380 }
0381
0382 static struct skcipher_alg ctr_des3_alg = {
0383 .base.cra_name = "ctr(des3_ede)",
0384 .base.cra_driver_name = "ctr-des3_ede-s390",
0385 .base.cra_priority = 400,
0386 .base.cra_blocksize = 1,
0387 .base.cra_ctxsize = sizeof(struct s390_des_ctx),
0388 .base.cra_module = THIS_MODULE,
0389 .min_keysize = DES3_KEY_SIZE,
0390 .max_keysize = DES3_KEY_SIZE,
0391 .ivsize = DES_BLOCK_SIZE,
0392 .setkey = des3_setkey_skcipher,
0393 .encrypt = ctr_des3_crypt,
0394 .decrypt = ctr_des3_crypt,
0395 .chunksize = DES_BLOCK_SIZE,
0396 };
0397
0398 static struct crypto_alg *des_s390_algs_ptr[2];
0399 static int des_s390_algs_num;
0400 static struct skcipher_alg *des_s390_skciphers_ptr[6];
0401 static int des_s390_skciphers_num;
0402
0403 static int des_s390_register_alg(struct crypto_alg *alg)
0404 {
0405 int ret;
0406
0407 ret = crypto_register_alg(alg);
0408 if (!ret)
0409 des_s390_algs_ptr[des_s390_algs_num++] = alg;
0410 return ret;
0411 }
0412
0413 static int des_s390_register_skcipher(struct skcipher_alg *alg)
0414 {
0415 int ret;
0416
0417 ret = crypto_register_skcipher(alg);
0418 if (!ret)
0419 des_s390_skciphers_ptr[des_s390_skciphers_num++] = alg;
0420 return ret;
0421 }
0422
0423 static void des_s390_exit(void)
0424 {
0425 while (des_s390_algs_num--)
0426 crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]);
0427 while (des_s390_skciphers_num--)
0428 crypto_unregister_skcipher(des_s390_skciphers_ptr[des_s390_skciphers_num]);
0429 if (ctrblk)
0430 free_page((unsigned long) ctrblk);
0431 }
0432
0433 static int __init des_s390_init(void)
0434 {
0435 int ret;
0436
0437
0438 cpacf_query(CPACF_KM, &km_functions);
0439 cpacf_query(CPACF_KMC, &kmc_functions);
0440 cpacf_query(CPACF_KMCTR, &kmctr_functions);
0441
0442 if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) {
0443 ret = des_s390_register_alg(&des_alg);
0444 if (ret)
0445 goto out_err;
0446 ret = des_s390_register_skcipher(&ecb_des_alg);
0447 if (ret)
0448 goto out_err;
0449 }
0450 if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) {
0451 ret = des_s390_register_skcipher(&cbc_des_alg);
0452 if (ret)
0453 goto out_err;
0454 }
0455 if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) {
0456 ret = des_s390_register_alg(&des3_alg);
0457 if (ret)
0458 goto out_err;
0459 ret = des_s390_register_skcipher(&ecb_des3_alg);
0460 if (ret)
0461 goto out_err;
0462 }
0463 if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) {
0464 ret = des_s390_register_skcipher(&cbc_des3_alg);
0465 if (ret)
0466 goto out_err;
0467 }
0468
0469 if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) ||
0470 cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) {
0471 ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
0472 if (!ctrblk) {
0473 ret = -ENOMEM;
0474 goto out_err;
0475 }
0476 }
0477
0478 if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) {
0479 ret = des_s390_register_skcipher(&ctr_des_alg);
0480 if (ret)
0481 goto out_err;
0482 }
0483 if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) {
0484 ret = des_s390_register_skcipher(&ctr_des3_alg);
0485 if (ret)
0486 goto out_err;
0487 }
0488
0489 return 0;
0490 out_err:
0491 des_s390_exit();
0492 return ret;
0493 }
0494
0495 module_cpu_feature_match(S390_CPU_FEATURE_MSA, des_s390_init);
0496 module_exit(des_s390_exit);
0497
0498 MODULE_ALIAS_CRYPTO("des");
0499 MODULE_ALIAS_CRYPTO("des3_ede");
0500
0501 MODULE_LICENSE("GPL");
0502 MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");