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