summaryrefslogtreecommitdiffstats
path: root/providers
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2019-09-15 19:55:10 +1000
committerShane Lontis <shane.lontis@oracle.com>2019-09-15 19:55:10 +1000
commit7bb82f92d94375e7673fe02cb8186595b2c539f2 (patch)
tree9ad368205615d359374430b91906e4c704135fae /providers
parentdd11c5f0fa809063b152cd2851c4c1e56fbd20c8 (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.info2
-rw-r--r--providers/fips/fipsprov.c12
-rw-r--r--providers/fips/selftest.c150
-rw-r--r--providers/fips/selftest.h7
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);