xref: /openbmc/linux/arch/s390/crypto/des_s390.c (revision fed28611)
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;
280200f3ecSGerald Schaefer 
2998971f84SJan Glauber struct s390_des_ctx {
30c1e26e1eSJan Glauber 	u8 iv[DES_BLOCK_SIZE];
3198971f84SJan Glauber 	u8 key[DES3_KEY_SIZE];
32c1e26e1eSJan Glauber };
33c1e26e1eSJan Glauber 
346c2bb98bSHerbert Xu static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
3598971f84SJan Glauber 		      unsigned int key_len)
36c1e26e1eSJan Glauber {
3798971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
38560c06aeSHerbert Xu 	u32 *flags = &tfm->crt_flags;
391efbd15cSJan Glauber 	u32 tmp[DES_EXPKEY_WORDS];
40c1e26e1eSJan Glauber 
411efbd15cSJan Glauber 	/* check for weak keys */
421efbd15cSJan Glauber 	if (!des_ekey(tmp, key) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
431efbd15cSJan Glauber 		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
441efbd15cSJan Glauber 		return -EINVAL;
451efbd15cSJan Glauber 	}
461efbd15cSJan Glauber 
4798971f84SJan Glauber 	memcpy(ctx->key, key, key_len);
481efbd15cSJan Glauber 	return 0;
49c1e26e1eSJan Glauber }
50c1e26e1eSJan Glauber 
516c2bb98bSHerbert Xu static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
52c1e26e1eSJan Glauber {
5398971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
54c1e26e1eSJan Glauber 
5598971f84SJan Glauber 	crypt_s390_km(KM_DEA_ENCRYPT, ctx->key, out, in, DES_BLOCK_SIZE);
56c1e26e1eSJan Glauber }
57c1e26e1eSJan Glauber 
586c2bb98bSHerbert Xu static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
59c1e26e1eSJan Glauber {
6098971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
61c1e26e1eSJan Glauber 
6298971f84SJan Glauber 	crypt_s390_km(KM_DEA_DECRYPT, ctx->key, out, in, DES_BLOCK_SIZE);
63b8dc6038SJan Glauber }
64b8dc6038SJan Glauber 
65c1e26e1eSJan Glauber static struct crypto_alg des_alg = {
66c1e26e1eSJan Glauber 	.cra_name		=	"des",
6765b75c36SHerbert Xu 	.cra_driver_name	=	"des-s390",
6865b75c36SHerbert Xu 	.cra_priority		=	CRYPT_S390_PRIORITY,
69c1e26e1eSJan Glauber 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
70c1e26e1eSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
7198971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
72c1e26e1eSJan Glauber 	.cra_module		=	THIS_MODULE,
73c1357833SJan Glauber 	.cra_u			=	{
74c1357833SJan Glauber 		.cipher = {
75c1e26e1eSJan Glauber 			.cia_min_keysize	=	DES_KEY_SIZE,
76c1e26e1eSJan Glauber 			.cia_max_keysize	=	DES_KEY_SIZE,
77c1e26e1eSJan Glauber 			.cia_setkey		=	des_setkey,
78c1e26e1eSJan Glauber 			.cia_encrypt		=	des_encrypt,
79b8dc6038SJan Glauber 			.cia_decrypt		=	des_decrypt,
80c1357833SJan Glauber 		}
81c1357833SJan Glauber 	}
82c1e26e1eSJan Glauber };
83c1e26e1eSJan Glauber 
84a9e62fadSHerbert Xu static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
8598971f84SJan Glauber 			    u8 *key, struct blkcipher_walk *walk)
86a9e62fadSHerbert Xu {
87a9e62fadSHerbert Xu 	int ret = blkcipher_walk_virt(desc, walk);
88a9e62fadSHerbert Xu 	unsigned int nbytes;
89a9e62fadSHerbert Xu 
90a9e62fadSHerbert Xu 	while ((nbytes = walk->nbytes)) {
91a9e62fadSHerbert Xu 		/* only use complete blocks */
92a9e62fadSHerbert Xu 		unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
93a9e62fadSHerbert Xu 		u8 *out = walk->dst.virt.addr;
94a9e62fadSHerbert Xu 		u8 *in = walk->src.virt.addr;
95a9e62fadSHerbert Xu 
9698971f84SJan Glauber 		ret = crypt_s390_km(func, key, out, in, n);
9736eb2caaSJan Glauber 		if (ret < 0 || ret != n)
9836eb2caaSJan Glauber 			return -EIO;
99a9e62fadSHerbert Xu 
100a9e62fadSHerbert Xu 		nbytes &= DES_BLOCK_SIZE - 1;
101a9e62fadSHerbert Xu 		ret = blkcipher_walk_done(desc, walk, nbytes);
102a9e62fadSHerbert Xu 	}
103a9e62fadSHerbert Xu 
104a9e62fadSHerbert Xu 	return ret;
105a9e62fadSHerbert Xu }
106a9e62fadSHerbert Xu 
107a9e62fadSHerbert Xu static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
10898971f84SJan Glauber 			    u8 *iv, struct blkcipher_walk *walk)
109a9e62fadSHerbert Xu {
110a9e62fadSHerbert Xu 	int ret = blkcipher_walk_virt(desc, walk);
111a9e62fadSHerbert Xu 	unsigned int nbytes = walk->nbytes;
112a9e62fadSHerbert Xu 
113a9e62fadSHerbert Xu 	if (!nbytes)
114a9e62fadSHerbert Xu 		goto out;
115a9e62fadSHerbert Xu 
11698971f84SJan Glauber 	memcpy(iv, walk->iv, DES_BLOCK_SIZE);
117a9e62fadSHerbert Xu 	do {
118a9e62fadSHerbert Xu 		/* only use complete blocks */
119a9e62fadSHerbert Xu 		unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
120a9e62fadSHerbert Xu 		u8 *out = walk->dst.virt.addr;
121a9e62fadSHerbert Xu 		u8 *in = walk->src.virt.addr;
122a9e62fadSHerbert Xu 
12398971f84SJan Glauber 		ret = crypt_s390_kmc(func, iv, out, in, n);
12436eb2caaSJan Glauber 		if (ret < 0 || ret != n)
12536eb2caaSJan Glauber 			return -EIO;
126a9e62fadSHerbert Xu 
127a9e62fadSHerbert Xu 		nbytes &= DES_BLOCK_SIZE - 1;
128a9e62fadSHerbert Xu 		ret = blkcipher_walk_done(desc, walk, nbytes);
129a9e62fadSHerbert Xu 	} while ((nbytes = walk->nbytes));
13098971f84SJan Glauber 	memcpy(walk->iv, iv, DES_BLOCK_SIZE);
131a9e62fadSHerbert Xu 
132a9e62fadSHerbert Xu out:
133a9e62fadSHerbert Xu 	return ret;
134a9e62fadSHerbert Xu }
135a9e62fadSHerbert Xu 
136a9e62fadSHerbert Xu static int ecb_des_encrypt(struct blkcipher_desc *desc,
137a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
138a9e62fadSHerbert Xu 			   unsigned int nbytes)
139a9e62fadSHerbert Xu {
14098971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
141a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
142a9e62fadSHerbert Xu 
143a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
14498971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, ctx->key, &walk);
145a9e62fadSHerbert Xu }
146a9e62fadSHerbert Xu 
147a9e62fadSHerbert Xu static int ecb_des_decrypt(struct blkcipher_desc *desc,
148a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
149a9e62fadSHerbert Xu 			   unsigned int nbytes)
150a9e62fadSHerbert Xu {
15198971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
152a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
153a9e62fadSHerbert Xu 
154a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
15598971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_DEA_DECRYPT, ctx->key, &walk);
156a9e62fadSHerbert Xu }
157a9e62fadSHerbert Xu 
158a9e62fadSHerbert Xu static struct crypto_alg ecb_des_alg = {
159a9e62fadSHerbert Xu 	.cra_name		=	"ecb(des)",
160a9e62fadSHerbert Xu 	.cra_driver_name	=	"ecb-des-s390",
161a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
162a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
163a9e62fadSHerbert Xu 	.cra_blocksize		=	DES_BLOCK_SIZE,
16498971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
165a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
166a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
167a9e62fadSHerbert Xu 	.cra_u			=	{
168a9e62fadSHerbert Xu 		.blkcipher = {
169a9e62fadSHerbert Xu 			.min_keysize		=	DES_KEY_SIZE,
170a9e62fadSHerbert Xu 			.max_keysize		=	DES_KEY_SIZE,
171a9e62fadSHerbert Xu 			.setkey			=	des_setkey,
172a9e62fadSHerbert Xu 			.encrypt		=	ecb_des_encrypt,
173a9e62fadSHerbert Xu 			.decrypt		=	ecb_des_decrypt,
174a9e62fadSHerbert Xu 		}
175a9e62fadSHerbert Xu 	}
176a9e62fadSHerbert Xu };
177a9e62fadSHerbert Xu 
178a9e62fadSHerbert Xu static int cbc_des_encrypt(struct blkcipher_desc *desc,
179a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
180a9e62fadSHerbert Xu 			   unsigned int nbytes)
181a9e62fadSHerbert Xu {
18298971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
183a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
184a9e62fadSHerbert Xu 
185a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
18698971f84SJan Glauber 	return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, ctx->iv, &walk);
187a9e62fadSHerbert Xu }
188a9e62fadSHerbert Xu 
189a9e62fadSHerbert Xu static int cbc_des_decrypt(struct blkcipher_desc *desc,
190a9e62fadSHerbert Xu 			   struct scatterlist *dst, struct scatterlist *src,
191a9e62fadSHerbert Xu 			   unsigned int nbytes)
192a9e62fadSHerbert Xu {
19398971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
194a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
195a9e62fadSHerbert Xu 
196a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
19798971f84SJan Glauber 	return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, ctx->iv, &walk);
198a9e62fadSHerbert Xu }
199a9e62fadSHerbert Xu 
200a9e62fadSHerbert Xu static struct crypto_alg cbc_des_alg = {
201a9e62fadSHerbert Xu 	.cra_name		=	"cbc(des)",
202a9e62fadSHerbert Xu 	.cra_driver_name	=	"cbc-des-s390",
203a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
204a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
205a9e62fadSHerbert Xu 	.cra_blocksize		=	DES_BLOCK_SIZE,
20698971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
207a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
208a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
209a9e62fadSHerbert Xu 	.cra_u			=	{
210a9e62fadSHerbert Xu 		.blkcipher = {
211a9e62fadSHerbert Xu 			.min_keysize		=	DES_KEY_SIZE,
212a9e62fadSHerbert Xu 			.max_keysize		=	DES_KEY_SIZE,
213a9e62fadSHerbert Xu 			.ivsize			=	DES_BLOCK_SIZE,
214a9e62fadSHerbert Xu 			.setkey			=	des_setkey,
215a9e62fadSHerbert Xu 			.encrypt		=	cbc_des_encrypt,
216a9e62fadSHerbert Xu 			.decrypt		=	cbc_des_decrypt,
217a9e62fadSHerbert Xu 		}
218a9e62fadSHerbert Xu 	}
219a9e62fadSHerbert Xu };
220a9e62fadSHerbert Xu 
221c1e26e1eSJan Glauber /*
222c1e26e1eSJan Glauber  * RFC2451:
223c1e26e1eSJan Glauber  *
224c1e26e1eSJan Glauber  *   For DES-EDE3, there is no known need to reject weak or
225c1e26e1eSJan Glauber  *   complementation keys.  Any weakness is obviated by the use of
226c1e26e1eSJan Glauber  *   multiple keys.
227c1e26e1eSJan Glauber  *
228c1e26e1eSJan Glauber  *   However, if the first two or last two independent 64-bit keys are
229c1e26e1eSJan Glauber  *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
230c1e26e1eSJan Glauber  *   same as DES.  Implementers MUST reject keys that exhibit this
231c1e26e1eSJan Glauber  *   property.
232c1e26e1eSJan Glauber  *
233c1e26e1eSJan Glauber  */
23498971f84SJan Glauber static int des3_setkey(struct crypto_tfm *tfm, const u8 *key,
23598971f84SJan Glauber 		       unsigned int key_len)
236c1e26e1eSJan Glauber {
23798971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
238560c06aeSHerbert Xu 	u32 *flags = &tfm->crt_flags;
239c1e26e1eSJan Glauber 
240fed28611SDaniel Borkmann 	if (!(crypto_memneq(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
241fed28611SDaniel Borkmann 	    crypto_memneq(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
24203b56ce5SJarod Wilson 			  DES_KEY_SIZE)) &&
24303b56ce5SJarod Wilson 	    (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
24403b56ce5SJarod Wilson 		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
245c1e26e1eSJan Glauber 		return -EINVAL;
246c1e26e1eSJan Glauber 	}
24798971f84SJan Glauber 	memcpy(ctx->key, key, key_len);
248c1e26e1eSJan Glauber 	return 0;
249c1e26e1eSJan Glauber }
250c1e26e1eSJan Glauber 
25198971f84SJan Glauber static void des3_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
252c1e26e1eSJan Glauber {
25398971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
254c1e26e1eSJan Glauber 
25598971f84SJan Glauber 	crypt_s390_km(KM_TDEA_192_ENCRYPT, ctx->key, dst, src, DES_BLOCK_SIZE);
256c1e26e1eSJan Glauber }
257c1e26e1eSJan Glauber 
25898971f84SJan Glauber static void des3_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
259c1e26e1eSJan Glauber {
26098971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_tfm_ctx(tfm);
261c1e26e1eSJan Glauber 
26298971f84SJan Glauber 	crypt_s390_km(KM_TDEA_192_DECRYPT, ctx->key, dst, src, DES_BLOCK_SIZE);
263c1e26e1eSJan Glauber }
264c1e26e1eSJan Glauber 
26598971f84SJan Glauber static struct crypto_alg des3_alg = {
266c1e26e1eSJan Glauber 	.cra_name		=	"des3_ede",
26765b75c36SHerbert Xu 	.cra_driver_name	=	"des3_ede-s390",
26865b75c36SHerbert Xu 	.cra_priority		=	CRYPT_S390_PRIORITY,
269c1e26e1eSJan Glauber 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
2701efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
27198971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
272c1e26e1eSJan Glauber 	.cra_module		=	THIS_MODULE,
273c1357833SJan Glauber 	.cra_u			=	{
274c1357833SJan Glauber 		.cipher = {
27598971f84SJan Glauber 			.cia_min_keysize	=	DES3_KEY_SIZE,
27698971f84SJan Glauber 			.cia_max_keysize	=	DES3_KEY_SIZE,
27798971f84SJan Glauber 			.cia_setkey		=	des3_setkey,
27898971f84SJan Glauber 			.cia_encrypt		=	des3_encrypt,
27998971f84SJan Glauber 			.cia_decrypt		=	des3_decrypt,
280c1357833SJan Glauber 		}
281c1357833SJan Glauber 	}
282c1e26e1eSJan Glauber };
283c1e26e1eSJan Glauber 
28498971f84SJan Glauber static int ecb_des3_encrypt(struct blkcipher_desc *desc,
28598971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
28698971f84SJan Glauber 			    unsigned int nbytes)
287a9e62fadSHerbert Xu {
28898971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
289a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
290a9e62fadSHerbert Xu 
291a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
29298971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, ctx->key, &walk);
293a9e62fadSHerbert Xu }
294a9e62fadSHerbert Xu 
29598971f84SJan Glauber static int ecb_des3_decrypt(struct blkcipher_desc *desc,
29698971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
29798971f84SJan Glauber 			    unsigned int nbytes)
298a9e62fadSHerbert Xu {
29998971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
300a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
301a9e62fadSHerbert Xu 
302a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
30398971f84SJan Glauber 	return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, ctx->key, &walk);
304a9e62fadSHerbert Xu }
305a9e62fadSHerbert Xu 
30698971f84SJan Glauber static struct crypto_alg ecb_des3_alg = {
307a9e62fadSHerbert Xu 	.cra_name		=	"ecb(des3_ede)",
308a9e62fadSHerbert Xu 	.cra_driver_name	=	"ecb-des3_ede-s390",
309a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
310a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
3111efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
31298971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
313a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
314a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
315a9e62fadSHerbert Xu 	.cra_u			=	{
316a9e62fadSHerbert Xu 		.blkcipher = {
31798971f84SJan Glauber 			.min_keysize		=	DES3_KEY_SIZE,
31898971f84SJan Glauber 			.max_keysize		=	DES3_KEY_SIZE,
31998971f84SJan Glauber 			.setkey			=	des3_setkey,
32098971f84SJan Glauber 			.encrypt		=	ecb_des3_encrypt,
32198971f84SJan Glauber 			.decrypt		=	ecb_des3_decrypt,
322a9e62fadSHerbert Xu 		}
323a9e62fadSHerbert Xu 	}
324a9e62fadSHerbert Xu };
325a9e62fadSHerbert Xu 
32698971f84SJan Glauber static int cbc_des3_encrypt(struct blkcipher_desc *desc,
32798971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
32898971f84SJan Glauber 			    unsigned int nbytes)
329a9e62fadSHerbert Xu {
33098971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
331a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
332a9e62fadSHerbert Xu 
333a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
33498971f84SJan Glauber 	return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, ctx->iv, &walk);
335a9e62fadSHerbert Xu }
336a9e62fadSHerbert Xu 
33798971f84SJan Glauber static int cbc_des3_decrypt(struct blkcipher_desc *desc,
33898971f84SJan Glauber 			    struct scatterlist *dst, struct scatterlist *src,
33998971f84SJan Glauber 			    unsigned int nbytes)
340a9e62fadSHerbert Xu {
34198971f84SJan Glauber 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
342a9e62fadSHerbert Xu 	struct blkcipher_walk walk;
343a9e62fadSHerbert Xu 
344a9e62fadSHerbert Xu 	blkcipher_walk_init(&walk, dst, src, nbytes);
34598971f84SJan Glauber 	return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, ctx->iv, &walk);
346a9e62fadSHerbert Xu }
347a9e62fadSHerbert Xu 
34898971f84SJan Glauber static struct crypto_alg cbc_des3_alg = {
349a9e62fadSHerbert Xu 	.cra_name		=	"cbc(des3_ede)",
350a9e62fadSHerbert Xu 	.cra_driver_name	=	"cbc-des3_ede-s390",
351a9e62fadSHerbert Xu 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
352a9e62fadSHerbert Xu 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
3531efbd15cSJan Glauber 	.cra_blocksize		=	DES_BLOCK_SIZE,
35498971f84SJan Glauber 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
355a9e62fadSHerbert Xu 	.cra_type		=	&crypto_blkcipher_type,
356a9e62fadSHerbert Xu 	.cra_module		=	THIS_MODULE,
357a9e62fadSHerbert Xu 	.cra_u			=	{
358a9e62fadSHerbert Xu 		.blkcipher = {
35998971f84SJan Glauber 			.min_keysize		=	DES3_KEY_SIZE,
36098971f84SJan Glauber 			.max_keysize		=	DES3_KEY_SIZE,
3611efbd15cSJan Glauber 			.ivsize			=	DES_BLOCK_SIZE,
36298971f84SJan Glauber 			.setkey			=	des3_setkey,
36398971f84SJan Glauber 			.encrypt		=	cbc_des3_encrypt,
36498971f84SJan Glauber 			.decrypt		=	cbc_des3_decrypt,
365a9e62fadSHerbert Xu 		}
366a9e62fadSHerbert Xu 	}
367a9e62fadSHerbert Xu };
368a9e62fadSHerbert Xu 
3690200f3ecSGerald Schaefer static int ctr_desall_crypt(struct blkcipher_desc *desc, long func,
3700200f3ecSGerald Schaefer 			    struct s390_des_ctx *ctx, struct blkcipher_walk *walk)
3710200f3ecSGerald Schaefer {
3720200f3ecSGerald Schaefer 	int ret = blkcipher_walk_virt_block(desc, walk, DES_BLOCK_SIZE);
3730200f3ecSGerald Schaefer 	unsigned int i, n, nbytes;
3740200f3ecSGerald Schaefer 	u8 buf[DES_BLOCK_SIZE];
3750200f3ecSGerald Schaefer 	u8 *out, *in;
3760200f3ecSGerald Schaefer 
3770200f3ecSGerald Schaefer 	memcpy(ctrblk, walk->iv, DES_BLOCK_SIZE);
3780200f3ecSGerald Schaefer 	while ((nbytes = walk->nbytes) >= DES_BLOCK_SIZE) {
3790200f3ecSGerald Schaefer 		out = walk->dst.virt.addr;
3800200f3ecSGerald Schaefer 		in = walk->src.virt.addr;
3810200f3ecSGerald Schaefer 		while (nbytes >= DES_BLOCK_SIZE) {
3820200f3ecSGerald Schaefer 			/* align to block size, max. PAGE_SIZE */
3830200f3ecSGerald Schaefer 			n = (nbytes > PAGE_SIZE) ? PAGE_SIZE :
3840200f3ecSGerald Schaefer 				nbytes & ~(DES_BLOCK_SIZE - 1);
3850200f3ecSGerald Schaefer 			for (i = DES_BLOCK_SIZE; i < n; i += DES_BLOCK_SIZE) {
3860200f3ecSGerald Schaefer 				memcpy(ctrblk + i, ctrblk + i - DES_BLOCK_SIZE,
3870200f3ecSGerald Schaefer 				       DES_BLOCK_SIZE);
3880200f3ecSGerald Schaefer 				crypto_inc(ctrblk + i, DES_BLOCK_SIZE);
3890200f3ecSGerald Schaefer 			}
3900200f3ecSGerald Schaefer 			ret = crypt_s390_kmctr(func, ctx->key, out, in, n, ctrblk);
39136eb2caaSJan Glauber 			if (ret < 0 || ret != n)
39236eb2caaSJan Glauber 				return -EIO;
3930200f3ecSGerald Schaefer 			if (n > DES_BLOCK_SIZE)
3940200f3ecSGerald Schaefer 				memcpy(ctrblk, ctrblk + n - DES_BLOCK_SIZE,
3950200f3ecSGerald Schaefer 				       DES_BLOCK_SIZE);
3960200f3ecSGerald Schaefer 			crypto_inc(ctrblk, DES_BLOCK_SIZE);
3970200f3ecSGerald Schaefer 			out += n;
3980200f3ecSGerald Schaefer 			in += n;
3990200f3ecSGerald Schaefer 			nbytes -= n;
4000200f3ecSGerald Schaefer 		}
4010200f3ecSGerald Schaefer 		ret = blkcipher_walk_done(desc, walk, nbytes);
4020200f3ecSGerald Schaefer 	}
4030200f3ecSGerald Schaefer 
4040200f3ecSGerald Schaefer 	/* final block may be < DES_BLOCK_SIZE, copy only nbytes */
4050200f3ecSGerald Schaefer 	if (nbytes) {
4060200f3ecSGerald Schaefer 		out = walk->dst.virt.addr;
4070200f3ecSGerald Schaefer 		in = walk->src.virt.addr;
4080200f3ecSGerald Schaefer 		ret = crypt_s390_kmctr(func, ctx->key, buf, in,
4090200f3ecSGerald Schaefer 				       DES_BLOCK_SIZE, ctrblk);
41036eb2caaSJan Glauber 		if (ret < 0 || ret != DES_BLOCK_SIZE)
41136eb2caaSJan Glauber 			return -EIO;
4120200f3ecSGerald Schaefer 		memcpy(out, buf, nbytes);
4130200f3ecSGerald Schaefer 		crypto_inc(ctrblk, DES_BLOCK_SIZE);
4140200f3ecSGerald Schaefer 		ret = blkcipher_walk_done(desc, walk, 0);
4150200f3ecSGerald Schaefer 	}
4160200f3ecSGerald Schaefer 	memcpy(walk->iv, ctrblk, DES_BLOCK_SIZE);
4170200f3ecSGerald Schaefer 	return ret;
4180200f3ecSGerald Schaefer }
4190200f3ecSGerald Schaefer 
4200200f3ecSGerald Schaefer static int ctr_des_encrypt(struct blkcipher_desc *desc,
4210200f3ecSGerald Schaefer 			   struct scatterlist *dst, struct scatterlist *src,
4220200f3ecSGerald Schaefer 			   unsigned int nbytes)
4230200f3ecSGerald Schaefer {
4240200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
4250200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
4260200f3ecSGerald Schaefer 
4270200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
4280200f3ecSGerald Schaefer 	return ctr_desall_crypt(desc, KMCTR_DEA_ENCRYPT, ctx, &walk);
4290200f3ecSGerald Schaefer }
4300200f3ecSGerald Schaefer 
4310200f3ecSGerald Schaefer static int ctr_des_decrypt(struct blkcipher_desc *desc,
4320200f3ecSGerald Schaefer 			   struct scatterlist *dst, struct scatterlist *src,
4330200f3ecSGerald Schaefer 			   unsigned int nbytes)
4340200f3ecSGerald Schaefer {
4350200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
4360200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
4370200f3ecSGerald Schaefer 
4380200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
4390200f3ecSGerald Schaefer 	return ctr_desall_crypt(desc, KMCTR_DEA_DECRYPT, ctx, &walk);
4400200f3ecSGerald Schaefer }
4410200f3ecSGerald Schaefer 
4420200f3ecSGerald Schaefer static struct crypto_alg ctr_des_alg = {
4430200f3ecSGerald Schaefer 	.cra_name		=	"ctr(des)",
4440200f3ecSGerald Schaefer 	.cra_driver_name	=	"ctr-des-s390",
4450200f3ecSGerald Schaefer 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
4460200f3ecSGerald Schaefer 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
4470200f3ecSGerald Schaefer 	.cra_blocksize		=	1,
4480200f3ecSGerald Schaefer 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
4490200f3ecSGerald Schaefer 	.cra_type		=	&crypto_blkcipher_type,
4500200f3ecSGerald Schaefer 	.cra_module		=	THIS_MODULE,
4510200f3ecSGerald Schaefer 	.cra_u			=	{
4520200f3ecSGerald Schaefer 		.blkcipher = {
4530200f3ecSGerald Schaefer 			.min_keysize		=	DES_KEY_SIZE,
4540200f3ecSGerald Schaefer 			.max_keysize		=	DES_KEY_SIZE,
4550200f3ecSGerald Schaefer 			.ivsize			=	DES_BLOCK_SIZE,
4560200f3ecSGerald Schaefer 			.setkey			=	des_setkey,
4570200f3ecSGerald Schaefer 			.encrypt		=	ctr_des_encrypt,
4580200f3ecSGerald Schaefer 			.decrypt		=	ctr_des_decrypt,
4590200f3ecSGerald Schaefer 		}
4600200f3ecSGerald Schaefer 	}
4610200f3ecSGerald Schaefer };
4620200f3ecSGerald Schaefer 
4630200f3ecSGerald Schaefer static int ctr_des3_encrypt(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_TDEA_192_ENCRYPT, ctx, &walk);
4720200f3ecSGerald Schaefer }
4730200f3ecSGerald Schaefer 
4740200f3ecSGerald Schaefer static int ctr_des3_decrypt(struct blkcipher_desc *desc,
4750200f3ecSGerald Schaefer 			    struct scatterlist *dst, struct scatterlist *src,
4760200f3ecSGerald Schaefer 			    unsigned int nbytes)
4770200f3ecSGerald Schaefer {
4780200f3ecSGerald Schaefer 	struct s390_des_ctx *ctx = crypto_blkcipher_ctx(desc->tfm);
4790200f3ecSGerald Schaefer 	struct blkcipher_walk walk;
4800200f3ecSGerald Schaefer 
4810200f3ecSGerald Schaefer 	blkcipher_walk_init(&walk, dst, src, nbytes);
4820200f3ecSGerald Schaefer 	return ctr_desall_crypt(desc, KMCTR_TDEA_192_DECRYPT, ctx, &walk);
4830200f3ecSGerald Schaefer }
4840200f3ecSGerald Schaefer 
4850200f3ecSGerald Schaefer static struct crypto_alg ctr_des3_alg = {
4860200f3ecSGerald Schaefer 	.cra_name		=	"ctr(des3_ede)",
4870200f3ecSGerald Schaefer 	.cra_driver_name	=	"ctr-des3_ede-s390",
4880200f3ecSGerald Schaefer 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
4890200f3ecSGerald Schaefer 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
4900200f3ecSGerald Schaefer 	.cra_blocksize		=	1,
4910200f3ecSGerald Schaefer 	.cra_ctxsize		=	sizeof(struct s390_des_ctx),
4920200f3ecSGerald Schaefer 	.cra_type		=	&crypto_blkcipher_type,
4930200f3ecSGerald Schaefer 	.cra_module		=	THIS_MODULE,
4940200f3ecSGerald Schaefer 	.cra_u			=	{
4950200f3ecSGerald Schaefer 		.blkcipher = {
4960200f3ecSGerald Schaefer 			.min_keysize		=	DES3_KEY_SIZE,
4970200f3ecSGerald Schaefer 			.max_keysize		=	DES3_KEY_SIZE,
4980200f3ecSGerald Schaefer 			.ivsize			=	DES_BLOCK_SIZE,
4990200f3ecSGerald Schaefer 			.setkey			=	des3_setkey,
5000200f3ecSGerald Schaefer 			.encrypt		=	ctr_des3_encrypt,
5010200f3ecSGerald Schaefer 			.decrypt		=	ctr_des3_decrypt,
5020200f3ecSGerald Schaefer 		}
5030200f3ecSGerald Schaefer 	}
5040200f3ecSGerald Schaefer };
5050200f3ecSGerald Schaefer 
50698971f84SJan Glauber static int __init des_s390_init(void)
507c1e26e1eSJan Glauber {
50880d663a4SJan Glauber 	int ret;
509c1e26e1eSJan Glauber 
5101822bc90SJan Glauber 	if (!crypt_s390_func_available(KM_DEA_ENCRYPT, CRYPT_S390_MSA) ||
5111822bc90SJan Glauber 	    !crypt_s390_func_available(KM_TDEA_192_ENCRYPT, CRYPT_S390_MSA))
51286aa9fc2SJan Glauber 		return -EOPNOTSUPP;
513c1e26e1eSJan Glauber 
514a9e62fadSHerbert Xu 	ret = crypto_register_alg(&des_alg);
515a9e62fadSHerbert Xu 	if (ret)
516a9e62fadSHerbert Xu 		goto des_err;
517a9e62fadSHerbert Xu 	ret = crypto_register_alg(&ecb_des_alg);
518a9e62fadSHerbert Xu 	if (ret)
519a9e62fadSHerbert Xu 		goto ecb_des_err;
520a9e62fadSHerbert Xu 	ret = crypto_register_alg(&cbc_des_alg);
521a9e62fadSHerbert Xu 	if (ret)
522a9e62fadSHerbert Xu 		goto cbc_des_err;
52398971f84SJan Glauber 	ret = crypto_register_alg(&des3_alg);
524a9e62fadSHerbert Xu 	if (ret)
52598971f84SJan Glauber 		goto des3_err;
52698971f84SJan Glauber 	ret = crypto_register_alg(&ecb_des3_alg);
527a9e62fadSHerbert Xu 	if (ret)
52898971f84SJan Glauber 		goto ecb_des3_err;
52998971f84SJan Glauber 	ret = crypto_register_alg(&cbc_des3_alg);
530a9e62fadSHerbert Xu 	if (ret)
53198971f84SJan Glauber 		goto cbc_des3_err;
5320200f3ecSGerald Schaefer 
5330200f3ecSGerald Schaefer 	if (crypt_s390_func_available(KMCTR_DEA_ENCRYPT,
5340200f3ecSGerald Schaefer 			CRYPT_S390_MSA | CRYPT_S390_MSA4) &&
5350200f3ecSGerald Schaefer 	    crypt_s390_func_available(KMCTR_TDEA_192_ENCRYPT,
5360200f3ecSGerald Schaefer 			CRYPT_S390_MSA | CRYPT_S390_MSA4)) {
5370200f3ecSGerald Schaefer 		ret = crypto_register_alg(&ctr_des_alg);
5380200f3ecSGerald Schaefer 		if (ret)
5390200f3ecSGerald Schaefer 			goto ctr_des_err;
5400200f3ecSGerald Schaefer 		ret = crypto_register_alg(&ctr_des3_alg);
5410200f3ecSGerald Schaefer 		if (ret)
5420200f3ecSGerald Schaefer 			goto ctr_des3_err;
5430200f3ecSGerald Schaefer 		ctrblk = (u8 *) __get_free_page(GFP_KERNEL);
5440200f3ecSGerald Schaefer 		if (!ctrblk) {
5450200f3ecSGerald Schaefer 			ret = -ENOMEM;
5460200f3ecSGerald Schaefer 			goto ctr_mem_err;
5470200f3ecSGerald Schaefer 		}
5480200f3ecSGerald Schaefer 	}
549a9e62fadSHerbert Xu out:
550a9e62fadSHerbert Xu 	return ret;
551a9e62fadSHerbert Xu 
5520200f3ecSGerald Schaefer ctr_mem_err:
5530200f3ecSGerald Schaefer 	crypto_unregister_alg(&ctr_des3_alg);
5540200f3ecSGerald Schaefer ctr_des3_err:
5550200f3ecSGerald Schaefer 	crypto_unregister_alg(&ctr_des_alg);
5560200f3ecSGerald Schaefer ctr_des_err:
5570200f3ecSGerald Schaefer 	crypto_unregister_alg(&cbc_des3_alg);
55898971f84SJan Glauber cbc_des3_err:
55998971f84SJan Glauber 	crypto_unregister_alg(&ecb_des3_alg);
56098971f84SJan Glauber ecb_des3_err:
56198971f84SJan Glauber 	crypto_unregister_alg(&des3_alg);
56298971f84SJan Glauber des3_err:
563a9e62fadSHerbert Xu 	crypto_unregister_alg(&cbc_des_alg);
564a9e62fadSHerbert Xu cbc_des_err:
565a9e62fadSHerbert Xu 	crypto_unregister_alg(&ecb_des_alg);
566a9e62fadSHerbert Xu ecb_des_err:
567c1e26e1eSJan Glauber 	crypto_unregister_alg(&des_alg);
568a9e62fadSHerbert Xu des_err:
569a9e62fadSHerbert Xu 	goto out;
570c1e26e1eSJan Glauber }
571c1e26e1eSJan Glauber 
5721efbd15cSJan Glauber static void __exit des_s390_exit(void)
573c1e26e1eSJan Glauber {
5740200f3ecSGerald Schaefer 	if (ctrblk) {
5750200f3ecSGerald Schaefer 		crypto_unregister_alg(&ctr_des_alg);
5760200f3ecSGerald Schaefer 		crypto_unregister_alg(&ctr_des3_alg);
5770200f3ecSGerald Schaefer 		free_page((unsigned long) ctrblk);
5780200f3ecSGerald Schaefer 	}
57998971f84SJan Glauber 	crypto_unregister_alg(&cbc_des3_alg);
58098971f84SJan Glauber 	crypto_unregister_alg(&ecb_des3_alg);
58198971f84SJan Glauber 	crypto_unregister_alg(&des3_alg);
582a9e62fadSHerbert Xu 	crypto_unregister_alg(&cbc_des_alg);
583a9e62fadSHerbert Xu 	crypto_unregister_alg(&ecb_des_alg);
584c1e26e1eSJan Glauber 	crypto_unregister_alg(&des_alg);
585c1e26e1eSJan Glauber }
586c1e26e1eSJan Glauber 
5879f7819c1SHeiko Carstens module_init(des_s390_init);
5881efbd15cSJan Glauber module_exit(des_s390_exit);
589c1e26e1eSJan Glauber 
590c1e26e1eSJan Glauber MODULE_ALIAS("des");
591c1e26e1eSJan Glauber MODULE_ALIAS("des3_ede");
592c1e26e1eSJan Glauber 
593c1e26e1eSJan Glauber MODULE_LICENSE("GPL");
594c1e26e1eSJan Glauber MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
595