blob: c7c43c9de0d90c0722a3dfcb02f6bf16e68e5785 [file] [log] [blame]
Jan Glauberbf754ae2006-01-06 00:19:18 -08001/*
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
30int has_aes_128 = 0;
31int has_aes_192 = 0;
32int has_aes_256 = 0;
33
34struct s390_aes_ctx {
35 u8 iv[AES_BLOCK_SIZE];
36 u8 key[AES_MAX_KEY_SIZE];
37 int key_len;
38};
39
Herbert Xu6c2bb982006-05-16 22:09:29 +100040static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key,
Herbert Xu560c06a2006-08-13 14:16:39 +100041 unsigned int key_len)
Jan Glauberbf754ae2006-01-06 00:19:18 -080042{
Herbert Xu6c2bb982006-05-16 22:09:29 +100043 struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
Herbert Xu560c06a2006-08-13 14:16:39 +100044 u32 *flags = &tfm->crt_flags;
Jan Glauberbf754ae2006-01-06 00:19:18 -080045
46 switch (key_len) {
47 case 16:
48 if (!has_aes_128)
49 goto fail;
50 break;
51 case 24:
52 if (!has_aes_192)
53 goto fail;
54
55 break;
56 case 32:
57 if (!has_aes_256)
58 goto fail;
59 break;
60 default:
61 /* invalid key length */
62 goto fail;
63 break;
64 }
65
66 sctx->key_len = key_len;
67 memcpy(sctx->key, in_key, key_len);
68 return 0;
69fail:
70 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
71 return -EINVAL;
72}
73
Herbert Xu6c2bb982006-05-16 22:09:29 +100074static void aes_encrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
Jan Glauberbf754ae2006-01-06 00:19:18 -080075{
Herbert Xu6c2bb982006-05-16 22:09:29 +100076 const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
Jan Glauberbf754ae2006-01-06 00:19:18 -080077
78 switch (sctx->key_len) {
79 case 16:
80 crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in,
81 AES_BLOCK_SIZE);
82 break;
83 case 24:
84 crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in,
85 AES_BLOCK_SIZE);
86 break;
87 case 32:
88 crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in,
89 AES_BLOCK_SIZE);
90 break;
91 }
92}
93
Herbert Xu6c2bb982006-05-16 22:09:29 +100094static void aes_decrypt(struct crypto_tfm *tfm, u8 *out, const u8 *in)
Jan Glauberbf754ae2006-01-06 00:19:18 -080095{
Herbert Xu6c2bb982006-05-16 22:09:29 +100096 const struct s390_aes_ctx *sctx = crypto_tfm_ctx(tfm);
Jan Glauberbf754ae2006-01-06 00:19:18 -080097
98 switch (sctx->key_len) {
99 case 16:
100 crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in,
101 AES_BLOCK_SIZE);
102 break;
103 case 24:
104 crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in,
105 AES_BLOCK_SIZE);
106 break;
107 case 32:
108 crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in,
109 AES_BLOCK_SIZE);
110 break;
111 }
112}
113
114static unsigned int aes_encrypt_ecb(const struct cipher_desc *desc, u8 *out,
115 const u8 *in, unsigned int nbytes)
116{
117 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
Jan Glauberfda5e1422006-01-14 13:20:55 -0800118 int ret;
119
120 /* only use complete blocks */
121 nbytes &= ~(AES_BLOCK_SIZE - 1);
Jan Glauberbf754ae2006-01-06 00:19:18 -0800122
123 switch (sctx->key_len) {
124 case 16:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800125 ret = crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
126 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800127 break;
128 case 24:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800129 ret = crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
130 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800131 break;
132 case 32:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800133 ret = crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
134 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800135 break;
136 }
Jan Glauberfda5e1422006-01-14 13:20:55 -0800137 return nbytes;
Jan Glauberbf754ae2006-01-06 00:19:18 -0800138}
139
140static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
141 const u8 *in, unsigned int nbytes)
142{
143 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
Jan Glauberfda5e1422006-01-14 13:20:55 -0800144 int ret;
145
146 /* only use complete blocks */
147 nbytes &= ~(AES_BLOCK_SIZE - 1);
Jan Glauberbf754ae2006-01-06 00:19:18 -0800148
149 switch (sctx->key_len) {
150 case 16:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800151 ret = crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes);
152 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800153 break;
154 case 24:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800155 ret = crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes);
156 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800157 break;
158 case 32:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800159 ret = crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes);
160 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800161 break;
162 }
Jan Glauberfda5e1422006-01-14 13:20:55 -0800163 return nbytes;
Jan Glauberbf754ae2006-01-06 00:19:18 -0800164}
165
166static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
167 const u8 *in, unsigned int nbytes)
168{
169 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
Jan Glauberfda5e1422006-01-14 13:20:55 -0800170 int ret;
171
172 /* only use complete blocks */
173 nbytes &= ~(AES_BLOCK_SIZE - 1);
Jan Glauberbf754ae2006-01-06 00:19:18 -0800174
175 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
176 switch (sctx->key_len) {
177 case 16:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800178 ret = crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
179 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800180 break;
181 case 24:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800182 ret = crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
183 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800184 break;
185 case 32:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800186 ret = crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
187 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800188 break;
189 }
190 memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
191
Jan Glauberfda5e1422006-01-14 13:20:55 -0800192 return nbytes;
Jan Glauberbf754ae2006-01-06 00:19:18 -0800193}
194
195static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
196 const u8 *in, unsigned int nbytes)
197{
198 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
Jan Glauberfda5e1422006-01-14 13:20:55 -0800199 int ret;
200
201 /* only use complete blocks */
202 nbytes &= ~(AES_BLOCK_SIZE - 1);
Jan Glauberbf754ae2006-01-06 00:19:18 -0800203
204 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
205 switch (sctx->key_len) {
206 case 16:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800207 ret = crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes);
208 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800209 break;
210 case 24:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800211 ret = crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes);
212 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800213 break;
214 case 32:
Jan Glauberfda5e1422006-01-14 13:20:55 -0800215 ret = crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes);
216 BUG_ON((ret < 0) || (ret != nbytes));
Jan Glauberbf754ae2006-01-06 00:19:18 -0800217 break;
218 }
Jan Glauberfda5e1422006-01-14 13:20:55 -0800219 return nbytes;
Jan Glauberbf754ae2006-01-06 00:19:18 -0800220}
221
222
223static struct crypto_alg aes_alg = {
224 .cra_name = "aes",
225 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
226 .cra_blocksize = AES_BLOCK_SIZE,
227 .cra_ctxsize = sizeof(struct s390_aes_ctx),
228 .cra_module = THIS_MODULE,
229 .cra_list = LIST_HEAD_INIT(aes_alg.cra_list),
230 .cra_u = {
231 .cipher = {
232 .cia_min_keysize = AES_MIN_KEY_SIZE,
233 .cia_max_keysize = AES_MAX_KEY_SIZE,
234 .cia_setkey = aes_set_key,
235 .cia_encrypt = aes_encrypt,
236 .cia_decrypt = aes_decrypt,
237 .cia_encrypt_ecb = aes_encrypt_ecb,
238 .cia_decrypt_ecb = aes_decrypt_ecb,
239 .cia_encrypt_cbc = aes_encrypt_cbc,
240 .cia_decrypt_cbc = aes_decrypt_cbc,
241 }
242 }
243};
244
245static int __init aes_init(void)
246{
247 int ret;
248
249 if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
250 has_aes_128 = 1;
251 if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
252 has_aes_192 = 1;
253 if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
254 has_aes_256 = 1;
255
256 if (!has_aes_128 && !has_aes_192 && !has_aes_256)
257 return -ENOSYS;
258
259 ret = crypto_register_alg(&aes_alg);
260 if (ret != 0)
261 printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n");
262 return ret;
263}
264
265static void __exit aes_fini(void)
266{
267 crypto_unregister_alg(&aes_alg);
268}
269
270module_init(aes_init);
271module_exit(aes_fini);
272
273MODULE_ALIAS("aes");
274
275MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
276MODULE_LICENSE("GPL");
277