blob: fadd474bf8bbc3e341f089007c77dbda2798ad68 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Cryptographic API.
3 *
Jan Glauberc1e26e12006-01-06 00:19:17 -08004 * s390 implementation of the DES Cipher Algorithm.
Linus Torvalds1da177e2005-04-16 15:20:36 -07005 *
Heiko Carstensa53c8fa2012-07-20 11:15:04 +02006 * Copyright IBM Corp. 2003, 2011
Jan Glauber86aa9fc2007-02-05 21:18:14 +01007 * Author(s): Thomas Spatzier
8 * Jan Glauber (jan.glauber@de.ibm.com)
Linus Torvalds1da177e2005-04-16 15:20:36 -07009 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 */
Herbert Xua9e62fa2006-08-21 21:39:24 +100016
Linus Torvalds1da177e2005-04-16 15:20:36 -070017#include <linux/init.h>
18#include <linux/module.h>
Hendrik Bruecknerd05377c2015-02-19 17:34:07 +010019#include <linux/cpufeature.h>
Jan Glauber1efbd152010-05-21 22:04:46 +100020#include <linux/crypto.h>
21#include <crypto/algapi.h>
22#include <crypto/des.h>
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +010023#include <asm/cpacf.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
Jan Glauber98971f82011-04-19 21:29:15 +020025#define DES3_KEY_SIZE (3 * DES_KEY_SIZE)
Linus Torvalds1da177e2005-04-16 15:20:36 -070026
Gerald Schaefer0200f3e2011-05-04 15:09:44 +100027static u8 *ctrblk;
Harald Freudenbergeree97dc72014-01-22 13:01:33 +010028static DEFINE_SPINLOCK(ctrblk_lock);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +100029
Jan Glauber98971f82011-04-19 21:29:15 +020030struct s390_des_ctx {
Linus Torvalds1da177e2005-04-16 15:20:36 -070031 u8 iv[DES_BLOCK_SIZE];
Jan Glauber98971f82011-04-19 21:29:15 +020032 u8 key[DES3_KEY_SIZE];
Linus Torvalds1da177e2005-04-16 15:20:36 -070033};
34
Herbert Xu6c2bb982006-05-16 22:09:29 +100035static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
Jan Glauber98971f82011-04-19 21:29:15 +020036 unsigned int key_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -070037{
Jan Glauber98971f82011-04-19 21:29:15 +020038 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
Herbert Xu560c06a2006-08-13 14:16:39 +100039 u32 *flags = &tfm->crt_flags;
Jan Glauber1efbd152010-05-21 22:04:46 +100040 u32 tmp[DES_EXPKEY_WORDS];
Linus Torvalds1da177e2005-04-16 15:20:36 -070041
Jan Glauber1efbd152010-05-21 22:04:46 +100042 /* check for weak keys */
43 if (!des_ekey(tmp, key) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
44 *flags |= CRYPTO_TFM_RES_WEAK_KEY;
45 return -EINVAL;
46 }
47
Jan Glauber98971f82011-04-19 21:29:15 +020048 memcpy(ctx->key, key, key_len);
Jan Glauber1efbd152010-05-21 22:04:46 +100049 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -070050}
51
Herbert Xu6c2bb982006-05-16 22:09:29 +100052static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
Linus Torvalds1da177e2005-04-16 15:20:36 -070053{
Jan Glauber98971f82011-04-19 21:29:15 +020054 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
Martin Schwidefskyedc63a32016-08-15 09:19:16 +020056 cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057}
58
Herbert Xu6c2bb982006-05-16 22:09:29 +100059static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
Linus Torvalds1da177e2005-04-16 15:20:36 -070060{
Jan Glauber98971f82011-04-19 21:29:15 +020061 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
Martin Schwidefskyedc63a32016-08-15 09:19:16 +020063 cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT,
64 ctx->key, out, in, DES_BLOCK_SIZE);
Jan Glauberb8dc6032006-01-14 13:20:53 -080065}
66
Linus Torvalds1da177e2005-04-16 15:20:36 -070067static struct crypto_alg des_alg = {
68 .cra_name = "des",
Herbert Xu65b75c32006-08-21 21:18:50 +100069 .cra_driver_name = "des-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +010070 .cra_priority = 300,
Linus Torvalds1da177e2005-04-16 15:20:36 -070071 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
72 .cra_blocksize = DES_BLOCK_SIZE,
Jan Glauber98971f82011-04-19 21:29:15 +020073 .cra_ctxsize = sizeof(struct s390_des_ctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -070074 .cra_module = THIS_MODULE,
Jan Glauberc1357832006-01-14 13:20:53 -080075 .cra_u = {
76 .cipher = {
77 .cia_min_keysize = DES_KEY_SIZE,
78 .cia_max_keysize = DES_KEY_SIZE,
79 .cia_setkey = des_setkey,
80 .cia_encrypt = des_encrypt,
Jan Glauberb8dc6032006-01-14 13:20:53 -080081 .cia_decrypt = des_decrypt,
Jan Glauberc1357832006-01-14 13:20:53 -080082 }
83 }
Linus Torvalds1da177e2005-04-16 15:20:36 -070084};
85
Herbert Xua9e62fa2006-08-21 21:39:24 +100086static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
Jan Glauber98971f82011-04-19 21:29:15 +020087 u8 *key, struct blkcipher_walk *walk)
Herbert Xua9e62fa2006-08-21 21:39:24 +100088{
89 int ret = blkcipher_walk_virt(desc, walk);
90 unsigned int nbytes;
91
92 while ((nbytes = walk->nbytes)) {
93 /* only use complete blocks */
94 unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
95 u8 *out = walk->dst.virt.addr;
96 u8 *in = walk->src.virt.addr;
97
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +010098 ret = cpacf_km(func, key, out, in, n);
Jan Glauber36eb2ca2012-10-26 15:06:12 +020099 if (ret < 0 || ret != n)
100 return -EIO;
Herbert Xua9e62fa2006-08-21 21:39:24 +1000101
102 nbytes &= DES_BLOCK_SIZE - 1;
103 ret = blkcipher_walk_done(desc, walk, nbytes);
104 }
105
106 return ret;
107}
108
109static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
Harald Freudenbergeradc3fcf2014-01-22 13:00:04 +0100110 struct blkcipher_walk *walk)
Herbert Xua9e62fa2006-08-21 21:39:24 +1000111{
Harald Freudenbergeradc3fcf2014-01-22 13:00:04 +0100112 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000113 int ret = blkcipher_walk_virt(desc, walk);
114 unsigned int nbytes = walk->nbytes;
Harald Freudenbergeradc3fcf2014-01-22 13:00:04 +0100115 struct {
116 u8 iv[DES_BLOCK_SIZE];
117 u8 key[DES3_KEY_SIZE];
118 } param;
Herbert Xua9e62fa2006-08-21 21:39:24 +1000119
120 if (!nbytes)
121 goto out;
122
Harald Freudenbergeradc3fcf2014-01-22 13:00:04 +0100123 memcpy(param.iv, walk->iv, DES_BLOCK_SIZE);
124 memcpy(param.key, ctx->key, DES3_KEY_SIZE);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000125 do {
126 /* only use complete blocks */
127 unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
128 u8 *out = walk->dst.virt.addr;
129 u8 *in = walk->src.virt.addr;
130
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100131 ret = cpacf_kmc(func, &param, out, in, n);
Jan Glauber36eb2ca2012-10-26 15:06:12 +0200132 if (ret < 0 || ret != n)
133 return -EIO;
Herbert Xua9e62fa2006-08-21 21:39:24 +1000134
135 nbytes &= DES_BLOCK_SIZE - 1;
136 ret = blkcipher_walk_done(desc, walk, nbytes);
137 } while ((nbytes = walk->nbytes));
Harald Freudenbergeradc3fcf2014-01-22 13:00:04 +0100138 memcpy(walk->iv, param.iv, DES_BLOCK_SIZE);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000139
140out:
141 return ret;
142}
143
144static int ecb_des_encrypt(struct blkcipher_desc *desc,
145 struct scatterlist *dst, struct scatterlist *src,
146 unsigned int nbytes)
147{
Jan Glauber98971f82011-04-19 21:29:15 +0200148 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000149 struct blkcipher_walk walk;
150
151 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200152 return ecb_desall_crypt(desc, CPACF_KM_DEA, ctx->key, &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000153}
154
155static int ecb_des_decrypt(struct blkcipher_desc *desc,
156 struct scatterlist *dst, struct scatterlist *src,
157 unsigned int nbytes)
158{
Jan Glauber98971f82011-04-19 21:29:15 +0200159 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000160 struct blkcipher_walk walk;
161
162 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200163 return ecb_desall_crypt(desc, CPACF_KM_DEA | CPACF_DECRYPT,
164 ctx->key, &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000165}
166
167static struct crypto_alg ecb_des_alg = {
168 .cra_name = "ecb(des)",
169 .cra_driver_name = "ecb-des-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100170 .cra_priority = 400, /* combo: des + ecb */
Herbert Xua9e62fa2006-08-21 21:39:24 +1000171 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
172 .cra_blocksize = DES_BLOCK_SIZE,
Jan Glauber98971f82011-04-19 21:29:15 +0200173 .cra_ctxsize = sizeof(struct s390_des_ctx),
Herbert Xua9e62fa2006-08-21 21:39:24 +1000174 .cra_type = &crypto_blkcipher_type,
175 .cra_module = THIS_MODULE,
Herbert Xua9e62fa2006-08-21 21:39:24 +1000176 .cra_u = {
177 .blkcipher = {
178 .min_keysize = DES_KEY_SIZE,
179 .max_keysize = DES_KEY_SIZE,
180 .setkey = des_setkey,
181 .encrypt = ecb_des_encrypt,
182 .decrypt = ecb_des_decrypt,
183 }
184 }
185};
186
187static int cbc_des_encrypt(struct blkcipher_desc *desc,
188 struct scatterlist *dst, struct scatterlist *src,
189 unsigned int nbytes)
190{
Herbert Xua9e62fa2006-08-21 21:39:24 +1000191 struct blkcipher_walk walk;
192
193 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200194 return cbc_desall_crypt(desc, CPACF_KMC_DEA, &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000195}
196
197static int cbc_des_decrypt(struct blkcipher_desc *desc,
198 struct scatterlist *dst, struct scatterlist *src,
199 unsigned int nbytes)
200{
Herbert Xua9e62fa2006-08-21 21:39:24 +1000201 struct blkcipher_walk walk;
202
203 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200204 return cbc_desall_crypt(desc, CPACF_KMC_DEA | CPACF_DECRYPT, &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000205}
206
207static struct crypto_alg cbc_des_alg = {
208 .cra_name = "cbc(des)",
209 .cra_driver_name = "cbc-des-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100210 .cra_priority = 400, /* combo: des + cbc */
Herbert Xua9e62fa2006-08-21 21:39:24 +1000211 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
212 .cra_blocksize = DES_BLOCK_SIZE,
Jan Glauber98971f82011-04-19 21:29:15 +0200213 .cra_ctxsize = sizeof(struct s390_des_ctx),
Herbert Xua9e62fa2006-08-21 21:39:24 +1000214 .cra_type = &crypto_blkcipher_type,
215 .cra_module = THIS_MODULE,
Herbert Xua9e62fa2006-08-21 21:39:24 +1000216 .cra_u = {
217 .blkcipher = {
218 .min_keysize = DES_KEY_SIZE,
219 .max_keysize = DES_KEY_SIZE,
220 .ivsize = DES_BLOCK_SIZE,
221 .setkey = des_setkey,
222 .encrypt = cbc_des_encrypt,
223 .decrypt = cbc_des_decrypt,
224 }
225 }
226};
227
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228/*
229 * RFC2451:
230 *
231 * For DES-EDE3, there is no known need to reject weak or
232 * complementation keys. Any weakness is obviated by the use of
233 * multiple keys.
234 *
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235 * However, if the first two or last two independent 64-bit keys are
236 * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
237 * same as DES. Implementers MUST reject keys that exhibit this
238 * property.
239 *
240 */
Jan Glauber98971f82011-04-19 21:29:15 +0200241static int des3_setkey(struct crypto_tfm *tfm, const u8 *key,
242 unsigned int key_len)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700243{
Jan Glauber98971f82011-04-19 21:29:15 +0200244 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
Herbert Xu560c06a2006-08-13 14:16:39 +1000245 u32 *flags = &tfm->crt_flags;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700246
Daniel Borkmannfed28612013-12-11 11:28:59 +0100247 if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
248 crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
249 DES_KEY_SIZE)) &&
Jarod Wilson03b56ce2009-06-18 19:52:59 +0800250 (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
251 *flags |= CRYPTO_TFM_RES_WEAK_KEY;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700252 return -EINVAL;
253 }
Jan Glauber98971f82011-04-19 21:29:15 +0200254 memcpy(ctx->key, key, key_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700255 return 0;
256}
257
Jan Glauber98971f82011-04-19 21:29:15 +0200258static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700259{
Jan Glauber98971f82011-04-19 21:29:15 +0200260 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200262 cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700263}
264
Jan Glauber98971f82011-04-19 21:29:15 +0200265static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700266{
Jan Glauber98971f82011-04-19 21:29:15 +0200267 struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700268
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200269 cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT,
270 ctx->key, dst, src, DES_BLOCK_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700271}
272
Jan Glauber98971f82011-04-19 21:29:15 +0200273static struct crypto_alg des3_alg = {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700274 .cra_name = "des3_ede",
Herbert Xu65b75c32006-08-21 21:18:50 +1000275 .cra_driver_name = "des3_ede-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100276 .cra_priority = 300,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700277 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
Jan Glauber1efbd152010-05-21 22:04:46 +1000278 .cra_blocksize = DES_BLOCK_SIZE,
Jan Glauber98971f82011-04-19 21:29:15 +0200279 .cra_ctxsize = sizeof(struct s390_des_ctx),
Linus Torvalds1da177e2005-04-16 15:20:36 -0700280 .cra_module = THIS_MODULE,
Jan Glauberc1357832006-01-14 13:20:53 -0800281 .cra_u = {
282 .cipher = {
Jan Glauber98971f82011-04-19 21:29:15 +0200283 .cia_min_keysize = DES3_KEY_SIZE,
284 .cia_max_keysize = DES3_KEY_SIZE,
285 .cia_setkey = des3_setkey,
286 .cia_encrypt = des3_encrypt,
287 .cia_decrypt = des3_decrypt,
Jan Glauberc1357832006-01-14 13:20:53 -0800288 }
289 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700290};
291
Jan Glauber98971f82011-04-19 21:29:15 +0200292static int ecb_des3_encrypt(struct blkcipher_desc *desc,
293 struct scatterlist *dst, struct scatterlist *src,
294 unsigned int nbytes)
Herbert Xua9e62fa2006-08-21 21:39:24 +1000295{
Jan Glauber98971f82011-04-19 21:29:15 +0200296 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000297 struct blkcipher_walk walk;
298
299 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200300 return ecb_desall_crypt(desc, CPACF_KM_TDEA_192, ctx->key, &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000301}
302
Jan Glauber98971f82011-04-19 21:29:15 +0200303static int ecb_des3_decrypt(struct blkcipher_desc *desc,
304 struct scatterlist *dst, struct scatterlist *src,
305 unsigned int nbytes)
Herbert Xua9e62fa2006-08-21 21:39:24 +1000306{
Jan Glauber98971f82011-04-19 21:29:15 +0200307 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000308 struct blkcipher_walk walk;
309
310 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200311 return ecb_desall_crypt(desc, CPACF_KM_TDEA_192 | CPACF_DECRYPT,
312 ctx->key, &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000313}
314
Jan Glauber98971f82011-04-19 21:29:15 +0200315static struct crypto_alg ecb_des3_alg = {
Herbert Xua9e62fa2006-08-21 21:39:24 +1000316 .cra_name = "ecb(des3_ede)",
317 .cra_driver_name = "ecb-des3_ede-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100318 .cra_priority = 400, /* combo: des3 + ecb */
Herbert Xua9e62fa2006-08-21 21:39:24 +1000319 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
Jan Glauber1efbd152010-05-21 22:04:46 +1000320 .cra_blocksize = DES_BLOCK_SIZE,
Jan Glauber98971f82011-04-19 21:29:15 +0200321 .cra_ctxsize = sizeof(struct s390_des_ctx),
Herbert Xua9e62fa2006-08-21 21:39:24 +1000322 .cra_type = &crypto_blkcipher_type,
323 .cra_module = THIS_MODULE,
Herbert Xua9e62fa2006-08-21 21:39:24 +1000324 .cra_u = {
325 .blkcipher = {
Jan Glauber98971f82011-04-19 21:29:15 +0200326 .min_keysize = DES3_KEY_SIZE,
327 .max_keysize = DES3_KEY_SIZE,
328 .setkey = des3_setkey,
329 .encrypt = ecb_des3_encrypt,
330 .decrypt = ecb_des3_decrypt,
Herbert Xua9e62fa2006-08-21 21:39:24 +1000331 }
332 }
333};
334
Jan Glauber98971f82011-04-19 21:29:15 +0200335static int cbc_des3_encrypt(struct blkcipher_desc *desc,
336 struct scatterlist *dst, struct scatterlist *src,
337 unsigned int nbytes)
Herbert Xua9e62fa2006-08-21 21:39:24 +1000338{
Herbert Xua9e62fa2006-08-21 21:39:24 +1000339 struct blkcipher_walk walk;
340
341 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200342 return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192, &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000343}
344
Jan Glauber98971f82011-04-19 21:29:15 +0200345static int cbc_des3_decrypt(struct blkcipher_desc *desc,
346 struct scatterlist *dst, struct scatterlist *src,
347 unsigned int nbytes)
Herbert Xua9e62fa2006-08-21 21:39:24 +1000348{
Herbert Xua9e62fa2006-08-21 21:39:24 +1000349 struct blkcipher_walk walk;
350
351 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200352 return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192 | CPACF_DECRYPT,
353 &walk);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000354}
355
Jan Glauber98971f82011-04-19 21:29:15 +0200356static struct crypto_alg cbc_des3_alg = {
Herbert Xua9e62fa2006-08-21 21:39:24 +1000357 .cra_name = "cbc(des3_ede)",
358 .cra_driver_name = "cbc-des3_ede-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100359 .cra_priority = 400, /* combo: des3 + cbc */
Herbert Xua9e62fa2006-08-21 21:39:24 +1000360 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
Jan Glauber1efbd152010-05-21 22:04:46 +1000361 .cra_blocksize = DES_BLOCK_SIZE,
Jan Glauber98971f82011-04-19 21:29:15 +0200362 .cra_ctxsize = sizeof(struct s390_des_ctx),
Herbert Xua9e62fa2006-08-21 21:39:24 +1000363 .cra_type = &crypto_blkcipher_type,
364 .cra_module = THIS_MODULE,
Herbert Xua9e62fa2006-08-21 21:39:24 +1000365 .cra_u = {
366 .blkcipher = {
Jan Glauber98971f82011-04-19 21:29:15 +0200367 .min_keysize = DES3_KEY_SIZE,
368 .max_keysize = DES3_KEY_SIZE,
Jan Glauber1efbd152010-05-21 22:04:46 +1000369 .ivsize = DES_BLOCK_SIZE,
Jan Glauber98971f82011-04-19 21:29:15 +0200370 .setkey = des3_setkey,
371 .encrypt = cbc_des3_encrypt,
372 .decrypt = cbc_des3_decrypt,
Herbert Xua9e62fa2006-08-21 21:39:24 +1000373 }
374 }
375};
376
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100377static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
378{
379 unsigned int i, n;
380
381 /* align to block size, max. PAGE_SIZE */
382 n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1);
383 for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
384 memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
385 crypto_inc(ctrptr + i, DES_BLOCK_SIZE);
386 }
387 return n;
388}
389
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000390static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100391 struct s390_des_ctx *ctx,
392 struct blkcipher_walk *walk)
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000393{
394 int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100395 unsigned int n, nbytes;
396 u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE];
397 u8 *out, *in, *ctrptr = ctrbuf;
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000398
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100399 if (!walk->nbytes)
400 return ret;
401
402 if (spin_trylock(&ctrblk_lock))
403 ctrptr = ctrblk;
404
405 memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000406 while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
407 out = walk->dst.virt.addr;
408 in = walk->src.virt.addr;
409 while (nbytes >= DES_BLOCK_SIZE) {
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100410 if (ctrptr == ctrblk)
411 n = __ctrblk_init(ctrptr, nbytes);
412 else
413 n = DES_BLOCK_SIZE;
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100414 ret = cpacf_kmctr(func, ctx->key, out, in, n, ctrptr);
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100415 if (ret < 0 || ret != n) {
416 if (ctrptr == ctrblk)
417 spin_unlock(&ctrblk_lock);
Jan Glauber36eb2ca2012-10-26 15:06:12 +0200418 return -EIO;
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100419 }
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000420 if (n > DES_BLOCK_SIZE)
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100421 memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE,
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000422 DES_BLOCK_SIZE);
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100423 crypto_inc(ctrptr, DES_BLOCK_SIZE);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000424 out += n;
425 in += n;
426 nbytes -= n;
427 }
428 ret = blkcipher_walk_done(desc, walk, nbytes);
429 }
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100430 if (ctrptr == ctrblk) {
431 if (nbytes)
432 memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE);
433 else
434 memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
435 spin_unlock(&ctrblk_lock);
Harald Freudenberger3901c112014-05-07 16:51:29 +0200436 } else {
437 if (!nbytes)
438 memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100439 }
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000440 /* final block may be < DES_BLOCK_SIZE, copy only nbytes */
441 if (nbytes) {
442 out = walk->dst.virt.addr;
443 in = walk->src.virt.addr;
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100444 ret = cpacf_kmctr(func, ctx->key, buf, in,
445 DES_BLOCK_SIZE, ctrbuf);
Jan Glauber36eb2ca2012-10-26 15:06:12 +0200446 if (ret < 0 || ret != DES_BLOCK_SIZE)
447 return -EIO;
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000448 memcpy(out, buf, nbytes);
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100449 crypto_inc(ctrbuf, DES_BLOCK_SIZE);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000450 ret = blkcipher_walk_done(desc, walk, 0);
Harald Freudenbergeree97dc72014-01-22 13:01:33 +0100451 memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000452 }
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000453 return ret;
454}
455
456static int ctr_des_encrypt(struct blkcipher_desc *desc,
457 struct scatterlist *dst, struct scatterlist *src,
458 unsigned int nbytes)
459{
460 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
461 struct blkcipher_walk walk;
462
463 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200464 return ctr_desall_crypt(desc, CPACF_KMCTR_DEA, ctx, &walk);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000465}
466
467static int ctr_des_decrypt(struct blkcipher_desc *desc,
468 struct scatterlist *dst, struct scatterlist *src,
469 unsigned int nbytes)
470{
471 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
472 struct blkcipher_walk walk;
473
474 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200475 return ctr_desall_crypt(desc, CPACF_KMCTR_DEA | CPACF_DECRYPT,
476 ctx, &walk);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000477}
478
479static struct crypto_alg ctr_des_alg = {
480 .cra_name = "ctr(des)",
481 .cra_driver_name = "ctr-des-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100482 .cra_priority = 400, /* combo: des + ctr */
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000483 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
484 .cra_blocksize = 1,
485 .cra_ctxsize = sizeof(struct s390_des_ctx),
486 .cra_type = &crypto_blkcipher_type,
487 .cra_module = THIS_MODULE,
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000488 .cra_u = {
489 .blkcipher = {
490 .min_keysize = DES_KEY_SIZE,
491 .max_keysize = DES_KEY_SIZE,
492 .ivsize = DES_BLOCK_SIZE,
493 .setkey = des_setkey,
494 .encrypt = ctr_des_encrypt,
495 .decrypt = ctr_des_decrypt,
496 }
497 }
498};
499
500static int ctr_des3_encrypt(struct blkcipher_desc *desc,
501 struct scatterlist *dst, struct scatterlist *src,
502 unsigned int nbytes)
503{
504 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
505 struct blkcipher_walk walk;
506
507 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200508 return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192, ctx, &walk);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000509}
510
511static int ctr_des3_decrypt(struct blkcipher_desc *desc,
512 struct scatterlist *dst, struct scatterlist *src,
513 unsigned int nbytes)
514{
515 struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
516 struct blkcipher_walk walk;
517
518 blkcipher_walk_init(&walk, dst, src, nbytes);
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200519 return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192 | CPACF_DECRYPT,
520 ctx, &walk);
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000521}
522
523static struct crypto_alg ctr_des3_alg = {
524 .cra_name = "ctr(des3_ede)",
525 .cra_driver_name = "ctr-des3_ede-s390",
Martin Schwidefskyc7d4d252016-03-17 15:22:12 +0100526 .cra_priority = 400, /* combo: des3 + ede */
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000527 .cra_flags = CRYPTO_ALG_TYPE_BLKCIPHER,
528 .cra_blocksize = 1,
529 .cra_ctxsize = sizeof(struct s390_des_ctx),
530 .cra_type = &crypto_blkcipher_type,
531 .cra_module = THIS_MODULE,
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000532 .cra_u = {
533 .blkcipher = {
534 .min_keysize = DES3_KEY_SIZE,
535 .max_keysize = DES3_KEY_SIZE,
536 .ivsize = DES_BLOCK_SIZE,
537 .setkey = des3_setkey,
538 .encrypt = ctr_des3_encrypt,
539 .decrypt = ctr_des3_decrypt,
540 }
541 }
542};
543
Jan Glauber98971f82011-04-19 21:29:15 +0200544static int __init des_s390_init(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700545{
Jan Glauber80d663a2010-05-21 22:04:08 +1000546 int ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200548 if (!cpacf_query(CPACF_KM, CPACF_KM_DEA) ||
549 !cpacf_query(CPACF_KM, CPACF_KM_TDEA_192))
Jan Glauber86aa9fc2007-02-05 21:18:14 +0100550 return -EOPNOTSUPP;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551
Herbert Xua9e62fa2006-08-21 21:39:24 +1000552 ret = crypto_register_alg(&des_alg);
553 if (ret)
554 goto des_err;
555 ret = crypto_register_alg(&ecb_des_alg);
556 if (ret)
557 goto ecb_des_err;
558 ret = crypto_register_alg(&cbc_des_alg);
559 if (ret)
560 goto cbc_des_err;
Jan Glauber98971f82011-04-19 21:29:15 +0200561 ret = crypto_register_alg(&des3_alg);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000562 if (ret)
Jan Glauber98971f82011-04-19 21:29:15 +0200563 goto des3_err;
564 ret = crypto_register_alg(&ecb_des3_alg);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000565 if (ret)
Jan Glauber98971f82011-04-19 21:29:15 +0200566 goto ecb_des3_err;
567 ret = crypto_register_alg(&cbc_des3_alg);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000568 if (ret)
Jan Glauber98971f82011-04-19 21:29:15 +0200569 goto cbc_des3_err;
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000570
Martin Schwidefskyedc63a32016-08-15 09:19:16 +0200571 if (cpacf_query(CPACF_KMCTR, CPACF_KMCTR_DEA) &&
572 cpacf_query(CPACF_KMCTR, CPACF_KMCTR_TDEA_192)) {
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000573 ret = crypto_register_alg(&ctr_des_alg);
574 if (ret)
575 goto ctr_des_err;
576 ret = crypto_register_alg(&ctr_des3_alg);
577 if (ret)
578 goto ctr_des3_err;
579 ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
580 if (!ctrblk) {
581 ret = -ENOMEM;
582 goto ctr_mem_err;
583 }
584 }
Herbert Xua9e62fa2006-08-21 21:39:24 +1000585out:
586 return ret;
587
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000588ctr_mem_err:
589 crypto_unregister_alg(&ctr_des3_alg);
590ctr_des3_err:
591 crypto_unregister_alg(&ctr_des_alg);
592ctr_des_err:
593 crypto_unregister_alg(&cbc_des3_alg);
Jan Glauber98971f82011-04-19 21:29:15 +0200594cbc_des3_err:
595 crypto_unregister_alg(&ecb_des3_alg);
596ecb_des3_err:
597 crypto_unregister_alg(&des3_alg);
598des3_err:
Herbert Xua9e62fa2006-08-21 21:39:24 +1000599 crypto_unregister_alg(&cbc_des_alg);
600cbc_des_err:
601 crypto_unregister_alg(&ecb_des_alg);
602ecb_des_err:
603 crypto_unregister_alg(&des_alg);
604des_err:
605 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606}
607
Jan Glauber1efbd152010-05-21 22:04:46 +1000608static void __exit des_s390_exit(void)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609{
Gerald Schaefer0200f3e2011-05-04 15:09:44 +1000610 if (ctrblk) {
611 crypto_unregister_alg(&ctr_des_alg);
612 crypto_unregister_alg(&ctr_des3_alg);
613 free_page((unsigned long) ctrblk);
614 }
Jan Glauber98971f82011-04-19 21:29:15 +0200615 crypto_unregister_alg(&cbc_des3_alg);
616 crypto_unregister_alg(&ecb_des3_alg);
617 crypto_unregister_alg(&des3_alg);
Herbert Xua9e62fa2006-08-21 21:39:24 +1000618 crypto_unregister_alg(&cbc_des_alg);
619 crypto_unregister_alg(&ecb_des_alg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 crypto_unregister_alg(&des_alg);
621}
622
Hendrik Bruecknerd05377c2015-02-19 17:34:07 +0100623module_cpu_feature_match(MSA, des_s390_init);
Jan Glauber1efbd152010-05-21 22:04:46 +1000624module_exit(des_s390_exit);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700625
Kees Cook5d26a102014-11-20 17:05:53 -0800626MODULE_ALIAS_CRYPTO("des");
627MODULE_ALIAS_CRYPTO("des3_ede");
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628
629MODULE_LICENSE("GPL");
630MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");