xref: /linux/arch/s390/crypto/aes_s390.c (revision f24e9f586b377749dff37554696cf3a105540c94)
1 /*
2  * Cryptographic API.
3  *
4  * s390 implementation of the AES Cipher Algorithm.
5  *
6  * s390 Version:
7  *   Copyright (C) 2005 IBM Deutschland GmbH, IBM Corporation
8  *   Author(s): Jan Glauber (jang@de.ibm.com)
9  *
10  * Derived from "crypto/aes.c"
11  *
12  * This program is free software; you can redistribute it and/or modify it
13  * under the terms of the GNU General Public License as published by the Free
14  * Software Foundation; either version 2 of the License, or (at your option)
15  * any later version.
16  *
17  */
18 
19 #include <crypto/algapi.h>
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include "crypt_s390.h"
23 
24 #define AES_MIN_KEY_SIZE	16
25 #define AES_MAX_KEY_SIZE	32
26 
27 /* data block size for all key lengths */
28 #define AES_BLOCK_SIZE		16
29 
30 int has_aes_128 = 0;
31 int has_aes_192 = 0;
32 int has_aes_256 = 0;
33 
34 struct s390_aes_ctx {
35 	u8 iv[AES_BLOCK_SIZE];
36 	u8 key[AES_MAX_KEY_SIZE];
37 	long enc;
38 	long dec;
39 	int key_len;
40 };
41 
42 static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
43 		       unsigned int key_len)
44 {
45 	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
46 	u32 *flags = &tfm->crt_flags;
47 
48 	switch (key_len) {
49 	case 16:
50 		if (!has_aes_128)
51 			goto fail;
52 		break;
53 	case 24:
54 		if (!has_aes_192)
55 			goto fail;
56 
57 		break;
58 	case 32:
59 		if (!has_aes_256)
60 			goto fail;
61 		break;
62 	default:
63 		/* invalid key length */
64 		goto fail;
65 		break;
66 	}
67 
68 	sctx->key_len = key_len;
69 	memcpy(sctx->key, in_key, key_len);
70 	return 0;
71 fail:
72 	*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
73 	return -EINVAL;
74 }
75 
76 static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
77 {
78 	const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
79 
80 	switch (sctx->key_len) {
81 	case 16:
82 		crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
83 			      AES_BLOCK_SIZE);
84 		break;
85 	case 24:
86 		crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in,
87 			      AES_BLOCK_SIZE);
88 		break;
89 	case 32:
90 		crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in,
91 			      AES_BLOCK_SIZE);
92 		break;
93 	}
94 }
95 
96 static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
97 {
98 	const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
99 
100 	switch (sctx->key_len) {
101 	case 16:
102 		crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
103 			      AES_BLOCK_SIZE);
104 		break;
105 	case 24:
106 		crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in,
107 			      AES_BLOCK_SIZE);
108 		break;
109 	case 32:
110 		crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in,
111 			      AES_BLOCK_SIZE);
112 		break;
113 	}
114 }
115 
116 
117 static struct crypto_alg aes_alg = {
118 	.cra_name		=	"aes",
119 	.cra_driver_name	=	"aes-s390",
120 	.cra_priority		=	CRYPT_S390_PRIORITY,
121 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
122 	.cra_blocksize		=	AES_BLOCK_SIZE,
123 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
124 	.cra_module		=	THIS_MODULE,
125 	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
126 	.cra_u			=	{
127 		.cipher = {
128 			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
129 			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
130 			.cia_setkey		=	aes_set_key,
131 			.cia_encrypt		=	aes_encrypt,
132 			.cia_decrypt		=	aes_decrypt,
133 		}
134 	}
135 };
136 
137 static int ecb_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
138 			   unsigned int key_len)
139 {
140 	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
141 
142 	switch (key_len) {
143 	case 16:
144 		sctx->enc = KM_AES_128_ENCRYPT;
145 		sctx->dec = KM_AES_128_DECRYPT;
146 		break;
147 	case 24:
148 		sctx->enc = KM_AES_192_ENCRYPT;
149 		sctx->dec = KM_AES_192_DECRYPT;
150 		break;
151 	case 32:
152 		sctx->enc = KM_AES_256_ENCRYPT;
153 		sctx->dec = KM_AES_256_DECRYPT;
154 		break;
155 	}
156 
157 	return aes_set_key(tfm, in_key, key_len);
158 }
159 
160 static int ecb_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
161 			 struct blkcipher_walk *walk)
162 {
163 	int ret = blkcipher_walk_virt(desc, walk);
164 	unsigned int nbytes;
165 
166 	while ((nbytes = walk->nbytes)) {
167 		/* only use complete blocks */
168 		unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
169 		u8 *out = walk->dst.virt.addr;
170 		u8 *in = walk->src.virt.addr;
171 
172 		ret = crypt_s390_km(func, param, out, in, n);
173 		BUG_ON((ret < 0) || (ret != n));
174 
175 		nbytes &= AES_BLOCK_SIZE - 1;
176 		ret = blkcipher_walk_done(desc, walk, nbytes);
177 	}
178 
179 	return ret;
180 }
181 
182 static int ecb_aes_encrypt(struct blkcipher_desc *desc,
183 			   struct scatterlist *dst, struct scatterlist *src,
184 			   unsigned int nbytes)
185 {
186 	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
187 	struct blkcipher_walk walk;
188 
189 	blkcipher_walk_init(&walk, dst, src, nbytes);
190 	return ecb_aes_crypt(desc, sctx->enc, sctx->key, &walk);
191 }
192 
193 static int ecb_aes_decrypt(struct blkcipher_desc *desc,
194 			   struct scatterlist *dst, struct scatterlist *src,
195 			   unsigned int nbytes)
196 {
197 	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
198 	struct blkcipher_walk walk;
199 
200 	blkcipher_walk_init(&walk, dst, src, nbytes);
201 	return ecb_aes_crypt(desc, sctx->dec, sctx->key, &walk);
202 }
203 
204 static struct crypto_alg ecb_aes_alg = {
205 	.cra_name		=	"ecb(aes)",
206 	.cra_driver_name	=	"ecb-aes-s390",
207 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
208 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
209 	.cra_blocksize		=	AES_BLOCK_SIZE,
210 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
211 	.cra_type		=	&crypto_blkcipher_type,
212 	.cra_module		=	THIS_MODULE,
213 	.cra_list		=	LIST_HEAD_INIT(ecb_aes_alg.cra_list),
214 	.cra_u			=	{
215 		.blkcipher = {
216 			.min_keysize		=	AES_MIN_KEY_SIZE,
217 			.max_keysize		=	AES_MAX_KEY_SIZE,
218 			.setkey			=	ecb_aes_set_key,
219 			.encrypt		=	ecb_aes_encrypt,
220 			.decrypt		=	ecb_aes_decrypt,
221 		}
222 	}
223 };
224 
225 static int cbc_aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
226 			   unsigned int key_len)
227 {
228 	struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
229 
230 	switch (key_len) {
231 	case 16:
232 		sctx->enc = KMC_AES_128_ENCRYPT;
233 		sctx->dec = KMC_AES_128_DECRYPT;
234 		break;
235 	case 24:
236 		sctx->enc = KMC_AES_192_ENCRYPT;
237 		sctx->dec = KMC_AES_192_DECRYPT;
238 		break;
239 	case 32:
240 		sctx->enc = KMC_AES_256_ENCRYPT;
241 		sctx->dec = KMC_AES_256_DECRYPT;
242 		break;
243 	}
244 
245 	return aes_set_key(tfm, in_key, key_len);
246 }
247 
248 static int cbc_aes_crypt(struct blkcipher_desc *desc, long func, void *param,
249 			 struct blkcipher_walk *walk)
250 {
251 	int ret = blkcipher_walk_virt(desc, walk);
252 	unsigned int nbytes = walk->nbytes;
253 
254 	if (!nbytes)
255 		goto out;
256 
257 	memcpy(param, walk->iv, AES_BLOCK_SIZE);
258 	do {
259 		/* only use complete blocks */
260 		unsigned int n = nbytes & ~(AES_BLOCK_SIZE - 1);
261 		u8 *out = walk->dst.virt.addr;
262 		u8 *in = walk->src.virt.addr;
263 
264 		ret = crypt_s390_kmc(func, param, out, in, n);
265 		BUG_ON((ret < 0) || (ret != n));
266 
267 		nbytes &= AES_BLOCK_SIZE - 1;
268 		ret = blkcipher_walk_done(desc, walk, nbytes);
269 	} while ((nbytes = walk->nbytes));
270 	memcpy(walk->iv, param, AES_BLOCK_SIZE);
271 
272 out:
273 	return ret;
274 }
275 
276 static int cbc_aes_encrypt(struct blkcipher_desc *desc,
277 			   struct scatterlist *dst, struct scatterlist *src,
278 			   unsigned int nbytes)
279 {
280 	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
281 	struct blkcipher_walk walk;
282 
283 	blkcipher_walk_init(&walk, dst, src, nbytes);
284 	return cbc_aes_crypt(desc, sctx->enc, sctx->iv, &walk);
285 }
286 
287 static int cbc_aes_decrypt(struct blkcipher_desc *desc,
288 			   struct scatterlist *dst, struct scatterlist *src,
289 			   unsigned int nbytes)
290 {
291 	struct s390_aes_ctx *sctx = crypto_blkcipher_ctx(desc->tfm);
292 	struct blkcipher_walk walk;
293 
294 	blkcipher_walk_init(&walk, dst, src, nbytes);
295 	return cbc_aes_crypt(desc, sctx->dec, sctx->iv, &walk);
296 }
297 
298 static struct crypto_alg cbc_aes_alg = {
299 	.cra_name		=	"cbc(aes)",
300 	.cra_driver_name	=	"cbc-aes-s390",
301 	.cra_priority		=	CRYPT_S390_COMPOSITE_PRIORITY,
302 	.cra_flags		=	CRYPTO_ALG_TYPE_BLKCIPHER,
303 	.cra_blocksize		=	AES_BLOCK_SIZE,
304 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
305 	.cra_type		=	&crypto_blkcipher_type,
306 	.cra_module		=	THIS_MODULE,
307 	.cra_list		=	LIST_HEAD_INIT(cbc_aes_alg.cra_list),
308 	.cra_u			=	{
309 		.blkcipher = {
310 			.min_keysize		=	AES_MIN_KEY_SIZE,
311 			.max_keysize		=	AES_MAX_KEY_SIZE,
312 			.ivsize			=	AES_BLOCK_SIZE,
313 			.setkey			=	cbc_aes_set_key,
314 			.encrypt		=	cbc_aes_encrypt,
315 			.decrypt		=	cbc_aes_decrypt,
316 		}
317 	}
318 };
319 
320 static int __init aes_init(void)
321 {
322 	int ret;
323 
324 	if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
325 		has_aes_128 = 1;
326 	if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
327 		has_aes_192 = 1;
328 	if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
329 		has_aes_256 = 1;
330 
331 	if (!has_aes_128 && !has_aes_192 && !has_aes_256)
332 		return -ENOSYS;
333 
334 	ret = crypto_register_alg(&aes_alg);
335 	if (ret != 0) {
336 		printk(KERN_INFO "crypt_s390: aes-s390 couldn't be loaded.\n");
337 		goto aes_err;
338 	}
339 
340 	ret = crypto_register_alg(&ecb_aes_alg);
341 	if (ret != 0) {
342 		printk(KERN_INFO
343 		       "crypt_s390: ecb-aes-s390 couldn't be loaded.\n");
344 		goto ecb_aes_err;
345 	}
346 
347 	ret = crypto_register_alg(&cbc_aes_alg);
348 	if (ret != 0) {
349 		printk(KERN_INFO
350 		       "crypt_s390: cbc-aes-s390 couldn't be loaded.\n");
351 		goto cbc_aes_err;
352 	}
353 
354 out:
355 	return ret;
356 
357 cbc_aes_err:
358 	crypto_unregister_alg(&ecb_aes_alg);
359 ecb_aes_err:
360 	crypto_unregister_alg(&aes_alg);
361 aes_err:
362 	goto out;
363 }
364 
365 static void __exit aes_fini(void)
366 {
367 	crypto_unregister_alg(&cbc_aes_alg);
368 	crypto_unregister_alg(&ecb_aes_alg);
369 	crypto_unregister_alg(&aes_alg);
370 }
371 
372 module_init(aes_init);
373 module_exit(aes_fini);
374 
375 MODULE_ALIAS("aes");
376 
377 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
378 MODULE_LICENSE("GPL");
379 
380