diff options
Diffstat (limited to 'arch/s390/crypto/crypt_s390.h')
-rw-r--r-- | arch/s390/crypto/crypt_s390.h | 397 |
1 files changed, 397 insertions, 0 deletions
diff --git a/arch/s390/crypto/crypt_s390.h b/arch/s390/crypto/crypt_s390.h new file mode 100644 index 000000000000..d1c259a7fe33 --- /dev/null +++ b/arch/s390/crypto/crypt_s390.h | |||
@@ -0,0 +1,397 @@ | |||
1 | /* | ||
2 | * Cryptographic API. | ||
3 | * | ||
4 | * Support for s390 cryptographic instructions. | ||
5 | * | ||
6 | * Copyright (C) 2003 IBM Deutschland GmbH, IBM Corporation | ||
7 | * Author(s): Thomas Spatzier (tspat@de.ibm.com) | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify it | ||
10 | * under the terms of the GNU General Public License as published by the Free | ||
11 | * Software Foundation; either version 2 of the License, or (at your option) | ||
12 | * any later version. | ||
13 | * | ||
14 | */ | ||
15 | #ifndef _CRYPTO_ARCH_S390_CRYPT_S390_H | ||
16 | #define _CRYPTO_ARCH_S390_CRYPT_S390_H | ||
17 | |||
18 | #include <asm/errno.h> | ||
19 | |||
20 | #define CRYPT_S390_OP_MASK 0xFF00 | ||
21 | #define CRYPT_S390_FUNC_MASK 0x00FF | ||
22 | |||
23 | /* s930 cryptographic operations */ | ||
24 | enum crypt_s390_operations { | ||
25 | CRYPT_S390_KM = 0x0100, | ||
26 | CRYPT_S390_KMC = 0x0200, | ||
27 | CRYPT_S390_KIMD = 0x0300, | ||
28 | CRYPT_S390_KLMD = 0x0400, | ||
29 | CRYPT_S390_KMAC = 0x0500 | ||
30 | }; | ||
31 | |||
32 | /* function codes for KM (CIPHER MESSAGE) instruction | ||
33 | * 0x80 is the decipher modifier bit | ||
34 | */ | ||
35 | enum crypt_s390_km_func { | ||
36 | KM_QUERY = CRYPT_S390_KM | 0x0, | ||
37 | KM_DEA_ENCRYPT = CRYPT_S390_KM | 0x1, | ||
38 | KM_DEA_DECRYPT = CRYPT_S390_KM | 0x1 | 0x80, | ||
39 | KM_TDEA_128_ENCRYPT = CRYPT_S390_KM | 0x2, | ||
40 | KM_TDEA_128_DECRYPT = CRYPT_S390_KM | 0x2 | 0x80, | ||
41 | KM_TDEA_192_ENCRYPT = CRYPT_S390_KM | 0x3, | ||
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, | ||
49 | }; | ||
50 | |||
51 | /* function codes for KMC (CIPHER MESSAGE WITH CHAINING) | ||
52 | * instruction | ||
53 | */ | ||
54 | enum crypt_s390_kmc_func { | ||
55 | KMC_QUERY = CRYPT_S390_KMC | 0x0, | ||
56 | KMC_DEA_ENCRYPT = CRYPT_S390_KMC | 0x1, | ||
57 | KMC_DEA_DECRYPT = CRYPT_S390_KMC | 0x1 | 0x80, | ||
58 | KMC_TDEA_128_ENCRYPT = CRYPT_S390_KMC | 0x2, | ||
59 | KMC_TDEA_128_DECRYPT = CRYPT_S390_KMC | 0x2 | 0x80, | ||
60 | KMC_TDEA_192_ENCRYPT = CRYPT_S390_KMC | 0x3, | ||
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, | ||
68 | }; | ||
69 | |||
70 | /* function codes for KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) | ||
71 | * instruction | ||
72 | */ | ||
73 | enum crypt_s390_kimd_func { | ||
74 | KIMD_QUERY = CRYPT_S390_KIMD | 0, | ||
75 | KIMD_SHA_1 = CRYPT_S390_KIMD | 1, | ||
76 | KIMD_SHA_256 = CRYPT_S390_KIMD | 2, | ||
77 | }; | ||
78 | |||
79 | /* function codes for KLMD (COMPUTE LAST MESSAGE DIGEST) | ||
80 | * instruction | ||
81 | */ | ||
82 | enum crypt_s390_klmd_func { | ||
83 | KLMD_QUERY = CRYPT_S390_KLMD | 0, | ||
84 | KLMD_SHA_1 = CRYPT_S390_KLMD | 1, | ||
85 | KLMD_SHA_256 = CRYPT_S390_KLMD | 2, | ||
86 | }; | ||
87 | |||
88 | /* function codes for KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) | ||
89 | * instruction | ||
90 | */ | ||
91 | enum crypt_s390_kmac_func { | ||
92 | KMAC_QUERY = CRYPT_S390_KMAC | 0, | ||
93 | KMAC_DEA = CRYPT_S390_KMAC | 1, | ||
94 | KMAC_TDEA_128 = CRYPT_S390_KMAC | 2, | ||
95 | KMAC_TDEA_192 = CRYPT_S390_KMAC | 3 | ||
96 | }; | ||
97 | |||
98 | /* status word for s390 crypto instructions' QUERY functions */ | ||
99 | struct crypt_s390_query_status { | ||
100 | u64 high; | ||
101 | u64 low; | ||
102 | }; | ||
103 | |||
104 | /* | ||
105 | * Standard fixup and ex_table sections for crypt_s390 inline functions. | ||
106 | * label 0: the s390 crypto operation | ||
107 | * label 1: just after 1 to catch illegal operation exception | ||
108 | * (unsupported model) | ||
109 | * label 6: the return point after fixup | ||
110 | * label 7: set error value if exception _in_ crypto operation | ||
111 | * label 8: set error value if illegal operation exception | ||
112 | * [ret] is the variable to receive the error code | ||
113 | * [ERR] is the error code value | ||
114 | */ | ||
115 | #ifndef CONFIG_64BIT | ||
116 | #define __crypt_s390_fixup \ | ||
117 | ".section .fixup,\"ax\" \n" \ | ||
118 | "7: lhi %0,%h[e1] \n" \ | ||
119 | " bras 1,9f \n" \ | ||
120 | " .long 6b \n" \ | ||
121 | "8: lhi %0,%h[e2] \n" \ | ||
122 | " bras 1,9f \n" \ | ||
123 | " .long 6b \n" \ | ||
124 | "9: l 1,0(1) \n" \ | ||
125 | " br 1 \n" \ | ||
126 | ".previous \n" \ | ||
127 | ".section __ex_table,\"a\" \n" \ | ||
128 | " .align 4 \n" \ | ||
129 | " .long 0b,7b \n" \ | ||
130 | " .long 1b,8b \n" \ | ||
131 | ".previous" | ||
132 | #else /* CONFIG_64BIT */ | ||
133 | #define __crypt_s390_fixup \ | ||
134 | ".section .fixup,\"ax\" \n" \ | ||
135 | "7: lhi %0,%h[e1] \n" \ | ||
136 | " jg 6b \n" \ | ||
137 | "8: lhi %0,%h[e2] \n" \ | ||
138 | " jg 6b \n" \ | ||
139 | ".previous\n" \ | ||
140 | ".section __ex_table,\"a\" \n" \ | ||
141 | " .align 8 \n" \ | ||
142 | " .quad 0b,7b \n" \ | ||
143 | " .quad 1b,8b \n" \ | ||
144 | ".previous" | ||
145 | #endif /* CONFIG_64BIT */ | ||
146 | |||
147 | /* | ||
148 | * Standard code for setting the result of s390 crypto instructions. | ||
149 | * %0: the register which will receive the result | ||
150 | * [result]: the register containing the result (e.g. second operand length | ||
151 | * to compute number of processed bytes]. | ||
152 | */ | ||
153 | #ifndef CONFIG_64BIT | ||
154 | #define __crypt_s390_set_result \ | ||
155 | " lr %0,%[result] \n" | ||
156 | #else /* CONFIG_64BIT */ | ||
157 | #define __crypt_s390_set_result \ | ||
158 | " lgr %0,%[result] \n" | ||
159 | #endif | ||
160 | |||
161 | /* | ||
162 | * Executes the KM (CIPHER MESSAGE) operation of the CPU. | ||
163 | * @param func: the function code passed to KM; see crypt_s390_km_func | ||
164 | * @param param: address of parameter block; see POP for details on each func | ||
165 | * @param dest: address of destination memory area | ||
166 | * @param src: address of source memory area | ||
167 | * @param src_len: length of src operand in bytes | ||
168 | * @returns < zero for failure, 0 for the query func, number of processed bytes | ||
169 | * for encryption/decryption funcs | ||
170 | */ | ||
171 | static inline int | ||
172 | crypt_s390_km(long func, void* param, u8* dest, const u8* src, long src_len) | ||
173 | { | ||
174 | register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; | ||
175 | register void* __param asm("1") = param; | ||
176 | register u8* __dest asm("4") = dest; | ||
177 | register const u8* __src asm("2") = src; | ||
178 | register long __src_len asm("3") = src_len; | ||
179 | int ret; | ||
180 | |||
181 | ret = 0; | ||
182 | __asm__ __volatile__ ( | ||
183 | "0: .insn rre,0xB92E0000,%1,%2 \n" /* KM opcode */ | ||
184 | "1: brc 1,0b \n" /* handle partial completion */ | ||
185 | __crypt_s390_set_result | ||
186 | "6: \n" | ||
187 | __crypt_s390_fixup | ||
188 | : "+d" (ret), "+a" (__dest), "+a" (__src), | ||
189 | [result] "+d" (__src_len) | ||
190 | : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), | ||
191 | "a" (__param) | ||
192 | : "cc", "memory" | ||
193 | ); | ||
194 | if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ | ||
195 | ret = src_len - ret; | ||
196 | } | ||
197 | return ret; | ||
198 | } | ||
199 | |||
200 | /* | ||
201 | * Executes the KMC (CIPHER MESSAGE WITH CHAINING) operation of the CPU. | ||
202 | * @param func: the function code passed to KM; see crypt_s390_kmc_func | ||
203 | * @param param: address of parameter block; see POP for details on each func | ||
204 | * @param dest: address of destination memory area | ||
205 | * @param src: address of source memory area | ||
206 | * @param src_len: length of src operand in bytes | ||
207 | * @returns < zero for failure, 0 for the query func, number of processed bytes | ||
208 | * for encryption/decryption funcs | ||
209 | */ | ||
210 | static inline int | ||
211 | crypt_s390_kmc(long func, void* param, u8* dest, const u8* src, long src_len) | ||
212 | { | ||
213 | register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; | ||
214 | register void* __param asm("1") = param; | ||
215 | register u8* __dest asm("4") = dest; | ||
216 | register const u8* __src asm("2") = src; | ||
217 | register long __src_len asm("3") = src_len; | ||
218 | int ret; | ||
219 | |||
220 | ret = 0; | ||
221 | __asm__ __volatile__ ( | ||
222 | "0: .insn rre,0xB92F0000,%1,%2 \n" /* KMC opcode */ | ||
223 | "1: brc 1,0b \n" /* handle partial completion */ | ||
224 | __crypt_s390_set_result | ||
225 | "6: \n" | ||
226 | __crypt_s390_fixup | ||
227 | : "+d" (ret), "+a" (__dest), "+a" (__src), | ||
228 | [result] "+d" (__src_len) | ||
229 | : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), | ||
230 | "a" (__param) | ||
231 | : "cc", "memory" | ||
232 | ); | ||
233 | if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ | ||
234 | ret = src_len - ret; | ||
235 | } | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | /* | ||
240 | * Executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST) operation | ||
241 | * of the CPU. | ||
242 | * @param func: the function code passed to KM; see crypt_s390_kimd_func | ||
243 | * @param param: address of parameter block; see POP for details on each func | ||
244 | * @param src: address of source memory area | ||
245 | * @param src_len: length of src operand in bytes | ||
246 | * @returns < zero for failure, 0 for the query func, number of processed bytes | ||
247 | * for digest funcs | ||
248 | */ | ||
249 | static inline int | ||
250 | crypt_s390_kimd(long func, void* param, const u8* src, long src_len) | ||
251 | { | ||
252 | register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; | ||
253 | register void* __param asm("1") = param; | ||
254 | register const u8* __src asm("2") = src; | ||
255 | register long __src_len asm("3") = src_len; | ||
256 | int ret; | ||
257 | |||
258 | ret = 0; | ||
259 | __asm__ __volatile__ ( | ||
260 | "0: .insn rre,0xB93E0000,%1,%1 \n" /* KIMD opcode */ | ||
261 | "1: brc 1,0b \n" /* handle partical completion */ | ||
262 | __crypt_s390_set_result | ||
263 | "6: \n" | ||
264 | __crypt_s390_fixup | ||
265 | : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) | ||
266 | : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), | ||
267 | "a" (__param) | ||
268 | : "cc", "memory" | ||
269 | ); | ||
270 | if (ret >= 0 && (func & CRYPT_S390_FUNC_MASK)){ | ||
271 | ret = src_len - ret; | ||
272 | } | ||
273 | return ret; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Executes the KLMD (COMPUTE LAST MESSAGE DIGEST) operation of the CPU. | ||
278 | * @param func: the function code passed to KM; see crypt_s390_klmd_func | ||
279 | * @param param: address of parameter block; see POP for details on each func | ||
280 | * @param src: address of source memory area | ||
281 | * @param src_len: length of src operand in bytes | ||
282 | * @returns < zero for failure, 0 for the query func, number of processed bytes | ||
283 | * for digest funcs | ||
284 | */ | ||
285 | static inline int | ||
286 | crypt_s390_klmd(long func, void* param, const u8* src, long src_len) | ||
287 | { | ||
288 | register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; | ||
289 | register void* __param asm("1") = param; | ||
290 | register const u8* __src asm("2") = src; | ||
291 | register long __src_len asm("3") = src_len; | ||
292 | int ret; | ||
293 | |||
294 | ret = 0; | ||
295 | __asm__ __volatile__ ( | ||
296 | "0: .insn rre,0xB93F0000,%1,%1 \n" /* KLMD opcode */ | ||
297 | "1: brc 1,0b \n" /* handle partical completion */ | ||
298 | __crypt_s390_set_result | ||
299 | "6: \n" | ||
300 | __crypt_s390_fixup | ||
301 | : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) | ||
302 | : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), | ||
303 | "a" (__param) | ||
304 | : "cc", "memory" | ||
305 | ); | ||
306 | if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ | ||
307 | ret = src_len - ret; | ||
308 | } | ||
309 | return ret; | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * Executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE) operation | ||
314 | * of the CPU. | ||
315 | * @param func: the function code passed to KM; see crypt_s390_klmd_func | ||
316 | * @param param: address of parameter block; see POP for details on each func | ||
317 | * @param src: address of source memory area | ||
318 | * @param src_len: length of src operand in bytes | ||
319 | * @returns < zero for failure, 0 for the query func, number of processed bytes | ||
320 | * for digest funcs | ||
321 | */ | ||
322 | static inline int | ||
323 | crypt_s390_kmac(long func, void* param, const u8* src, long src_len) | ||
324 | { | ||
325 | register long __func asm("0") = func & CRYPT_S390_FUNC_MASK; | ||
326 | register void* __param asm("1") = param; | ||
327 | register const u8* __src asm("2") = src; | ||
328 | register long __src_len asm("3") = src_len; | ||
329 | int ret; | ||
330 | |||
331 | ret = 0; | ||
332 | __asm__ __volatile__ ( | ||
333 | "0: .insn rre,0xB91E0000,%5,%5 \n" /* KMAC opcode */ | ||
334 | "1: brc 1,0b \n" /* handle partical completion */ | ||
335 | __crypt_s390_set_result | ||
336 | "6: \n" | ||
337 | __crypt_s390_fixup | ||
338 | : "+d" (ret), "+a" (__src), [result] "+d" (__src_len) | ||
339 | : [e1] "K" (-EFAULT), [e2] "K" (-ENOSYS), "d" (__func), | ||
340 | "a" (__param) | ||
341 | : "cc", "memory" | ||
342 | ); | ||
343 | if (ret >= 0 && func & CRYPT_S390_FUNC_MASK){ | ||
344 | ret = src_len - ret; | ||
345 | } | ||
346 | return ret; | ||
347 | } | ||
348 | |||
349 | /** | ||
350 | * Tests if a specific crypto function is implemented on the machine. | ||
351 | * @param func: the function code of the specific function; 0 if op in general | ||
352 | * @return 1 if func available; 0 if func or op in general not available | ||
353 | */ | ||
354 | static inline int | ||
355 | crypt_s390_func_available(int func) | ||
356 | { | ||
357 | int ret; | ||
358 | |||
359 | struct crypt_s390_query_status status = { | ||
360 | .high = 0, | ||
361 | .low = 0 | ||
362 | }; | ||
363 | switch (func & CRYPT_S390_OP_MASK){ | ||
364 | case CRYPT_S390_KM: | ||
365 | ret = crypt_s390_km(KM_QUERY, &status, NULL, NULL, 0); | ||
366 | break; | ||
367 | case CRYPT_S390_KMC: | ||
368 | ret = crypt_s390_kmc(KMC_QUERY, &status, NULL, NULL, 0); | ||
369 | break; | ||
370 | case CRYPT_S390_KIMD: | ||
371 | ret = crypt_s390_kimd(KIMD_QUERY, &status, NULL, 0); | ||
372 | break; | ||
373 | case CRYPT_S390_KLMD: | ||
374 | ret = crypt_s390_klmd(KLMD_QUERY, &status, NULL, 0); | ||
375 | break; | ||
376 | case CRYPT_S390_KMAC: | ||
377 | ret = crypt_s390_kmac(KMAC_QUERY, &status, NULL, 0); | ||
378 | break; | ||
379 | default: | ||
380 | ret = 0; | ||
381 | return ret; | ||
382 | } | ||
383 | if (ret >= 0){ | ||
384 | func &= CRYPT_S390_FUNC_MASK; | ||
385 | func &= 0x7f; //mask modifier bit | ||
386 | if (func < 64){ | ||
387 | ret = (status.high >> (64 - func - 1)) & 0x1; | ||
388 | } else { | ||
389 | ret = (status.low >> (128 - func - 1)) & 0x1; | ||
390 | } | ||
391 | } else { | ||
392 | ret = 0; | ||
393 | } | ||
394 | return ret; | ||
395 | } | ||
396 | |||
397 | #endif // _CRYPTO_ARCH_S390_CRYPT_S390_H | ||