Hi, Sorry for taking so long to review. At least some early review comments:
On 04-12-17 22:16, j...@carroll.com wrote: > From: Jim Carroll <j...@carroll.com> > > Signed-off-by: Jim Carroll <j...@carroll.com> > --- > INSTALL | 78 > ++++++++++++++++++++++++++++++++++++++++++++ > Makefile.am | 5 +++ > configure.ac | 41 +++++++++++++++++++++++ > src/openvpn/crypto.c | 2 +- > src/openvpn/crypto_backend.h | 3 +- > src/openvpn/crypto_openssl.c | 16 ++++++++- > src/openvpn/crypto_openssl.h | 8 +++++ > src/openvpn/ntlm.c | 2 +- > src/openvpn/openvpn.c | 9 +++++ > src/openvpn/options.c | 18 ++++++++++ > src/openvpn/options.h | 3 ++ > src/openvpn/ssl.c | 12 +++++-- > src/openvpn/ssl.h | 4 +++ > 13 files changed, 195 insertions(+), 6 deletions(-) > > diff --git a/INSTALL b/INSTALL > index 3a31e6f..b001cb1 100644 > --- a/INSTALL > +++ b/INSTALL > @@ -305,6 +305,84 @@ TUN/TAP Driver Configuration: > > ************************************************************************* > > +OpenSSL FIPS Object Module v2.0 Configuration: > + > +These instructions were adapted from > + > + https://www.openssl.org/docs/fipsnotes.html > + > +Requirements: > + > + * OpenSSL 1.0.2m > + * openssl-fips-2.0.2 > + > +WARNING > + > +To install FIPS Validated encryption, you must follow the instructions in the > +FIPS 2.0 User's Guide precisely. You are not permitted to modify any of the > FIPS > +build artifacts, makefiles or scripts. The FIPS 2.0 module is only > compatible with > +OpenSSL 1.0.1 and 1.0.2. > + > +These instructions describe the use of OpenSSL 1.0.2m. > + > +PRE-INSTALLATION CHECKUP: > + > + The INSTALLATION procecure describes how to install an OpenSSL library > that > + is built with FIPS support. If your platform already provides a FIPS > + enabled library you can skip to step 6 (build OpenVPN). > + > +INSTALLATION: > + > + 1. Surf to https://www.openssl.org/source/ > + 2. Download source AND validate the download was correct (preferably > using PGP) > + 3. Untar and uncompress tarball > + 4. You must build using this precise command (do NOT choose any other > options): > + > + # ./config && make install > + > + (you may optionslly pass 'no-asm' to config) > + > + If the above procedure does not build on your system -- STOP. You are > not > + building on a FIPS supported platform, and therefore will not have a > + FIPS validated encryption environment. See chapter 3 of the FIPS 2.0 > + User's Guide for the complete list of supported platforms: > + > + https://openssl.org/docs/fips/UserGuide-2.0.pdf > + > + 5. Download, build & install openssl 1.0.2m (you are permitted to > + modify this step to suite your preferences): > + > + # git clone https://github.com/openssl/openssl.git > + # (cd openssl && \ > + git checkout OpenSSL_1_0_2m && \ > + ./config fips && \ > + make depend && \ > + make install) > + > + 6. Now build openvpn and tell it where to find you recently installed > OpenSSL > + > + # ./configure --enable-fips-mode \ > + OPENSSL_CFLAGS=-I/usr/local/ssl/include \ > + OPENSSL_LIBS="-ldl -L/usr/local/ssl/lib -lssl -lcrypto" > + > + # make install > + > + 7. You can confirm FIPS mode is available with the command > + > + # ./openvpn --version | grep 'library version' > + library versions: OpenSSL 1.0.2m-fips 2 Nov 2017, LZO 2.08 > + > +USAGE: > + > +The above adds a new '--enable-fips-mode' command line option to OpenVPN. > Add this to your > +invocation statement. If you've successfully configured OpenVPN for FIPS > mode, check your > +OpenVPN logs for the statement: > + > + *** FIPS MODE ENABLE *** > + > + > +************************************************************************* > + > CAVEATS & BUGS: > > * I have noticed cases where TCP sessions tunneled over the Linux > diff --git a/Makefile.am b/Makefile.am > index 773b786..6d571ec 100644 > --- a/Makefile.am > +++ b/Makefile.am > @@ -83,6 +83,11 @@ rootdir=$(prefix) > root_DATA = version.sh > endif > > +if FIPSMODE > +export CC > +export FIPSLD_CC > +endif > + > config-version.h: > @CONFIGURE_GIT_CHFILES="`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) > diff-files --name-status -r --ignore-submodules --quiet -- || echo \"+\"`"; \ > CONFIGURE_GIT_UNCOMMITTED="`GIT_DIR=\"$(top_srcdir)/.git\" $(GIT) > diff-index --cached --quiet --ignore-submodules HEAD || echo \"*\"`"; \ > diff --git a/configure.ac b/configure.ac > index b4fd1b3..dc74230 100644 > --- a/configure.ac > +++ b/configure.ac > @@ -286,6 +286,17 @@ AC_ARG_WITH( > [with_crypto_library="openssl"] > ) > > +AC_ARG_ENABLE( > + [fips-mode], > + [AS_HELP_STRING([--enable-fips-mode], [OpenSSL FIPS Object Module 2.0 > @<:@default=no@:>@])], > + [ > + if test "${with_crypto_library}" != "openssl"; then > + AC_MSG_ERROR([enable_fips_mode requires > --with_crypto_library=openssl]) > + fi > + ], > + [enable_fips_mode="no"] > +) > + > AC_ARG_VAR([PLUGINDIR], [Path of plug-in directory > @<:@default=LIBDIR/openvpn/plugins@:>@]) > if test -n "${PLUGINDIR}"; then > plugindir="${PLUGINDIR}" > @@ -948,6 +959,35 @@ if test "${with_crypto_library}" = "openssl"; then > ] > ) > > + if test "${enable_fips_mode}" = "yes"; then > + AC_CHECK_FUNCS( > + [ \ > + FIPS_mode \ > + FIPS_mode_set \ > + SSLeay_version > + ], > + [], > + [AC_MSG_ERROR([Incorrect version of OpenSSL, require 1.0.2])] This isn't really the version check that fails, right? Something like "Couldn't find functions required for FIPS" sounds more accurate. > + ) > + AC_RUN_IFELSE( > + [AC_LANG_PROGRAM( > + [[#include <openssl/crypto.h>]], > + [[printf("%s\n", SSLeay_version(SSLEAY_DIR));]]) > + ], > + [AC_SUBST(OPENSSLDIR, > + [[`./conftest$EXEEXT | $SED -n 's/.*"\(.*\)".*/\1/p'`]]) > + ] > + ) Instead of calling SSLeay_version(), consider using the OPENSSL_VERSION define, like we already do elsewhere in configure.ac. That will not break as soon as there is a FIPS-compliant 1.1 release (which the openssl devs say there will be "soon"). > + if ! test -x "${OPENSSLDIR}/fips-2.0/bin/fipsld"; then > + AC_MSG_ERROR([Incomplete OpenSSL FIPS installation; missing > fipsld]) > + fi > + AC_SUBST([FIPSLD_CC], ["${CC}"]) > + AC_SUBST([CC], ["${OPENSSLDIR}/fips-2.0/bin/fipsld"]) > + export CC > + export FIPSLD_CC > + AC_DEFINE([ENABLE_FIPS], [1], [Enable OpenSSL FIPS 2.0 Options]) > + fi > + > CFLAGS="${saved_CFLAGS}" > LIBS="${saved_LIBS}" > > @@ -1359,6 +1399,7 @@ AM_CONDITIONAL([GIT_CHECKOUT], [test "${GIT_CHECKOUT}" > = "yes"]) > AM_CONDITIONAL([ENABLE_PLUGIN_AUTH_PAM], [test "${enable_plugin_auth_pam}" = > "yes"]) > AM_CONDITIONAL([ENABLE_PLUGIN_DOWN_ROOT], [test "${enable_plugin_down_root}" > = "yes"]) > AM_CONDITIONAL([HAVE_LD_WRAP_SUPPORT], [test "${have_ld_wrap_support}" = > "yes"]) > +AM_CONDITIONAL([FIPSMODE], [test "${enable_fips_mode}" = "yes"]) > > sampledir="\$(docdir)/sample" > AC_SUBST([plugindir]) > diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c > index 3096f3b..97d117b 100644 > --- a/src/openvpn/crypto.c > +++ b/src/openvpn/crypto.c > @@ -852,7 +852,7 @@ init_key_ctx(struct key_ctx *ctx, const struct key *key, > if (kt->digest && kt->hmac_length > 0) > { > ctx->hmac = hmac_ctx_new(); > - hmac_ctx_init(ctx->hmac, key->hmac, kt->hmac_length, kt->digest); > + hmac_ctx_init(ctx->hmac, key->hmac, kt->hmac_length, kt->digest, > false); > > msg(D_HANDSHAKE, > "%s: Using %d bit message hash '%s' for HMAC authentication", > diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h > index 567fd9b..8790ca5 100644 > --- a/src/openvpn/crypto_backend.h > +++ b/src/openvpn/crypto_backend.h > @@ -604,10 +604,11 @@ void hmac_ctx_free(hmac_ctx_t *ctx); > * @param key The key to use for the HMAC > * @param key_len The key length to use > * @param kt Static message digest parameters > + * @param prf_use Intended use for PRF in TLS protocol > * > */ > void hmac_ctx_init(hmac_ctx_t *ctx, const uint8_t *key, int key_length, > - const md_kt_t *kt); > + const md_kt_t *kt, bool prf_use); Instead of adding this parameter, I'd prefer to add a hmac_ctx_set_fips_prf() function. That way all the non-prf hmac calls don't have to change. > /* > * Free the given HMAC context. > diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c > index 20a519e..fe4cef3 100644 > --- a/src/openvpn/crypto_openssl.c > +++ b/src/openvpn/crypto_openssl.c > @@ -159,6 +159,18 @@ crypto_init_lib(void) > #endif > } > > +int > +crypto_enable_fips_mode(int mode) > +{ > + if (!FIPS_mode_set(mode)) > + { > + ERR_print_errors_fp(stderr); > + return 1; > + } > + msg(M_INFO, "*** FIPS MODE ENABLED ***"); > + return 0; > +} > + > void > crypto_uninit_lib(void) > { > @@ -926,11 +938,13 @@ hmac_ctx_free(HMAC_CTX *ctx) > > void > hmac_ctx_init(HMAC_CTX *ctx, const uint8_t *key, int key_len, > - const EVP_MD *kt) > + const EVP_MD *kt, bool prf_use) > { > ASSERT(NULL != kt && NULL != ctx); > > HMAC_CTX_reset(ctx); > + if (kt == EVP_md5() && prf_use) > + HMAC_CTX_set_flags(ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW); Please always use braces for a branch. > HMAC_Init_ex(ctx, key, key_len, kt, NULL); > > /* make sure we used a big enough key */ > diff --git a/src/openvpn/crypto_openssl.h b/src/openvpn/crypto_openssl.h > index 60a2812..fbc8b2a 100644 > --- a/src/openvpn/crypto_openssl.h > +++ b/src/openvpn/crypto_openssl.h > @@ -102,4 +102,12 @@ void crypto_print_openssl_errors(const unsigned int > flags); > } while (false) > > > +/** > + * Enable FIPS Mode. Returns non-zero to indicate an error. > + * > + * @param mode Should be 1. Future versions of OpenSSL FIPS > + * code are expected to accept extended modes. > + */ > +int crypto_enable_fips_mode(int mode); > + > #endif /* CRYPTO_OPENSSL_H_ */ > diff --git a/src/openvpn/ntlm.c b/src/openvpn/ntlm.c > index 077fa3e..fe39ab1 100644 > --- a/src/openvpn/ntlm.c > +++ b/src/openvpn/ntlm.c > @@ -88,7 +88,7 @@ gen_hmac_md5(const uint8_t *data, int data_len, const > uint8_t *key, int key_len, > const md_kt_t *md5_kt = md_kt_get("MD5"); > hmac_ctx_t *hmac_ctx = hmac_ctx_new(); > > - hmac_ctx_init(hmac_ctx, key, key_len, md5_kt); > + hmac_ctx_init(hmac_ctx, key, key_len, md5_kt, false); > hmac_ctx_update(hmac_ctx, data, data_len); > hmac_ctx_final(hmac_ctx, result); > hmac_ctx_cleanup(hmac_ctx); > diff --git a/src/openvpn/openvpn.c b/src/openvpn/openvpn.c > index e237ee5..da8e852 100644 > --- a/src/openvpn/openvpn.c > +++ b/src/openvpn/openvpn.c > @@ -210,6 +210,15 @@ openvpn_main(int argc, char *argv[]) > /* parse command line options, and read configuration file */ > parse_argv(&c.options, argc, argv, M_USAGE, OPT_P_DEFAULT, NULL, > c.es); > > +#if ENABLE_FIPS > + if (c.options.fips_mode) > + { > + if (enable_fips_mode(c.options.fips_mode)) > + { > + break; > + } > + } > +#endif > #ifdef ENABLE_PLUGIN > /* plugins may contribute options configuration */ > init_verb_mute(&c, IVM_LEVEL_1); > diff --git a/src/openvpn/options.c b/src/openvpn/options.c > index 7be5f38..99d3ccc 100644 > --- a/src/openvpn/options.c > +++ b/src/openvpn/options.c > @@ -517,6 +517,11 @@ static const char usage_message[] = > "\n" > "Data Channel Encryption Options (must be compatible between peers):\n" > "(These options are meaningful for both Static Key & TLS-mode)\n" > +#ifdef ENABLE_FIPS > + "--enable-fips-mode : Enable OpenSSL FIPS Object Module v2.0.\n" > + " Setting this on the server will enforce FIPS > validated\n" > + " encryption on both client and server.\n" > +#endif > "--secret f [d] : Enable Static Key encryption mode (non-TLS).\n" > " Use shared secret file f, generate with --genkey.\n" > " The optional d parameter controls key > directionality.\n" > @@ -847,6 +852,9 @@ init_options(struct options *o, const bool init_gc) > o->scheduled_exit_interval = 5; > #endif > o->ciphername = "BF-CBC"; > +#ifdef ENABLE_FIPS > + o->fips_mode = 0; > +#endif > #ifdef HAVE_AEAD_CIPHER_MODES /* IV_NCP=2 requires GCM support */ > o->ncp_enabled = true; > #else > @@ -1550,6 +1558,9 @@ show_settings(const struct options *o) > SHOW_INT(persist_mode); > #endif > > +#ifdef ENABLE_FIPS > + SHOW_INT(fips_mode); > +#endif > SHOW_BOOL(show_ciphers); > SHOW_BOOL(show_digests); > SHOW_BOOL(show_engines); > @@ -7389,6 +7400,13 @@ add_option(struct options *options, > } > } > #endif /* USE_COMP */ > +#ifdef ENABLE_FIPS > + else if (streq(p[0], "enable-fips-mode") && !p[1]) > + { > + VERIFY_PERMISSION(OPT_P_GENERAL); > + options->fips_mode = 1; > + } > +#endif > else if (streq(p[0], "show-ciphers") && !p[1]) > { > VERIFY_PERMISSION(OPT_P_GENERAL); > diff --git a/src/openvpn/options.h b/src/openvpn/options.h > index f70760c..6ffe646 100644 > --- a/src/openvpn/options.h > +++ b/src/openvpn/options.h > @@ -186,6 +186,9 @@ struct options > bool persist_config; > int persist_mode; > > +#ifdef ENABLE_FIPS > + int fips_mode; > +#endif Use spaces for indentation. Also, sounds like this should be bool, rather than an int? > const char *key_pass_file; > bool show_ciphers; > bool show_digests; > diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c > index 7b42845..3992f4d 100644 > --- a/src/openvpn/ssl.c > +++ b/src/openvpn/ssl.c > @@ -352,6 +352,14 @@ init_ssl_lib(void) > crypto_init_lib(); > } > > +#if ENABLE_FIPS > +int > +enable_fips_mode(int mode) > +{ > + return crypto_enable_fips_mode(mode); > +} > +#endif > + > void > free_ssl_lib(void) > { > @@ -1638,8 +1646,8 @@ tls1_P_hash(const md_kt_t *md_kt, > chunk = md_kt_size(md_kt); > A1_len = md_kt_size(md_kt); > > - hmac_ctx_init(ctx, sec, sec_len, md_kt); > - hmac_ctx_init(ctx_tmp, sec, sec_len, md_kt); > + hmac_ctx_init(ctx, sec, sec_len, md_kt, true); > + hmac_ctx_init(ctx_tmp, sec, sec_len, md_kt, true); > > hmac_ctx_update(ctx,seed,seed_len); > hmac_ctx_final(ctx, A1); > diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h > index dd1ab0f..f251765 100644 > --- a/src/openvpn/ssl.h > +++ b/src/openvpn/ssl.h > @@ -598,4 +598,8 @@ bool is_hard_reset(int op, int key_method); > > void delayed_auth_pass_purge(void); > > +#if ENABLE_FIPS > +int enable_fips_mode(int mode); > +#endif > + > #endif /* ifndef OPENVPN_SSL_H */ > I hope to look into this patch more, and run some test later. Thanks so far, -Steffan ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, Slashdot.org! http://sdm.link/slashdot _______________________________________________ Openvpn-devel mailing list Openvpn-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/openvpn-devel