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