aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorJan Glauber <jan.glauber@de.ibm.com>2006-01-06 03:19:18 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-06 11:33:50 -0500
commitbf754ae8ef8bc443c067601d9401103e4001e7c5 (patch)
tree4241bc75205a638006f40f577e99430099bbe53e /arch/s390
parent0a497c17fee428604e06320272ff74415eacdc31 (diff)
[PATCH] s390: aes support
Add support for the hardware accelerated AES crypto algorithm. Signed-off-by: Jan Glauber <jan.glauber@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/crypto/Makefile1
-rw-r--r--arch/s390/crypto/aes_s390.c248
-rw-r--r--arch/s390/crypto/crypt_s390.h40
-rw-r--r--arch/s390/crypto/crypt_s390_query.c12
-rw-r--r--arch/s390/defconfig1
5 files changed, 288 insertions, 14 deletions
diff --git a/arch/s390/crypto/Makefile b/arch/s390/crypto/Makefile
index 3fccf61ee1d1..bfe2541dc5cf 100644
--- a/arch/s390/crypto/Makefile
+++ b/arch/s390/crypto/Makefile
@@ -5,5 +5,6 @@
5obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o 5obj-$(CONFIG_CRYPTO_SHA1_S390) += sha1_s390.o
6obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o 6obj-$(CONFIG_CRYPTO_SHA256_S390) += sha256_s390.o
7obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o 7obj-$(CONFIG_CRYPTO_DES_S390) += des_s390.o des_check_key.o
8obj-$(CONFIG_CRYPTO_AES_S390) += aes_s390.o
8 9
9obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o 10obj-$(CONFIG_CRYPTO_TEST) += crypt_s390_query.o
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
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h
index b70a410ac311..d6712cfa6def 100644
--- a/arch/s390/crypto/crypt_s390.h
+++ b/arch/s390/crypto/crypt_s390.h
@@ -33,26 +33,38 @@ enum crypt_s390_operations {
33 * 0x80 is the decipher modifier bit 33 * 0x80 is the decipher modifier bit
34 */ 34 */
35enum crypt_s390_km_func { 35enum crypt_s390_km_func {
36 KM_QUERY = CRYPT_S390_KM | 0, 36 KM_QUERY = CRYPT_S390_KM | 0x0,
37 KM_DEA_ENCRYPT = CRYPT_S390_KM | 1, 37 KM_DEA_ENCRYPT = CRYPT_S390_KM | 0x1,
38 KM_DEA_DECRYPT = CRYPT_S390_KM | 1 | 0x80, 38 KM_DEA_DECRYPT = CRYPT_S390_KM | 0x1 | 0x80,
39 KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 2, 39 KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2,
40 KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 2 | 0x80, 40 KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80,
41 KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 3, 41 KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3,
42 KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 3 | 0x80, 42 KM_TDEA_192_DECRYPT = CRYPT_S390_KM | 0x3 | 0x80,
43 KM_AES_128_ENCRYPT = CRYPT_S390_KM | 0x12,
44 KM_AES_128_DECRYPT = CRYPT_S390_KM | 0x12 | 0x80,
45 KM_AES_192_ENCRYPT = CRYPT_S390_KM | 0x13,
46 KM_AES_192_DECRYPT = CRYPT_S390_KM | 0x13 | 0x80,
47 KM_AES_256_ENCRYPT = CRYPT_S390_KM | 0x14,
48 KM_AES_256_DECRYPT = CRYPT_S390_KM | 0x14 | 0x80,
43}; 49};
44 50
45/* function codes for KMC (CIPHER MESSAGE WITH CHAINING) 51/* function codes for KMC (CIPHER MESSAGE WITH CHAINING)
46 * instruction 52 * instruction
47 */ 53 */
48enum crypt_s390_kmc_func { 54enum crypt_s390_kmc_func {
49 KMC_QUERY = CRYPT_S390_KMC | 0, 55 KMC_QUERY = CRYPT_S390_KMC | 0x0,
50 KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 1, 56 KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 0x1,
51 KMC_DEA_DECRYPT = CRYPT_S390_KMC | 1 | 0x80, 57 KMC_DEA_DECRYPT = CRYPT_S390_KMC | 0x1 | 0x80,
52 KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 2, 58 KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2,
53 KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 2 | 0x80, 59 KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80,
54 KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 3, 60 KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3,
55 KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 3 | 0x80, 61 KMC_TDEA_192_DECRYPT = CRYPT_S390_KMC | 0x3 | 0x80,
62 KMC_AES_128_ENCRYPT = CRYPT_S390_KMC | 0x12,
63 KMC_AES_128_DECRYPT = CRYPT_S390_KMC | 0x12 | 0x80,
64 KMC_AES_192_ENCRYPT = CRYPT_S390_KMC | 0x13,
65 KMC_AES_192_DECRYPT = CRYPT_S390_KMC | 0x13 | 0x80,
66 KMC_AES_256_ENCRYPT = CRYPT_S390_KMC | 0x14,
67 KMC_AES_256_DECRYPT = CRYPT_S390_KMC | 0x14 | 0x80,
56}; 68};
57 69
58/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) 70/* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
diff --git a/arch/s390/crypto/crypt_s390_query.c b/arch/s390/crypto/crypt_s390_query.c
index 67081b81a4a3..def02bdc44a4 100644
--- a/arch/s390/crypto/crypt_s390_query.c
+++ b/arch/s390/crypto/crypt_s390_query.c
@@ -32,6 +32,12 @@ static void query_available_functions(void)
32 crypt_s390_func_available(KM_TDEA_128_ENCRYPT)); 32 crypt_s390_func_available(KM_TDEA_128_ENCRYPT));
33 printk(KERN_INFO "KM_TDEA_192: %d\n", 33 printk(KERN_INFO "KM_TDEA_192: %d\n",
34 crypt_s390_func_available(KM_TDEA_192_ENCRYPT)); 34 crypt_s390_func_available(KM_TDEA_192_ENCRYPT));
35 printk(KERN_INFO "KM_AES_128: %d\n",
36 crypt_s390_func_available(KM_AES_128_ENCRYPT));
37 printk(KERN_INFO "KM_AES_192: %d\n",
38 crypt_s390_func_available(KM_AES_192_ENCRYPT));
39 printk(KERN_INFO "KM_AES_256: %d\n",
40 crypt_s390_func_available(KM_AES_256_ENCRYPT));
35 41
36 /* query available KMC functions */ 42 /* query available KMC functions */
37 printk(KERN_INFO "KMC_QUERY: %d\n", 43 printk(KERN_INFO "KMC_QUERY: %d\n",
@@ -42,6 +48,12 @@ static void query_available_functions(void)
42 crypt_s390_func_available(KMC_TDEA_128_ENCRYPT)); 48 crypt_s390_func_available(KMC_TDEA_128_ENCRYPT));
43 printk(KERN_INFO "KMC_TDEA_192: %d\n", 49 printk(KERN_INFO "KMC_TDEA_192: %d\n",
44 crypt_s390_func_available(KMC_TDEA_192_ENCRYPT)); 50 crypt_s390_func_available(KMC_TDEA_192_ENCRYPT));
51 printk(KERN_INFO "KMC_AES_128: %d\n",
52 crypt_s390_func_available(KMC_AES_128_ENCRYPT));
53 printk(KERN_INFO "KMC_AES_192: %d\n",
54 crypt_s390_func_available(KMC_AES_192_ENCRYPT));
55 printk(KERN_INFO "KMC_AES_256: %d\n",
56 crypt_s390_func_available(KMC_AES_256_ENCRYPT));
45 57
46 /* query available KIMD fucntions */ 58 /* query available KIMD fucntions */
47 printk(KERN_INFO "KIMD_QUERY: %d\n", 59 printk(KERN_INFO "KIMD_QUERY: %d\n",
diff --git a/arch/s390/defconfig b/arch/s390/defconfig
index fd00a9f53d53..f195c7ea1d7b 100644
--- a/arch/s390/defconfig
+++ b/arch/s390/defconfig
@@ -644,6 +644,7 @@ CONFIG_CRYPTO=y
644# CONFIG_CRYPTO_TWOFISH is not set 644# CONFIG_CRYPTO_TWOFISH is not set
645# CONFIG_CRYPTO_SERPENT is not set 645# CONFIG_CRYPTO_SERPENT is not set
646# CONFIG_CRYPTO_AES is not set 646# CONFIG_CRYPTO_AES is not set
647# CONFIG_CRYPTO_AES_S390 is not set
647# CONFIG_CRYPTO_CAST5 is not set 648# CONFIG_CRYPTO_CAST5 is not set
648# CONFIG_CRYPTO_CAST6 is not set 649# CONFIG_CRYPTO_CAST6 is not set
649# CONFIG_CRYPTO_TEA is not set 650# CONFIG_CRYPTO_TEA is not set