From 319e518a5ae17fb8def2bd9209675acbaa6c22c2 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Mon, 13 May 2019 06:41:06 +0100 Subject: [PATCH] Make some EVP code available from within the FIPS module Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/8728) --- crypto/build.info | 3 +- crypto/evp/build.info | 4 ++ crypto/evp/digest.c | 39 +++++++++++++++---- crypto/evp/evp_enc.c | 32 ++++++++++----- crypto/evp/evp_lib.c | 25 ++++++++---- crypto/lhash/build.info | 2 + crypto/property/build.info | 2 + crypto/property/property.c | 3 ++ providers/fips/fipsprov.c | 79 ++++++++++++++++++++++++++++++++++---- 9 files changed, 156 insertions(+), 33 deletions(-) diff --git a/crypto/build.info b/crypto/build.info index 546865bdc9..db6d6afbdc 100644 --- a/crypto/build.info +++ b/crypto/build.info @@ -27,7 +27,8 @@ SOURCE[../libcrypto]=\ # FIPS module SOURCE[../providers/fips]=\ cryptlib.c mem.c mem_clr.c params.c bsearch.c ex_data.c o_str.c \ - threads_pthread.c threads_win.c threads_none.c context.c + ctype.c threads_pthread.c threads_win.c threads_none.c context.c \ + sparse_array.c DEPEND[cversion.o]=buildinf.h diff --git a/crypto/evp/build.info b/crypto/evp/build.info index 23aa733a66..61e8880632 100644 --- a/crypto/evp/build.info +++ b/crypto/evp/build.info @@ -20,6 +20,10 @@ SOURCE[../../libcrypto]=\ SOURCE[../../libcrypto]=\ evp_fetch.c +# FIPS Module +SOURCE[../../providers/fips]=\ + digest.c evp_enc.c evp_lib.c evp_fetch.c cmeth_lib.c + INCLUDE[e_aes.o]=.. ../modes INCLUDE[e_aes_cbc_hmac_sha1.o]=../modes INCLUDE[e_aes_cbc_hmac_sha256.o]=../modes diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index dc50528607..a1f0154a7f 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -55,10 +55,14 @@ int EVP_MD_CTX_reset(EVP_MD_CTX *ctx) * pctx should be freed by the user of EVP_MD_CTX * if EVP_MD_CTX_FLAG_KEEP_PKEY_CTX is set */ +#ifndef FIPS_MODE + /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */ if (!EVP_MD_CTX_test_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX)) EVP_PKEY_CTX_free(ctx->pctx); -#ifndef OPENSSL_NO_ENGINE + +# ifndef OPENSSL_NO_ENGINE ENGINE_finish(ctx->engine); +# endif #endif OPENSSL_cleanse(ctx, sizeof(*ctx)); @@ -102,8 +106,9 @@ int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type) int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) { - EVP_MD *provmd; +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) ENGINE *tmpimpl = NULL; +#endif EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_CLEANED); @@ -111,7 +116,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) ctx->reqdigest = type; /* TODO(3.0): Legacy work around code below. Remove this */ -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) /* * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so * this context may already have an ENGINE! Try to avoid releasing the @@ -132,7 +137,9 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) */ if (ctx->engine != NULL || impl != NULL +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) || tmpimpl != NULL +#endif || ctx->pctx != NULL || (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) != 0) { if (ctx->digest == ctx->fetched_digest) @@ -160,7 +167,13 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) /* TODO(3.0): Start of non-legacy code below */ if (type->prov == NULL) { - provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), ""); +#ifdef FIPS_MODE + /* We only do explict fetches inside the FIPS module */ + EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; +#else + EVP_MD *provmd = EVP_MD_fetch(NULL, OBJ_nid2sn(type->type), ""); + if (provmd == NULL) { EVPerr(EVP_F_EVP_DIGESTINIT_EX, EVP_R_INITIALIZATION_ERROR); return 0; @@ -168,6 +181,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) type = provmd; EVP_MD_meth_free(ctx->fetched_digest); ctx->fetched_digest = provmd; +#endif } ctx->digest = type; @@ -189,7 +203,7 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) /* TODO(3.0): Remove legacy code below */ legacy: -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) if (type) { /* * Ensure an ENGINE left lying around from last time is cleared (the @@ -247,16 +261,19 @@ int EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *type, ENGINE *impl) } } } -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) skip_to_init: #endif - if (ctx->pctx) { +#ifndef FIPS_MODE + /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */ + if (ctx->pctx != NULL) { int r; r = EVP_PKEY_CTX_ctrl(ctx->pctx, -1, EVP_PKEY_OP_TYPE_SIG, EVP_PKEY_CTRL_DIGESTINIT, 0, ctx); if (r <= 0 && (r != -2)) return 0; } +#endif if (ctx->flags & EVP_MD_CTX_FLAG_NO_INIT) return 1; return ctx->digest->init(ctx); @@ -397,6 +414,8 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) /* copied EVP_MD_CTX should free the copied EVP_PKEY_CTX */ EVP_MD_CTX_clear_flags(out, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); +#ifndef FIPS_MODE + /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */ if (in->pctx != NULL) { out->pctx = EVP_PKEY_CTX_dup(in->pctx); if (out->pctx == NULL) { @@ -405,12 +424,13 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) return 0; } } +#endif return 1; /* TODO(3.0): Remove legacy code below */ legacy: -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) /* Make sure it's safe to copy a digest context using an ENGINE */ if (in->engine && !ENGINE_init(in->engine)) { EVPerr(EVP_F_EVP_MD_CTX_COPY_EX, ERR_R_ENGINE_LIB); @@ -451,6 +471,8 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) out->update = in->update; +#ifndef FIPS_MODE + /* TODO(3.0): Temporarily no support for EVP_DigestSign* in FIPS module */ if (in->pctx) { out->pctx = EVP_PKEY_CTX_dup(in->pctx); if (!out->pctx) { @@ -458,6 +480,7 @@ int EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in) return 0; } } +#endif if (out->digest->copy) return out->digest->copy(out, in); diff --git a/crypto/evp/evp_enc.c b/crypto/evp/evp_enc.c index d0566ad170..b3e97d005d 100644 --- a/crypto/evp/evp_enc.c +++ b/crypto/evp/evp_enc.c @@ -51,7 +51,7 @@ int EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *ctx) OPENSSL_cleanse(ctx->cipher_data, ctx->cipher->ctx_size); } OPENSSL_free(ctx->cipher_data); -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) ENGINE_finish(ctx->engine); #endif memset(ctx, 0, sizeof(*ctx)); @@ -81,8 +81,9 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc) { - EVP_CIPHER *provciph = NULL; +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) ENGINE *tmpimpl = NULL; +#endif const EVP_CIPHER *tmpcipher; /* @@ -105,7 +106,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, /* TODO(3.0): Legacy work around code below. Remove this */ -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) /* * Whether it's nice or not, "Inits" can be used on "Final"'d contexts so * this context may already have an ENGINE! Try to avoid releasing the @@ -126,8 +127,10 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, * If there are engines involved then we should use legacy handling for now. */ if (ctx->engine != NULL - || impl != NULL - || tmpimpl != NULL) { +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) + || tmpimpl != NULL +#endif + || impl != NULL) { if (ctx->cipher == ctx->fetched_cipher) ctx->cipher = NULL; EVP_CIPHER_meth_free(ctx->fetched_cipher); @@ -194,7 +197,14 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, cipher = ctx->cipher; if (cipher->prov == NULL) { - provciph = EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), ""); +#ifdef FIPS_MODE + /* We only do explict fetches inside the FIPS module */ + EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); + return 0; +#else + EVP_CIPHER *provciph = + EVP_CIPHER_fetch(NULL, OBJ_nid2sn(cipher->nid), ""); + if (provciph == NULL) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); return 0; @@ -202,6 +212,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, cipher = provciph; EVP_CIPHER_meth_free(ctx->fetched_cipher); ctx->fetched_cipher = provciph; +#endif } ctx->cipher = cipher; @@ -279,7 +290,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ctx->encrypt = enc; ctx->flags = flags; } -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) if (impl != NULL) { if (!ENGINE_init(impl)) { EVPerr(EVP_F_EVP_CIPHERINIT_EX, EVP_R_INITIALIZATION_ERROR); @@ -335,7 +346,7 @@ int EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, } } } -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) skip_to_init: #endif if (ctx->cipher == NULL) @@ -966,6 +977,8 @@ int EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr) return ret; } +#if !defined(FIPS_MODE) +/* TODO(3.0): No support for RAND yet in the FIPS module */ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) { int kl; @@ -976,6 +989,7 @@ int EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, unsigned char *key) return 0; return 1; } +#endif int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) { @@ -1013,7 +1027,7 @@ int EVP_CIPHER_CTX_copy(EVP_CIPHER_CTX *out, const EVP_CIPHER_CTX *in) /* TODO(3.0): Remove legacy code below */ legacy: -#ifndef OPENSSL_NO_ENGINE +#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE) /* Make sure it's safe to copy a cipher context using an ENGINE */ if (in->engine && !ENGINE_init(in->engine)) { EVPerr(EVP_F_EVP_CIPHER_CTX_COPY, ERR_R_ENGINE_LIB); diff --git a/crypto/evp/evp_lib.c b/crypto/evp/evp_lib.c index 34b938281e..faaa69d338 100644 --- a/crypto/evp/evp_lib.c +++ b/crypto/evp/evp_lib.c @@ -17,6 +17,7 @@ #include "internal/provider.h" #include "evp_locl.h" +#if !defined(FIPS_MODE) int EVP_CIPHER_param_to_asn1(EVP_CIPHER_CTX *c, ASN1_TYPE *type) { int ret; @@ -146,12 +147,12 @@ int EVP_CIPHER_set_asn1_iv(EVP_CIPHER_CTX *c, ASN1_TYPE *type) } return i; } +#endif /* !defined(FIPS_MODE) */ /* Convert the various cipher NIDs and dummies to a proper OID NID */ int EVP_CIPHER_type(const EVP_CIPHER *ctx) { int nid; - ASN1_OBJECT *otmp; nid = EVP_CIPHER_nid(ctx); switch (nid) { @@ -198,12 +199,19 @@ int EVP_CIPHER_type(const EVP_CIPHER *ctx) return NID_des_cfb64; default: - /* Check it has an OID and it is valid */ - otmp = OBJ_nid2obj(nid); - if (OBJ_get0_data(otmp) == NULL) - nid = NID_undef; - ASN1_OBJECT_free(otmp); - return nid; +#ifdef FIPS_MODE + return NID_undef; +#else + { + /* Check it has an OID and it is valid */ + ASN1_OBJECT *otmp = OBJ_nid2obj(nid); + + if (OBJ_get0_data(otmp) == NULL) + nid = NID_undef; + ASN1_OBJECT_free(otmp); + return nid; + } +#endif } } @@ -596,6 +604,8 @@ EVP_PKEY_CTX *EVP_MD_CTX_pkey_ctx(const EVP_MD_CTX *ctx) return ctx->pctx; } +#if !defined(FIPS_MODE) +/* TODO(3.0): EVP_DigestSign* not yet supported in FIPS module */ void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx) { /* @@ -614,6 +624,7 @@ void EVP_MD_CTX_set_pkey_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pctx) EVP_MD_CTX_clear_flags(ctx, EVP_MD_CTX_FLAG_KEEP_PKEY_CTX); } } +#endif /* !defined(FIPS_MODE) */ void *EVP_MD_CTX_md_data(const EVP_MD_CTX *ctx) { diff --git a/crypto/lhash/build.info b/crypto/lhash/build.info index 30797f2caf..0aa12a1eb3 100644 --- a/crypto/lhash/build.info +++ b/crypto/lhash/build.info @@ -1,3 +1,5 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ lhash.c lh_stats.c +SOURCE[../../providers/fips]=\ + lhash.c diff --git a/crypto/property/build.info b/crypto/property/build.info index 3a86b6e141..3bdf307c92 100644 --- a/crypto/property/build.info +++ b/crypto/property/build.info @@ -1,3 +1,5 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=property_string.c property_parse.c property.c \ property_err.c defn_cache.c +SOURCE[../../providers/fips]=\ + property_string.c property_parse.c property.c defn_cache.c diff --git a/crypto/property/property.c b/crypto/property/property.c index 9dd8f6a3ff..4c328ffbd8 100644 --- a/crypto/property/property.c +++ b/crypto/property/property.c @@ -391,6 +391,8 @@ IMPLEMENT_LHASH_DOALL_ARG(QUERY, IMPL_CACHE_FLUSH); */ static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state) { +#if !defined(FIPS_MODE) +/* TODO(3.0): No RAND_bytes yet in FIPS module. Add this back when available */ OSSL_METHOD_STORE *store = state->store; unsigned int n; @@ -404,6 +406,7 @@ static void impl_cache_flush_cache(QUERY *c, IMPL_CACHE_FLUSH *state) OPENSSL_free(lh_QUERY_delete(state->cache, c)); else state->nelem++; +#endif /* !defined(FIPS_MODE) */ } static void impl_cache_flush_one_alg(ossl_uintmax_t idx, ALGORITHM *alg, diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c index 026dd2f9a9..801a9fd045 100644 --- a/providers/fips/fipsprov.c +++ b/providers/fips/fipsprov.c @@ -14,7 +14,12 @@ #include #include #include +#include +/* TODO(3.0): Needed for dummy_evp_call(). To be removed */ +#include #include "internal/cryptlib.h" +#include "internal/property.h" +#include "internal/evp_int.h" /* Functions provided by the core */ static OSSL_core_get_param_types_fn *c_get_param_types = NULL; @@ -30,9 +35,38 @@ static const OSSL_ITEM fips_param_types[] = { { 0, NULL } }; -static void fips_teardown(void) +/* TODO(3.0): To be removed */ +static int dummy_evp_call(OPENSSL_CTX *libctx) { - do_default_context_deinit(); + EVP_MD_CTX *ctx = EVP_MD_CTX_new(); + EVP_MD *sha256 = EVP_MD_fetch(libctx, "SHA256", NULL); + char msg[] = "Hello World!"; + const unsigned char exptd[] = { + 0x7f, 0x83, 0xb1, 0x65, 0x7f, 0xf1, 0xfc, 0x53, 0xb9, 0x2d, 0xc1, 0x81, + 0x48, 0xa1, 0xd6, 0x5d, 0xfc, 0x2d, 0x4b, 0x1f, 0xa3, 0xd6, 0x77, 0x28, + 0x4a, 0xdd, 0xd2, 0x00, 0x12, 0x6d, 0x90, 0x69 + }; + unsigned int dgstlen = 0; + unsigned char dgst[SHA256_DIGEST_LENGTH]; + int ret = 0; + + if (ctx == NULL || sha256 == NULL) + goto err; + + if (!EVP_DigestInit_ex(ctx, sha256, NULL)) + goto err; + if (!EVP_DigestUpdate(ctx, msg, sizeof(msg) - 1)) + goto err; + if (!EVP_DigestFinal(ctx, dgst, &dgstlen)) + goto err; + if (dgstlen != sizeof(exptd) || memcmp(dgst, exptd, sizeof(exptd)) != 0) + goto err; + + ret = 1; + err: + EVP_MD_CTX_free(ctx); + EVP_MD_meth_free(sha256); + return ret; } static const OSSL_ITEM *fips_get_param_types(const OSSL_PROVIDER *prov) @@ -79,18 +113,31 @@ static const OSSL_ALGORITHM *fips_query(OSSL_PROVIDER *prov, /* Functions we provide to the core */ static const OSSL_DISPATCH fips_dispatch_table[] = { - { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))fips_teardown }, + /* + * To release our resources we just need to free the OPENSSL_CTX so we just + * use OPENSSL_CTX_free directly as our teardown function + */ + { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))OPENSSL_CTX_free }, { OSSL_FUNC_PROVIDER_GET_PARAM_TYPES, (void (*)(void))fips_get_param_types }, { OSSL_FUNC_PROVIDER_GET_PARAMS, (void (*)(void))fips_get_params }, { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query }, { 0, NULL } }; +/* Functions we provide to ourself */ +static const OSSL_DISPATCH intern_dispatch_table[] = { + { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))fips_query }, + { 0, NULL } +}; + + int OSSL_provider_init(const OSSL_PROVIDER *provider, const OSSL_DISPATCH *in, const OSSL_DISPATCH **out, void **provctx) { + OPENSSL_CTX *ctx; + for (; in->function_id != 0; in++) { switch (in->function_id) { case OSSL_FUNC_CORE_GET_PARAM_TYPES: @@ -111,19 +158,35 @@ int OSSL_provider_init(const OSSL_PROVIDER *provider, } } + ctx = OPENSSL_CTX_new(); + if (ctx == NULL) + return 0; + + /* + * TODO(3.0): Remove me. This is just a dummy call to demonstrate making + * EVP calls from within the FIPS module. + */ + if (!dummy_evp_call(ctx)) { + OPENSSL_CTX_free(ctx); + return 0; + } + *out = fips_dispatch_table; + *provctx = ctx; return 1; } +/* + * The internal init function used when the FIPS module uses EVP to call + * another algorithm also in the FIPS module. + */ OSSL_provider_init_fn fips_intern_provider_init; int fips_intern_provider_init(const OSSL_PROVIDER *provider, const OSSL_DISPATCH *in, - const OSSL_DISPATCH **out) + const OSSL_DISPATCH **out, + void **provctx) { - /* - * The internal init function used when the FIPS module uses EVP to call - * another algorithm also in the FIPS module. - */ + *out = intern_dispatch_table; return 1; } -- 2.34.1