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