xref: /linux/arch/s390/crypto/aes_s390.c (revision f3d9478b2ce468c3115b02ecae7e975990697f15)
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 <linux/module.h>
20 #include <linux/init.h>
21 #include <linux/crypto.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 	int key_len;
38 };
39 
40 static int aes_set_key(void *ctx, const u8 *in_key, unsigned int key_len,
41 		       u32 *flags)
42 {
43 	struct s390_aes_ctx *sctx = ctx;
44 
45 	switch (key_len) {
46 	case 16:
47 		if (!has_aes_128)
48 			goto fail;
49 		break;
50 	case 24:
51 		if (!has_aes_192)
52 			goto fail;
53 
54 		break;
55 	case 32:
56 		if (!has_aes_256)
57 			goto fail;
58 		break;
59 	default:
60 		/* invalid key length */
61 		goto fail;
62 		break;
63 	}
64 
65 	sctx->key_len = key_len;
66 	memcpy(sctx->key, in_key, key_len);
67 	return 0;
68 fail:
69 	*flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
70 	return -EINVAL;
71 }
72 
73 static void aes_encrypt(void *ctx, u8 *out, const u8 *in)
74 {
75 	const struct s390_aes_ctx *sctx = ctx;
76 
77 	switch (sctx->key_len) {
78 	case 16:
79 		crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
80 			      AES_BLOCK_SIZE);
81 		break;
82 	case 24:
83 		crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in,
84 			      AES_BLOCK_SIZE);
85 		break;
86 	case 32:
87 		crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in,
88 			      AES_BLOCK_SIZE);
89 		break;
90 	}
91 }
92 
93 static void aes_decrypt(void *ctx, u8 *out, const u8 *in)
94 {
95 	const struct s390_aes_ctx *sctx = ctx;
96 
97 	switch (sctx->key_len) {
98 	case 16:
99 		crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
100 			      AES_BLOCK_SIZE);
101 		break;
102 	case 24:
103 		crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in,
104 			      AES_BLOCK_SIZE);
105 		break;
106 	case 32:
107 		crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in,
108 			      AES_BLOCK_SIZE);
109 		break;
110 	}
111 }
112 
113 static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
114 				    const u8 *in, unsigned int nbytes)
115 {
116 	struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
117 	int ret;
118 
119 	/* only use complete blocks */
120 	nbytes &= ~(AES_BLOCK_SIZE - 1);
121 
122 	switch (sctx->key_len) {
123 	case 16:
124 		ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
125 		BUG_ON((ret < 0) || (ret != nbytes));
126 		break;
127 	case 24:
128 		ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
129 		BUG_ON((ret < 0) || (ret != nbytes));
130 		break;
131 	case 32:
132 		ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
133 		BUG_ON((ret < 0) || (ret != nbytes));
134 		break;
135 	}
136 	return nbytes;
137 }
138 
139 static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
140 				    const u8 *in, unsigned int nbytes)
141 {
142 	struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
143 	int ret;
144 
145 	/* only use complete blocks */
146 	nbytes &= ~(AES_BLOCK_SIZE - 1);
147 
148 	switch (sctx->key_len) {
149 	case 16:
150 		ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes);
151 		BUG_ON((ret < 0) || (ret != nbytes));
152 		break;
153 	case 24:
154 		ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes);
155 		BUG_ON((ret < 0) || (ret != nbytes));
156 		break;
157 	case 32:
158 		ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes);
159 		BUG_ON((ret < 0) || (ret != nbytes));
160 		break;
161 	}
162 	return nbytes;
163 }
164 
165 static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
166 				    const u8 *in, unsigned int nbytes)
167 {
168 	struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
169 	int ret;
170 
171 	/* only use complete blocks */
172 	nbytes &= ~(AES_BLOCK_SIZE - 1);
173 
174 	memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
175 	switch (sctx->key_len) {
176 	case 16:
177 		ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
178 		BUG_ON((ret < 0) || (ret != nbytes));
179 		break;
180 	case 24:
181 		ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
182 		BUG_ON((ret < 0) || (ret != nbytes));
183 		break;
184 	case 32:
185 		ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
186 		BUG_ON((ret < 0) || (ret != nbytes));
187 		break;
188 	}
189 	memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
190 
191 	return nbytes;
192 }
193 
194 static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
195 				    const u8 *in, unsigned int nbytes)
196 {
197 	struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
198 	int ret;
199 
200 	/* only use complete blocks */
201 	nbytes &= ~(AES_BLOCK_SIZE - 1);
202 
203 	memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
204 	switch (sctx->key_len) {
205 	case 16:
206 		ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes);
207 		BUG_ON((ret < 0) || (ret != nbytes));
208 		break;
209 	case 24:
210 		ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes);
211 		BUG_ON((ret < 0) || (ret != nbytes));
212 		break;
213 	case 32:
214 		ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes);
215 		BUG_ON((ret < 0) || (ret != nbytes));
216 		break;
217 	}
218 	return nbytes;
219 }
220 
221 
222 static struct crypto_alg aes_alg = {
223 	.cra_name		=	"aes",
224 	.cra_flags		=	CRYPTO_ALG_TYPE_CIPHER,
225 	.cra_blocksize		=	AES_BLOCK_SIZE,
226 	.cra_ctxsize		=	sizeof(struct s390_aes_ctx),
227 	.cra_module		=	THIS_MODULE,
228 	.cra_list		=	LIST_HEAD_INIT(aes_alg.cra_list),
229 	.cra_u			=	{
230 		.cipher = {
231 			.cia_min_keysize	=	AES_MIN_KEY_SIZE,
232 			.cia_max_keysize	=	AES_MAX_KEY_SIZE,
233 			.cia_setkey		=	aes_set_key,
234 			.cia_encrypt		=	aes_encrypt,
235 			.cia_decrypt		=	aes_decrypt,
236 			.cia_encrypt_ecb	=	aes_encrypt_ecb,
237 			.cia_decrypt_ecb	=	aes_decrypt_ecb,
238 			.cia_encrypt_cbc	=	aes_encrypt_cbc,
239 			.cia_decrypt_cbc	=	aes_decrypt_cbc,
240 		}
241 	}
242 };
243 
244 static int __init aes_init(void)
245 {
246 	int ret;
247 
248 	if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
249 		has_aes_128 = 1;
250 	if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
251 		has_aes_192 = 1;
252 	if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
253 		has_aes_256 = 1;
254 
255 	if (!has_aes_128 && !has_aes_192 && !has_aes_256)
256 		return -ENOSYS;
257 
258 	ret = crypto_register_alg(&aes_alg);
259 	if (ret != 0)
260 		printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n");
261 	return ret;
262 }
263 
264 static void __exit aes_fini(void)
265 {
266 	crypto_unregister_alg(&aes_alg);
267 }
268 
269 module_init(aes_init);
270 module_exit(aes_fini);
271 
272 MODULE_ALIAS("aes");
273 
274 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
275 MODULE_LICENSE("GPL");
276 
277