aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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
-rw-r--r--crypto/Kconfig20
6 files changed, 308 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
diff --git a/crypto/Kconfig b/crypto/Kconfig
index 9fdab742b10f..c696f7ab729e 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -215,6 +215,26 @@ config CRYPTO_AES_X86_64
215 215
216 See <http://csrc.nist.gov/encryption/aes/> for more information. 216 See <http://csrc.nist.gov/encryption/aes/> for more information.
217 217
218config CRYPTO_AES_S390
219 tristate "AES cipher algorithms (s390)"
220 depends on CRYPTO && ARCH_S390
221 help
222 This is the s390 hardware accelerated implementation of the
223 AES cipher algorithms (FIPS-197). AES uses the Rijndael
224 algorithm.
225
226 Rijndael appears to be consistently a very good performer in
227 both hardware and software across a wide range of computing
228 environments regardless of its use in feedback or non-feedback
229 modes. Its key setup time is excellent, and its key agility is
230 good. Rijndael's very low memory requirements make it very well
231 suited for restricted-space environments, in which it also
232 demonstrates excellent performance. Rijndael's operations are
233 among the easiest to defend against power and timing attacks.
234
235 On s390 the System z9-109 currently only supports the key size
236 of 128 bit.
237
218config CRYPTO_CAST5 238config CRYPTO_CAST5
219 tristate "CAST5 (CAST-128) cipher algorithm" 239 tristate "CAST5 (CAST-128) cipher algorithm"
220 depends on CRYPTO 240 depends on CRYPTO