xref: /openbmc/linux/arch/s390/crypto/des_s390.c (revision edc63a37)
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, &param, 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