xref: /openbmc/linux/arch/s390/crypto/des_s390.c (revision 69c0e360)
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 
3069c0e360SMartin Schwidefsky static cpacf_mask_t km_functions, kmc_functions, kmctr_functions;
3169c0e360SMartin Schwidefsky 
3298971f84SJan Glauber struct s390_des_ctx {
33c1e26e1eSJan Glauber 	u8 iv[DES_BLOCK_SIZE];
3498971f84SJan Glauber 	u8 key[DES3_KEY_SIZE];
35c1e26e1eSJan Glauber };
36c1e26e1eSJan Glauber 
376c2bb98bSHerbert Xu static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
3898971f84SJan Glauber 		      unsigned int key_len)
39c1e26e1eSJan Glauber {
4098971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
411efbd15cSJan Glauber 	u32 tmp[DES_EXPKEY_WORDS];
42c1e26e1eSJan Glauber 
431efbd15cSJan Glauber 	/* check for weak keys */
4469c0e360SMartin Schwidefsky 	if (!des_ekey(tmp, key) &&
4569c0e360SMartin Schwidefsky 	    (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
4669c0e360SMartin Schwidefsky 		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
471efbd15cSJan Glauber 		return -EINVAL;
481efbd15cSJan Glauber 	}
491efbd15cSJan Glauber 
5098971f84SJan Glauber 	memcpy(ctx->key, key, key_len);
511efbd15cSJan Glauber 	return 0;
52c1e26e1eSJan Glauber }
53c1e26e1eSJan Glauber 
546c2bb98bSHerbert Xu static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
55c1e26e1eSJan Glauber {
5698971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
57c1e26e1eSJan Glauber 
58edc63a37SMartin Schwidefsky 	cpacf_km(CPACF_KM_DEA, ctx->key, out, in, DES_BLOCK_SIZE);
59c1e26e1eSJan Glauber }
60c1e26e1eSJan Glauber 
616c2bb98bSHerbert Xu static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
62c1e26e1eSJan Glauber {
6398971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
64c1e26e1eSJan Glauber 
65edc63a37SMartin Schwidefsky 	cpacf_km(CPACF_KM_DEA | CPACF_DECRYPT,
66edc63a37SMartin Schwidefsky 		 ctx->key, out, in, DES_BLOCK_SIZE);
67b8dc6038SJan Glauber }
68b8dc6038SJan Glauber 
69c1e26e1eSJan Glauber static struct crypto_alg des_alg = {
70c1e26e1eSJan Glauber 	.cra_name		=	"des",
7165b75c36SHerbert Xu 	.cra_driver_name	=	"des-s390",
72c7d4d259SMartin Schwidefsky 	.cra_priority		=	300,
73c1e26e1eSJan Glauber 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
74c1e26e1eSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
7598971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
76c1e26e1eSJan Glauber 	.cra_module		=	THIS_MODULE,
77c1357833SJan Glauber 	.cra_u			=	{
78c1357833SJan Glauber 		.cipher = {
79c1e26e1eSJan Glauber 			.cia_min_keysize	=	DES_KEY_SIZE,
80c1e26e1eSJan Glauber 			.cia_max_keysize	=	DES_KEY_SIZE,
81c1e26e1eSJan Glauber 			.cia_setkey		=	des_setkey,
82c1e26e1eSJan Glauber 			.cia_encrypt		=	des_encrypt,
83b8dc6038SJan Glauber 			.cia_decrypt		=	des_decrypt,
84c1357833SJan Glauber 		}
85c1357833SJan Glauber 	}
86c1e26e1eSJan Glauber };
87c1e26e1eSJan Glauber 
88a9e62fadSHerbert Xu static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
8998971f84SJan Glauber 			    u8 *key, struct blkcipher_walk *walk)
90a9e62fadSHerbert Xu {
91a9e62fadSHerbert Xu 	int ret = blkcipher_walk_virt(desc, walk);
92a9e62fadSHerbert Xu 	unsigned int nbytes;
93a9e62fadSHerbert Xu 
94a9e62fadSHerbert Xu 	while ((nbytes = walk->nbytes)) {
95a9e62fadSHerbert Xu 		/* only use complete blocks */
96a9e62fadSHerbert Xu 		unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
97a9e62fadSHerbert Xu 		u8 *out = walk->dst.virt.addr;
98a9e62fadSHerbert Xu 		u8 *in = walk->src.virt.addr;
99a9e62fadSHerbert Xu 
1000177db01SMartin Schwidefsky 		cpacf_km(func, key, out, in, n);
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 
1310177db01SMartin Schwidefsky 		cpacf_kmc(func, &param, out, in, n);
132a9e62fadSHerbert Xu 
133a9e62fadSHerbert Xu 		nbytes &= DES_BLOCK_SIZE - 1;
134a9e62fadSHerbert Xu 		ret = blkcipher_walk_done(desc, walk, nbytes);
135a9e62fadSHerbert Xu 	} while ((nbytes = walk->nbytes));
136adc3fcf1SHarald Freudenberger 	memcpy(walk->iv, param.iv, DES_BLOCK_SIZE);
137a9e62fadSHerbert Xu 
138a9e62fadSHerbert Xu out:
139a9e62fadSHerbert Xu 	return ret;
140a9e62fadSHerbert Xu }
141a9e62fadSHerbert Xu 
142a9e62fadSHerbert Xu static int ecb_des_encrypt(struct blkcipher_desc *desc,
143a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
144a9e62fadSHerbert Xu 			   unsigned int nbytes)
145a9e62fadSHerbert Xu {
14698971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
147a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
148a9e62fadSHerbert Xu 
149a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
150edc63a37SMartin Schwidefsky 	return ecb_desall_crypt(desc, CPACF_KM_DEA, ctx->key, &walk);
151a9e62fadSHerbert Xu }
152a9e62fadSHerbert Xu 
153a9e62fadSHerbert Xu static int ecb_des_decrypt(struct blkcipher_desc *desc,
154a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
155a9e62fadSHerbert Xu 			   unsigned int nbytes)
156a9e62fadSHerbert Xu {
15798971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
158a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
159a9e62fadSHerbert Xu 
160a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
161edc63a37SMartin Schwidefsky 	return ecb_desall_crypt(desc, CPACF_KM_DEA | CPACF_DECRYPT,
162edc63a37SMartin Schwidefsky 				ctx->key, &walk);
163a9e62fadSHerbert Xu }
164a9e62fadSHerbert Xu 
165a9e62fadSHerbert Xu static struct crypto_alg ecb_des_alg = {
166a9e62fadSHerbert Xu 	.cra_name		=	"ecb(des)",
167a9e62fadSHerbert Xu 	.cra_driver_name	=	"ecb-des-s390",
168c7d4d259SMartin Schwidefsky 	.cra_priority		=	400,	/* combo: des + ecb */
169a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
170a9e62fadSHerbert Xu 	.cra_blocksize		=	DES_BLOCK_SIZE,
17198971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
172a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
173a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
174a9e62fadSHerbert Xu 	.cra_u			=	{
175a9e62fadSHerbert Xu 		.blkcipher = {
176a9e62fadSHerbert Xu 			.min_keysize		=	DES_KEY_SIZE,
177a9e62fadSHerbert Xu 			.max_keysize		=	DES_KEY_SIZE,
178a9e62fadSHerbert Xu 			.setkey			=	des_setkey,
179a9e62fadSHerbert Xu 			.encrypt		=	ecb_des_encrypt,
180a9e62fadSHerbert Xu 			.decrypt		=	ecb_des_decrypt,
181a9e62fadSHerbert Xu 		}
182a9e62fadSHerbert Xu 	}
183a9e62fadSHerbert Xu };
184a9e62fadSHerbert Xu 
185a9e62fadSHerbert Xu static int cbc_des_encrypt(struct blkcipher_desc *desc,
186a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
187a9e62fadSHerbert Xu 			   unsigned int nbytes)
188a9e62fadSHerbert Xu {
189a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
190a9e62fadSHerbert Xu 
191a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
192edc63a37SMartin Schwidefsky 	return cbc_desall_crypt(desc, CPACF_KMC_DEA, &walk);
193a9e62fadSHerbert Xu }
194a9e62fadSHerbert Xu 
195a9e62fadSHerbert Xu static int cbc_des_decrypt(struct blkcipher_desc *desc,
196a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
197a9e62fadSHerbert Xu 			   unsigned int nbytes)
198a9e62fadSHerbert Xu {
199a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
200a9e62fadSHerbert Xu 
201a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
202edc63a37SMartin Schwidefsky 	return cbc_desall_crypt(desc, CPACF_KMC_DEA | CPACF_DECRYPT, &walk);
203a9e62fadSHerbert Xu }
204a9e62fadSHerbert Xu 
205a9e62fadSHerbert Xu static struct crypto_alg cbc_des_alg = {
206a9e62fadSHerbert Xu 	.cra_name		=	"cbc(des)",
207a9e62fadSHerbert Xu 	.cra_driver_name	=	"cbc-des-s390",
208c7d4d259SMartin Schwidefsky 	.cra_priority		=	400,	/* combo: des + cbc */
209a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
210a9e62fadSHerbert Xu 	.cra_blocksize		=	DES_BLOCK_SIZE,
21198971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
212a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
213a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
214a9e62fadSHerbert Xu 	.cra_u			=	{
215a9e62fadSHerbert Xu 		.blkcipher = {
216a9e62fadSHerbert Xu 			.min_keysize		=	DES_KEY_SIZE,
217a9e62fadSHerbert Xu 			.max_keysize		=	DES_KEY_SIZE,
218a9e62fadSHerbert Xu 			.ivsize			=	DES_BLOCK_SIZE,
219a9e62fadSHerbert Xu 			.setkey			=	des_setkey,
220a9e62fadSHerbert Xu 			.encrypt		=	cbc_des_encrypt,
221a9e62fadSHerbert Xu 			.decrypt		=	cbc_des_decrypt,
222a9e62fadSHerbert Xu 		}
223a9e62fadSHerbert Xu 	}
224a9e62fadSHerbert Xu };
225a9e62fadSHerbert Xu 
226c1e26e1eSJan Glauber /*
227c1e26e1eSJan Glauber  * RFC2451:
228c1e26e1eSJan Glauber  *
229c1e26e1eSJan Glauber  *   For DES-EDE3, there is no known need to reject weak or
230c1e26e1eSJan Glauber  *   complementation keys.  Any weakness is obviated by the use of
231c1e26e1eSJan Glauber  *   multiple keys.
232c1e26e1eSJan Glauber  *
233c1e26e1eSJan Glauber  *   However, if the first two or last two independent 64-bit keys are
234c1e26e1eSJan Glauber  *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
235c1e26e1eSJan Glauber  *   same as DES.  Implementers MUST reject keys that exhibit this
236c1e26e1eSJan Glauber  *   property.
237c1e26e1eSJan Glauber  *
238c1e26e1eSJan Glauber  */
23998971f84SJan Glauber static int des3_setkey(struct crypto_tfm *tfm, const u8 *key,
24098971f84SJan Glauber 		       unsigned int key_len)
241c1e26e1eSJan Glauber {
24298971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
243c1e26e1eSJan Glauber 
244fed28611SDaniel Borkmann 	if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
245fed28611SDaniel Borkmann 	    crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
24603b56ce5SJarod Wilson 			  DES_KEY_SIZE)) &&
24769c0e360SMartin Schwidefsky 	    (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
24869c0e360SMartin Schwidefsky 		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
249c1e26e1eSJan Glauber 		return -EINVAL;
250c1e26e1eSJan Glauber 	}
25198971f84SJan Glauber 	memcpy(ctx->key, key, key_len);
252c1e26e1eSJan Glauber 	return 0;
253c1e26e1eSJan Glauber }
254c1e26e1eSJan Glauber 
25598971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
256c1e26e1eSJan Glauber {
25798971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
258c1e26e1eSJan Glauber 
259edc63a37SMartin Schwidefsky 	cpacf_km(CPACF_KM_TDEA_192, ctx->key, dst, src, DES_BLOCK_SIZE);
260c1e26e1eSJan Glauber }
261c1e26e1eSJan Glauber 
26298971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
263c1e26e1eSJan Glauber {
26498971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
265c1e26e1eSJan Glauber 
266edc63a37SMartin Schwidefsky 	cpacf_km(CPACF_KM_TDEA_192 | CPACF_DECRYPT,
267edc63a37SMartin Schwidefsky 		 ctx->key, dst, src, DES_BLOCK_SIZE);
268c1e26e1eSJan Glauber }
269c1e26e1eSJan Glauber 
27098971f84SJan Glauber static struct crypto_alg des3_alg = {
271c1e26e1eSJan Glauber 	.cra_name		=	"des3_ede",
27265b75c36SHerbert Xu 	.cra_driver_name	=	"des3_ede-s390",
273c7d4d259SMartin Schwidefsky 	.cra_priority		=	300,
274c1e26e1eSJan Glauber 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
2751efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
27698971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
277c1e26e1eSJan Glauber 	.cra_module		=	THIS_MODULE,
278c1357833SJan Glauber 	.cra_u			=	{
279c1357833SJan Glauber 		.cipher = {
28098971f84SJan Glauber 			.cia_min_keysize	=	DES3_KEY_SIZE,
28198971f84SJan Glauber 			.cia_max_keysize	=	DES3_KEY_SIZE,
28298971f84SJan Glauber 			.cia_setkey		=	des3_setkey,
28398971f84SJan Glauber 			.cia_encrypt		=	des3_encrypt,
28498971f84SJan Glauber 			.cia_decrypt		=	des3_decrypt,
285c1357833SJan Glauber 		}
286c1357833SJan Glauber 	}
287c1e26e1eSJan Glauber };
288c1e26e1eSJan Glauber 
28998971f84SJan Glauber static int ecb_des3_encrypt(struct blkcipher_desc *desc,
29098971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
29198971f84SJan Glauber 			    unsigned int nbytes)
292a9e62fadSHerbert Xu {
29398971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
294a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
295a9e62fadSHerbert Xu 
296a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
297edc63a37SMartin Schwidefsky 	return ecb_desall_crypt(desc, CPACF_KM_TDEA_192, ctx->key, &walk);
298a9e62fadSHerbert Xu }
299a9e62fadSHerbert Xu 
30098971f84SJan Glauber static int ecb_des3_decrypt(struct blkcipher_desc *desc,
30198971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
30298971f84SJan Glauber 			    unsigned int nbytes)
303a9e62fadSHerbert Xu {
30498971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
305a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
306a9e62fadSHerbert Xu 
307a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
308edc63a37SMartin Schwidefsky 	return ecb_desall_crypt(desc, CPACF_KM_TDEA_192 | CPACF_DECRYPT,
309edc63a37SMartin Schwidefsky 				ctx->key, &walk);
310a9e62fadSHerbert Xu }
311a9e62fadSHerbert Xu 
31298971f84SJan Glauber static struct crypto_alg ecb_des3_alg = {
313a9e62fadSHerbert Xu 	.cra_name		=	"ecb(des3_ede)",
314a9e62fadSHerbert Xu 	.cra_driver_name	=	"ecb-des3_ede-s390",
315c7d4d259SMartin Schwidefsky 	.cra_priority		=	400,	/* combo: des3 + ecb */
316a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
3171efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
31898971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
319a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
320a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
321a9e62fadSHerbert Xu 	.cra_u			=	{
322a9e62fadSHerbert Xu 		.blkcipher = {
32398971f84SJan Glauber 			.min_keysize		=	DES3_KEY_SIZE,
32498971f84SJan Glauber 			.max_keysize		=	DES3_KEY_SIZE,
32598971f84SJan Glauber 			.setkey			=	des3_setkey,
32698971f84SJan Glauber 			.encrypt		=	ecb_des3_encrypt,
32798971f84SJan Glauber 			.decrypt		=	ecb_des3_decrypt,
328a9e62fadSHerbert Xu 		}
329a9e62fadSHerbert Xu 	}
330a9e62fadSHerbert Xu };
331a9e62fadSHerbert Xu 
33298971f84SJan Glauber static int cbc_des3_encrypt(struct blkcipher_desc *desc,
33398971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
33498971f84SJan Glauber 			    unsigned int nbytes)
335a9e62fadSHerbert Xu {
336a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
337a9e62fadSHerbert Xu 
338a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
339edc63a37SMartin Schwidefsky 	return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192, &walk);
340a9e62fadSHerbert Xu }
341a9e62fadSHerbert Xu 
34298971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc,
34398971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
34498971f84SJan Glauber 			    unsigned int nbytes)
345a9e62fadSHerbert Xu {
346a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
347a9e62fadSHerbert Xu 
348a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
349edc63a37SMartin Schwidefsky 	return cbc_desall_crypt(desc, CPACF_KMC_TDEA_192 | CPACF_DECRYPT,
350edc63a37SMartin Schwidefsky 				&walk);
351a9e62fadSHerbert Xu }
352a9e62fadSHerbert Xu 
35398971f84SJan Glauber static struct crypto_alg cbc_des3_alg = {
354a9e62fadSHerbert Xu 	.cra_name		=	"cbc(des3_ede)",
355a9e62fadSHerbert Xu 	.cra_driver_name	=	"cbc-des3_ede-s390",
356c7d4d259SMartin Schwidefsky 	.cra_priority		=	400,	/* combo: des3 + cbc */
357a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
3581efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
35998971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
360a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
361a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
362a9e62fadSHerbert Xu 	.cra_u			=	{
363a9e62fadSHerbert Xu 		.blkcipher = {
36498971f84SJan Glauber 			.min_keysize		=	DES3_KEY_SIZE,
36598971f84SJan Glauber 			.max_keysize		=	DES3_KEY_SIZE,
3661efbd15cSJan Glauber 			.ivsize			=	DES_BLOCK_SIZE,
36798971f84SJan Glauber 			.setkey			=	des3_setkey,
36898971f84SJan Glauber 			.encrypt		=	cbc_des3_encrypt,
36998971f84SJan Glauber 			.decrypt		=	cbc_des3_decrypt,
370a9e62fadSHerbert Xu 		}
371a9e62fadSHerbert Xu 	}
372a9e62fadSHerbert Xu };
373a9e62fadSHerbert Xu 
374ee97dc7dSHarald Freudenberger static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
375ee97dc7dSHarald Freudenberger {
376ee97dc7dSHarald Freudenberger 	unsigned int i, n;
377ee97dc7dSHarald Freudenberger 
378ee97dc7dSHarald Freudenberger 	/* align to block size, max. PAGE_SIZE */
379ee97dc7dSHarald Freudenberger 	n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1);
380ee97dc7dSHarald Freudenberger 	for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
381ee97dc7dSHarald Freudenberger 		memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
382ee97dc7dSHarald Freudenberger 		crypto_inc(ctrptr + i, DES_BLOCK_SIZE);
383ee97dc7dSHarald Freudenberger 	}
384ee97dc7dSHarald Freudenberger 	return n;
385ee97dc7dSHarald Freudenberger }
386ee97dc7dSHarald Freudenberger 
3870200f3ecSGerald Schaefer static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
388ee97dc7dSHarald Freudenberger 			    struct s390_des_ctx *ctx,
389ee97dc7dSHarald Freudenberger 			    struct blkcipher_walk *walk)
3900200f3ecSGerald Schaefer {
3910200f3ecSGerald Schaefer 	int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
392ee97dc7dSHarald Freudenberger 	unsigned int n, nbytes;
393ee97dc7dSHarald Freudenberger 	u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE];
394ee97dc7dSHarald Freudenberger 	u8 *out, *in, *ctrptr = ctrbuf;
3950200f3ecSGerald Schaefer 
396ee97dc7dSHarald Freudenberger 	if (!walk->nbytes)
397ee97dc7dSHarald Freudenberger 		return ret;
398ee97dc7dSHarald Freudenberger 
399ee97dc7dSHarald Freudenberger 	if (spin_trylock(&ctrblk_lock))
400ee97dc7dSHarald Freudenberger 		ctrptr = ctrblk;
401ee97dc7dSHarald Freudenberger 
402ee97dc7dSHarald Freudenberger 	memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE);
4030200f3ecSGerald Schaefer 	while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
4040200f3ecSGerald Schaefer 		out = walk->dst.virt.addr;
4050200f3ecSGerald Schaefer 		in = walk->src.virt.addr;
4060200f3ecSGerald Schaefer 		while (nbytes >= DES_BLOCK_SIZE) {
407ee97dc7dSHarald Freudenberger 			if (ctrptr == ctrblk)
408ee97dc7dSHarald Freudenberger 				n = __ctrblk_init(ctrptr, nbytes);
409ee97dc7dSHarald Freudenberger 			else
410ee97dc7dSHarald Freudenberger 				n = DES_BLOCK_SIZE;
4110177db01SMartin Schwidefsky 			cpacf_kmctr(func, ctx->key, out, in, n, ctrptr);
4120200f3ecSGerald Schaefer 			if (n > DES_BLOCK_SIZE)
413ee97dc7dSHarald Freudenberger 				memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE,
4140200f3ecSGerald Schaefer 				       DES_BLOCK_SIZE);
415ee97dc7dSHarald Freudenberger 			crypto_inc(ctrptr, DES_BLOCK_SIZE);
4160200f3ecSGerald Schaefer 			out += n;
4170200f3ecSGerald Schaefer 			in += n;
4180200f3ecSGerald Schaefer 			nbytes -= n;
4190200f3ecSGerald Schaefer 		}
4200200f3ecSGerald Schaefer 		ret = blkcipher_walk_done(desc, walk, nbytes);
4210200f3ecSGerald Schaefer 	}
422ee97dc7dSHarald Freudenberger 	if (ctrptr == ctrblk) {
423ee97dc7dSHarald Freudenberger 		if (nbytes)
424ee97dc7dSHarald Freudenberger 			memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE);
425ee97dc7dSHarald Freudenberger 		else
426ee97dc7dSHarald Freudenberger 			memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
427ee97dc7dSHarald Freudenberger 		spin_unlock(&ctrblk_lock);
4283901c112SHarald Freudenberger 	} else {
4293901c112SHarald Freudenberger 		if (!nbytes)
4303901c112SHarald Freudenberger 			memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
431ee97dc7dSHarald Freudenberger 	}
4320200f3ecSGerald Schaefer 	/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
4330200f3ecSGerald Schaefer 	if (nbytes) {
4340200f3ecSGerald Schaefer 		out = walk->dst.virt.addr;
4350200f3ecSGerald Schaefer 		in = walk->src.virt.addr;
4360177db01SMartin Schwidefsky 		cpacf_kmctr(func, ctx->key, buf, in, DES_BLOCK_SIZE, ctrbuf);
4370200f3ecSGerald Schaefer 		memcpy(out, buf, nbytes);
438ee97dc7dSHarald Freudenberger 		crypto_inc(ctrbuf, DES_BLOCK_SIZE);
4390200f3ecSGerald Schaefer 		ret = blkcipher_walk_done(desc, walk, 0);
440ee97dc7dSHarald Freudenberger 		memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE);
4410200f3ecSGerald Schaefer 	}
4420200f3ecSGerald Schaefer 	return ret;
4430200f3ecSGerald Schaefer }
4440200f3ecSGerald Schaefer 
4450200f3ecSGerald Schaefer static int ctr_des_encrypt(struct blkcipher_desc *desc,
4460200f3ecSGerald Schaefer 			   struct scatterlist *dst, struct scatterlist *src,
4470200f3ecSGerald Schaefer 			   unsigned int nbytes)
4480200f3ecSGerald Schaefer {
4490200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
4500200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
4510200f3ecSGerald Schaefer 
4520200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
453edc63a37SMartin Schwidefsky 	return ctr_desall_crypt(desc, CPACF_KMCTR_DEA, ctx, &walk);
4540200f3ecSGerald Schaefer }
4550200f3ecSGerald Schaefer 
4560200f3ecSGerald Schaefer static int ctr_des_decrypt(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 | CPACF_DECRYPT,
465edc63a37SMartin Schwidefsky 				ctx, &walk);
4660200f3ecSGerald Schaefer }
4670200f3ecSGerald Schaefer 
4680200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = {
4690200f3ecSGerald Schaefer 	.cra_name		=	"ctr(des)",
4700200f3ecSGerald Schaefer 	.cra_driver_name	=	"ctr-des-s390",
471c7d4d259SMartin Schwidefsky 	.cra_priority		=	400,	/* combo: des + ctr */
4720200f3ecSGerald Schaefer 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
4730200f3ecSGerald Schaefer 	.cra_blocksize		=	1,
4740200f3ecSGerald Schaefer 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
4750200f3ecSGerald Schaefer 	.cra_type		=	&crypto_blkcipher_type,
4760200f3ecSGerald Schaefer 	.cra_module		=	THIS_MODULE,
4770200f3ecSGerald Schaefer 	.cra_u			=	{
4780200f3ecSGerald Schaefer 		.blkcipher = {
4790200f3ecSGerald Schaefer 			.min_keysize		=	DES_KEY_SIZE,
4800200f3ecSGerald Schaefer 			.max_keysize		=	DES_KEY_SIZE,
4810200f3ecSGerald Schaefer 			.ivsize			=	DES_BLOCK_SIZE,
4820200f3ecSGerald Schaefer 			.setkey			=	des_setkey,
4830200f3ecSGerald Schaefer 			.encrypt		=	ctr_des_encrypt,
4840200f3ecSGerald Schaefer 			.decrypt		=	ctr_des_decrypt,
4850200f3ecSGerald Schaefer 		}
4860200f3ecSGerald Schaefer 	}
4870200f3ecSGerald Schaefer };
4880200f3ecSGerald Schaefer 
4890200f3ecSGerald Schaefer static int ctr_des3_encrypt(struct blkcipher_desc *desc,
4900200f3ecSGerald Schaefer 			    struct scatterlist *dst, struct scatterlist *src,
4910200f3ecSGerald Schaefer 			    unsigned int nbytes)
4920200f3ecSGerald Schaefer {
4930200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
4940200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
4950200f3ecSGerald Schaefer 
4960200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
497edc63a37SMartin Schwidefsky 	return ctr_desall_crypt(desc, CPACF_KMCTR_TDEA_192, ctx, &walk);
4980200f3ecSGerald Schaefer }
4990200f3ecSGerald Schaefer 
5000200f3ecSGerald Schaefer static int ctr_des3_decrypt(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 | CPACF_DECRYPT,
509edc63a37SMartin Schwidefsky 				ctx, &walk);
5100200f3ecSGerald Schaefer }
5110200f3ecSGerald Schaefer 
5120200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = {
5130200f3ecSGerald Schaefer 	.cra_name		=	"ctr(des3_ede)",
5140200f3ecSGerald Schaefer 	.cra_driver_name	=	"ctr-des3_ede-s390",
515c7d4d259SMartin Schwidefsky 	.cra_priority		=	400,	/* combo: des3 + ede */
5160200f3ecSGerald Schaefer 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
5170200f3ecSGerald Schaefer 	.cra_blocksize		=	1,
5180200f3ecSGerald Schaefer 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
5190200f3ecSGerald Schaefer 	.cra_type		=	&crypto_blkcipher_type,
5200200f3ecSGerald Schaefer 	.cra_module		=	THIS_MODULE,
5210200f3ecSGerald Schaefer 	.cra_u			=	{
5220200f3ecSGerald Schaefer 		.blkcipher = {
5230200f3ecSGerald Schaefer 			.min_keysize		=	DES3_KEY_SIZE,
5240200f3ecSGerald Schaefer 			.max_keysize		=	DES3_KEY_SIZE,
5250200f3ecSGerald Schaefer 			.ivsize			=	DES_BLOCK_SIZE,
5260200f3ecSGerald Schaefer 			.setkey			=	des3_setkey,
5270200f3ecSGerald Schaefer 			.encrypt		=	ctr_des3_encrypt,
5280200f3ecSGerald Schaefer 			.decrypt		=	ctr_des3_decrypt,
5290200f3ecSGerald Schaefer 		}
5300200f3ecSGerald Schaefer 	}
5310200f3ecSGerald Schaefer };
5320200f3ecSGerald Schaefer 
533d863d594SMartin Schwidefsky static struct crypto_alg *des_s390_algs_ptr[8];
534d863d594SMartin Schwidefsky static int des_s390_algs_num;
535d863d594SMartin Schwidefsky 
536d863d594SMartin Schwidefsky static int des_s390_register_alg(struct crypto_alg *alg)
537d863d594SMartin Schwidefsky {
538d863d594SMartin Schwidefsky 	int ret;
539d863d594SMartin Schwidefsky 
540d863d594SMartin Schwidefsky 	ret = crypto_register_alg(alg);
541d863d594SMartin Schwidefsky 	if (!ret)
542d863d594SMartin Schwidefsky 		des_s390_algs_ptr[des_s390_algs_num++] = alg;
543d863d594SMartin Schwidefsky 	return ret;
544d863d594SMartin Schwidefsky }
545d863d594SMartin Schwidefsky 
546d863d594SMartin Schwidefsky static void des_s390_exit(void)
547d863d594SMartin Schwidefsky {
548d863d594SMartin Schwidefsky 	while (des_s390_algs_num--)
549d863d594SMartin Schwidefsky 		crypto_unregister_alg(des_s390_algs_ptr[des_s390_algs_num]);
550d863d594SMartin Schwidefsky 	if (ctrblk)
551d863d594SMartin Schwidefsky 		free_page((unsigned long) ctrblk);
552d863d594SMartin Schwidefsky }
553d863d594SMartin Schwidefsky 
55498971f84SJan Glauber static int __init des_s390_init(void)
555c1e26e1eSJan Glauber {
55680d663a4SJan Glauber 	int ret;
557c1e26e1eSJan Glauber 
55869c0e360SMartin Schwidefsky 	/* Query available functions for KM, KMC and KMCTR */
55969c0e360SMartin Schwidefsky 	cpacf_query(CPACF_KM, &km_functions);
56069c0e360SMartin Schwidefsky 	cpacf_query(CPACF_KMC, &kmc_functions);
56169c0e360SMartin Schwidefsky 	cpacf_query(CPACF_KMCTR, &kmctr_functions);
562c1e26e1eSJan Glauber 
56369c0e360SMartin Schwidefsky 	if (cpacf_test_func(&km_functions, CPACF_KM_DEA)) {
564d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&des_alg);
565a9e62fadSHerbert Xu 		if (ret)
566d863d594SMartin Schwidefsky 			goto out_err;
567d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&ecb_des_alg);
568a9e62fadSHerbert Xu 		if (ret)
569d863d594SMartin Schwidefsky 			goto out_err;
57069c0e360SMartin Schwidefsky 	}
57169c0e360SMartin Schwidefsky 	if (cpacf_test_func(&kmc_functions, CPACF_KMC_DEA)) {
572d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&cbc_des_alg);
573a9e62fadSHerbert Xu 		if (ret)
574d863d594SMartin Schwidefsky 			goto out_err;
57569c0e360SMartin Schwidefsky 	}
57669c0e360SMartin Schwidefsky 	if (cpacf_test_func(&km_functions, CPACF_KM_TDEA_192)) {
577d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&des3_alg);
578a9e62fadSHerbert Xu 		if (ret)
579d863d594SMartin Schwidefsky 			goto out_err;
580d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&ecb_des3_alg);
581a9e62fadSHerbert Xu 		if (ret)
582d863d594SMartin Schwidefsky 			goto out_err;
58369c0e360SMartin Schwidefsky 	}
58469c0e360SMartin Schwidefsky 	if (cpacf_test_func(&kmc_functions, CPACF_KMC_TDEA_192)) {
585d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&cbc_des3_alg);
586a9e62fadSHerbert Xu 		if (ret)
587d863d594SMartin Schwidefsky 			goto out_err;
58869c0e360SMartin Schwidefsky 	}
5890200f3ecSGerald Schaefer 
59069c0e360SMartin Schwidefsky 	if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA) ||
59169c0e360SMartin Schwidefsky 	    cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) {
5920200f3ecSGerald Schaefer 		ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
5930200f3ecSGerald Schaefer 		if (!ctrblk) {
5940200f3ecSGerald Schaefer 			ret = -ENOMEM;
595d863d594SMartin Schwidefsky 			goto out_err;
5960200f3ecSGerald Schaefer 		}
59769c0e360SMartin Schwidefsky 	}
59869c0e360SMartin Schwidefsky 
59969c0e360SMartin Schwidefsky 	if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_DEA)) {
600d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&ctr_des_alg);
601d863d594SMartin Schwidefsky 		if (ret)
602d863d594SMartin Schwidefsky 			goto out_err;
60369c0e360SMartin Schwidefsky 	}
60469c0e360SMartin Schwidefsky 	if (cpacf_test_func(&kmctr_functions, CPACF_KMCTR_TDEA_192)) {
605d863d594SMartin Schwidefsky 		ret = des_s390_register_alg(&ctr_des3_alg);
606d863d594SMartin Schwidefsky 		if (ret)
607d863d594SMartin Schwidefsky 			goto out_err;
6080200f3ecSGerald Schaefer 	}
609d863d594SMartin Schwidefsky 
610d863d594SMartin Schwidefsky 	return 0;
611d863d594SMartin Schwidefsky out_err:
612d863d594SMartin Schwidefsky 	des_s390_exit();
613a9e62fadSHerbert Xu 	return ret;
614c1e26e1eSJan Glauber }
615c1e26e1eSJan Glauber 
616d05377c1SHendrik Brueckner module_cpu_feature_match(MSA, des_s390_init);
6171efbd15cSJan Glauber module_exit(des_s390_exit);
618c1e26e1eSJan Glauber 
6195d26a105SKees Cook MODULE_ALIAS_CRYPTO("des");
6205d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede");
621c1e26e1eSJan Glauber 
622c1e26e1eSJan Glauber MODULE_LICENSE("GPL");
623c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
624