• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/s390/crypto/
1/*
2 * Cryptographic API.
3 *
4 * s390 implementation of the AES Cipher Algorithm.
5 *
6 * s390 Version:
7 *   Copyright IBM Corp. 2005,2007
8 *   Author(s): Jan Glauber (jang@de.ibm.com)
9 *		Sebastian Siewior (sebastian@breakpoint.cc> SW-Fallback
10 *
11 * Derived from "crypto/aes_generic.c"
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the Free
15 * Software Foundation; either version 2 of the License, or (at your option)
16 * any later version.
17 *
18 */
19
20#define KMSG_COMPONENT "aes_s390"
21#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
22
23#include <crypto/aes.h>
24#include <crypto/algapi.h>
25#include <linux/err.h>
26#include <linux/module.h>
27#include <linux/init.h>
28#include "crypt_s390.h"
29
30#define AES_KEYLEN_128		1
31#define AES_KEYLEN_192		2
32#define AES_KEYLEN_256		4
33
34static char keylen_flag = 0;
35
36struct s390_aes_ctx {
37	u8 iv[AES_BLOCK_SIZE];
38	u8 key[AES_MAX_KEY_SIZE];
39	long enc;
40	long dec;
41	int key_len;
42	union {
43		struct crypto_blkcipher *blk;
44		struct crypto_cipher *cip;
45	} fallback;
46};
47
48/*
49 * Check if the key_len is supported by the HW.
50 * Returns 0 if it is, a positive number if it is not and software fallback is
51 * required or a negative number in case the key size is not valid
52 */
53static int need_fallback(unsigned int key_len)
54{
55	switch (key_len) {
56	case 16:
57		if (!(keylen_flag & AES_KEYLEN_128))
58			return 1;
59		break;
60	case 24:
61		if (!(keylen_flag & AES_KEYLEN_192))
62			return 1;
63		break;
64	case 32:
65		if (!(keylen_flag & AES_KEYLEN_256))
66			return 1;
67		break;
68	default:
69		return -1;
70		break;
71	}
72	return 0;
73}
74
75static int setkey_fallback_cip(struct crypto_tfm *tfm, const u8 *in_key,
76		unsigned int key_len)
77{
78	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
79	int ret;
80
81	sctx->fallback.cip->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
82	sctx->fallback.cip->base.crt_flags |= (tfm->crt_flags &
83			CRYPTO_TFM_REQ_MASK);
84
85	ret = crypto_cipher_setkey(sctx->fallback.cip, in_key, key_len);
86	if (ret) {
87		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
88		tfm->crt_flags |= (sctx->fallback.cip->base.crt_flags &
89				CRYPTO_TFM_RES_MASK);
90	}
91	return ret;
92}
93
94static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
95		       unsigned int key_len)
96{
97	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
98	u32 *flags = &tfm->crt_flags;
99	int ret;
100
101	ret = need_fallback(key_len);
102	if (ret < 0) {
103		*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
104		return -EINVAL;
105	}
106
107	sctx->key_len = key_len;
108	if (!ret) {
109		memcpy(sctx->key, in_key, key_len);
110		return 0;
111	}
112
113	return setkey_fallback_cip(tfm, in_key, key_len);
114}
115
116static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
117{
118	const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
119
120	if (unlikely(need_fallback(sctx->key_len))) {
121		crypto_cipher_encrypt_one(sctx->fallback.cip, out, in);
122		return;
123	}
124
125	switch (sctx->key_len) {
126	case 16:
127		crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
128			      AES_BLOCK_SIZE);
129		break;
130	case 24:
131		crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in,
132			      AES_BLOCK_SIZE);
133		break;
134	case 32:
135		crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in,
136			      AES_BLOCK_SIZE);
137		break;
138	}
139}
140
141static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
142{
143	const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
144
145	if (unlikely(need_fallback(sctx->key_len))) {
146		crypto_cipher_decrypt_one(sctx->fallback.cip, out, in);
147		return;
148	}
149
150	switch (sctx->key_len) {
151	case 16:
152		crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
153			      AES_BLOCK_SIZE);
154		break;
155	case 24:
156		crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in,
157			      AES_BLOCK_SIZE);
158		break;
159	case 32:
160		crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in,
161			      AES_BLOCK_SIZE);
162		break;
163	}
164}
165
166static int fallback_init_cip(struct crypto_tfm *tfm)
167{
168	const char *name = tfm->__crt_alg->cra_name;
169	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
170
171	sctx->fallback.cip = crypto_alloc_cipher(name, 0,
172			CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
173
174	if (IS_ERR(sctx->fallback.cip)) {
175		pr_err("Allocating AES fallback algorithm %s failed\n",
176		       name);
177		return PTR_ERR(sctx->fallback.cip);
178	}
179
180	return 0;
181}
182
183static void fallback_exit_cip(struct crypto_tfm *tfm)
184{
185	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
186
187	crypto_free_cipher(sctx->fallback.cip);
188	sctx->fallback.cip = NULL;
189}
190
191static struct crypto_alg aes_alg = {
192	.cra_name		=	"aes",
193	.cra_driver_name	=	"aes-s390",
194	.cra_priority		=	CRYPT_S390_PRIORITY,
195	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER |
196					CRYPTO_ALG_NEED_FALLBACK,
197	.cra_blocksize		=	AES_BLOCK_SIZE,
198	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
199	.cra_module		=	THIS_MODULE,
200	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
201	.cra_init               =       fallback_init_cip,
202	.cra_exit               =       fallback_exit_cip,
203	.cra_u			=	{
204		.cipher = {
205			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
206			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
207			.cia_setkey		=	aes_set_key,
208			.cia_encrypt		=	aes_encrypt,
209			.cia_decrypt		=	aes_decrypt,
210		}
211	}
212};
213
214static int setkey_fallback_blk(struct crypto_tfm *tfm, const u8 *key,
215		unsigned int len)
216{
217	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
218	unsigned int ret;
219
220	sctx->fallback.blk->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
221	sctx->fallback.blk->base.crt_flags |= (tfm->crt_flags &
222			CRYPTO_TFM_REQ_MASK);
223
224	ret = crypto_blkcipher_setkey(sctx->fallback.blk, key, len);
225	if (ret) {
226		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
227		tfm->crt_flags |= (sctx->fallback.blk->base.crt_flags &
228				CRYPTO_TFM_RES_MASK);
229	}
230	return ret;
231}
232
233static int fallback_blk_dec(struct blkcipher_desc *desc,
234		struct scatterlist *dst, struct scatterlist *src,
235		unsigned int nbytes)
236{
237	unsigned int ret;
238	struct crypto_blkcipher *tfm;
239	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
240
241	tfm = desc->tfm;
242	desc->tfm = sctx->fallback.blk;
243
244	ret = crypto_blkcipher_decrypt_iv(desc, dst, src, nbytes);
245
246	desc->tfm = tfm;
247	return ret;
248}
249
250static int fallback_blk_enc(struct blkcipher_desc *desc,
251		struct scatterlist *dst, struct scatterlist *src,
252		unsigned int nbytes)
253{
254	unsigned int ret;
255	struct crypto_blkcipher *tfm;
256	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
257
258	tfm = desc->tfm;
259	desc->tfm = sctx->fallback.blk;
260
261	ret = crypto_blkcipher_encrypt_iv(desc, dst, src, nbytes);
262
263	desc->tfm = tfm;
264	return ret;
265}
266
267static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
268			   unsigned int key_len)
269{
270	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
271	int ret;
272
273	ret = need_fallback(key_len);
274	if (ret > 0) {
275		sctx->key_len = key_len;
276		return setkey_fallback_blk(tfm, in_key, key_len);
277	}
278
279	switch (key_len) {
280	case 16:
281		sctx->enc = KM_AES_128_ENCRYPT;
282		sctx->dec = KM_AES_128_DECRYPT;
283		break;
284	case 24:
285		sctx->enc = KM_AES_192_ENCRYPT;
286		sctx->dec = KM_AES_192_DECRYPT;
287		break;
288	case 32:
289		sctx->enc = KM_AES_256_ENCRYPT;
290		sctx->dec = KM_AES_256_DECRYPT;
291		break;
292	}
293
294	return aes_set_key(tfm, in_key, key_len);
295}
296
297static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
298			 struct blkcipher_walk *walk)
299{
300	int ret = blkcipher_walk_virt(desc, walk);
301	unsigned int nbytes;
302
303	while ((nbytes = walk->nbytes)) {
304		/* only use complete blocks */
305		unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
306		u8 *out = walk->dst.virt.addr;
307		u8 *in = walk->src.virt.addr;
308
309		ret = crypt_s390_km(func, param, out, in, n);
310		BUG_ON((ret < 0) || (ret != n));
311
312		nbytes &= AES_BLOCK_SIZE - 1;
313		ret = blkcipher_walk_done(desc, walk, nbytes);
314	}
315
316	return ret;
317}
318
319static int ecb_aes_encrypt(struct blkcipher_desc *desc,
320			   struct scatterlist *dst, struct scatterlist *src,
321			   unsigned int nbytes)
322{
323	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
324	struct blkcipher_walk walk;
325
326	if (unlikely(need_fallback(sctx->key_len)))
327		return fallback_blk_enc(desc, dst, src, nbytes);
328
329	blkcipher_walk_init(&walk, dst, src, nbytes);
330	return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk);
331}
332
333static int ecb_aes_decrypt(struct blkcipher_desc *desc,
334			   struct scatterlist *dst, struct scatterlist *src,
335			   unsigned int nbytes)
336{
337	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
338	struct blkcipher_walk walk;
339
340	if (unlikely(need_fallback(sctx->key_len)))
341		return fallback_blk_dec(desc, dst, src, nbytes);
342
343	blkcipher_walk_init(&walk, dst, src, nbytes);
344	return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk);
345}
346
347static int fallback_init_blk(struct crypto_tfm *tfm)
348{
349	const char *name = tfm->__crt_alg->cra_name;
350	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
351
352	sctx->fallback.blk = crypto_alloc_blkcipher(name, 0,
353			CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
354
355	if (IS_ERR(sctx->fallback.blk)) {
356		pr_err("Allocating AES fallback algorithm %s failed\n",
357		       name);
358		return PTR_ERR(sctx->fallback.blk);
359	}
360
361	return 0;
362}
363
364static void fallback_exit_blk(struct crypto_tfm *tfm)
365{
366	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
367
368	crypto_free_blkcipher(sctx->fallback.blk);
369	sctx->fallback.blk = NULL;
370}
371
372static struct crypto_alg ecb_aes_alg = {
373	.cra_name		=	"ecb(aes)",
374	.cra_driver_name	=	"ecb-aes-s390",
375	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
376	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
377					CRYPTO_ALG_NEED_FALLBACK,
378	.cra_blocksize		=	AES_BLOCK_SIZE,
379	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
380	.cra_type		=	&crypto_blkcipher_type,
381	.cra_module		=	THIS_MODULE,
382	.cra_list		=	LIST_HEAD_INIT(ecb_aes_alg.cra_list),
383	.cra_init		=	fallback_init_blk,
384	.cra_exit		=	fallback_exit_blk,
385	.cra_u			=	{
386		.blkcipher = {
387			.min_keysize		=	AES_MIN_KEY_SIZE,
388			.max_keysize		=	AES_MAX_KEY_SIZE,
389			.setkey			=	ecb_aes_set_key,
390			.encrypt		=	ecb_aes_encrypt,
391			.decrypt		=	ecb_aes_decrypt,
392		}
393	}
394};
395
396static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
397			   unsigned int key_len)
398{
399	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
400	int ret;
401
402	ret = need_fallback(key_len);
403	if (ret > 0) {
404		sctx->key_len = key_len;
405		return setkey_fallback_blk(tfm, in_key, key_len);
406	}
407
408	switch (key_len) {
409	case 16:
410		sctx->enc = KMC_AES_128_ENCRYPT;
411		sctx->dec = KMC_AES_128_DECRYPT;
412		break;
413	case 24:
414		sctx->enc = KMC_AES_192_ENCRYPT;
415		sctx->dec = KMC_AES_192_DECRYPT;
416		break;
417	case 32:
418		sctx->enc = KMC_AES_256_ENCRYPT;
419		sctx->dec = KMC_AES_256_DECRYPT;
420		break;
421	}
422
423	return aes_set_key(tfm, in_key, key_len);
424}
425
426static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
427			 struct blkcipher_walk *walk)
428{
429	int ret = blkcipher_walk_virt(desc, walk);
430	unsigned int nbytes = walk->nbytes;
431
432	if (!nbytes)
433		goto out;
434
435	memcpy(param, walk->iv, AES_BLOCK_SIZE);
436	do {
437		/* only use complete blocks */
438		unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
439		u8 *out = walk->dst.virt.addr;
440		u8 *in = walk->src.virt.addr;
441
442		ret = crypt_s390_kmc(func, param, out, in, n);
443		BUG_ON((ret < 0) || (ret != n));
444
445		nbytes &= AES_BLOCK_SIZE - 1;
446		ret = blkcipher_walk_done(desc, walk, nbytes);
447	} while ((nbytes = walk->nbytes));
448	memcpy(walk->iv, param, AES_BLOCK_SIZE);
449
450out:
451	return ret;
452}
453
454static int cbc_aes_encrypt(struct blkcipher_desc *desc,
455			   struct scatterlist *dst, struct scatterlist *src,
456			   unsigned int nbytes)
457{
458	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
459	struct blkcipher_walk walk;
460
461	if (unlikely(need_fallback(sctx->key_len)))
462		return fallback_blk_enc(desc, dst, src, nbytes);
463
464	blkcipher_walk_init(&walk, dst, src, nbytes);
465	return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
466}
467
468static int cbc_aes_decrypt(struct blkcipher_desc *desc,
469			   struct scatterlist *dst, struct scatterlist *src,
470			   unsigned int nbytes)
471{
472	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
473	struct blkcipher_walk walk;
474
475	if (unlikely(need_fallback(sctx->key_len)))
476		return fallback_blk_dec(desc, dst, src, nbytes);
477
478	blkcipher_walk_init(&walk, dst, src, nbytes);
479	return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
480}
481
482static struct crypto_alg cbc_aes_alg = {
483	.cra_name		=	"cbc(aes)",
484	.cra_driver_name	=	"cbc-aes-s390",
485	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
486	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER |
487					CRYPTO_ALG_NEED_FALLBACK,
488	.cra_blocksize		=	AES_BLOCK_SIZE,
489	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
490	.cra_type		=	&crypto_blkcipher_type,
491	.cra_module		=	THIS_MODULE,
492	.cra_list		=	LIST_HEAD_INIT(cbc_aes_alg.cra_list),
493	.cra_init		=	fallback_init_blk,
494	.cra_exit		=	fallback_exit_blk,
495	.cra_u			=	{
496		.blkcipher = {
497			.min_keysize		=	AES_MIN_KEY_SIZE,
498			.max_keysize		=	AES_MAX_KEY_SIZE,
499			.ivsize			=	AES_BLOCK_SIZE,
500			.setkey			=	cbc_aes_set_key,
501			.encrypt		=	cbc_aes_encrypt,
502			.decrypt		=	cbc_aes_decrypt,
503		}
504	}
505};
506
507static int __init aes_s390_init(void)
508{
509	int ret;
510
511	if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
512		keylen_flag |= AES_KEYLEN_128;
513	if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
514		keylen_flag |= AES_KEYLEN_192;
515	if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
516		keylen_flag |= AES_KEYLEN_256;
517
518	if (!keylen_flag)
519		return -EOPNOTSUPP;
520
521	/* z9 109 and z9 BC/EC only support 128 bit key length */
522	if (keylen_flag == AES_KEYLEN_128)
523		pr_info("AES hardware acceleration is only available for"
524			" 128-bit keys\n");
525
526	ret = crypto_register_alg(&aes_alg);
527	if (ret)
528		goto aes_err;
529
530	ret = crypto_register_alg(&ecb_aes_alg);
531	if (ret)
532		goto ecb_aes_err;
533
534	ret = crypto_register_alg(&cbc_aes_alg);
535	if (ret)
536		goto cbc_aes_err;
537
538out:
539	return ret;
540
541cbc_aes_err:
542	crypto_unregister_alg(&ecb_aes_alg);
543ecb_aes_err:
544	crypto_unregister_alg(&aes_alg);
545aes_err:
546	goto out;
547}
548
549static void __exit aes_s390_fini(void)
550{
551	crypto_unregister_alg(&cbc_aes_alg);
552	crypto_unregister_alg(&ecb_aes_alg);
553	crypto_unregister_alg(&aes_alg);
554}
555
556module_init(aes_s390_init);
557module_exit(aes_s390_fini);
558
559MODULE_ALIAS("aes-all");
560
561MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
562MODULE_LICENSE("GPL");
563