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