1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci#include <string.h>
11e1051a39Sopenharmony_ci#include <openssl/evp.h>
12e1051a39Sopenharmony_ci#include <openssl/params.h>
13e1051a39Sopenharmony_ci#include <openssl/crypto.h>
14e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
15e1051a39Sopenharmony_ci#include <openssl/fipskey.h>
16e1051a39Sopenharmony_ci#include <openssl/err.h>
17e1051a39Sopenharmony_ci#include <openssl/proverr.h>
18e1051a39Sopenharmony_ci#include "e_os.h"
19e1051a39Sopenharmony_ci#include "prov/providercommon.h"
20e1051a39Sopenharmony_ci
21e1051a39Sopenharmony_ci/*
22e1051a39Sopenharmony_ci * We're cheating here. Normally we don't allow RUN_ONCE usage inside the FIPS
23e1051a39Sopenharmony_ci * module because all such initialisation should be associated with an
24e1051a39Sopenharmony_ci * individual OSSL_LIB_CTX. That doesn't work with the self test though because
25e1051a39Sopenharmony_ci * it should be run once regardless of the number of OSSL_LIB_CTXs we have.
26e1051a39Sopenharmony_ci */
27e1051a39Sopenharmony_ci#define ALLOW_RUN_ONCE_IN_FIPS
28e1051a39Sopenharmony_ci#include "internal/thread_once.h"
29e1051a39Sopenharmony_ci#include "self_test.h"
30e1051a39Sopenharmony_ci
31e1051a39Sopenharmony_ci#define FIPS_STATE_INIT     0
32e1051a39Sopenharmony_ci#define FIPS_STATE_SELFTEST 1
33e1051a39Sopenharmony_ci#define FIPS_STATE_RUNNING  2
34e1051a39Sopenharmony_ci#define FIPS_STATE_ERROR    3
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ci/*
37e1051a39Sopenharmony_ci * The number of times the module will report it is in the error state
38e1051a39Sopenharmony_ci * before going quiet.
39e1051a39Sopenharmony_ci */
40e1051a39Sopenharmony_ci#define FIPS_ERROR_REPORTING_RATE_LIMIT     10
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci/* The size of a temp buffer used to read in data */
43e1051a39Sopenharmony_ci#define INTEGRITY_BUF_SIZE (4096)
44e1051a39Sopenharmony_ci#define MAX_MD_SIZE 64
45e1051a39Sopenharmony_ci#define MAC_NAME    "HMAC"
46e1051a39Sopenharmony_ci#define DIGEST_NAME "SHA256"
47e1051a39Sopenharmony_ci
48e1051a39Sopenharmony_cistatic int FIPS_conditional_error_check = 1;
49e1051a39Sopenharmony_cistatic CRYPTO_RWLOCK *self_test_lock = NULL;
50e1051a39Sopenharmony_cistatic CRYPTO_RWLOCK *fips_state_lock = NULL;
51e1051a39Sopenharmony_cistatic unsigned char fixed_key[32] = { FIPS_KEY_ELEMENTS };
52e1051a39Sopenharmony_ci
53e1051a39Sopenharmony_cistatic CRYPTO_ONCE fips_self_test_init = CRYPTO_ONCE_STATIC_INIT;
54e1051a39Sopenharmony_ciDEFINE_RUN_ONCE_STATIC(do_fips_self_test_init)
55e1051a39Sopenharmony_ci{
56e1051a39Sopenharmony_ci    /*
57e1051a39Sopenharmony_ci     * These locks get freed in platform specific ways that may occur after we
58e1051a39Sopenharmony_ci     * do mem leak checking. If we don't know how to free it for a particular
59e1051a39Sopenharmony_ci     * platform then we just leak it deliberately.
60e1051a39Sopenharmony_ci     */
61e1051a39Sopenharmony_ci    self_test_lock = CRYPTO_THREAD_lock_new();
62e1051a39Sopenharmony_ci    fips_state_lock = CRYPTO_THREAD_lock_new();
63e1051a39Sopenharmony_ci    return self_test_lock != NULL;
64e1051a39Sopenharmony_ci}
65e1051a39Sopenharmony_ci
66e1051a39Sopenharmony_ci/*
67e1051a39Sopenharmony_ci * Declarations for the DEP entry/exit points.
68e1051a39Sopenharmony_ci * Ones not required or incorrect need to be undefined or redefined respectively.
69e1051a39Sopenharmony_ci */
70e1051a39Sopenharmony_ci#define DEP_INITIAL_STATE   FIPS_STATE_INIT
71e1051a39Sopenharmony_ci#define DEP_INIT_ATTRIBUTE  static
72e1051a39Sopenharmony_ci#define DEP_FINI_ATTRIBUTE  static
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_cistatic void init(void);
75e1051a39Sopenharmony_cistatic void cleanup(void);
76e1051a39Sopenharmony_ci
77e1051a39Sopenharmony_ci/*
78e1051a39Sopenharmony_ci * This is the Default Entry Point (DEP) code.
79e1051a39Sopenharmony_ci * See FIPS 140-2 IG 9.10
80e1051a39Sopenharmony_ci */
81e1051a39Sopenharmony_ci#if defined(_WIN32) || defined(__CYGWIN__)
82e1051a39Sopenharmony_ci# ifdef __CYGWIN__
83e1051a39Sopenharmony_ci/* pick DLL_[PROCESS|THREAD]_[ATTACH|DETACH] definitions */
84e1051a39Sopenharmony_ci#  include <windows.h>
85e1051a39Sopenharmony_ci/*
86e1051a39Sopenharmony_ci * this has side-effect of _WIN32 getting defined, which otherwise is
87e1051a39Sopenharmony_ci * mutually exclusive with __CYGWIN__...
88e1051a39Sopenharmony_ci */
89e1051a39Sopenharmony_ci# endif
90e1051a39Sopenharmony_ci
91e1051a39Sopenharmony_ciBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
92e1051a39Sopenharmony_ciBOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
93e1051a39Sopenharmony_ci{
94e1051a39Sopenharmony_ci    switch (fdwReason) {
95e1051a39Sopenharmony_ci    case DLL_PROCESS_ATTACH:
96e1051a39Sopenharmony_ci        init();
97e1051a39Sopenharmony_ci        break;
98e1051a39Sopenharmony_ci    case DLL_PROCESS_DETACH:
99e1051a39Sopenharmony_ci        cleanup();
100e1051a39Sopenharmony_ci        break;
101e1051a39Sopenharmony_ci    default:
102e1051a39Sopenharmony_ci        break;
103e1051a39Sopenharmony_ci    }
104e1051a39Sopenharmony_ci    return TRUE;
105e1051a39Sopenharmony_ci}
106e1051a39Sopenharmony_ci
107e1051a39Sopenharmony_ci#elif defined(__GNUC__) && !defined(_AIX)
108e1051a39Sopenharmony_ci# undef DEP_INIT_ATTRIBUTE
109e1051a39Sopenharmony_ci# undef DEP_FINI_ATTRIBUTE
110e1051a39Sopenharmony_ci# define DEP_INIT_ATTRIBUTE static __attribute__((constructor))
111e1051a39Sopenharmony_ci# define DEP_FINI_ATTRIBUTE static __attribute__((destructor))
112e1051a39Sopenharmony_ci
113e1051a39Sopenharmony_ci#elif defined(__sun)
114e1051a39Sopenharmony_ci# pragma init(init)
115e1051a39Sopenharmony_ci# pragma fini(cleanup)
116e1051a39Sopenharmony_ci
117e1051a39Sopenharmony_ci#elif defined(_AIX) && !defined(__GNUC__)
118e1051a39Sopenharmony_civoid _init(void);
119e1051a39Sopenharmony_civoid _cleanup(void);
120e1051a39Sopenharmony_ci# pragma init(_init)
121e1051a39Sopenharmony_ci# pragma fini(_cleanup)
122e1051a39Sopenharmony_civoid _init(void)
123e1051a39Sopenharmony_ci{
124e1051a39Sopenharmony_ci    init();
125e1051a39Sopenharmony_ci}
126e1051a39Sopenharmony_civoid _cleanup(void)
127e1051a39Sopenharmony_ci{
128e1051a39Sopenharmony_ci    cleanup();
129e1051a39Sopenharmony_ci}
130e1051a39Sopenharmony_ci
131e1051a39Sopenharmony_ci#elif defined(__hpux)
132e1051a39Sopenharmony_ci# pragma init "init"
133e1051a39Sopenharmony_ci# pragma fini "cleanup"
134e1051a39Sopenharmony_ci
135e1051a39Sopenharmony_ci#elif defined(__TANDEM)
136e1051a39Sopenharmony_ci/* Method automatically called by the NonStop OS when the DLL loads */
137e1051a39Sopenharmony_civoid __INIT__init(void) {
138e1051a39Sopenharmony_ci    init();
139e1051a39Sopenharmony_ci}
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci/* Method automatically called by the NonStop OS prior to unloading the DLL */
142e1051a39Sopenharmony_civoid __TERM__cleanup(void) {
143e1051a39Sopenharmony_ci    cleanup();
144e1051a39Sopenharmony_ci}
145e1051a39Sopenharmony_ci
146e1051a39Sopenharmony_ci#else
147e1051a39Sopenharmony_ci/*
148e1051a39Sopenharmony_ci * This build does not support any kind of DEP.
149e1051a39Sopenharmony_ci * We force the self-tests to run as part of the FIPS provider initialisation
150e1051a39Sopenharmony_ci * rather than being triggered by the DEP.
151e1051a39Sopenharmony_ci */
152e1051a39Sopenharmony_ci# undef DEP_INIT_ATTRIBUTE
153e1051a39Sopenharmony_ci# undef DEP_FINI_ATTRIBUTE
154e1051a39Sopenharmony_ci# undef DEP_INITIAL_STATE
155e1051a39Sopenharmony_ci# define DEP_INITIAL_STATE  FIPS_STATE_SELFTEST
156e1051a39Sopenharmony_ci#endif
157e1051a39Sopenharmony_ci
158e1051a39Sopenharmony_cistatic int FIPS_state = DEP_INITIAL_STATE;
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci#if defined(DEP_INIT_ATTRIBUTE)
161e1051a39Sopenharmony_ciDEP_INIT_ATTRIBUTE void init(void)
162e1051a39Sopenharmony_ci{
163e1051a39Sopenharmony_ci    FIPS_state = FIPS_STATE_SELFTEST;
164e1051a39Sopenharmony_ci}
165e1051a39Sopenharmony_ci#endif
166e1051a39Sopenharmony_ci
167e1051a39Sopenharmony_ci#if defined(DEP_FINI_ATTRIBUTE)
168e1051a39Sopenharmony_ciDEP_FINI_ATTRIBUTE void cleanup(void)
169e1051a39Sopenharmony_ci{
170e1051a39Sopenharmony_ci    CRYPTO_THREAD_lock_free(self_test_lock);
171e1051a39Sopenharmony_ci    CRYPTO_THREAD_lock_free(fips_state_lock);
172e1051a39Sopenharmony_ci}
173e1051a39Sopenharmony_ci#endif
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci/*
176e1051a39Sopenharmony_ci * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify
177e1051a39Sopenharmony_ci * the result matches the expected value.
178e1051a39Sopenharmony_ci * Return 1 if verified, or 0 if it fails.
179e1051a39Sopenharmony_ci */
180e1051a39Sopenharmony_cistatic int verify_integrity(OSSL_CORE_BIO *bio, OSSL_FUNC_BIO_read_ex_fn read_ex_cb,
181e1051a39Sopenharmony_ci                            unsigned char *expected, size_t expected_len,
182e1051a39Sopenharmony_ci                            OSSL_LIB_CTX *libctx, OSSL_SELF_TEST *ev,
183e1051a39Sopenharmony_ci                            const char *event_type)
184e1051a39Sopenharmony_ci{
185e1051a39Sopenharmony_ci    int ret = 0, status;
186e1051a39Sopenharmony_ci    unsigned char out[MAX_MD_SIZE];
187e1051a39Sopenharmony_ci    unsigned char buf[INTEGRITY_BUF_SIZE];
188e1051a39Sopenharmony_ci    size_t bytes_read = 0, out_len = 0;
189e1051a39Sopenharmony_ci    EVP_MAC *mac = NULL;
190e1051a39Sopenharmony_ci    EVP_MAC_CTX *ctx = NULL;
191e1051a39Sopenharmony_ci    OSSL_PARAM params[2], *p = params;
192e1051a39Sopenharmony_ci
193e1051a39Sopenharmony_ci    OSSL_SELF_TEST_onbegin(ev, event_type, OSSL_SELF_TEST_DESC_INTEGRITY_HMAC);
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci    mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL);
196e1051a39Sopenharmony_ci    if (mac == NULL)
197e1051a39Sopenharmony_ci        goto err;
198e1051a39Sopenharmony_ci    ctx = EVP_MAC_CTX_new(mac);
199e1051a39Sopenharmony_ci    if (ctx == NULL)
200e1051a39Sopenharmony_ci        goto err;
201e1051a39Sopenharmony_ci
202e1051a39Sopenharmony_ci    *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, 0);
203e1051a39Sopenharmony_ci    *p = OSSL_PARAM_construct_end();
204e1051a39Sopenharmony_ci
205e1051a39Sopenharmony_ci    if (!EVP_MAC_init(ctx, fixed_key, sizeof(fixed_key), params))
206e1051a39Sopenharmony_ci        goto err;
207e1051a39Sopenharmony_ci
208e1051a39Sopenharmony_ci    while (1) {
209e1051a39Sopenharmony_ci        status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read);
210e1051a39Sopenharmony_ci        if (status != 1)
211e1051a39Sopenharmony_ci            break;
212e1051a39Sopenharmony_ci        if (!EVP_MAC_update(ctx, buf, bytes_read))
213e1051a39Sopenharmony_ci            goto err;
214e1051a39Sopenharmony_ci    }
215e1051a39Sopenharmony_ci    if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out)))
216e1051a39Sopenharmony_ci        goto err;
217e1051a39Sopenharmony_ci
218e1051a39Sopenharmony_ci    OSSL_SELF_TEST_oncorrupt_byte(ev, out);
219e1051a39Sopenharmony_ci    if (expected_len != out_len
220e1051a39Sopenharmony_ci            || memcmp(expected, out, out_len) != 0)
221e1051a39Sopenharmony_ci        goto err;
222e1051a39Sopenharmony_ci    ret = 1;
223e1051a39Sopenharmony_cierr:
224e1051a39Sopenharmony_ci    OSSL_SELF_TEST_onend(ev, ret);
225e1051a39Sopenharmony_ci    EVP_MAC_CTX_free(ctx);
226e1051a39Sopenharmony_ci    EVP_MAC_free(mac);
227e1051a39Sopenharmony_ci    return ret;
228e1051a39Sopenharmony_ci}
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_cistatic void set_fips_state(int state)
231e1051a39Sopenharmony_ci{
232e1051a39Sopenharmony_ci    if (ossl_assert(CRYPTO_THREAD_write_lock(fips_state_lock) != 0)) {
233e1051a39Sopenharmony_ci        FIPS_state = state;
234e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(fips_state_lock);
235e1051a39Sopenharmony_ci    }
236e1051a39Sopenharmony_ci}
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci/* This API is triggered either on loading of the FIPS module or on demand */
239e1051a39Sopenharmony_ciint SELF_TEST_post(SELF_TEST_POST_PARAMS *st, int on_demand_test)
240e1051a39Sopenharmony_ci{
241e1051a39Sopenharmony_ci    int ok = 0;
242e1051a39Sopenharmony_ci    int kats_already_passed = 0;
243e1051a39Sopenharmony_ci    long checksum_len;
244e1051a39Sopenharmony_ci    OSSL_CORE_BIO *bio_module = NULL, *bio_indicator = NULL;
245e1051a39Sopenharmony_ci    unsigned char *module_checksum = NULL;
246e1051a39Sopenharmony_ci    unsigned char *indicator_checksum = NULL;
247e1051a39Sopenharmony_ci    int loclstate;
248e1051a39Sopenharmony_ci    OSSL_SELF_TEST *ev = NULL;
249e1051a39Sopenharmony_ci
250e1051a39Sopenharmony_ci    if (!RUN_ONCE(&fips_self_test_init, do_fips_self_test_init))
251e1051a39Sopenharmony_ci        return 0;
252e1051a39Sopenharmony_ci
253e1051a39Sopenharmony_ci    if (!CRYPTO_THREAD_read_lock(fips_state_lock))
254e1051a39Sopenharmony_ci        return 0;
255e1051a39Sopenharmony_ci    loclstate = FIPS_state;
256e1051a39Sopenharmony_ci    CRYPTO_THREAD_unlock(fips_state_lock);
257e1051a39Sopenharmony_ci
258e1051a39Sopenharmony_ci    if (loclstate == FIPS_STATE_RUNNING) {
259e1051a39Sopenharmony_ci        if (!on_demand_test)
260e1051a39Sopenharmony_ci            return 1;
261e1051a39Sopenharmony_ci    } else if (loclstate != FIPS_STATE_SELFTEST) {
262e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
263e1051a39Sopenharmony_ci        return 0;
264e1051a39Sopenharmony_ci    }
265e1051a39Sopenharmony_ci
266e1051a39Sopenharmony_ci    if (!CRYPTO_THREAD_write_lock(self_test_lock))
267e1051a39Sopenharmony_ci        return 0;
268e1051a39Sopenharmony_ci    if (!CRYPTO_THREAD_read_lock(fips_state_lock)) {
269e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(self_test_lock);
270e1051a39Sopenharmony_ci        return 0;
271e1051a39Sopenharmony_ci    }
272e1051a39Sopenharmony_ci    if (FIPS_state == FIPS_STATE_RUNNING) {
273e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(fips_state_lock);
274e1051a39Sopenharmony_ci        if (!on_demand_test) {
275e1051a39Sopenharmony_ci            CRYPTO_THREAD_unlock(self_test_lock);
276e1051a39Sopenharmony_ci            return 1;
277e1051a39Sopenharmony_ci        }
278e1051a39Sopenharmony_ci        set_fips_state(FIPS_STATE_SELFTEST);
279e1051a39Sopenharmony_ci    } else if (FIPS_state != FIPS_STATE_SELFTEST) {
280e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(fips_state_lock);
281e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(self_test_lock);
282e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_STATE);
283e1051a39Sopenharmony_ci        return 0;
284e1051a39Sopenharmony_ci    } else {
285e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(fips_state_lock);
286e1051a39Sopenharmony_ci    }
287e1051a39Sopenharmony_ci
288e1051a39Sopenharmony_ci    if (st == NULL
289e1051a39Sopenharmony_ci            || st->module_checksum_data == NULL) {
290e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA);
291e1051a39Sopenharmony_ci        goto end;
292e1051a39Sopenharmony_ci    }
293e1051a39Sopenharmony_ci
294e1051a39Sopenharmony_ci    ev = OSSL_SELF_TEST_new(st->cb, st->cb_arg);
295e1051a39Sopenharmony_ci    if (ev == NULL)
296e1051a39Sopenharmony_ci        goto end;
297e1051a39Sopenharmony_ci
298e1051a39Sopenharmony_ci    module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data,
299e1051a39Sopenharmony_ci                                         &checksum_len);
300e1051a39Sopenharmony_ci    if (module_checksum == NULL) {
301e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
302e1051a39Sopenharmony_ci        goto end;
303e1051a39Sopenharmony_ci    }
304e1051a39Sopenharmony_ci    bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb");
305e1051a39Sopenharmony_ci
306e1051a39Sopenharmony_ci    /* Always check the integrity of the fips module */
307e1051a39Sopenharmony_ci    if (bio_module == NULL
308e1051a39Sopenharmony_ci            || !verify_integrity(bio_module, st->bio_read_ex_cb,
309e1051a39Sopenharmony_ci                                 module_checksum, checksum_len, st->libctx,
310e1051a39Sopenharmony_ci                                 ev, OSSL_SELF_TEST_TYPE_MODULE_INTEGRITY)) {
311e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_MODULE_INTEGRITY_FAILURE);
312e1051a39Sopenharmony_ci        goto end;
313e1051a39Sopenharmony_ci    }
314e1051a39Sopenharmony_ci
315e1051a39Sopenharmony_ci    /* This will be NULL during installation - so the self test KATS will run */
316e1051a39Sopenharmony_ci    if (st->indicator_data != NULL) {
317e1051a39Sopenharmony_ci        /*
318e1051a39Sopenharmony_ci         * If the kats have already passed indicator is set - then check the
319e1051a39Sopenharmony_ci         * integrity of the indicator.
320e1051a39Sopenharmony_ci         */
321e1051a39Sopenharmony_ci        if (st->indicator_checksum_data == NULL) {
322e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_CONFIG_DATA);
323e1051a39Sopenharmony_ci            goto end;
324e1051a39Sopenharmony_ci        }
325e1051a39Sopenharmony_ci        indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data,
326e1051a39Sopenharmony_ci                                                &checksum_len);
327e1051a39Sopenharmony_ci        if (indicator_checksum == NULL) {
328e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CONFIG_DATA);
329e1051a39Sopenharmony_ci            goto end;
330e1051a39Sopenharmony_ci        }
331e1051a39Sopenharmony_ci
332e1051a39Sopenharmony_ci        bio_indicator =
333e1051a39Sopenharmony_ci            (*st->bio_new_buffer_cb)(st->indicator_data,
334e1051a39Sopenharmony_ci                                     strlen(st->indicator_data));
335e1051a39Sopenharmony_ci        if (bio_indicator == NULL
336e1051a39Sopenharmony_ci                || !verify_integrity(bio_indicator, st->bio_read_ex_cb,
337e1051a39Sopenharmony_ci                                     indicator_checksum, checksum_len,
338e1051a39Sopenharmony_ci                                     st->libctx, ev,
339e1051a39Sopenharmony_ci                                     OSSL_SELF_TEST_TYPE_INSTALL_INTEGRITY)) {
340e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_INDICATOR_INTEGRITY_FAILURE);
341e1051a39Sopenharmony_ci            goto end;
342e1051a39Sopenharmony_ci        } else {
343e1051a39Sopenharmony_ci            kats_already_passed = 1;
344e1051a39Sopenharmony_ci        }
345e1051a39Sopenharmony_ci    }
346e1051a39Sopenharmony_ci
347e1051a39Sopenharmony_ci    /*
348e1051a39Sopenharmony_ci     * Only runs the KAT's during installation OR on_demand().
349e1051a39Sopenharmony_ci     * NOTE: If the installation option 'self_test_onload' is chosen then this
350e1051a39Sopenharmony_ci     * path will always be run, since kats_already_passed will always be 0.
351e1051a39Sopenharmony_ci     */
352e1051a39Sopenharmony_ci    if (on_demand_test || kats_already_passed == 0) {
353e1051a39Sopenharmony_ci        if (!SELF_TEST_kats(ev, st->libctx)) {
354e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_SELF_TEST_KAT_FAILURE);
355e1051a39Sopenharmony_ci            goto end;
356e1051a39Sopenharmony_ci        }
357e1051a39Sopenharmony_ci    }
358e1051a39Sopenharmony_ci    ok = 1;
359e1051a39Sopenharmony_ciend:
360e1051a39Sopenharmony_ci    OSSL_SELF_TEST_free(ev);
361e1051a39Sopenharmony_ci    OPENSSL_free(module_checksum);
362e1051a39Sopenharmony_ci    OPENSSL_free(indicator_checksum);
363e1051a39Sopenharmony_ci
364e1051a39Sopenharmony_ci    if (st != NULL) {
365e1051a39Sopenharmony_ci        (*st->bio_free_cb)(bio_indicator);
366e1051a39Sopenharmony_ci        (*st->bio_free_cb)(bio_module);
367e1051a39Sopenharmony_ci    }
368e1051a39Sopenharmony_ci    if (ok)
369e1051a39Sopenharmony_ci        set_fips_state(FIPS_STATE_RUNNING);
370e1051a39Sopenharmony_ci    else
371e1051a39Sopenharmony_ci        ossl_set_error_state(OSSL_SELF_TEST_TYPE_NONE);
372e1051a39Sopenharmony_ci    CRYPTO_THREAD_unlock(self_test_lock);
373e1051a39Sopenharmony_ci
374e1051a39Sopenharmony_ci    return ok;
375e1051a39Sopenharmony_ci}
376e1051a39Sopenharmony_ci
377e1051a39Sopenharmony_civoid SELF_TEST_disable_conditional_error_state(void)
378e1051a39Sopenharmony_ci{
379e1051a39Sopenharmony_ci    FIPS_conditional_error_check = 0;
380e1051a39Sopenharmony_ci}
381e1051a39Sopenharmony_ci
382e1051a39Sopenharmony_civoid ossl_set_error_state(const char *type)
383e1051a39Sopenharmony_ci{
384e1051a39Sopenharmony_ci    int cond_test = (type != NULL && strcmp(type, OSSL_SELF_TEST_TYPE_PCT) == 0);
385e1051a39Sopenharmony_ci
386e1051a39Sopenharmony_ci    if (!cond_test || (FIPS_conditional_error_check == 1)) {
387e1051a39Sopenharmony_ci        set_fips_state(FIPS_STATE_ERROR);
388e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_ENTERING_ERROR_STATE);
389e1051a39Sopenharmony_ci    } else {
390e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_CONDITIONAL_ERROR);
391e1051a39Sopenharmony_ci    }
392e1051a39Sopenharmony_ci}
393e1051a39Sopenharmony_ci
394e1051a39Sopenharmony_ciint ossl_prov_is_running(void)
395e1051a39Sopenharmony_ci{
396e1051a39Sopenharmony_ci    int res;
397e1051a39Sopenharmony_ci    static unsigned int rate_limit = 0;
398e1051a39Sopenharmony_ci
399e1051a39Sopenharmony_ci    if (!CRYPTO_THREAD_read_lock(fips_state_lock))
400e1051a39Sopenharmony_ci        return 0;
401e1051a39Sopenharmony_ci    res = FIPS_state == FIPS_STATE_RUNNING
402e1051a39Sopenharmony_ci                        || FIPS_state == FIPS_STATE_SELFTEST;
403e1051a39Sopenharmony_ci    if (FIPS_state == FIPS_STATE_ERROR) {
404e1051a39Sopenharmony_ci        CRYPTO_THREAD_unlock(fips_state_lock);
405e1051a39Sopenharmony_ci        if (!CRYPTO_THREAD_write_lock(fips_state_lock))
406e1051a39Sopenharmony_ci            return 0;
407e1051a39Sopenharmony_ci        if (rate_limit++ < FIPS_ERROR_REPORTING_RATE_LIMIT)
408e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_FIPS_MODULE_IN_ERROR_STATE);
409e1051a39Sopenharmony_ci    }
410e1051a39Sopenharmony_ci    CRYPTO_THREAD_unlock(fips_state_lock);
411e1051a39Sopenharmony_ci    return res;
412e1051a39Sopenharmony_ci}
413