xref: /openbmc/linux/arch/s390/crypto/des_s390.c (revision 5d26a105)
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>
191efbd15cSJan Glauber #include <linux/crypto.h>
201efbd15cSJan Glauber #include <crypto/algapi.h>
211efbd15cSJan Glauber #include <crypto/des.h>
22c1357833SJan Glauber 
23c1e26e1eSJan Glauber #include "crypt_s390.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 
5698971f84SJan Glauber 	crypt_s390_km(KM_DEA_ENCRYPT, 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 
6398971f84SJan Glauber 	crypt_s390_km(KM_DEA_DECRYPT, ctx->key, out, in, DES_BLOCK_SIZE);
64b8dc6038SJan Glauber }
65b8dc6038SJan Glauber 
66c1e26e1eSJan Glauber static struct crypto_alg des_alg = {
67c1e26e1eSJan Glauber 	.cra_name		=	"des",
6865b75c36SHerbert Xu 	.cra_driver_name	=	"des-s390",
6965b75c36SHerbert Xu 	.cra_priority		=	CRYPT_S390_PRIORITY,
70c1e26e1eSJan Glauber 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
71c1e26e1eSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
7298971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
73c1e26e1eSJan Glauber 	.cra_module		=	THIS_MODULE,
74c1357833SJan Glauber 	.cra_u			=	{
75c1357833SJan Glauber 		.cipher = {
76c1e26e1eSJan Glauber 			.cia_min_keysize	=	DES_KEY_SIZE,
77c1e26e1eSJan Glauber 			.cia_max_keysize	=	DES_KEY_SIZE,
78c1e26e1eSJan Glauber 			.cia_setkey		=	des_setkey,
79c1e26e1eSJan Glauber 			.cia_encrypt		=	des_encrypt,
80b8dc6038SJan Glauber 			.cia_decrypt		=	des_decrypt,
81c1357833SJan Glauber 		}
82c1357833SJan Glauber 	}
83c1e26e1eSJan Glauber };
84c1e26e1eSJan Glauber 
85a9e62fadSHerbert Xu static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
8698971f84SJan Glauber 			    u8 *key, struct blkcipher_walk *walk)
87a9e62fadSHerbert Xu {
88a9e62fadSHerbert Xu 	int ret = blkcipher_walk_virt(desc, walk);
89a9e62fadSHerbert Xu 	unsigned int nbytes;
90a9e62fadSHerbert Xu 
91a9e62fadSHerbert Xu 	while ((nbytes = walk->nbytes)) {
92a9e62fadSHerbert Xu 		/* only use complete blocks */
93a9e62fadSHerbert Xu 		unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
94a9e62fadSHerbert Xu 		u8 *out = walk->dst.virt.addr;
95a9e62fadSHerbert Xu 		u8 *in = walk->src.virt.addr;
96a9e62fadSHerbert Xu 
9798971f84SJan Glauber 		ret = crypt_s390_km(func, key, out, in, n);
9836eb2caaSJan Glauber 		if (ret < 0 || ret != n)
9936eb2caaSJan Glauber 			return -EIO;
100a9e62fadSHerbert Xu 
101a9e62fadSHerbert Xu 		nbytes &= DES_BLOCK_SIZE - 1;
102a9e62fadSHerbert Xu 		ret = blkcipher_walk_done(desc, walk, nbytes);
103a9e62fadSHerbert Xu 	}
104a9e62fadSHerbert Xu 
105a9e62fadSHerbert Xu 	return ret;
106a9e62fadSHerbert Xu }
107a9e62fadSHerbert Xu 
108a9e62fadSHerbert Xu static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
109adc3fcf1SHarald Freudenberger 			    struct blkcipher_walk *walk)
110a9e62fadSHerbert Xu {
111adc3fcf1SHarald Freudenberger 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
112a9e62fadSHerbert Xu 	int ret = blkcipher_walk_virt(desc, walk);
113a9e62fadSHerbert Xu 	unsigned int nbytes = walk->nbytes;
114adc3fcf1SHarald Freudenberger 	struct {
115adc3fcf1SHarald Freudenberger 		u8 iv[DES_BLOCK_SIZE];
116adc3fcf1SHarald Freudenberger 		u8 key[DES3_KEY_SIZE];
117adc3fcf1SHarald Freudenberger 	} param;
118a9e62fadSHerbert Xu 
119a9e62fadSHerbert Xu 	if (!nbytes)
120a9e62fadSHerbert Xu 		goto out;
121a9e62fadSHerbert Xu 
122adc3fcf1SHarald Freudenberger 	memcpy(param.iv, walk->iv, DES_BLOCK_SIZE);
123adc3fcf1SHarald Freudenberger 	memcpy(param.key, ctx->key, DES3_KEY_SIZE);
124a9e62fadSHerbert Xu 	do {
125a9e62fadSHerbert Xu 		/* only use complete blocks */
126a9e62fadSHerbert Xu 		unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
127a9e62fadSHerbert Xu 		u8 *out = walk->dst.virt.addr;
128a9e62fadSHerbert Xu 		u8 *in = walk->src.virt.addr;
129a9e62fadSHerbert Xu 
130adc3fcf1SHarald Freudenberger 		ret = crypt_s390_kmc(func, &param, out, in, n);
13136eb2caaSJan Glauber 		if (ret < 0 || ret != n)
13236eb2caaSJan Glauber 			return -EIO;
133a9e62fadSHerbert Xu 
134a9e62fadSHerbert Xu 		nbytes &= DES_BLOCK_SIZE - 1;
135a9e62fadSHerbert Xu 		ret = blkcipher_walk_done(desc, walk, nbytes);
136a9e62fadSHerbert Xu 	} while ((nbytes = walk->nbytes));
137adc3fcf1SHarald Freudenberger 	memcpy(walk->iv, param.iv, DES_BLOCK_SIZE);
138a9e62fadSHerbert Xu 
139a9e62fadSHerbert Xu out:
140a9e62fadSHerbert Xu 	return ret;
141a9e62fadSHerbert Xu }
142a9e62fadSHerbert Xu 
143a9e62fadSHerbert Xu static int ecb_des_encrypt(struct blkcipher_desc *desc,
144a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
145a9e62fadSHerbert Xu 			   unsigned int nbytes)
146a9e62fadSHerbert Xu {
14798971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
148a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
149a9e62fadSHerbert Xu 
150a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
15198971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, ctx->key, &walk);
152a9e62fadSHerbert Xu }
153a9e62fadSHerbert Xu 
154a9e62fadSHerbert Xu static int ecb_des_decrypt(struct blkcipher_desc *desc,
155a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
156a9e62fadSHerbert Xu 			   unsigned int nbytes)
157a9e62fadSHerbert Xu {
15898971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
159a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
160a9e62fadSHerbert Xu 
161a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
16298971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_DEA_DECRYPT, 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",
168a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
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);
192adc3fcf1SHarald Freudenberger 	return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, &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);
202adc3fcf1SHarald Freudenberger 	return cbc_desall_crypt(desc, KMC_DEA_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",
208a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
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);
243560c06aeSHerbert Xu 	u32 *flags = &tfm->crt_flags;
244c1e26e1eSJan Glauber 
245fed28611SDaniel Borkmann 	if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
246fed28611SDaniel Borkmann 	    crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
24703b56ce5SJarod Wilson 			  DES_KEY_SIZE)) &&
24803b56ce5SJarod Wilson 	    (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
24903b56ce5SJarod Wilson 		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
250c1e26e1eSJan Glauber 		return -EINVAL;
251c1e26e1eSJan Glauber 	}
25298971f84SJan Glauber 	memcpy(ctx->key, key, key_len);
253c1e26e1eSJan Glauber 	return 0;
254c1e26e1eSJan Glauber }
255c1e26e1eSJan Glauber 
25698971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
257c1e26e1eSJan Glauber {
25898971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
259c1e26e1eSJan Glauber 
26098971f84SJan Glauber 	crypt_s390_km(KM_TDEA_192_ENCRYPT, ctx->key, dst, src, DES_BLOCK_SIZE);
261c1e26e1eSJan Glauber }
262c1e26e1eSJan Glauber 
26398971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
264c1e26e1eSJan Glauber {
26598971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
266c1e26e1eSJan Glauber 
26798971f84SJan Glauber 	crypt_s390_km(KM_TDEA_192_DECRYPT, 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",
27365b75c36SHerbert Xu 	.cra_priority		=	CRYPT_S390_PRIORITY,
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);
29798971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, 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);
30898971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, ctx->key, &walk);
309a9e62fadSHerbert Xu }
310a9e62fadSHerbert Xu 
31198971f84SJan Glauber static struct crypto_alg ecb_des3_alg = {
312a9e62fadSHerbert Xu 	.cra_name		=	"ecb(des3_ede)",
313a9e62fadSHerbert Xu 	.cra_driver_name	=	"ecb-des3_ede-s390",
314a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
315a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
3161efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
31798971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
318a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
319a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
320a9e62fadSHerbert Xu 	.cra_u			=	{
321a9e62fadSHerbert Xu 		.blkcipher = {
32298971f84SJan Glauber 			.min_keysize		=	DES3_KEY_SIZE,
32398971f84SJan Glauber 			.max_keysize		=	DES3_KEY_SIZE,
32498971f84SJan Glauber 			.setkey			=	des3_setkey,
32598971f84SJan Glauber 			.encrypt		=	ecb_des3_encrypt,
32698971f84SJan Glauber 			.decrypt		=	ecb_des3_decrypt,
327a9e62fadSHerbert Xu 		}
328a9e62fadSHerbert Xu 	}
329a9e62fadSHerbert Xu };
330a9e62fadSHerbert Xu 
33198971f84SJan Glauber static int cbc_des3_encrypt(struct blkcipher_desc *desc,
33298971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
33398971f84SJan Glauber 			    unsigned int nbytes)
334a9e62fadSHerbert Xu {
335a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
336a9e62fadSHerbert Xu 
337a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
338adc3fcf1SHarald Freudenberger 	return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, &walk);
339a9e62fadSHerbert Xu }
340a9e62fadSHerbert Xu 
34198971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc,
34298971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
34398971f84SJan Glauber 			    unsigned int nbytes)
344a9e62fadSHerbert Xu {
345a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
346a9e62fadSHerbert Xu 
347a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
348adc3fcf1SHarald Freudenberger 	return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, &walk);
349a9e62fadSHerbert Xu }
350a9e62fadSHerbert Xu 
35198971f84SJan Glauber static struct crypto_alg cbc_des3_alg = {
352a9e62fadSHerbert Xu 	.cra_name		=	"cbc(des3_ede)",
353a9e62fadSHerbert Xu 	.cra_driver_name	=	"cbc-des3_ede-s390",
354a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
355a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
3561efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
35798971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
358a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
359a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
360a9e62fadSHerbert Xu 	.cra_u			=	{
361a9e62fadSHerbert Xu 		.blkcipher = {
36298971f84SJan Glauber 			.min_keysize		=	DES3_KEY_SIZE,
36398971f84SJan Glauber 			.max_keysize		=	DES3_KEY_SIZE,
3641efbd15cSJan Glauber 			.ivsize			=	DES_BLOCK_SIZE,
36598971f84SJan Glauber 			.setkey			=	des3_setkey,
36698971f84SJan Glauber 			.encrypt		=	cbc_des3_encrypt,
36798971f84SJan Glauber 			.decrypt		=	cbc_des3_decrypt,
368a9e62fadSHerbert Xu 		}
369a9e62fadSHerbert Xu 	}
370a9e62fadSHerbert Xu };
371a9e62fadSHerbert Xu 
372ee97dc7dSHarald Freudenberger static unsigned int __ctrblk_init(u8 *ctrptr, unsigned int nbytes)
373ee97dc7dSHarald Freudenberger {
374ee97dc7dSHarald Freudenberger 	unsigned int i, n;
375ee97dc7dSHarald Freudenberger 
376ee97dc7dSHarald Freudenberger 	/* align to block size, max. PAGE_SIZE */
377ee97dc7dSHarald Freudenberger 	n = (nbytes > PAGE_SIZE) ? PAGE_SIZE : nbytes & ~(DES_BLOCK_SIZE - 1);
378ee97dc7dSHarald Freudenberger 	for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
379ee97dc7dSHarald Freudenberger 		memcpy(ctrptr + i, ctrptr + i - DES_BLOCK_SIZE, DES_BLOCK_SIZE);
380ee97dc7dSHarald Freudenberger 		crypto_inc(ctrptr + i, DES_BLOCK_SIZE);
381ee97dc7dSHarald Freudenberger 	}
382ee97dc7dSHarald Freudenberger 	return n;
383ee97dc7dSHarald Freudenberger }
384ee97dc7dSHarald Freudenberger 
3850200f3ecSGerald Schaefer static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
386ee97dc7dSHarald Freudenberger 			    struct s390_des_ctx *ctx,
387ee97dc7dSHarald Freudenberger 			    struct blkcipher_walk *walk)
3880200f3ecSGerald Schaefer {
3890200f3ecSGerald Schaefer 	int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
390ee97dc7dSHarald Freudenberger 	unsigned int n, nbytes;
391ee97dc7dSHarald Freudenberger 	u8 buf[DES_BLOCK_SIZE], ctrbuf[DES_BLOCK_SIZE];
392ee97dc7dSHarald Freudenberger 	u8 *out, *in, *ctrptr = ctrbuf;
3930200f3ecSGerald Schaefer 
394ee97dc7dSHarald Freudenberger 	if (!walk->nbytes)
395ee97dc7dSHarald Freudenberger 		return ret;
396ee97dc7dSHarald Freudenberger 
397ee97dc7dSHarald Freudenberger 	if (spin_trylock(&ctrblk_lock))
398ee97dc7dSHarald Freudenberger 		ctrptr = ctrblk;
399ee97dc7dSHarald Freudenberger 
400ee97dc7dSHarald Freudenberger 	memcpy(ctrptr, walk->iv, DES_BLOCK_SIZE);
4010200f3ecSGerald Schaefer 	while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
4020200f3ecSGerald Schaefer 		out = walk->dst.virt.addr;
4030200f3ecSGerald Schaefer 		in = walk->src.virt.addr;
4040200f3ecSGerald Schaefer 		while (nbytes >= DES_BLOCK_SIZE) {
405ee97dc7dSHarald Freudenberger 			if (ctrptr == ctrblk)
406ee97dc7dSHarald Freudenberger 				n = __ctrblk_init(ctrptr, nbytes);
407ee97dc7dSHarald Freudenberger 			else
408ee97dc7dSHarald Freudenberger 				n = DES_BLOCK_SIZE;
409ee97dc7dSHarald Freudenberger 			ret = crypt_s390_kmctr(func, ctx->key, out, in,
410ee97dc7dSHarald Freudenberger 					       n, ctrptr);
411ee97dc7dSHarald Freudenberger 			if (ret < 0 || ret != n) {
412ee97dc7dSHarald Freudenberger 				if (ctrptr == ctrblk)
413ee97dc7dSHarald Freudenberger 					spin_unlock(&ctrblk_lock);
41436eb2caaSJan Glauber 				return -EIO;
415ee97dc7dSHarald Freudenberger 			}
4160200f3ecSGerald Schaefer 			if (n > DES_BLOCK_SIZE)
417ee97dc7dSHarald Freudenberger 				memcpy(ctrptr, ctrptr + n - DES_BLOCK_SIZE,
4180200f3ecSGerald Schaefer 				       DES_BLOCK_SIZE);
419ee97dc7dSHarald Freudenberger 			crypto_inc(ctrptr, DES_BLOCK_SIZE);
4200200f3ecSGerald Schaefer 			out += n;
4210200f3ecSGerald Schaefer 			in += n;
4220200f3ecSGerald Schaefer 			nbytes -= n;
4230200f3ecSGerald Schaefer 		}
4240200f3ecSGerald Schaefer 		ret = blkcipher_walk_done(desc, walk, nbytes);
4250200f3ecSGerald Schaefer 	}
426ee97dc7dSHarald Freudenberger 	if (ctrptr == ctrblk) {
427ee97dc7dSHarald Freudenberger 		if (nbytes)
428ee97dc7dSHarald Freudenberger 			memcpy(ctrbuf, ctrptr, DES_BLOCK_SIZE);
429ee97dc7dSHarald Freudenberger 		else
430ee97dc7dSHarald Freudenberger 			memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
431ee97dc7dSHarald Freudenberger 		spin_unlock(&ctrblk_lock);
4323901c112SHarald Freudenberger 	} else {
4333901c112SHarald Freudenberger 		if (!nbytes)
4343901c112SHarald Freudenberger 			memcpy(walk->iv, ctrptr, DES_BLOCK_SIZE);
435ee97dc7dSHarald Freudenberger 	}
4360200f3ecSGerald Schaefer 	/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
4370200f3ecSGerald Schaefer 	if (nbytes) {
4380200f3ecSGerald Schaefer 		out = walk->dst.virt.addr;
4390200f3ecSGerald Schaefer 		in = walk->src.virt.addr;
4400200f3ecSGerald Schaefer 		ret = crypt_s390_kmctr(func, ctx->key, buf, in,
441ee97dc7dSHarald Freudenberger 				       DES_BLOCK_SIZE, ctrbuf);
44236eb2caaSJan Glauber 		if (ret < 0 || ret != DES_BLOCK_SIZE)
44336eb2caaSJan Glauber 			return -EIO;
4440200f3ecSGerald Schaefer 		memcpy(out, buf, nbytes);
445ee97dc7dSHarald Freudenberger 		crypto_inc(ctrbuf, DES_BLOCK_SIZE);
4460200f3ecSGerald Schaefer 		ret = blkcipher_walk_done(desc, walk, 0);
447ee97dc7dSHarald Freudenberger 		memcpy(walk->iv, ctrbuf, DES_BLOCK_SIZE);
4480200f3ecSGerald Schaefer 	}
4490200f3ecSGerald Schaefer 	return ret;
4500200f3ecSGerald Schaefer }
4510200f3ecSGerald Schaefer 
4520200f3ecSGerald Schaefer static int ctr_des_encrypt(struct blkcipher_desc *desc,
4530200f3ecSGerald Schaefer 			   struct scatterlist *dst, struct scatterlist *src,
4540200f3ecSGerald Schaefer 			   unsigned int nbytes)
4550200f3ecSGerald Schaefer {
4560200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
4570200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
4580200f3ecSGerald Schaefer 
4590200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
4600200f3ecSGerald Schaefer 	return ctr_desall_crypt(desc, KMCTR_DEA_ENCRYPT, ctx, &walk);
4610200f3ecSGerald Schaefer }
4620200f3ecSGerald Schaefer 
4630200f3ecSGerald Schaefer static int ctr_des_decrypt(struct blkcipher_desc *desc,
4640200f3ecSGerald Schaefer 			   struct scatterlist *dst, struct scatterlist *src,
4650200f3ecSGerald Schaefer 			   unsigned int nbytes)
4660200f3ecSGerald Schaefer {
4670200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
4680200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
4690200f3ecSGerald Schaefer 
4700200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
4710200f3ecSGerald Schaefer 	return ctr_desall_crypt(desc, KMCTR_DEA_DECRYPT, ctx, &walk);
4720200f3ecSGerald Schaefer }
4730200f3ecSGerald Schaefer 
4740200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = {
4750200f3ecSGerald Schaefer 	.cra_name		=	"ctr(des)",
4760200f3ecSGerald Schaefer 	.cra_driver_name	=	"ctr-des-s390",
4770200f3ecSGerald Schaefer 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
4780200f3ecSGerald Schaefer 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
4790200f3ecSGerald Schaefer 	.cra_blocksize		=	1,
4800200f3ecSGerald Schaefer 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
4810200f3ecSGerald Schaefer 	.cra_type		=	&crypto_blkcipher_type,
4820200f3ecSGerald Schaefer 	.cra_module		=	THIS_MODULE,
4830200f3ecSGerald Schaefer 	.cra_u			=	{
4840200f3ecSGerald Schaefer 		.blkcipher = {
4850200f3ecSGerald Schaefer 			.min_keysize		=	DES_KEY_SIZE,
4860200f3ecSGerald Schaefer 			.max_keysize		=	DES_KEY_SIZE,
4870200f3ecSGerald Schaefer 			.ivsize			=	DES_BLOCK_SIZE,
4880200f3ecSGerald Schaefer 			.setkey			=	des_setkey,
4890200f3ecSGerald Schaefer 			.encrypt		=	ctr_des_encrypt,
4900200f3ecSGerald Schaefer 			.decrypt		=	ctr_des_decrypt,
4910200f3ecSGerald Schaefer 		}
4920200f3ecSGerald Schaefer 	}
4930200f3ecSGerald Schaefer };
4940200f3ecSGerald Schaefer 
4950200f3ecSGerald Schaefer static int ctr_des3_encrypt(struct blkcipher_desc *desc,
4960200f3ecSGerald Schaefer 			    struct scatterlist *dst, struct scatterlist *src,
4970200f3ecSGerald Schaefer 			    unsigned int nbytes)
4980200f3ecSGerald Schaefer {
4990200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
5000200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
5010200f3ecSGerald Schaefer 
5020200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
5030200f3ecSGerald Schaefer 	return ctr_desall_crypt(desc, KMCTR_TDEA_192_ENCRYPT, ctx, &walk);
5040200f3ecSGerald Schaefer }
5050200f3ecSGerald Schaefer 
5060200f3ecSGerald Schaefer static int ctr_des3_decrypt(struct blkcipher_desc *desc,
5070200f3ecSGerald Schaefer 			    struct scatterlist *dst, struct scatterlist *src,
5080200f3ecSGerald Schaefer 			    unsigned int nbytes)
5090200f3ecSGerald Schaefer {
5100200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
5110200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
5120200f3ecSGerald Schaefer 
5130200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
5140200f3ecSGerald Schaefer 	return ctr_desall_crypt(desc, KMCTR_TDEA_192_DECRYPT, ctx, &walk);
5150200f3ecSGerald Schaefer }
5160200f3ecSGerald Schaefer 
5170200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = {
5180200f3ecSGerald Schaefer 	.cra_name		=	"ctr(des3_ede)",
5190200f3ecSGerald Schaefer 	.cra_driver_name	=	"ctr-des3_ede-s390",
5200200f3ecSGerald Schaefer 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
5210200f3ecSGerald Schaefer 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
5220200f3ecSGerald Schaefer 	.cra_blocksize		=	1,
5230200f3ecSGerald Schaefer 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
5240200f3ecSGerald Schaefer 	.cra_type		=	&crypto_blkcipher_type,
5250200f3ecSGerald Schaefer 	.cra_module		=	THIS_MODULE,
5260200f3ecSGerald Schaefer 	.cra_u			=	{
5270200f3ecSGerald Schaefer 		.blkcipher = {
5280200f3ecSGerald Schaefer 			.min_keysize		=	DES3_KEY_SIZE,
5290200f3ecSGerald Schaefer 			.max_keysize		=	DES3_KEY_SIZE,
5300200f3ecSGerald Schaefer 			.ivsize			=	DES_BLOCK_SIZE,
5310200f3ecSGerald Schaefer 			.setkey			=	des3_setkey,
5320200f3ecSGerald Schaefer 			.encrypt		=	ctr_des3_encrypt,
5330200f3ecSGerald Schaefer 			.decrypt		=	ctr_des3_decrypt,
5340200f3ecSGerald Schaefer 		}
5350200f3ecSGerald Schaefer 	}
5360200f3ecSGerald Schaefer };
5370200f3ecSGerald Schaefer 
53898971f84SJan Glauber static int __init des_s390_init(void)
539c1e26e1eSJan Glauber {
54080d663a4SJan Glauber 	int ret;
541c1e26e1eSJan Glauber 
5421822bc90SJan Glauber 	if (!crypt_s390_func_available(KM_DEA_ENCRYPT, CRYPT_S390_MSA) ||
5431822bc90SJan Glauber 	    !crypt_s390_func_available(KM_TDEA_192_ENCRYPT, CRYPT_S390_MSA))
54486aa9fc2SJan Glauber 		return -EOPNOTSUPP;
545c1e26e1eSJan Glauber 
546a9e62fadSHerbert Xu 	ret = crypto_register_alg(&des_alg);
547a9e62fadSHerbert Xu 	if (ret)
548a9e62fadSHerbert Xu 		goto des_err;
549a9e62fadSHerbert Xu 	ret = crypto_register_alg(&ecb_des_alg);
550a9e62fadSHerbert Xu 	if (ret)
551a9e62fadSHerbert Xu 		goto ecb_des_err;
552a9e62fadSHerbert Xu 	ret = crypto_register_alg(&cbc_des_alg);
553a9e62fadSHerbert Xu 	if (ret)
554a9e62fadSHerbert Xu 		goto cbc_des_err;
55598971f84SJan Glauber 	ret = crypto_register_alg(&des3_alg);
556a9e62fadSHerbert Xu 	if (ret)
55798971f84SJan Glauber 		goto des3_err;
55898971f84SJan Glauber 	ret = crypto_register_alg(&ecb_des3_alg);
559a9e62fadSHerbert Xu 	if (ret)
56098971f84SJan Glauber 		goto ecb_des3_err;
56198971f84SJan Glauber 	ret = crypto_register_alg(&cbc_des3_alg);
562a9e62fadSHerbert Xu 	if (ret)
56398971f84SJan Glauber 		goto cbc_des3_err;
5640200f3ecSGerald Schaefer 
5650200f3ecSGerald Schaefer 	if (crypt_s390_func_available(KMCTR_DEA_ENCRYPT,
5660200f3ecSGerald Schaefer 			CRYPT_S390_MSA | CRYPT_S390_MSA4) &&
5670200f3ecSGerald Schaefer 	    crypt_s390_func_available(KMCTR_TDEA_192_ENCRYPT,
5680200f3ecSGerald Schaefer 			CRYPT_S390_MSA | CRYPT_S390_MSA4)) {
5690200f3ecSGerald Schaefer 		ret = crypto_register_alg(&ctr_des_alg);
5700200f3ecSGerald Schaefer 		if (ret)
5710200f3ecSGerald Schaefer 			goto ctr_des_err;
5720200f3ecSGerald Schaefer 		ret = crypto_register_alg(&ctr_des3_alg);
5730200f3ecSGerald Schaefer 		if (ret)
5740200f3ecSGerald Schaefer 			goto ctr_des3_err;
5750200f3ecSGerald Schaefer 		ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
5760200f3ecSGerald Schaefer 		if (!ctrblk) {
5770200f3ecSGerald Schaefer 			ret = -ENOMEM;
5780200f3ecSGerald Schaefer 			goto ctr_mem_err;
5790200f3ecSGerald Schaefer 		}
5800200f3ecSGerald Schaefer 	}
581a9e62fadSHerbert Xu out:
582a9e62fadSHerbert Xu 	return ret;
583a9e62fadSHerbert Xu 
5840200f3ecSGerald Schaefer ctr_mem_err:
5850200f3ecSGerald Schaefer 	crypto_unregister_alg(&ctr_des3_alg);
5860200f3ecSGerald Schaefer ctr_des3_err:
5870200f3ecSGerald Schaefer 	crypto_unregister_alg(&ctr_des_alg);
5880200f3ecSGerald Schaefer ctr_des_err:
5890200f3ecSGerald Schaefer 	crypto_unregister_alg(&cbc_des3_alg);
59098971f84SJan Glauber cbc_des3_err:
59198971f84SJan Glauber 	crypto_unregister_alg(&ecb_des3_alg);
59298971f84SJan Glauber ecb_des3_err:
59398971f84SJan Glauber 	crypto_unregister_alg(&des3_alg);
59498971f84SJan Glauber des3_err:
595a9e62fadSHerbert Xu 	crypto_unregister_alg(&cbc_des_alg);
596a9e62fadSHerbert Xu cbc_des_err:
597a9e62fadSHerbert Xu 	crypto_unregister_alg(&ecb_des_alg);
598a9e62fadSHerbert Xu ecb_des_err:
599c1e26e1eSJan Glauber 	crypto_unregister_alg(&des_alg);
600a9e62fadSHerbert Xu des_err:
601a9e62fadSHerbert Xu 	goto out;
602c1e26e1eSJan Glauber }
603c1e26e1eSJan Glauber 
6041efbd15cSJan Glauber static void __exit des_s390_exit(void)
605c1e26e1eSJan Glauber {
6060200f3ecSGerald Schaefer 	if (ctrblk) {
6070200f3ecSGerald Schaefer 		crypto_unregister_alg(&ctr_des_alg);
6080200f3ecSGerald Schaefer 		crypto_unregister_alg(&ctr_des3_alg);
6090200f3ecSGerald Schaefer 		free_page((unsigned long) ctrblk);
6100200f3ecSGerald Schaefer 	}
61198971f84SJan Glauber 	crypto_unregister_alg(&cbc_des3_alg);
61298971f84SJan Glauber 	crypto_unregister_alg(&ecb_des3_alg);
61398971f84SJan Glauber 	crypto_unregister_alg(&des3_alg);
614a9e62fadSHerbert Xu 	crypto_unregister_alg(&cbc_des_alg);
615a9e62fadSHerbert Xu 	crypto_unregister_alg(&ecb_des_alg);
616c1e26e1eSJan Glauber 	crypto_unregister_alg(&des_alg);
617c1e26e1eSJan Glauber }
618c1e26e1eSJan Glauber 
6199f7819c1SHeiko Carstens module_init(des_s390_init);
6201efbd15cSJan Glauber module_exit(des_s390_exit);
621c1e26e1eSJan Glauber 
6225d26a105SKees Cook MODULE_ALIAS_CRYPTO("des");
6235d26a105SKees Cook MODULE_ALIAS_CRYPTO("des3_ede");
624c1e26e1eSJan Glauber 
625c1e26e1eSJan Glauber MODULE_LICENSE("GPL");
626c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
627