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