xref: /openssl/crypto/s390xcap.c (revision f928304a)
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]) == 2) {                             \
46                                                                         \
47         off = (tok[0][0] == '~') ? 1 : 0;                               \
48         if (sscanf(tok[0] + off, "%llx", &cap->NAME[0]) != 1)           \
49             goto ret;                                                   \
50         if (off)                                                        \
51             cap->NAME[0] = ~cap->NAME[0];                               \
52                                                                         \
53         off = (tok[1][0] == '~') ? 1 : 0;                               \
54         if (sscanf(tok[1] + off, "%llx", &cap->NAME[1]) != 1)           \
55             goto ret;                                                   \
56         if (off)                                                        \
57             cap->NAME[1] = ~cap->NAME[1];                               \
58     }
59 
60 #define TOK_CPU_ALIAS(NAME, STRUCT_NAME)                                \
61     (sscanf(tok_begin,                                                  \
62             " %" STR(LEN) "s %" STR(LEN) "s ",                          \
63             tok[0], tok[1]) == 1                                        \
64      && !strcmp(tok[0], #NAME)) {                                       \
65             memcpy(cap, &STRUCT_NAME, sizeof(*cap));                    \
66     }
67 
68 #define TOK_CPU(NAME) TOK_CPU_ALIAS(NAME, NAME)
69 
70 #ifndef OSSL_IMPLEMENT_GETAUXVAL
71 static sigjmp_buf ill_jmp;
ill_handler(int sig)72 static void ill_handler(int sig)
73 {
74     siglongjmp(ill_jmp, sig);
75 }
76 
77 void OPENSSL_vx_probe(void);
78 #endif
79 
80 static const char *env;
81 static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex);
82 
83 void OPENSSL_s390x_facilities(void);
84 void OPENSSL_s390x_functions(void);
85 
86 struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
87 
88 #ifdef S390X_MOD_EXP
89 int OPENSSL_s390xcex;
90 int OPENSSL_s390xcex_nodev;
91 
92 #if defined(__GNUC__)
93 __attribute__ ((visibility("hidden")))
94 #endif
95 void OPENSSL_s390x_cleanup(void);
96 
97 #if defined(__GNUC__)
98 __attribute__ ((visibility("hidden")))
99 #endif
OPENSSL_s390x_cleanup(void)100 void OPENSSL_s390x_cleanup(void)
101 {
102     if (OPENSSL_s390xcex != -1) {
103         (void)close(OPENSSL_s390xcex);
104         OPENSSL_s390xcex = -1;
105     }
106 }
107 #endif
108 
109 #if defined(__GNUC__) && defined(__linux)
110 __attribute__ ((visibility("hidden")))
111 #endif
OPENSSL_cpuid_setup(void)112 void OPENSSL_cpuid_setup(void)
113 {
114     struct OPENSSL_s390xcap_st cap;
115     int cex = 1;
116 
117     if (OPENSSL_s390xcap_P.stfle[0])
118         return;
119 
120     /* set a bit that will not be tested later */
121     OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0);
122 
123 #if defined(OSSL_IMPLEMENT_GETAUXVAL)
124     {
125         const unsigned long hwcap = getauxval(AT_HWCAP);
126 
127         /* protection against missing store-facility-list-extended */
128         if (hwcap & HWCAP_S390_STFLE)
129             OPENSSL_s390x_facilities();
130 
131         /* protection against disabled vector facility */
132         if (!(hwcap & HWCAP_S390_VX)) {
133             OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
134                                              | S390X_CAPBIT(S390X_VXD)
135                                              | S390X_CAPBIT(S390X_VXE));
136         }
137     }
138 #else
139     {
140         sigset_t oset;
141         struct sigaction ill_act, oact_ill, oact_fpe;
142 
143         memset(&ill_act, 0, sizeof(ill_act));
144         ill_act.sa_handler = ill_handler;
145         sigfillset(&ill_act.sa_mask);
146         sigdelset(&ill_act.sa_mask, SIGILL);
147         sigdelset(&ill_act.sa_mask, SIGFPE);
148         sigdelset(&ill_act.sa_mask, SIGTRAP);
149 
150         sigprocmask(SIG_SETMASK, &ill_act.sa_mask, &oset);
151         sigaction(SIGILL, &ill_act, &oact_ill);
152         sigaction(SIGFPE, &ill_act, &oact_fpe);
153 
154         /* protection against missing store-facility-list-extended */
155         if (sigsetjmp(ill_jmp, 1) == 0)
156             OPENSSL_s390x_facilities();
157 
158         /* protection against disabled vector facility */
159         if ((OPENSSL_s390xcap_P.stfle[2] & S390X_CAPBIT(S390X_VX))
160             && (sigsetjmp(ill_jmp, 1) == 0)) {
161             OPENSSL_vx_probe();
162         } else {
163             OPENSSL_s390xcap_P.stfle[2] &= ~(S390X_CAPBIT(S390X_VX)
164                                              | S390X_CAPBIT(S390X_VXD)
165                                              | S390X_CAPBIT(S390X_VXE));
166         }
167 
168         sigaction(SIGFPE, &oact_fpe, NULL);
169         sigaction(SIGILL, &oact_ill, NULL);
170         sigprocmask(SIG_SETMASK, &oset, NULL);
171     }
172 #endif
173 
174     env = getenv("OPENSSL_s390xcap");
175     if (env != NULL) {
176         if (!parse_env(&cap, &cex))
177             env = NULL;
178     }
179 
180     if (env != NULL) {
181         OPENSSL_s390xcap_P.stfle[0] &= cap.stfle[0];
182         OPENSSL_s390xcap_P.stfle[1] &= cap.stfle[1];
183         OPENSSL_s390xcap_P.stfle[2] &= cap.stfle[2];
184     }
185 
186     OPENSSL_s390x_functions(); /* check OPENSSL_s390xcap_P.stfle */
187 
188     if (env != NULL) {
189         OPENSSL_s390xcap_P.kimd[0] &= cap.kimd[0];
190         OPENSSL_s390xcap_P.kimd[1] &= cap.kimd[1];
191         OPENSSL_s390xcap_P.klmd[0] &= cap.klmd[0];
192         OPENSSL_s390xcap_P.klmd[1] &= cap.klmd[1];
193         OPENSSL_s390xcap_P.km[0] &= cap.km[0];
194         OPENSSL_s390xcap_P.km[1] &= cap.km[1];
195         OPENSSL_s390xcap_P.kmc[0] &= cap.kmc[0];
196         OPENSSL_s390xcap_P.kmc[1] &= cap.kmc[1];
197         OPENSSL_s390xcap_P.kmac[0] &= cap.kmac[0];
198         OPENSSL_s390xcap_P.kmac[1] &= cap.kmac[1];
199         OPENSSL_s390xcap_P.kmctr[0] &= cap.kmctr[0];
200         OPENSSL_s390xcap_P.kmctr[1] &= cap.kmctr[1];
201         OPENSSL_s390xcap_P.kmo[0] &= cap.kmo[0];
202         OPENSSL_s390xcap_P.kmo[1] &= cap.kmo[1];
203         OPENSSL_s390xcap_P.kmf[0] &= cap.kmf[0];
204         OPENSSL_s390xcap_P.kmf[1] &= cap.kmf[1];
205         OPENSSL_s390xcap_P.prno[0] &= cap.prno[0];
206         OPENSSL_s390xcap_P.prno[1] &= cap.prno[1];
207         OPENSSL_s390xcap_P.kma[0] &= cap.kma[0];
208         OPENSSL_s390xcap_P.kma[1] &= cap.kma[1];
209         OPENSSL_s390xcap_P.pcc[0] &= cap.pcc[0];
210         OPENSSL_s390xcap_P.pcc[1] &= cap.pcc[1];
211         OPENSSL_s390xcap_P.kdsa[0] &= cap.kdsa[0];
212         OPENSSL_s390xcap_P.kdsa[1] &= cap.kdsa[1];
213     }
214 
215 #ifdef S390X_MOD_EXP
216     if (cex == 0) {
217         OPENSSL_s390xcex = -1;
218     } else {
219         OPENSSL_s390xcex = open("/dev/z90crypt", O_RDWR | O_CLOEXEC);
220         OPENSSL_atexit(OPENSSL_s390x_cleanup);
221     }
222     OPENSSL_s390xcex_nodev = 0;
223 #endif
224 }
225 
parse_env(struct OPENSSL_s390xcap_st * cap,int * cex)226 static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex)
227 {
228     /*-
229      * CPU model data
230      * (only the STFLE- and QUERY-bits relevant to libcrypto are set)
231      */
232 
233     /*-
234      * z900 (2000) - z/Architecture POP SA22-7832-00
235      * Facility detection would fail on real hw (no STFLE).
236      */
237     static const struct OPENSSL_s390xcap_st z900 = {
238         /*.stfle  = */{0ULL, 0ULL, 0ULL, 0ULL},
239         /*.kimd   = */{0ULL, 0ULL},
240         /*.klmd   = */{0ULL, 0ULL},
241         /*.km     = */{0ULL, 0ULL},
242         /*.kmc    = */{0ULL, 0ULL},
243         /*.kmac   = */{0ULL, 0ULL},
244         /*.kmctr  = */{0ULL, 0ULL},
245         /*.kmo    = */{0ULL, 0ULL},
246         /*.kmf    = */{0ULL, 0ULL},
247         /*.prno   = */{0ULL, 0ULL},
248         /*.kma    = */{0ULL, 0ULL},
249         /*.pcc    = */{0ULL, 0ULL},
250         /*.kdsa   = */{0ULL, 0ULL},
251     };
252 
253     /*-
254      * z990 (2003) - z/Architecture POP SA22-7832-02
255      * Implements MSA. Facility detection would fail on real hw (no STFLE).
256      */
257     static const struct OPENSSL_s390xcap_st z990 = {
258         /*.stfle  = */{S390X_CAPBIT(S390X_MSA),
259                        0ULL, 0ULL, 0ULL},
260         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
261                        | S390X_CAPBIT(S390X_SHA_1),
262                        0ULL},
263         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
264                        | S390X_CAPBIT(S390X_SHA_1),
265                        0ULL},
266         /*.km     = */{S390X_CAPBIT(S390X_QUERY),
267                        0ULL},
268         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY),
269                        0ULL},
270         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY),
271                        0ULL},
272         /*.kmctr  = */{0ULL, 0ULL},
273         /*.kmo    = */{0ULL, 0ULL},
274         /*.kmf    = */{0ULL, 0ULL},
275         /*.prno   = */{0ULL, 0ULL},
276         /*.kma    = */{0ULL, 0ULL},
277         /*.pcc    = */{0ULL, 0ULL},
278         /*.kdsa   = */{0ULL, 0ULL},
279     };
280 
281     /*-
282      * z9 (2005) - z/Architecture POP SA22-7832-04
283      * Implements MSA and MSA1.
284      */
285     static const struct OPENSSL_s390xcap_st z9 = {
286         /*.stfle  = */{S390X_CAPBIT(S390X_MSA)
287                        | S390X_CAPBIT(S390X_STCKF),
288                        0ULL, 0ULL, 0ULL},
289         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
290                        | S390X_CAPBIT(S390X_SHA_1)
291                        | S390X_CAPBIT(S390X_SHA_256),
292                        0ULL},
293         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
294                        | S390X_CAPBIT(S390X_SHA_1)
295                        | S390X_CAPBIT(S390X_SHA_256),
296                        0ULL},
297         /*.km     = */{S390X_CAPBIT(S390X_QUERY)
298                        | S390X_CAPBIT(S390X_AES_128),
299                        0ULL},
300         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY)
301                        | S390X_CAPBIT(S390X_AES_128),
302                        0ULL},
303         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY),
304                        0ULL},
305         /*.kmctr  = */{0ULL, 0ULL},
306         /*.kmo    = */{0ULL, 0ULL},
307         /*.kmf    = */{0ULL, 0ULL},
308         /*.prno   = */{0ULL, 0ULL},
309         /*.kma    = */{0ULL, 0ULL},
310         /*.pcc    = */{0ULL, 0ULL},
311         /*.kdsa   = */{0ULL, 0ULL},
312     };
313 
314     /*-
315      * z10 (2008) - z/Architecture POP SA22-7832-06
316      * Implements MSA and MSA1-2.
317      */
318     static const struct OPENSSL_s390xcap_st z10 = {
319         /*.stfle  = */{S390X_CAPBIT(S390X_MSA)
320                        | S390X_CAPBIT(S390X_STCKF),
321                        0ULL, 0ULL, 0ULL},
322         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
323                        | S390X_CAPBIT(S390X_SHA_1)
324                        | S390X_CAPBIT(S390X_SHA_256)
325                        | S390X_CAPBIT(S390X_SHA_512),
326                        0ULL},
327         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
328                        | S390X_CAPBIT(S390X_SHA_1)
329                        | S390X_CAPBIT(S390X_SHA_256)
330                        | S390X_CAPBIT(S390X_SHA_512),
331                        0ULL},
332         /*.km     = */{S390X_CAPBIT(S390X_QUERY)
333                        | S390X_CAPBIT(S390X_AES_128)
334                        | S390X_CAPBIT(S390X_AES_192)
335                        | S390X_CAPBIT(S390X_AES_256),
336                        0ULL},
337         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY)
338                        | S390X_CAPBIT(S390X_AES_128)
339                        | S390X_CAPBIT(S390X_AES_192)
340                        | S390X_CAPBIT(S390X_AES_256),
341                        0ULL},
342         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY),
343                        0ULL},
344         /*.kmctr  = */{0ULL, 0ULL},
345         /*.kmo    = */{0ULL, 0ULL},
346         /*.kmf    = */{0ULL, 0ULL},
347         /*.prno   = */{0ULL, 0ULL},
348         /*.kma    = */{0ULL, 0ULL},
349         /*.pcc    = */{0ULL, 0ULL},
350         /*.kdsa   = */{0ULL, 0ULL},
351     };
352 
353     /*-
354      * z196 (2010) - z/Architecture POP SA22-7832-08
355      * Implements MSA and MSA1-4.
356      */
357     static const struct OPENSSL_s390xcap_st z196 = {
358         /*.stfle  = */{S390X_CAPBIT(S390X_MSA)
359                        | S390X_CAPBIT(S390X_STCKF),
360                        S390X_CAPBIT(S390X_MSA3)
361                        | S390X_CAPBIT(S390X_MSA4),
362                        0ULL, 0ULL},
363         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
364                        | S390X_CAPBIT(S390X_SHA_1)
365                        | S390X_CAPBIT(S390X_SHA_256)
366                        | S390X_CAPBIT(S390X_SHA_512),
367                        S390X_CAPBIT(S390X_GHASH)},
368         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
369                        | S390X_CAPBIT(S390X_SHA_1)
370                        | S390X_CAPBIT(S390X_SHA_256)
371                        | S390X_CAPBIT(S390X_SHA_512),
372                        0ULL},
373         /*.km     = */{S390X_CAPBIT(S390X_QUERY)
374                        | S390X_CAPBIT(S390X_AES_128)
375                        | S390X_CAPBIT(S390X_AES_192)
376                        | S390X_CAPBIT(S390X_AES_256)
377                        | S390X_CAPBIT(S390X_XTS_AES_128)
378                        | S390X_CAPBIT(S390X_XTS_AES_256),
379                        0ULL},
380         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY)
381                        | S390X_CAPBIT(S390X_AES_128)
382                        | S390X_CAPBIT(S390X_AES_192)
383                        | S390X_CAPBIT(S390X_AES_256),
384                        0ULL},
385         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY)
386                        | S390X_CAPBIT(S390X_AES_128)
387                        | S390X_CAPBIT(S390X_AES_192)
388                        | S390X_CAPBIT(S390X_AES_256),
389                        0ULL},
390         /*.kmctr  = */{S390X_CAPBIT(S390X_QUERY)
391                        | S390X_CAPBIT(S390X_AES_128)
392                        | S390X_CAPBIT(S390X_AES_192)
393                        | S390X_CAPBIT(S390X_AES_256),
394                        0ULL},
395         /*.kmo    = */{S390X_CAPBIT(S390X_QUERY)
396                        | S390X_CAPBIT(S390X_AES_128)
397                        | S390X_CAPBIT(S390X_AES_192)
398                        | S390X_CAPBIT(S390X_AES_256),
399                        0ULL},
400         /*.kmf    = */{S390X_CAPBIT(S390X_QUERY)
401                        | S390X_CAPBIT(S390X_AES_128)
402                        | S390X_CAPBIT(S390X_AES_192)
403                        | S390X_CAPBIT(S390X_AES_256),
404                        0ULL},
405         /*.prno   = */{0ULL, 0ULL},
406         /*.kma    = */{0ULL, 0ULL},
407         /*.pcc    = */{S390X_CAPBIT(S390X_QUERY),
408                        0ULL},
409         /*.kdsa   = */{0ULL, 0ULL},
410     };
411 
412     /*-
413      * zEC12 (2012) - z/Architecture POP SA22-7832-09
414      * Implements MSA and MSA1-4.
415      */
416     static const struct OPENSSL_s390xcap_st zEC12 = {
417         /*.stfle  = */{S390X_CAPBIT(S390X_MSA)
418                        | S390X_CAPBIT(S390X_STCKF),
419                        S390X_CAPBIT(S390X_MSA3)
420                        | S390X_CAPBIT(S390X_MSA4),
421                        0ULL, 0ULL},
422         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
423                        | S390X_CAPBIT(S390X_SHA_1)
424                        | S390X_CAPBIT(S390X_SHA_256)
425                        | S390X_CAPBIT(S390X_SHA_512),
426                    S390X_CAPBIT(S390X_GHASH)},
427         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
428                        | S390X_CAPBIT(S390X_SHA_1)
429                        | S390X_CAPBIT(S390X_SHA_256)
430                        | S390X_CAPBIT(S390X_SHA_512),
431                        0ULL},
432         /*.km     = */{S390X_CAPBIT(S390X_QUERY)
433                        | S390X_CAPBIT(S390X_AES_128)
434                        | S390X_CAPBIT(S390X_AES_192)
435                        | S390X_CAPBIT(S390X_AES_256)
436                        | S390X_CAPBIT(S390X_XTS_AES_128)
437                        | S390X_CAPBIT(S390X_XTS_AES_256),
438                        0ULL},
439         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY)
440                        | S390X_CAPBIT(S390X_AES_128)
441                        | S390X_CAPBIT(S390X_AES_192)
442                        | S390X_CAPBIT(S390X_AES_256),
443                        0ULL},
444         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY)
445                        | S390X_CAPBIT(S390X_AES_128)
446                        | S390X_CAPBIT(S390X_AES_192)
447                        | S390X_CAPBIT(S390X_AES_256),
448                        0ULL},
449         /*.kmctr  = */{S390X_CAPBIT(S390X_QUERY)
450                        | S390X_CAPBIT(S390X_AES_128)
451                        | S390X_CAPBIT(S390X_AES_192)
452                        | S390X_CAPBIT(S390X_AES_256),
453                        0ULL},
454         /*.kmo    = */{S390X_CAPBIT(S390X_QUERY)
455                        | S390X_CAPBIT(S390X_AES_128)
456                        | S390X_CAPBIT(S390X_AES_192)
457                        | S390X_CAPBIT(S390X_AES_256),
458                        0ULL},
459         /*.kmf    = */{S390X_CAPBIT(S390X_QUERY)
460                        | S390X_CAPBIT(S390X_AES_128)
461                        | S390X_CAPBIT(S390X_AES_192)
462                        | S390X_CAPBIT(S390X_AES_256),
463                        0ULL},
464         /*.prno   = */{0ULL, 0ULL},
465         /*.kma    = */{0ULL, 0ULL},
466         /*.pcc    = */{S390X_CAPBIT(S390X_QUERY),
467                        0ULL},
468         /*.kdsa   = */{0ULL, 0ULL},
469     };
470 
471     /*-
472      * z13 (2015) - z/Architecture POP SA22-7832-10
473      * Implements MSA and MSA1-5.
474      */
475     static const struct OPENSSL_s390xcap_st z13 = {
476         /*.stfle  = */{S390X_CAPBIT(S390X_MSA)
477                        | S390X_CAPBIT(S390X_STCKF)
478                        | S390X_CAPBIT(S390X_MSA5),
479                        S390X_CAPBIT(S390X_MSA3)
480                        | S390X_CAPBIT(S390X_MSA4),
481                        S390X_CAPBIT(S390X_VX),
482                        0ULL},
483         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
484                        | S390X_CAPBIT(S390X_SHA_1)
485                        | S390X_CAPBIT(S390X_SHA_256)
486                        | S390X_CAPBIT(S390X_SHA_512),
487                        S390X_CAPBIT(S390X_GHASH)},
488         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
489                        | S390X_CAPBIT(S390X_SHA_1)
490                        | S390X_CAPBIT(S390X_SHA_256)
491                        | S390X_CAPBIT(S390X_SHA_512),
492                        0ULL},
493         /*.km     = */{S390X_CAPBIT(S390X_QUERY)
494                        | S390X_CAPBIT(S390X_AES_128)
495                        | S390X_CAPBIT(S390X_AES_192)
496                        | S390X_CAPBIT(S390X_AES_256)
497                        | S390X_CAPBIT(S390X_XTS_AES_128)
498                        | S390X_CAPBIT(S390X_XTS_AES_256),
499                        0ULL},
500         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY)
501                        | S390X_CAPBIT(S390X_AES_128)
502                        | S390X_CAPBIT(S390X_AES_192)
503                        | S390X_CAPBIT(S390X_AES_256),
504                        0ULL},
505         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY)
506                        | S390X_CAPBIT(S390X_AES_128)
507                        | S390X_CAPBIT(S390X_AES_192)
508                        | S390X_CAPBIT(S390X_AES_256),
509                        0ULL},
510         /*.kmctr  = */{S390X_CAPBIT(S390X_QUERY)
511                        | S390X_CAPBIT(S390X_AES_128)
512                        | S390X_CAPBIT(S390X_AES_192)
513                        | S390X_CAPBIT(S390X_AES_256),
514                        0ULL},
515         /*.kmo    = */{S390X_CAPBIT(S390X_QUERY)
516                        | S390X_CAPBIT(S390X_AES_128)
517                        | S390X_CAPBIT(S390X_AES_192)
518                        | S390X_CAPBIT(S390X_AES_256),
519                        0ULL},
520         /*.kmf    = */{S390X_CAPBIT(S390X_QUERY)
521                        | S390X_CAPBIT(S390X_AES_128)
522                        | S390X_CAPBIT(S390X_AES_192)
523                        | S390X_CAPBIT(S390X_AES_256),
524                        0ULL},
525         /*.prno   = */{S390X_CAPBIT(S390X_QUERY)
526                        | S390X_CAPBIT(S390X_SHA_512_DRNG),
527                        0ULL},
528         /*.kma    = */{0ULL, 0ULL},
529         /*.pcc    = */{S390X_CAPBIT(S390X_QUERY),
530                        0ULL},
531         /*.kdsa   = */{0ULL, 0ULL},
532     };
533 
534     /*-
535      * z14 (2017) - z/Architecture POP SA22-7832-11
536      * Implements MSA and MSA1-8.
537      */
538     static const struct OPENSSL_s390xcap_st z14 = {
539         /*.stfle  = */{S390X_CAPBIT(S390X_MSA)
540                        | S390X_CAPBIT(S390X_STCKF)
541                        | S390X_CAPBIT(S390X_MSA5),
542                        S390X_CAPBIT(S390X_MSA3)
543                        | S390X_CAPBIT(S390X_MSA4),
544                        S390X_CAPBIT(S390X_VX)
545                        | S390X_CAPBIT(S390X_VXD)
546                        | S390X_CAPBIT(S390X_VXE)
547                        | S390X_CAPBIT(S390X_MSA8),
548                        0ULL},
549         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
550                        | S390X_CAPBIT(S390X_SHA_1)
551                        | S390X_CAPBIT(S390X_SHA_256)
552                        | S390X_CAPBIT(S390X_SHA_512)
553                        | S390X_CAPBIT(S390X_SHA3_224)
554                        | S390X_CAPBIT(S390X_SHA3_256)
555                        | S390X_CAPBIT(S390X_SHA3_384)
556                        | S390X_CAPBIT(S390X_SHA3_512)
557                        | S390X_CAPBIT(S390X_SHAKE_128)
558                        | S390X_CAPBIT(S390X_SHAKE_256),
559                        S390X_CAPBIT(S390X_GHASH)},
560         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
561                        | S390X_CAPBIT(S390X_SHA_1)
562                        | S390X_CAPBIT(S390X_SHA_256)
563                        | S390X_CAPBIT(S390X_SHA_512)
564                        | S390X_CAPBIT(S390X_SHA3_224)
565                        | S390X_CAPBIT(S390X_SHA3_256)
566                        | S390X_CAPBIT(S390X_SHA3_384)
567                        | S390X_CAPBIT(S390X_SHA3_512)
568                        | S390X_CAPBIT(S390X_SHAKE_128)
569                        | S390X_CAPBIT(S390X_SHAKE_256),
570                        0ULL},
571         /*.km     = */{S390X_CAPBIT(S390X_QUERY)
572                        | S390X_CAPBIT(S390X_AES_128)
573                        | S390X_CAPBIT(S390X_AES_192)
574                        | S390X_CAPBIT(S390X_AES_256)
575                        | S390X_CAPBIT(S390X_XTS_AES_128)
576                        | S390X_CAPBIT(S390X_XTS_AES_256),
577                        0ULL},
578         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY)
579                        | S390X_CAPBIT(S390X_AES_128)
580                        | S390X_CAPBIT(S390X_AES_192)
581                        | S390X_CAPBIT(S390X_AES_256),
582                        0ULL},
583         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY)
584                        | S390X_CAPBIT(S390X_AES_128)
585                        | S390X_CAPBIT(S390X_AES_192)
586                        | S390X_CAPBIT(S390X_AES_256),
587                        0ULL},
588         /*.kmctr  = */{S390X_CAPBIT(S390X_QUERY)
589                        | S390X_CAPBIT(S390X_AES_128)
590                        | S390X_CAPBIT(S390X_AES_192)
591                        | S390X_CAPBIT(S390X_AES_256),
592                        0ULL},
593         /*.kmo    = */{S390X_CAPBIT(S390X_QUERY)
594                        | S390X_CAPBIT(S390X_AES_128)
595                        | S390X_CAPBIT(S390X_AES_192)
596                        | S390X_CAPBIT(S390X_AES_256),
597                        0ULL},
598         /*.kmf    = */{S390X_CAPBIT(S390X_QUERY)
599                        | S390X_CAPBIT(S390X_AES_128)
600                        | S390X_CAPBIT(S390X_AES_192)
601                        | S390X_CAPBIT(S390X_AES_256),
602                        0ULL},
603         /*.prno   = */{S390X_CAPBIT(S390X_QUERY)
604                        | S390X_CAPBIT(S390X_SHA_512_DRNG),
605                        S390X_CAPBIT(S390X_TRNG)},
606         /*.kma    = */{S390X_CAPBIT(S390X_QUERY)
607                        | S390X_CAPBIT(S390X_AES_128)
608                        | S390X_CAPBIT(S390X_AES_192)
609                        | S390X_CAPBIT(S390X_AES_256),
610                        0ULL},
611         /*.pcc    = */{S390X_CAPBIT(S390X_QUERY),
612                        0ULL},
613         /*.kdsa   = */{0ULL, 0ULL},
614     };
615 
616     /*-
617      * z15 (2019) - z/Architecture POP SA22-7832-12
618      * Implements MSA and MSA1-9.
619      */
620     static const struct OPENSSL_s390xcap_st z15 = {
621         /*.stfle  = */{S390X_CAPBIT(S390X_MSA)
622                        | S390X_CAPBIT(S390X_STCKF)
623                        | S390X_CAPBIT(S390X_MSA5),
624                        S390X_CAPBIT(S390X_MSA3)
625                        | S390X_CAPBIT(S390X_MSA4),
626                        S390X_CAPBIT(S390X_VX)
627                        | S390X_CAPBIT(S390X_VXD)
628                        | S390X_CAPBIT(S390X_VXE)
629                        | S390X_CAPBIT(S390X_MSA8)
630                        | S390X_CAPBIT(S390X_MSA9),
631                        0ULL},
632         /*.kimd   = */{S390X_CAPBIT(S390X_QUERY)
633                        | S390X_CAPBIT(S390X_SHA_1)
634                        | S390X_CAPBIT(S390X_SHA_256)
635                        | S390X_CAPBIT(S390X_SHA_512)
636                        | S390X_CAPBIT(S390X_SHA3_224)
637                        | S390X_CAPBIT(S390X_SHA3_256)
638                        | S390X_CAPBIT(S390X_SHA3_384)
639                        | S390X_CAPBIT(S390X_SHA3_512)
640                        | S390X_CAPBIT(S390X_SHAKE_128)
641                        | S390X_CAPBIT(S390X_SHAKE_256),
642                        S390X_CAPBIT(S390X_GHASH)},
643         /*.klmd   = */{S390X_CAPBIT(S390X_QUERY)
644                        | S390X_CAPBIT(S390X_SHA_1)
645                        | S390X_CAPBIT(S390X_SHA_256)
646                        | S390X_CAPBIT(S390X_SHA_512)
647                        | S390X_CAPBIT(S390X_SHA3_224)
648                        | S390X_CAPBIT(S390X_SHA3_256)
649                        | S390X_CAPBIT(S390X_SHA3_384)
650                        | S390X_CAPBIT(S390X_SHA3_512)
651                        | S390X_CAPBIT(S390X_SHAKE_128)
652                        | S390X_CAPBIT(S390X_SHAKE_256),
653                        0ULL},
654         /*.km     = */{S390X_CAPBIT(S390X_QUERY)
655                        | S390X_CAPBIT(S390X_AES_128)
656                        | S390X_CAPBIT(S390X_AES_192)
657                        | S390X_CAPBIT(S390X_AES_256)
658                        | S390X_CAPBIT(S390X_XTS_AES_128)
659                        | S390X_CAPBIT(S390X_XTS_AES_256),
660                        0ULL},
661         /*.kmc    = */{S390X_CAPBIT(S390X_QUERY)
662                        | S390X_CAPBIT(S390X_AES_128)
663                        | S390X_CAPBIT(S390X_AES_192)
664                        | S390X_CAPBIT(S390X_AES_256),
665                        0ULL},
666         /*.kmac   = */{S390X_CAPBIT(S390X_QUERY)
667                        | S390X_CAPBIT(S390X_AES_128)
668                        | S390X_CAPBIT(S390X_AES_192)
669                        | S390X_CAPBIT(S390X_AES_256),
670                        0ULL},
671         /*.kmctr  = */{S390X_CAPBIT(S390X_QUERY)
672                        | S390X_CAPBIT(S390X_AES_128)
673                        | S390X_CAPBIT(S390X_AES_192)
674                        | S390X_CAPBIT(S390X_AES_256),
675                        0ULL},
676         /*.kmo    = */{S390X_CAPBIT(S390X_QUERY)
677                        | S390X_CAPBIT(S390X_AES_128)
678                        | S390X_CAPBIT(S390X_AES_192)
679                        | S390X_CAPBIT(S390X_AES_256),
680                        0ULL},
681         /*.kmf    = */{S390X_CAPBIT(S390X_QUERY)
682                        | S390X_CAPBIT(S390X_AES_128)
683                        | S390X_CAPBIT(S390X_AES_192)
684                        | S390X_CAPBIT(S390X_AES_256),
685                        0ULL},
686         /*.prno   = */{S390X_CAPBIT(S390X_QUERY)
687                        | S390X_CAPBIT(S390X_SHA_512_DRNG),
688                        S390X_CAPBIT(S390X_TRNG)},
689         /*.kma    = */{S390X_CAPBIT(S390X_QUERY)
690                        | S390X_CAPBIT(S390X_AES_128)
691                        | S390X_CAPBIT(S390X_AES_192)
692                        | S390X_CAPBIT(S390X_AES_256),
693                        0ULL},
694         /*.pcc    = */{S390X_CAPBIT(S390X_QUERY),
695                        S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P256)
696                        | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P384)
697                        | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P521)
698                        | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
699                        | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
700                        | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)
701                        | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)},
702         /*.kdsa   = */{S390X_CAPBIT(S390X_QUERY)
703                        | S390X_CAPBIT(S390X_ECDSA_VERIFY_P256)
704                        | S390X_CAPBIT(S390X_ECDSA_VERIFY_P384)
705                        | S390X_CAPBIT(S390X_ECDSA_VERIFY_P521)
706                        | S390X_CAPBIT(S390X_ECDSA_SIGN_P256)
707                        | S390X_CAPBIT(S390X_ECDSA_SIGN_P384)
708                        | S390X_CAPBIT(S390X_ECDSA_SIGN_P521)
709                        | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)
710                        | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)
711                        | S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
712                        | S390X_CAPBIT(S390X_EDDSA_SIGN_ED448),
713                        0ULL},
714     };
715 
716     /*-
717      * z16 (2022) - z/Architecture POP
718      * Implements MSA and MSA1-9 (same as z15, no need to repeat).
719      */
720 
721     char *tok_begin, *tok_end, *buff, tok[S390X_STFLE_MAX][LEN + 1];
722     int rc, off, i, n;
723 
724     buff = malloc(strlen(env) + 1);
725     if (buff == NULL)
726         return 0;
727 
728     rc = 0;
729     memset(cap, ~0, sizeof(*cap));
730     strcpy(buff, env);
731 
732     tok_begin = buff + strspn(buff, ";");
733     strtok(tok_begin, ";");
734     tok_end = strtok(NULL, ";");
735 
736     while (tok_begin != NULL) {
737         /* stfle token */
738         if ((n = sscanf(tok_begin,
739                         " stfle : %" STR(LEN) "[^:] : "
740                         "%" STR(LEN) "[^:] : %" STR(LEN) "s ",
741                         tok[0], tok[1], tok[2]))) {
742             for (i = 0; i < n; i++) {
743                 off = (tok[i][0] == '~') ? 1 : 0;
744                 if (sscanf(tok[i] + off, "%llx", &cap->stfle[i]) != 1)
745                     goto ret;
746                 if (off)
747                     cap->stfle[i] = ~cap->stfle[i];
748             }
749         }
750 
751         /* query function tokens */
752         else if TOK_FUNC(kimd)
753         else if TOK_FUNC(klmd)
754         else if TOK_FUNC(km)
755         else if TOK_FUNC(kmc)
756         else if TOK_FUNC(kmac)
757         else if TOK_FUNC(kmctr)
758         else if TOK_FUNC(kmo)
759         else if TOK_FUNC(kmf)
760         else if TOK_FUNC(prno)
761         else if TOK_FUNC(kma)
762         else if TOK_FUNC(pcc)
763         else if TOK_FUNC(kdsa)
764 
765         /* CPU model tokens */
766         else if TOK_CPU(z900)
767         else if TOK_CPU(z990)
768         else if TOK_CPU(z9)
769         else if TOK_CPU(z10)
770         else if TOK_CPU(z196)
771         else if TOK_CPU(zEC12)
772         else if TOK_CPU(z13)
773         else if TOK_CPU(z14)
774         else if TOK_CPU(z15)
775         else if TOK_CPU_ALIAS(z16, z15)
776 
777         /* nocex to deactivate cex support */
778         else if (sscanf(tok_begin, " %" STR(LEN) "s %" STR(LEN) "s ",
779                         tok[0], tok[1]) == 1
780                 && !strcmp(tok[0], "nocex")) {
781             *cex = 0;
782         }
783 
784         /* whitespace(ignored) or invalid tokens */
785         else {
786             while (*tok_begin != '\0') {
787                 if (!ossl_isspace(*tok_begin))
788                     goto ret;
789                 tok_begin++;
790             }
791         }
792 
793         tok_begin = tok_end;
794         tok_end = strtok(NULL, ";");
795     }
796 
797     rc = 1;
798 ret:
799     free(buff);
800     return rc;
801 }
802