diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2019-09-15 19:55:10 +1000 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2019-09-15 19:55:10 +1000 |
commit | 7bb82f92d94375e7673fe02cb8186595b2c539f2 (patch) | |
tree | 9ad368205615d359374430b91906e4c704135fae /providers | |
parent | dd11c5f0fa809063b152cd2851c4c1e56fbd20c8 (diff) |
Add fips module integrity check
Add environment variable for setting CONF .include path
Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9769)
Diffstat (limited to 'providers')
-rw-r--r-- | providers/fips/build.info | 2 | ||||
-rw-r--r-- | providers/fips/fipsprov.c | 12 | ||||
-rw-r--r-- | providers/fips/selftest.c | 150 | ||||
-rw-r--r-- | providers/fips/selftest.h | 7 |
4 files changed, 166 insertions, 5 deletions
diff --git a/providers/fips/build.info b/providers/fips/build.info index 9372062261..9b8effa85c 100644 --- a/providers/fips/build.info +++ b/providers/fips/build.info @@ -1,2 +1,2 @@ -SOURCE[../fips]=fipsprov.c +SOURCE[../fips]=fipsprov.c selftest.c diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index cff172921c..67ce90ac13 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -464,8 +464,8 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider, case OSSL_FUNC_BIO_NEW_MEMBUF: selftest_params.bio_new_buffer_cb = OSSL_get_BIO_new_membuf(in); break; - case OSSL_FUNC_BIO_READ: - selftest_params.bio_read_cb = OSSL_get_BIO_read(in); + case OSSL_FUNC_BIO_READ_EX: + selftest_params.bio_read_ex_cb = OSSL_get_BIO_read_ex(in); break; case OSSL_FUNC_BIO_FREE: selftest_params.bio_free_cb = OSSL_get_BIO_free(in); @@ -487,7 +487,15 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider, OPENSSL_CTX_free(ctx); return 0; } + fgbl->prov = provider; + + selftest_params.libctx = PROV_LIBRARY_CONTEXT_OF(ctx); + if (!SELF_TEST_post(&selftest_params)) { + OPENSSL_CTX_free(ctx); + return 0; + } + *out = fips_dispatch_table; *provctx = ctx; diff --git a/providers/fips/selftest.c b/providers/fips/selftest.c new file mode 100644 index 0000000000..a817b070e0 --- /dev/null +++ b/providers/fips/selftest.c @@ -0,0 +1,150 @@ +/* + * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <string.h> +#include <openssl/evp.h> +#include <openssl/params.h> +#include "selftest.h" + +#define FIPS_STATE_INIT 0 +#define FIPS_STATE_RUNNING 1 +#define FIPS_STATE_SELFTEST 2 +#define FIPS_STATE_ERROR 3 + +/* The size of a temp buffer used to read in data */ +#define INTEGRITY_BUF_SIZE (4096) +#define MAX_MD_SIZE 64 +#define MAC_NAME "HMAC" +#define DIGEST_NAME "SHA256" + +static int FIPS_state = FIPS_STATE_INIT; +static unsigned char fixed_key[32] = { 0 }; + +/* + * Calculate the HMAC SHA256 of data read using a BIO and read_cb, and verify + * the result matches the expected value. + * Return 1 if verified, or 0 if it fails. + */ +static int verify_integrity(BIO *bio, OSSL_BIO_read_ex_fn read_ex_cb, + unsigned char *expected, size_t expected_len, + OPENSSL_CTX *libctx) +{ + int ret = 0, status; + unsigned char out[MAX_MD_SIZE]; + unsigned char buf[INTEGRITY_BUF_SIZE]; + size_t bytes_read = 0, out_len = 0; + EVP_MAC *mac = NULL; + EVP_MAC_CTX *ctx = NULL; + OSSL_PARAM params[3], *p = params; + + mac = EVP_MAC_fetch(libctx, MAC_NAME, NULL); + ctx = EVP_MAC_CTX_new(mac); + if (mac == NULL || ctx == NULL) + goto err; + + *p++ = OSSL_PARAM_construct_utf8_string("digest", DIGEST_NAME, + strlen(DIGEST_NAME) + 1); + *p++ = OSSL_PARAM_construct_octet_string("key", fixed_key, + sizeof(fixed_key)); + *p = OSSL_PARAM_construct_end(); + + if (EVP_MAC_CTX_set_params(ctx, params) <= 0 + || !EVP_MAC_init(ctx)) + goto err; + + while (1) { + status = read_ex_cb(bio, buf, sizeof(buf), &bytes_read); + if (status != 1) + break; + if (!EVP_MAC_update(ctx, buf, bytes_read)) + goto err; + } + if (!EVP_MAC_final(ctx, out, &out_len, sizeof(out))) + goto err; + + if (expected_len != out_len + || memcmp(expected, out, out_len) != 0) + goto err; + ret = 1; +err: + EVP_MAC_CTX_free(ctx); + EVP_MAC_free(mac); + return ret; +} + +/* This API is triggered either on loading of the FIPS module or on demand */ +int SELF_TEST_post(SELF_TEST_POST_PARAMS *st) +{ + int ok = 0; + int kats_already_passed = 0; + int on_demand_test = (FIPS_state != FIPS_STATE_INIT); + long checksum_len; + BIO *bio_module = NULL, *bio_indicator = NULL; + unsigned char *module_checksum = NULL; + unsigned char *indicator_checksum = NULL; + + if (st == NULL + || FIPS_state == FIPS_STATE_ERROR + || FIPS_state == FIPS_STATE_SELFTEST + || st->module_checksum_data == NULL) + goto end; + + module_checksum = OPENSSL_hexstr2buf(st->module_checksum_data, + &checksum_len); + if (module_checksum == NULL) + goto end; + bio_module = (*st->bio_new_file_cb)(st->module_filename, "rb"); + + /* Always check the integrity of the fips module */ + if (bio_module == NULL + || !verify_integrity(bio_module, st->bio_read_ex_cb, + module_checksum, checksum_len, st->libctx)) + goto end; + + /* This will be NULL during installation - so the self test KATS will run */ + if (st->indicator_data != NULL) { + /* + * If the kats have already passed indicator is set - then check the + * integrity of the indicator. + */ + if (st->indicator_checksum_data == NULL) + goto end; + indicator_checksum = OPENSSL_hexstr2buf(st->indicator_checksum_data, + &checksum_len); + if (indicator_checksum == NULL) + goto end; + + bio_indicator = + (*st->bio_new_buffer_cb)(st->indicator_data, + strlen(st->indicator_data)); + if (bio_indicator == NULL + || !verify_integrity(bio_indicator, st->bio_read_ex_cb, + indicator_checksum, checksum_len, + st->libctx)) + goto end; + else + kats_already_passed = 1; + } + + /* Only runs the KAT's during installation OR on_demand() */ + if (on_demand_test || kats_already_passed == 0) { + /*TODO (3.0) Add self test KATS */ + } + ok = 1; +end: + OPENSSL_free(module_checksum); + OPENSSL_free(indicator_checksum); + + (*st->bio_free_cb)(bio_indicator); + (*st->bio_free_cb)(bio_module); + + FIPS_state = ok ? FIPS_STATE_RUNNING : FIPS_STATE_ERROR; + + return ok; +} diff --git a/providers/fips/selftest.h b/providers/fips/selftest.h index 3a183f4d02..3e97e0d786 100644 --- a/providers/fips/selftest.h +++ b/providers/fips/selftest.h @@ -7,8 +7,8 @@ * https://www.openssl.org/source/license.html */ -#include <openssl/params.h> #include <openssl/core_numbers.h> +#include <openssl/ossl_typ.h> typedef struct self_test_post_params_st { /* FIPS module integrity check parameters */ @@ -23,7 +23,10 @@ typedef struct self_test_post_params_st { /* BIO callbacks supplied to the FIPS provider */ OSSL_BIO_new_file_fn *bio_new_file_cb; OSSL_BIO_new_membuf_fn *bio_new_buffer_cb; - OSSL_BIO_read_fn *bio_read_cb; + OSSL_BIO_read_ex_fn *bio_read_ex_cb; OSSL_BIO_free_fn *bio_free_cb; + OPENSSL_CTX *libctx; } SELF_TEST_POST_PARAMS; + +int SELF_TEST_post(SELF_TEST_POST_PARAMS *st); |