1 /*
2 * Copyright 2010-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <setjmp.h>
14 #include <signal.h>
15 #include "internal/cryptlib.h"
16 #include "crypto/ctype.h"
17 #include "s390x_arch.h"
18
19 #if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE)
20 #include <sys/types.h>
21 #include <sys/stat.h>
22 #include <fcntl.h>
23 #include <asm/zcrypt.h>
24 #include <sys/ioctl.h>
25 #include <unistd.h>
26 #endif
27
28 #if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
29 #if __GLIBC_PREREQ(2, 16)
30 #include <sys/auxv.h>
31 #if defined(HWCAP_S390_STFLE) && defined(HWCAP_S390_VX)
32 #define OSSL_IMPLEMENT_GETAUXVAL
33 #endif
34 #endif
35 #endif
36
37 #define LEN 128
38 #define STR_(S) #S
39 #define STR(S) STR_(S)
40
41 #define TOK_FUNC(NAME) \
42 (sscanf(tok_begin, \
43 " " STR(NAME) " : %" STR(LEN) "[^:] : " \
44 "%" STR(LEN) "s %" STR(LEN) "s ", \
45 tok[0], tok[1], tok[2]) \
46 == 2) \
47 { \
48 \
49 off = (tok[0][0] == '~') ? 1 : 0; \
50 if (sscanf(tok[0] + off, "%llx", &cap->NAME[0]) != 1) \
51 goto ret; \
52 if (off) \
53 cap->NAME[0] = ~cap->NAME[0]; \
54 \
55 off = (tok[1][0] == '~') ? 1 : 0; \
56 if (sscanf(tok[1] + off, "%llx", &cap->NAME[1]) != 1) \
57 goto ret; \
58 if (off) \
59 cap->NAME[1] = ~cap->NAME[1]; \
60 }
61
62 #define TOK_CPU_ALIAS(NAME, STRUCT_NAME) \
63 (sscanf(tok_begin, \
64 " %" STR(LEN) "s %" STR(LEN) "s ", \
65 tok[0], tok[1]) \
66 == 1 \
67 && !strcmp(tok[0], #NAME)) \
68 { \
69 memcpy(cap, &STRUCT_NAME, sizeof(*cap)); \
70 }
71
72 #define TOK_CPU(NAME) TOK_CPU_ALIAS(NAME, NAME)
73
74 #ifndef OSSL_IMPLEMENT_GETAUXVAL
75 static sigjmp_buf ill_jmp;
ill_handler(int sig)76 static void ill_handler(int sig)
77 {
78 siglongjmp(ill_jmp, sig);
79 }
80
81 void OPENSSL_vx_probe(void);
82 #endif
83
84 static const char *env;
85 static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex);
86
87 void OPENSSL_s390x_facilities(void);
88 void OPENSSL_s390x_functions(void);
89
90 struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
91
92 #ifdef S390X_MOD_EXP
93 int OPENSSL_s390xcex;
94 int OPENSSL_s390xcex_nodev;
95
96 #if defined(__GNUC__)
97 __attribute__((visibility("hidden")))
98 #endif
99 void OPENSSL_s390x_cleanup(void);
100
101 #if defined(__GNUC__)
102 __attribute__((visibility("hidden")))
103 #endif
OPENSSL_s390x_cleanup(void)104 void OPENSSL_s390x_cleanup(void)
105 {
106 if (OPENSSL_s390xcex != -1) {
107 (void)close(OPENSSL_s390xcex);
108 OPENSSL_s390xcex = -1;
109 }
110 }
111 #endif
112
113 #if defined(__GNUC__) && defined(__linux)
114 __attribute__((visibility("hidden")))
115 #endif
OPENSSL_cpuid_setup(void)116 void OPENSSL_cpuid_setup(void)
117 {
118 struct OPENSSL_s390xcap_st cap;
119 int cex = 1;
120
121 if (OPENSSL_s390xcap_P.stfle[0])
122 return;
123
124 /* set a bit that will not be tested later */
125 OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0);
126
127 #if defined(OSSL_IMPLEMENT_GETAUXVAL)
128 {
129 const unsigned long hwcap = getauxval(AT_HWCAP);
130
131 /* protection against missing store-facility-list-extended */
132 if (hwcap & HWCAP_S390_STFLE)
133 OPENSSL_s390x_facilities();
134
135 /* protection against disabled vector facility */
136 if (!(hwcap & HWCAP_S390_VX)) {
137 OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
138 | S390X_CAPBIT(S390X_VXD)
139 | S390X_CAPBIT(S390X_VXE));
140 }
141 }
142 #else
143 {
144 sigset_t oset;
145 struct sigaction ill_act, oact_ill, oact_fpe;
146
147 memset(&ill_act, 0, sizeof(ill_act));
148 ill_act.sa_handler = ill_handler;
149 sigfillset(&ill_act.sa_mask);
150 sigdelset(&ill_act.sa_mask, SIGILL);
151 sigdelset(&ill_act.sa_mask, SIGFPE);
152 sigdelset(&ill_act.sa_mask, SIGTRAP);
153
154 sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
155 sigaction(SIGILL, &ill_act, &oact_ill);
156 sigaction(SIGFPE, &ill_act, &oact_fpe);
157
158 /* protection against missing store-facility-list-extended */
159 if (sigsetjmp(ill_jmp, 1) == 0)
160 OPENSSL_s390x_facilities();
161
162 /* protection against disabled vector facility */
163 if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX))
164 && (sigsetjmp(ill_jmp, 1) == 0)) {
165 OPENSSL_vx_probe();
166 } else {
167 OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
168 | S390X_CAPBIT(S390X_VXD)
169 | S390X_CAPBIT(S390X_VXE));
170 }
171
172 sigaction(SIGFPE, &oact_fpe, NULL);
173 sigaction(SIGILL, &oact_ill, NULL);
174 sigprocmask(SIG_SETMASK, &oset, NULL);
175 }
176 #endif
177
178 env = getenv("OPENSSL_s390xcap");
179 if (env != NULL) {
180 if (!parse_env(&cap, &cex))
181 env = NULL;
182 }
183
184 if (env != NULL) {
185 OPENSSL_s390xcap_P.stfle[0] &= cap.stfle[0];
186 OPENSSL_s390xcap_P.stfle[1] &= cap.stfle[1];
187 OPENSSL_s390xcap_P.stfle[2] &= cap.stfle[2];
188 }
189
190 OPENSSL_s390x_functions(); /* check OPENSSL_s390xcap_P.stfle */
191
192 if (env != NULL) {
193 OPENSSL_s390xcap_P.kimd[0] &= cap.kimd[0];
194 OPENSSL_s390xcap_P.kimd[1] &= cap.kimd[1];
195 OPENSSL_s390xcap_P.klmd[0] &= cap.klmd[0];
196 OPENSSL_s390xcap_P.klmd[1] &= cap.klmd[1];
197 OPENSSL_s390xcap_P.km[0] &= cap.km[0];
198 OPENSSL_s390xcap_P.km[1] &= cap.km[1];
199 OPENSSL_s390xcap_P.kmc[0] &= cap.kmc[0];
200 OPENSSL_s390xcap_P.kmc[1] &= cap.kmc[1];
201 OPENSSL_s390xcap_P.kmac[0] &= cap.kmac[0];
202 OPENSSL_s390xcap_P.kmac[1] &= cap.kmac[1];
203 OPENSSL_s390xcap_P.kmctr[0] &= cap.kmctr[0];
204 OPENSSL_s390xcap_P.kmctr[1] &= cap.kmctr[1];
205 OPENSSL_s390xcap_P.kmo[0] &= cap.kmo[0];
206 OPENSSL_s390xcap_P.kmo[1] &= cap.kmo[1];
207 OPENSSL_s390xcap_P.kmf[0] &= cap.kmf[0];
208 OPENSSL_s390xcap_P.kmf[1] &= cap.kmf[1];
209 OPENSSL_s390xcap_P.prno[0] &= cap.prno[0];
210 OPENSSL_s390xcap_P.prno[1] &= cap.prno[1];
211 OPENSSL_s390xcap_P.kma[0] &= cap.kma[0];
212 OPENSSL_s390xcap_P.kma[1] &= cap.kma[1];
213 OPENSSL_s390xcap_P.pcc[0] &= cap.pcc[0];
214 OPENSSL_s390xcap_P.pcc[1] &= cap.pcc[1];
215 OPENSSL_s390xcap_P.kdsa[0] &= cap.kdsa[0];
216 OPENSSL_s390xcap_P.kdsa[1] &= cap.kdsa[1];
217 }
218
219 #ifdef S390X_MOD_EXP
220 if (cex == 0) {
221 OPENSSL_s390xcex = -1;
222 } else {
223 OPENSSL_s390xcex = open("/dev/z90crypt", O_RDWR | O_CLOEXEC);
224 OPENSSL_atexit(OPENSSL_s390x_cleanup);
225 }
226 OPENSSL_s390xcex_nodev = 0;
227 #endif
228 }
229
parse_env(struct OPENSSL_s390xcap_st * cap,int * cex)230 static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex)
231 {
232 /*-
233 * CPU model data
234 * (only the STFLE- and QUERY-bits relevant to libcrypto are set)
235 */
236
237 /*-
238 * z900 (2000) - z/Architecture POP SA22-7832-00
239 * Facility detection would fail on real hw (no STFLE).
240 */
241 static const struct OPENSSL_s390xcap_st z900 = {
242 /*.stfle = */ { 0ULL, 0ULL, 0ULL, 0ULL },
243 /*.kimd = */ { 0ULL, 0ULL },
244 /*.klmd = */ { 0ULL, 0ULL },
245 /*.km = */ { 0ULL, 0ULL },
246 /*.kmc = */ { 0ULL, 0ULL },
247 /*.kmac = */ { 0ULL, 0ULL },
248 /*.kmctr = */ { 0ULL, 0ULL },
249 /*.kmo = */ { 0ULL, 0ULL },
250 /*.kmf = */ { 0ULL, 0ULL },
251 /*.prno = */ { 0ULL, 0ULL },
252 /*.kma = */ { 0ULL, 0ULL },
253 /*.pcc = */ { 0ULL, 0ULL },
254 /*.kdsa = */ { 0ULL, 0ULL },
255 };
256
257 /*-
258 * z990 (2003) - z/Architecture POP SA22-7832-02
259 * Implements MSA. Facility detection would fail on real hw (no STFLE).
260 */
261 static const struct OPENSSL_s390xcap_st z990 = {
262 /*.stfle = */ { S390X_CAPBIT(S390X_MSA),
263 0ULL, 0ULL, 0ULL },
264 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1), 0ULL },
265 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1), 0ULL },
266 /*.km = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
267 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
268 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
269 /*.kmctr = */ { 0ULL, 0ULL },
270 /*.kmo = */ { 0ULL, 0ULL },
271 /*.kmf = */ { 0ULL, 0ULL },
272 /*.prno = */ { 0ULL, 0ULL },
273 /*.kma = */ { 0ULL, 0ULL },
274 /*.pcc = */ { 0ULL, 0ULL },
275 /*.kdsa = */ { 0ULL, 0ULL },
276 };
277
278 /*-
279 * z9 (2005) - z/Architecture POP SA22-7832-04
280 * Implements MSA and MSA1.
281 */
282 static const struct OPENSSL_s390xcap_st z9 = {
283 /*.stfle = */ { S390X_CAPBIT(S390X_MSA)
284 | S390X_CAPBIT(S390X_STCKF),
285 0ULL, 0ULL, 0ULL },
286 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256), 0ULL },
287 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256), 0ULL },
288 /*.km = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128), 0ULL },
289 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128), 0ULL },
290 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
291 /*.kmctr = */ { 0ULL, 0ULL },
292 /*.kmo = */ { 0ULL, 0ULL },
293 /*.kmf = */ { 0ULL, 0ULL },
294 /*.prno = */ { 0ULL, 0ULL },
295 /*.kma = */ { 0ULL, 0ULL },
296 /*.pcc = */ { 0ULL, 0ULL },
297 /*.kdsa = */ { 0ULL, 0ULL },
298 };
299
300 /*-
301 * z10 (2008) - z/Architecture POP SA22-7832-06
302 * Implements MSA and MSA1-2.
303 */
304 static const struct OPENSSL_s390xcap_st z10 = {
305 /*.stfle = */ { S390X_CAPBIT(S390X_MSA)
306 | S390X_CAPBIT(S390X_STCKF),
307 0ULL, 0ULL, 0ULL },
308 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), 0ULL },
309 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), 0ULL },
310 /*.km = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
311 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
312 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
313 /*.kmctr = */ { 0ULL, 0ULL },
314 /*.kmo = */ { 0ULL, 0ULL },
315 /*.kmf = */ { 0ULL, 0ULL },
316 /*.prno = */ { 0ULL, 0ULL },
317 /*.kma = */ { 0ULL, 0ULL },
318 /*.pcc = */ { 0ULL, 0ULL },
319 /*.kdsa = */ { 0ULL, 0ULL },
320 };
321
322 /*-
323 * z196 (2010) - z/Architecture POP SA22-7832-08
324 * Implements MSA and MSA1-4.
325 */
326 static const struct OPENSSL_s390xcap_st z196 = {
327 /*.stfle = */ { S390X_CAPBIT(S390X_MSA)
328 | S390X_CAPBIT(S390X_STCKF),
329 S390X_CAPBIT(S390X_MSA3)
330 | S390X_CAPBIT(S390X_MSA4),
331 0ULL, 0ULL },
332 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), S390X_CAPBIT(S390X_GHASH) },
333 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), 0ULL },
334 /*.km = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256) | S390X_CAPBIT(S390X_XTS_AES_128) | S390X_CAPBIT(S390X_XTS_AES_256), 0ULL },
335 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
336 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
337 /*.kmctr = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
338 /*.kmo = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
339 /*.kmf = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
340 /*.prno = */ { 0ULL, 0ULL },
341 /*.kma = */ { 0ULL, 0ULL },
342 /*.pcc = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
343 /*.kdsa = */ { 0ULL, 0ULL },
344 };
345
346 /*-
347 * zEC12 (2012) - z/Architecture POP SA22-7832-09
348 * Implements MSA and MSA1-4.
349 */
350 static const struct OPENSSL_s390xcap_st zEC12 = {
351 /*.stfle = */ { S390X_CAPBIT(S390X_MSA)
352 | S390X_CAPBIT(S390X_STCKF),
353 S390X_CAPBIT(S390X_MSA3)
354 | S390X_CAPBIT(S390X_MSA4),
355 0ULL, 0ULL },
356 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), S390X_CAPBIT(S390X_GHASH) },
357 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), 0ULL },
358 /*.km = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256) | S390X_CAPBIT(S390X_XTS_AES_128) | S390X_CAPBIT(S390X_XTS_AES_256), 0ULL },
359 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
360 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
361 /*.kmctr = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
362 /*.kmo = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
363 /*.kmf = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
364 /*.prno = */ { 0ULL, 0ULL },
365 /*.kma = */ { 0ULL, 0ULL },
366 /*.pcc = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
367 /*.kdsa = */ { 0ULL, 0ULL },
368 };
369
370 /*-
371 * z13 (2015) - z/Architecture POP SA22-7832-10
372 * Implements MSA and MSA1-5.
373 */
374 static const struct OPENSSL_s390xcap_st z13 = {
375 /*.stfle = */ { S390X_CAPBIT(S390X_MSA)
376 | S390X_CAPBIT(S390X_STCKF)
377 | S390X_CAPBIT(S390X_MSA5),
378 S390X_CAPBIT(S390X_MSA3)
379 | S390X_CAPBIT(S390X_MSA4),
380 S390X_CAPBIT(S390X_VX),
381 0ULL },
382 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), S390X_CAPBIT(S390X_GHASH) },
383 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512), 0ULL },
384 /*.km = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256) | S390X_CAPBIT(S390X_XTS_AES_128) | S390X_CAPBIT(S390X_XTS_AES_256), 0ULL },
385 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
386 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
387 /*.kmctr = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
388 /*.kmo = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
389 /*.kmf = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
390 /*.prno = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_512_DRNG), 0ULL },
391 /*.kma = */ { 0ULL, 0ULL },
392 /*.pcc = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
393 /*.kdsa = */ { 0ULL, 0ULL },
394 };
395
396 /*-
397 * z14 (2017) - z/Architecture POP SA22-7832-11
398 * Implements MSA and MSA1-8.
399 */
400 static const struct OPENSSL_s390xcap_st z14 = {
401 /*.stfle = */ { S390X_CAPBIT(S390X_MSA)
402 | S390X_CAPBIT(S390X_STCKF)
403 | S390X_CAPBIT(S390X_MSA5),
404 S390X_CAPBIT(S390X_MSA3)
405 | S390X_CAPBIT(S390X_MSA4),
406 S390X_CAPBIT(S390X_VX)
407 | S390X_CAPBIT(S390X_VXD)
408 | S390X_CAPBIT(S390X_VXE)
409 | S390X_CAPBIT(S390X_MSA8),
410 0ULL },
411 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512) | S390X_CAPBIT(S390X_SHA3_224) | S390X_CAPBIT(S390X_SHA3_256) | S390X_CAPBIT(S390X_SHA3_384) | S390X_CAPBIT(S390X_SHA3_512) | S390X_CAPBIT(S390X_SHAKE_128) | S390X_CAPBIT(S390X_SHAKE_256), S390X_CAPBIT(S390X_GHASH) },
412 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512) | S390X_CAPBIT(S390X_SHA3_224) | S390X_CAPBIT(S390X_SHA3_256) | S390X_CAPBIT(S390X_SHA3_384) | S390X_CAPBIT(S390X_SHA3_512) | S390X_CAPBIT(S390X_SHAKE_128) | S390X_CAPBIT(S390X_SHAKE_256), 0ULL },
413 /*.km = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256) | S390X_CAPBIT(S390X_XTS_AES_128) | S390X_CAPBIT(S390X_XTS_AES_256), 0ULL },
414 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
415 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
416 /*.kmctr = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
417 /*.kmo = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
418 /*.kmf = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
419 /*.prno = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_512_DRNG), S390X_CAPBIT(S390X_TRNG) },
420 /*.kma = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
421 /*.pcc = */ { S390X_CAPBIT(S390X_QUERY), 0ULL },
422 /*.kdsa = */ { 0ULL, 0ULL },
423 };
424
425 /*-
426 * z15 (2019) - z/Architecture POP SA22-7832-12
427 * Implements MSA and MSA1-9.
428 */
429 static const struct OPENSSL_s390xcap_st z15 = {
430 /*.stfle = */ { S390X_CAPBIT(S390X_MSA)
431 | S390X_CAPBIT(S390X_STCKF)
432 | S390X_CAPBIT(S390X_MSA5),
433 S390X_CAPBIT(S390X_MSA3)
434 | S390X_CAPBIT(S390X_MSA4),
435 S390X_CAPBIT(S390X_VX)
436 | S390X_CAPBIT(S390X_VXD)
437 | S390X_CAPBIT(S390X_VXE)
438 | S390X_CAPBIT(S390X_MSA8)
439 | S390X_CAPBIT(S390X_MSA9),
440 0ULL },
441 /*.kimd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512) | S390X_CAPBIT(S390X_SHA3_224) | S390X_CAPBIT(S390X_SHA3_256) | S390X_CAPBIT(S390X_SHA3_384) | S390X_CAPBIT(S390X_SHA3_512) | S390X_CAPBIT(S390X_SHAKE_128) | S390X_CAPBIT(S390X_SHAKE_256), S390X_CAPBIT(S390X_GHASH) },
442 /*.klmd = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_1) | S390X_CAPBIT(S390X_SHA_256) | S390X_CAPBIT(S390X_SHA_512) | S390X_CAPBIT(S390X_SHA3_224) | S390X_CAPBIT(S390X_SHA3_256) | S390X_CAPBIT(S390X_SHA3_384) | S390X_CAPBIT(S390X_SHA3_512) | S390X_CAPBIT(S390X_SHAKE_128) | S390X_CAPBIT(S390X_SHAKE_256), 0ULL },
443 /*.km = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256) | S390X_CAPBIT(S390X_XTS_AES_128) | S390X_CAPBIT(S390X_XTS_AES_256), 0ULL },
444 /*.kmc = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
445 /*.kmac = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
446 /*.kmctr = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
447 /*.kmo = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
448 /*.kmf = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
449 /*.prno = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_SHA_512_DRNG), S390X_CAPBIT(S390X_TRNG) },
450 /*.kma = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_AES_128) | S390X_CAPBIT(S390X_AES_192) | S390X_CAPBIT(S390X_AES_256), 0ULL },
451 /*.pcc = */ { S390X_CAPBIT(S390X_QUERY), S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P256) | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P384) | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P521) | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519) | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448) | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519) | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448) },
452 /*.kdsa = */ { S390X_CAPBIT(S390X_QUERY) | S390X_CAPBIT(S390X_ECDSA_VERIFY_P256) | S390X_CAPBIT(S390X_ECDSA_VERIFY_P384) | S390X_CAPBIT(S390X_ECDSA_VERIFY_P521) | S390X_CAPBIT(S390X_ECDSA_SIGN_P256) | S390X_CAPBIT(S390X_ECDSA_SIGN_P384) | S390X_CAPBIT(S390X_ECDSA_SIGN_P521) | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519) | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448) | S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519) | S390X_CAPBIT(S390X_EDDSA_SIGN_ED448), 0ULL },
453 };
454
455 /*-
456 * z16 (2022) - z/Architecture POP
457 * Implements MSA and MSA1-9 (same as z15, no need to repeat).
458 */
459
460 char *tok_begin, *tok_end, *buff, tok[S390X_STFLE_MAX][LEN + 1];
461 int rc, off, i, n;
462
463 buff = malloc(strlen(env) + 1);
464 if (buff == NULL)
465 return 0;
466
467 rc = 0;
468 memset(cap, ~0, sizeof(*cap));
469 strcpy(buff, env);
470
471 tok_begin = buff + strspn(buff, ";");
472 strtok(tok_begin, ";");
473 tok_end = strtok(NULL, ";");
474
475 while (tok_begin != NULL) {
476 /* stfle token */
477 if ((n = sscanf(tok_begin,
478 " stfle : %" STR(LEN) "[^:] : "
479 "%" STR(LEN) "[^:] : %" STR(LEN) "s ",
480 tok[0], tok[1], tok[2]))) {
481 for (i = 0; i < n; i++) {
482 off = (tok[i][0] == '~') ? 1 : 0;
483 if (sscanf(tok[i] + off, "%llx", &cap->stfle[i]) != 1)
484 goto ret;
485 if (off)
486 cap->stfle[i] = ~cap->stfle[i];
487 }
488 }
489
490 /* query function tokens */
491 else if TOK_FUNC (kimd)
492 else if TOK_FUNC (klmd) else if TOK_FUNC (km) else if TOK_FUNC (kmc) else if TOK_FUNC (kmac) else if TOK_FUNC (kmctr) else if TOK_FUNC (kmo) else if TOK_FUNC (kmf) else if TOK_FUNC (prno) else if TOK_FUNC (kma) else if TOK_FUNC (pcc) else if TOK_FUNC (kdsa)
493
494 /* CPU model tokens */
495 else if TOK_CPU (z900) else if TOK_CPU (z990) else if TOK_CPU (z9) else if TOK_CPU (z10) else if TOK_CPU (z196) else if TOK_CPU (zEC12) else if TOK_CPU (z13) else if TOK_CPU (z14) else if TOK_CPU (z15) else if TOK_CPU_ALIAS (z16, z15)
496
497 /* nocex to deactivate cex support */
498 else if (sscanf(tok_begin, " %" STR(LEN) "s %" STR(LEN) "s ",
499 tok[0], tok[1])
500 == 1
501 && !strcmp(tok[0], "nocex"))
502 {
503 *cex = 0;
504 }
505
506 /* whitespace(ignored) or invalid tokens */
507 else {
508 while (*tok_begin != '\0') {
509 if (!ossl_isspace(*tok_begin))
510 goto ret;
511 tok_begin++;
512 }
513 }
514
515 tok_begin = tok_end;
516 tok_end = strtok(NULL, ";");
517 }
518
519 rc = 1;
520 ret:
521 free(buff);
522 return rc;
523 }
524