aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/crypto/aes_s390.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/crypto/aes_s390.c')
-rw-r--r--arch/s390/crypto/aes_s390.c248
1 files changed, 248 insertions, 0 deletions
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
new file mode 100644
index 000000000000..7a1033d8e00f
--- /dev/null
+++ b/arch/s390/crypto/aes_s390.c
@@ -0,0 +1,248 @@
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
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
40static 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;
68fail:
69 *flags |= CRYPTO_TFM_RES_BAD_KEY_LEN;
70 return -EINVAL;
71}
72
73static 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
93static 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
113static 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
118 switch (sctx->key_len) {
119 case 16:
120 crypt_s390_km(KM_AES_128_ENCRYPT, &sctx->key, out, in, nbytes);
121 break;
122 case 24:
123 crypt_s390_km(KM_AES_192_ENCRYPT, &sctx->key, out, in, nbytes);
124 break;
125 case 32:
126 crypt_s390_km(KM_AES_256_ENCRYPT, &sctx->key, out, in, nbytes);
127 break;
128 }
129 return nbytes & ~(AES_BLOCK_SIZE - 1);
130}
131
132static unsigned int aes_decrypt_ecb(const struct cipher_desc *desc, u8 *out,
133 const u8 *in, unsigned int nbytes)
134{
135 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
136
137 switch (sctx->key_len) {
138 case 16:
139 crypt_s390_km(KM_AES_128_DECRYPT, &sctx->key, out, in, nbytes);
140 break;
141 case 24:
142 crypt_s390_km(KM_AES_192_DECRYPT, &sctx->key, out, in, nbytes);
143 break;
144 case 32:
145 crypt_s390_km(KM_AES_256_DECRYPT, &sctx->key, out, in, nbytes);
146 break;
147 }
148 return nbytes & ~(AES_BLOCK_SIZE - 1);
149}
150
151static unsigned int aes_encrypt_cbc(const struct cipher_desc *desc, u8 *out,
152 const u8 *in, unsigned int nbytes)
153{
154 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
155
156 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
157 switch (sctx->key_len) {
158 case 16:
159 crypt_s390_kmc(KMC_AES_128_ENCRYPT, &sctx->iv, out, in, nbytes);
160 break;
161 case 24:
162 crypt_s390_kmc(KMC_AES_192_ENCRYPT, &sctx->iv, out, in, nbytes);
163 break;
164 case 32:
165 crypt_s390_kmc(KMC_AES_256_ENCRYPT, &sctx->iv, out, in, nbytes);
166 break;
167 }
168 memcpy(desc->info, &sctx->iv, AES_BLOCK_SIZE);
169
170 return nbytes & ~(AES_BLOCK_SIZE - 1);
171}
172
173static unsigned int aes_decrypt_cbc(const struct cipher_desc *desc, u8 *out,
174 const u8 *in, unsigned int nbytes)
175{
176 struct s390_aes_ctx *sctx = crypto_tfm_ctx(desc->tfm);
177
178 memcpy(&sctx->iv, desc->info, AES_BLOCK_SIZE);
179 switch (sctx->key_len) {
180 case 16:
181 crypt_s390_kmc(KMC_AES_128_DECRYPT, &sctx->iv, out, in, nbytes);
182 break;
183 case 24:
184 crypt_s390_kmc(KMC_AES_192_DECRYPT, &sctx->iv, out, in, nbytes);
185 break;
186 case 32:
187 crypt_s390_kmc(KMC_AES_256_DECRYPT, &sctx->iv, out, in, nbytes);
188 break;
189 }
190 return nbytes & ~(AES_BLOCK_SIZE - 1);
191}
192
193
194static struct crypto_alg aes_alg = {
195 .cra_name = "aes",
196 .cra_flags = CRYPTO_ALG_TYPE_CIPHER,
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_u = {
202 .cipher = {
203 .cia_min_keysize = AES_MIN_KEY_SIZE,
204 .cia_max_keysize = AES_MAX_KEY_SIZE,
205 .cia_setkey = aes_set_key,
206 .cia_encrypt = aes_encrypt,
207 .cia_decrypt = aes_decrypt,
208 .cia_encrypt_ecb = aes_encrypt_ecb,
209 .cia_decrypt_ecb = aes_decrypt_ecb,
210 .cia_encrypt_cbc = aes_encrypt_cbc,
211 .cia_decrypt_cbc = aes_decrypt_cbc,
212 }
213 }
214};
215
216static int __init aes_init(void)
217{
218 int ret;
219
220 if (crypt_s390_func_available(KM_AES_128_ENCRYPT))
221 has_aes_128 = 1;
222 if (crypt_s390_func_available(KM_AES_192_ENCRYPT))
223 has_aes_192 = 1;
224 if (crypt_s390_func_available(KM_AES_256_ENCRYPT))
225 has_aes_256 = 1;
226
227 if (!has_aes_128 && !has_aes_192 && !has_aes_256)
228 return -ENOSYS;
229
230 ret = crypto_register_alg(&aes_alg);
231 if (ret != 0)
232 printk(KERN_INFO "crypt_s390: aes_s390 couldn't be loaded.\n");
233 return ret;
234}
235
236static void __exit aes_fini(void)
237{
238 crypto_unregister_alg(&aes_alg);
239}
240
241module_init(aes_init);
242module_exit(aes_fini);
243
244MODULE_ALIAS("aes");
245
246MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
247MODULE_LICENSE("GPL");
248