• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/s390/crypto/
1/*
2 * Cryptographic API.
3 *
4 * s390 implementation of the DES Cipher Algorithm.
5 *
6 * Copyright IBM Corp. 2003,2007
7 * Author(s): Thomas Spatzier
8 *	      Jan Glauber (jan.glauber@de.ibm.com)
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/crypto.h>
20#include <crypto/algapi.h>
21#include <crypto/des.h>
22
23#include "crypt_s390.h"
24
25#define DES3_192_KEY_SIZE	(3 * DES_KEY_SIZE)
26
27struct crypt_s390_des_ctx {
28	u8 iv[DES_BLOCK_SIZE];
29	u8 key[DES_KEY_SIZE];
30};
31
32struct crypt_s390_des3_192_ctx {
33	u8 iv[DES_BLOCK_SIZE];
34	u8 key[DES3_192_KEY_SIZE];
35};
36
37static int des_setkey(struct crypto_tfm *tfm, const u8 *key,
38		      unsigned int keylen)
39{
40	struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
41	u32 *flags = &tfm->crt_flags;
42	u32 tmp[DES_EXPKEY_WORDS];
43
44	/* check for weak keys */
45	if (!des_ekey(tmp, key) && (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
46		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
47		return -EINVAL;
48	}
49
50	memcpy(dctx->key, key, keylen);
51	return 0;
52}
53
54static void des_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
55{
56	struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
57
58	crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
59}
60
61static void des_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
62{
63	struct crypt_s390_des_ctx *dctx = crypto_tfm_ctx(tfm);
64
65	crypt_s390_km(KM_DEA_DECRYPT, dctx->key, out, in, DES_BLOCK_SIZE);
66}
67
68static struct crypto_alg des_alg = {
69	.cra_name		=	"des",
70	.cra_driver_name	=	"des-s390",
71	.cra_priority		=	CRYPT_S390_PRIORITY,
72	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
73	.cra_blocksize		=	DES_BLOCK_SIZE,
74	.cra_ctxsize		=	sizeof(struct crypt_s390_des_ctx),
75	.cra_module		=	THIS_MODULE,
76	.cra_list		=	LIST_HEAD_INIT(des_alg.cra_list),
77	.cra_u			=	{
78		.cipher = {
79			.cia_min_keysize	=	DES_KEY_SIZE,
80			.cia_max_keysize	=	DES_KEY_SIZE,
81			.cia_setkey		=	des_setkey,
82			.cia_encrypt		=	des_encrypt,
83			.cia_decrypt		=	des_decrypt,
84		}
85	}
86};
87
88static int ecb_desall_crypt(struct blkcipher_desc *desc, long func,
89			    void *param, struct blkcipher_walk *walk)
90{
91	int ret = blkcipher_walk_virt(desc, walk);
92	unsigned int nbytes;
93
94	while ((nbytes = walk->nbytes)) {
95		/* only use complete blocks */
96		unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
97		u8 *out = walk->dst.virt.addr;
98		u8 *in = walk->src.virt.addr;
99
100		ret = crypt_s390_km(func, param, out, in, n);
101		BUG_ON((ret < 0) || (ret != n));
102
103		nbytes &= DES_BLOCK_SIZE - 1;
104		ret = blkcipher_walk_done(desc, walk, nbytes);
105	}
106
107	return ret;
108}
109
110static int cbc_desall_crypt(struct blkcipher_desc *desc, long func,
111			    void *param, struct blkcipher_walk *walk)
112{
113	int ret = blkcipher_walk_virt(desc, walk);
114	unsigned int nbytes = walk->nbytes;
115
116	if (!nbytes)
117		goto out;
118
119	memcpy(param, walk->iv, DES_BLOCK_SIZE);
120	do {
121		/* only use complete blocks */
122		unsigned int n = nbytes & ~(DES_BLOCK_SIZE - 1);
123		u8 *out = walk->dst.virt.addr;
124		u8 *in = walk->src.virt.addr;
125
126		ret = crypt_s390_kmc(func, param, out, in, n);
127		BUG_ON((ret < 0) || (ret != n));
128
129		nbytes &= DES_BLOCK_SIZE - 1;
130		ret = blkcipher_walk_done(desc, walk, nbytes);
131	} while ((nbytes = walk->nbytes));
132	memcpy(walk->iv, param, DES_BLOCK_SIZE);
133
134out:
135	return ret;
136}
137
138static int ecb_des_encrypt(struct blkcipher_desc *desc,
139			   struct scatterlist *dst, struct scatterlist *src,
140			   unsigned int nbytes)
141{
142	struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
143	struct blkcipher_walk walk;
144
145	blkcipher_walk_init(&walk, dst, src, nbytes);
146	return ecb_desall_crypt(desc, KM_DEA_ENCRYPT, sctx->key, &walk);
147}
148
149static int ecb_des_decrypt(struct blkcipher_desc *desc,
150			   struct scatterlist *dst, struct scatterlist *src,
151			   unsigned int nbytes)
152{
153	struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
154	struct blkcipher_walk walk;
155
156	blkcipher_walk_init(&walk, dst, src, nbytes);
157	return ecb_desall_crypt(desc, KM_DEA_DECRYPT, sctx->key, &walk);
158}
159
160static struct crypto_alg ecb_des_alg = {
161	.cra_name		=	"ecb(des)",
162	.cra_driver_name	=	"ecb-des-s390",
163	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
164	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
165	.cra_blocksize		=	DES_BLOCK_SIZE,
166	.cra_ctxsize		=	sizeof(struct crypt_s390_des_ctx),
167	.cra_type		=	&crypto_blkcipher_type,
168	.cra_module		=	THIS_MODULE,
169	.cra_list		=	LIST_HEAD_INIT(ecb_des_alg.cra_list),
170	.cra_u			=	{
171		.blkcipher = {
172			.min_keysize		=	DES_KEY_SIZE,
173			.max_keysize		=	DES_KEY_SIZE,
174			.setkey			=	des_setkey,
175			.encrypt		=	ecb_des_encrypt,
176			.decrypt		=	ecb_des_decrypt,
177		}
178	}
179};
180
181static int cbc_des_encrypt(struct blkcipher_desc *desc,
182			   struct scatterlist *dst, struct scatterlist *src,
183			   unsigned int nbytes)
184{
185	struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
186	struct blkcipher_walk walk;
187
188	blkcipher_walk_init(&walk, dst, src, nbytes);
189	return cbc_desall_crypt(desc, KMC_DEA_ENCRYPT, sctx->iv, &walk);
190}
191
192static int cbc_des_decrypt(struct blkcipher_desc *desc,
193			   struct scatterlist *dst, struct scatterlist *src,
194			   unsigned int nbytes)
195{
196	struct crypt_s390_des_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
197	struct blkcipher_walk walk;
198
199	blkcipher_walk_init(&walk, dst, src, nbytes);
200	return cbc_desall_crypt(desc, KMC_DEA_DECRYPT, sctx->iv, &walk);
201}
202
203static struct crypto_alg cbc_des_alg = {
204	.cra_name		=	"cbc(des)",
205	.cra_driver_name	=	"cbc-des-s390",
206	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
207	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
208	.cra_blocksize		=	DES_BLOCK_SIZE,
209	.cra_ctxsize		=	sizeof(struct crypt_s390_des_ctx),
210	.cra_type		=	&crypto_blkcipher_type,
211	.cra_module		=	THIS_MODULE,
212	.cra_list		=	LIST_HEAD_INIT(cbc_des_alg.cra_list),
213	.cra_u			=	{
214		.blkcipher = {
215			.min_keysize		=	DES_KEY_SIZE,
216			.max_keysize		=	DES_KEY_SIZE,
217			.ivsize			=	DES_BLOCK_SIZE,
218			.setkey			=	des_setkey,
219			.encrypt		=	cbc_des_encrypt,
220			.decrypt		=	cbc_des_decrypt,
221		}
222	}
223};
224
225/*
226 * RFC2451:
227 *
228 *   For DES-EDE3, there is no known need to reject weak or
229 *   complementation keys.  Any weakness is obviated by the use of
230 *   multiple keys.
231 *
232 *   However, if the first two or last two independent 64-bit keys are
233 *   equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the
234 *   same as DES.  Implementers MUST reject keys that exhibit this
235 *   property.
236 *
237 */
238static int des3_192_setkey(struct crypto_tfm *tfm, const u8 *key,
239			   unsigned int keylen)
240{
241	struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm);
242	u32 *flags = &tfm->crt_flags;
243
244	if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) &&
245	    memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2],
246		   DES_KEY_SIZE)) &&
247	    (*flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
248		*flags |= CRYPTO_TFM_RES_WEAK_KEY;
249		return -EINVAL;
250	}
251	memcpy(dctx->key, key, keylen);
252	return 0;
253}
254
255static void des3_192_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
256{
257	struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm);
258
259	crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src,
260		      DES_BLOCK_SIZE);
261}
262
263static void des3_192_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src)
264{
265	struct crypt_s390_des3_192_ctx *dctx = crypto_tfm_ctx(tfm);
266
267	crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src,
268		      DES_BLOCK_SIZE);
269}
270
271static struct crypto_alg des3_192_alg = {
272	.cra_name		=	"des3_ede",
273	.cra_driver_name	=	"des3_ede-s390",
274	.cra_priority		=	CRYPT_S390_PRIORITY,
275	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
276	.cra_blocksize		=	DES_BLOCK_SIZE,
277	.cra_ctxsize		=	sizeof(struct crypt_s390_des3_192_ctx),
278	.cra_module		=	THIS_MODULE,
279	.cra_list		=	LIST_HEAD_INIT(des3_192_alg.cra_list),
280	.cra_u			=	{
281		.cipher = {
282			.cia_min_keysize	=	DES3_192_KEY_SIZE,
283			.cia_max_keysize	=	DES3_192_KEY_SIZE,
284			.cia_setkey		=	des3_192_setkey,
285			.cia_encrypt		=	des3_192_encrypt,
286			.cia_decrypt		=	des3_192_decrypt,
287		}
288	}
289};
290
291static int ecb_des3_192_encrypt(struct blkcipher_desc *desc,
292				struct scatterlist *dst,
293				struct scatterlist *src, unsigned int nbytes)
294{
295	struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
296	struct blkcipher_walk walk;
297
298	blkcipher_walk_init(&walk, dst, src, nbytes);
299	return ecb_desall_crypt(desc, KM_TDEA_192_ENCRYPT, sctx->key, &walk);
300}
301
302static int ecb_des3_192_decrypt(struct blkcipher_desc *desc,
303				struct scatterlist *dst,
304				struct scatterlist *src, unsigned int nbytes)
305{
306	struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
307	struct blkcipher_walk walk;
308
309	blkcipher_walk_init(&walk, dst, src, nbytes);
310	return ecb_desall_crypt(desc, KM_TDEA_192_DECRYPT, sctx->key, &walk);
311}
312
313static struct crypto_alg ecb_des3_192_alg = {
314	.cra_name		=	"ecb(des3_ede)",
315	.cra_driver_name	=	"ecb-des3_ede-s390",
316	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
317	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
318	.cra_blocksize		=	DES_BLOCK_SIZE,
319	.cra_ctxsize		=	sizeof(struct crypt_s390_des3_192_ctx),
320	.cra_type		=	&crypto_blkcipher_type,
321	.cra_module		=	THIS_MODULE,
322	.cra_list		=	LIST_HEAD_INIT(
323						ecb_des3_192_alg.cra_list),
324	.cra_u			=	{
325		.blkcipher = {
326			.min_keysize		=	DES3_192_KEY_SIZE,
327			.max_keysize		=	DES3_192_KEY_SIZE,
328			.setkey			=	des3_192_setkey,
329			.encrypt		=	ecb_des3_192_encrypt,
330			.decrypt		=	ecb_des3_192_decrypt,
331		}
332	}
333};
334
335static int cbc_des3_192_encrypt(struct blkcipher_desc *desc,
336				struct scatterlist *dst,
337				struct scatterlist *src, unsigned int nbytes)
338{
339	struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
340	struct blkcipher_walk walk;
341
342	blkcipher_walk_init(&walk, dst, src, nbytes);
343	return cbc_desall_crypt(desc, KMC_TDEA_192_ENCRYPT, sctx->iv, &walk);
344}
345
346static int cbc_des3_192_decrypt(struct blkcipher_desc *desc,
347				struct scatterlist *dst,
348				struct scatterlist *src, unsigned int nbytes)
349{
350	struct crypt_s390_des3_192_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
351	struct blkcipher_walk walk;
352
353	blkcipher_walk_init(&walk, dst, src, nbytes);
354	return cbc_desall_crypt(desc, KMC_TDEA_192_DECRYPT, sctx->iv, &walk);
355}
356
357static struct crypto_alg cbc_des3_192_alg = {
358	.cra_name		=	"cbc(des3_ede)",
359	.cra_driver_name	=	"cbc-des3_ede-s390",
360	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
361	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
362	.cra_blocksize		=	DES_BLOCK_SIZE,
363	.cra_ctxsize		=	sizeof(struct crypt_s390_des3_192_ctx),
364	.cra_type		=	&crypto_blkcipher_type,
365	.cra_module		=	THIS_MODULE,
366	.cra_list		=	LIST_HEAD_INIT(
367						cbc_des3_192_alg.cra_list),
368	.cra_u			=	{
369		.blkcipher = {
370			.min_keysize		=	DES3_192_KEY_SIZE,
371			.max_keysize		=	DES3_192_KEY_SIZE,
372			.ivsize			=	DES_BLOCK_SIZE,
373			.setkey			=	des3_192_setkey,
374			.encrypt		=	cbc_des3_192_encrypt,
375			.decrypt		=	cbc_des3_192_decrypt,
376		}
377	}
378};
379
380static int des_s390_init(void)
381{
382	int ret;
383
384	if (!crypt_s390_func_available(KM_DEA_ENCRYPT) ||
385	    !crypt_s390_func_available(KM_TDEA_192_ENCRYPT))
386		return -EOPNOTSUPP;
387
388	ret = crypto_register_alg(&des_alg);
389	if (ret)
390		goto des_err;
391	ret = crypto_register_alg(&ecb_des_alg);
392	if (ret)
393		goto ecb_des_err;
394	ret = crypto_register_alg(&cbc_des_alg);
395	if (ret)
396		goto cbc_des_err;
397	ret = crypto_register_alg(&des3_192_alg);
398	if (ret)
399		goto des3_192_err;
400	ret = crypto_register_alg(&ecb_des3_192_alg);
401	if (ret)
402		goto ecb_des3_192_err;
403	ret = crypto_register_alg(&cbc_des3_192_alg);
404	if (ret)
405		goto cbc_des3_192_err;
406out:
407	return ret;
408
409cbc_des3_192_err:
410	crypto_unregister_alg(&ecb_des3_192_alg);
411ecb_des3_192_err:
412	crypto_unregister_alg(&des3_192_alg);
413des3_192_err:
414	crypto_unregister_alg(&cbc_des_alg);
415cbc_des_err:
416	crypto_unregister_alg(&ecb_des_alg);
417ecb_des_err:
418	crypto_unregister_alg(&des_alg);
419des_err:
420	goto out;
421}
422
423static void __exit des_s390_exit(void)
424{
425	crypto_unregister_alg(&cbc_des3_192_alg);
426	crypto_unregister_alg(&ecb_des3_192_alg);
427	crypto_unregister_alg(&des3_192_alg);
428	crypto_unregister_alg(&cbc_des_alg);
429	crypto_unregister_alg(&ecb_des_alg);
430	crypto_unregister_alg(&des_alg);
431}
432
433module_init(des_s390_init);
434module_exit(des_s390_exit);
435
436MODULE_ALIAS("des");
437MODULE_ALIAS("des3_ede");
438
439MODULE_LICENSE("GPL");
440MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms");
441