Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * Cryptographic API. | |
3 | * | |
c1e26e1e | 4 | * s390 implementation of the DES Cipher Algorithm. |
1da177e4 LT |
5 | * |
6 | * Copyright (c) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation | |
7 | * Author(s): Thomas Spatzier (tspat@de.ibm.com) | |
8 | * | |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2 of the License, or | |
13 | * (at your option) any later version. | |
14 | * | |
15 | */ | |
16 | #include <linux/init.h> | |
17 | #include <linux/module.h> | |
18 | #include <linux/mm.h> | |
19 | #include <linux/errno.h> | |
20 | #include <asm/scatterlist.h> | |
21 | #include <linux/crypto.h> | |
c1e26e1e | 22 | #include "crypt_s390.h" |
1da177e4 LT |
23 | #include "crypto_des.h" |
24 | ||
25 | #define DES_BLOCK_SIZE 8 | |
26 | #define DES_KEY_SIZE 8 | |
27 | ||
28 | #define DES3_128_KEY_SIZE (2 * DES_KEY_SIZE) | |
29 | #define DES3_128_BLOCK_SIZE DES_BLOCK_SIZE | |
30 | ||
31 | #define DES3_192_KEY_SIZE (3 * DES_KEY_SIZE) | |
32 | #define DES3_192_BLOCK_SIZE DES_BLOCK_SIZE | |
33 | ||
c1e26e1e | 34 | struct crypt_s390_des_ctx { |
1da177e4 LT |
35 | u8 iv[DES_BLOCK_SIZE]; |
36 | u8 key[DES_KEY_SIZE]; | |
37 | }; | |
38 | ||
c1e26e1e | 39 | struct crypt_s390_des3_128_ctx { |
1da177e4 LT |
40 | u8 iv[DES_BLOCK_SIZE]; |
41 | u8 key[DES3_128_KEY_SIZE]; | |
42 | }; | |
43 | ||
c1e26e1e | 44 | struct crypt_s390_des3_192_ctx { |
1da177e4 LT |
45 | u8 iv[DES_BLOCK_SIZE]; |
46 | u8 key[DES3_192_KEY_SIZE]; | |
47 | }; | |
48 | ||
49 | static int | |
50 | des_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) | |
51 | { | |
c1e26e1e | 52 | struct crypt_s390_des_ctx *dctx; |
1da177e4 LT |
53 | int ret; |
54 | ||
55 | dctx = ctx; | |
56 | //test if key is valid (not a weak key) | |
57 | ret = crypto_des_check_key(key, keylen, flags); | |
58 | if (ret == 0){ | |
59 | memcpy(dctx->key, key, keylen); | |
60 | } | |
61 | return ret; | |
62 | } | |
63 | ||
64 | ||
65 | static void | |
66 | des_encrypt(void *ctx, u8 *dst, const u8 *src) | |
67 | { | |
c1e26e1e | 68 | struct crypt_s390_des_ctx *dctx; |
1da177e4 LT |
69 | |
70 | dctx = ctx; | |
c1e26e1e | 71 | crypt_s390_km(KM_DEA_ENCRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); |
1da177e4 LT |
72 | } |
73 | ||
74 | static void | |
75 | des_decrypt(void *ctx, u8 *dst, const u8 *src) | |
76 | { | |
c1e26e1e | 77 | struct crypt_s390_des_ctx *dctx; |
1da177e4 LT |
78 | |
79 | dctx = ctx; | |
c1e26e1e | 80 | crypt_s390_km(KM_DEA_DECRYPT, dctx->key, dst, src, DES_BLOCK_SIZE); |
1da177e4 LT |
81 | } |
82 | ||
83 | static struct crypto_alg des_alg = { | |
84 | .cra_name = "des", | |
85 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, | |
86 | .cra_blocksize = DES_BLOCK_SIZE, | |
c1e26e1e | 87 | .cra_ctxsize = sizeof(struct crypt_s390_des_ctx), |
1da177e4 LT |
88 | .cra_module = THIS_MODULE, |
89 | .cra_list = LIST_HEAD_INIT(des_alg.cra_list), | |
90 | .cra_u = { .cipher = { | |
91 | .cia_min_keysize = DES_KEY_SIZE, | |
92 | .cia_max_keysize = DES_KEY_SIZE, | |
93 | .cia_setkey = des_setkey, | |
94 | .cia_encrypt = des_encrypt, | |
95 | .cia_decrypt = des_decrypt } } | |
96 | }; | |
97 | ||
98 | /* | |
99 | * RFC2451: | |
100 | * | |
101 | * For DES-EDE3, there is no known need to reject weak or | |
102 | * complementation keys. Any weakness is obviated by the use of | |
103 | * multiple keys. | |
104 | * | |
105 | * However, if the two independent 64-bit keys are equal, | |
106 | * then the DES3 operation is simply the same as DES. | |
107 | * Implementers MUST reject keys that exhibit this property. | |
108 | * | |
109 | */ | |
110 | static int | |
111 | des3_128_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) | |
112 | { | |
113 | int i, ret; | |
c1e26e1e | 114 | struct crypt_s390_des3_128_ctx *dctx; |
1da177e4 LT |
115 | const u8* temp_key = key; |
116 | ||
117 | dctx = ctx; | |
118 | if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE))) { | |
119 | ||
120 | *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; | |
121 | return -EINVAL; | |
122 | } | |
123 | for (i = 0; i < 2; i++, temp_key += DES_KEY_SIZE) { | |
124 | ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); | |
125 | if (ret < 0) | |
126 | return ret; | |
127 | } | |
128 | memcpy(dctx->key, key, keylen); | |
129 | return 0; | |
130 | } | |
131 | ||
132 | static void | |
133 | des3_128_encrypt(void *ctx, u8 *dst, const u8 *src) | |
134 | { | |
c1e26e1e | 135 | struct crypt_s390_des3_128_ctx *dctx; |
1da177e4 LT |
136 | |
137 | dctx = ctx; | |
c1e26e1e | 138 | crypt_s390_km(KM_TDEA_128_ENCRYPT, dctx->key, dst, (void*)src, |
1da177e4 LT |
139 | DES3_128_BLOCK_SIZE); |
140 | } | |
141 | ||
142 | static void | |
143 | des3_128_decrypt(void *ctx, u8 *dst, const u8 *src) | |
144 | { | |
c1e26e1e | 145 | struct crypt_s390_des3_128_ctx *dctx; |
1da177e4 LT |
146 | |
147 | dctx = ctx; | |
c1e26e1e | 148 | crypt_s390_km(KM_TDEA_128_DECRYPT, dctx->key, dst, (void*)src, |
1da177e4 LT |
149 | DES3_128_BLOCK_SIZE); |
150 | } | |
151 | ||
152 | static struct crypto_alg des3_128_alg = { | |
153 | .cra_name = "des3_ede128", | |
154 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, | |
155 | .cra_blocksize = DES3_128_BLOCK_SIZE, | |
c1e26e1e | 156 | .cra_ctxsize = sizeof(struct crypt_s390_des3_128_ctx), |
1da177e4 LT |
157 | .cra_module = THIS_MODULE, |
158 | .cra_list = LIST_HEAD_INIT(des3_128_alg.cra_list), | |
159 | .cra_u = { .cipher = { | |
160 | .cia_min_keysize = DES3_128_KEY_SIZE, | |
161 | .cia_max_keysize = DES3_128_KEY_SIZE, | |
162 | .cia_setkey = des3_128_setkey, | |
163 | .cia_encrypt = des3_128_encrypt, | |
164 | .cia_decrypt = des3_128_decrypt } } | |
165 | }; | |
166 | ||
167 | /* | |
168 | * RFC2451: | |
169 | * | |
170 | * For DES-EDE3, there is no known need to reject weak or | |
171 | * complementation keys. Any weakness is obviated by the use of | |
172 | * multiple keys. | |
173 | * | |
174 | * However, if the first two or last two independent 64-bit keys are | |
175 | * equal (k1 == k2 or k2 == k3), then the DES3 operation is simply the | |
176 | * same as DES. Implementers MUST reject keys that exhibit this | |
177 | * property. | |
178 | * | |
179 | */ | |
180 | static int | |
181 | des3_192_setkey(void *ctx, const u8 *key, unsigned int keylen, u32 *flags) | |
182 | { | |
183 | int i, ret; | |
c1e26e1e | 184 | struct crypt_s390_des3_192_ctx *dctx; |
1da177e4 LT |
185 | const u8* temp_key; |
186 | ||
187 | dctx = ctx; | |
188 | temp_key = key; | |
189 | if (!(memcmp(key, &key[DES_KEY_SIZE], DES_KEY_SIZE) && | |
190 | memcmp(&key[DES_KEY_SIZE], &key[DES_KEY_SIZE * 2], | |
191 | DES_KEY_SIZE))) { | |
192 | ||
193 | *flags |= CRYPTO_TFM_RES_BAD_KEY_SCHED; | |
194 | return -EINVAL; | |
195 | } | |
196 | for (i = 0; i < 3; i++, temp_key += DES_KEY_SIZE) { | |
197 | ret = crypto_des_check_key(temp_key, DES_KEY_SIZE, flags); | |
198 | if (ret < 0){ | |
199 | return ret; | |
200 | } | |
201 | } | |
202 | memcpy(dctx->key, key, keylen); | |
203 | return 0; | |
204 | } | |
205 | ||
206 | static void | |
207 | des3_192_encrypt(void *ctx, u8 *dst, const u8 *src) | |
208 | { | |
c1e26e1e | 209 | struct crypt_s390_des3_192_ctx *dctx; |
1da177e4 LT |
210 | |
211 | dctx = ctx; | |
c1e26e1e | 212 | crypt_s390_km(KM_TDEA_192_ENCRYPT, dctx->key, dst, (void*)src, |
1da177e4 LT |
213 | DES3_192_BLOCK_SIZE); |
214 | } | |
215 | ||
216 | static void | |
217 | des3_192_decrypt(void *ctx, u8 *dst, const u8 *src) | |
218 | { | |
c1e26e1e | 219 | struct crypt_s390_des3_192_ctx *dctx; |
1da177e4 LT |
220 | |
221 | dctx = ctx; | |
c1e26e1e | 222 | crypt_s390_km(KM_TDEA_192_DECRYPT, dctx->key, dst, (void*)src, |
1da177e4 LT |
223 | DES3_192_BLOCK_SIZE); |
224 | } | |
225 | ||
226 | static struct crypto_alg des3_192_alg = { | |
227 | .cra_name = "des3_ede", | |
228 | .cra_flags = CRYPTO_ALG_TYPE_CIPHER, | |
229 | .cra_blocksize = DES3_192_BLOCK_SIZE, | |
c1e26e1e | 230 | .cra_ctxsize = sizeof(struct crypt_s390_des3_192_ctx), |
1da177e4 LT |
231 | .cra_module = THIS_MODULE, |
232 | .cra_list = LIST_HEAD_INIT(des3_192_alg.cra_list), | |
233 | .cra_u = { .cipher = { | |
234 | .cia_min_keysize = DES3_192_KEY_SIZE, | |
235 | .cia_max_keysize = DES3_192_KEY_SIZE, | |
236 | .cia_setkey = des3_192_setkey, | |
237 | .cia_encrypt = des3_192_encrypt, | |
238 | .cia_decrypt = des3_192_decrypt } } | |
239 | }; | |
240 | ||
241 | ||
242 | ||
243 | static int | |
244 | init(void) | |
245 | { | |
246 | int ret; | |
247 | ||
c1e26e1e JG |
248 | if (!crypt_s390_func_available(KM_DEA_ENCRYPT) || |
249 | !crypt_s390_func_available(KM_TDEA_128_ENCRYPT) || | |
250 | !crypt_s390_func_available(KM_TDEA_192_ENCRYPT)){ | |
1da177e4 LT |
251 | return -ENOSYS; |
252 | } | |
253 | ||
254 | ret = 0; | |
255 | ret |= (crypto_register_alg(&des_alg) == 0)? 0:1; | |
256 | ret |= (crypto_register_alg(&des3_128_alg) == 0)? 0:2; | |
257 | ret |= (crypto_register_alg(&des3_192_alg) == 0)? 0:4; | |
258 | if (ret){ | |
259 | crypto_unregister_alg(&des3_192_alg); | |
260 | crypto_unregister_alg(&des3_128_alg); | |
261 | crypto_unregister_alg(&des_alg); | |
262 | return -EEXIST; | |
263 | } | |
264 | ||
c1e26e1e | 265 | printk(KERN_INFO "crypt_s390: des_s390 loaded.\n"); |
1da177e4 LT |
266 | return 0; |
267 | } | |
268 | ||
269 | static void __exit | |
270 | fini(void) | |
271 | { | |
272 | crypto_unregister_alg(&des3_192_alg); | |
273 | crypto_unregister_alg(&des3_128_alg); | |
274 | crypto_unregister_alg(&des_alg); | |
275 | } | |
276 | ||
277 | module_init(init); | |
278 | module_exit(fini); | |
279 | ||
280 | MODULE_ALIAS("des"); | |
281 | MODULE_ALIAS("des3_ede"); | |
282 | ||
283 | MODULE_LICENSE("GPL"); | |
284 | MODULE_DESCRIPTION("DES & Triple DES EDE Cipher Algorithms"); |