From c4b3183feeb45d11e87f605bd99001ef92f99c47 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Mon, 1 Jun 2015 23:49:43 +0200 Subject: [PATCH] crypto: support FIPS mode of OpenSSL Support building and running with FIPS-compliant OpenSSL. The process is following: 1. Download and verify `openssl-fips-x.x.x.tar.gz` from https://www.openssl.org/source/ 2. Extract source to `openssl-fips` folder 3. `cd openssl-fips && ./config fipscanisterbuild --prefix=`pwd`/out` 4. `make -j && make install` 5. Get into io.js checkout folder 6. `./configure --openssl-fips=/path/to/openssl-fips/out` 7. Build io.js with `make -j` Fix: https://github.com/joyent/node/issues/25463 --- configure | 26 ++++++++++++++- deps/openssl/fips/fipsld.diff | 60 +++++++++++++++++++++++++++++++++++ deps/openssl/openssl.gyp | 20 ++++++++++++ src/node_crypto.cc | 10 ++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 deps/openssl/fips/fipsld.diff diff --git a/configure b/configure index 5c9b29bf2c2d40..85c75f41fbf851 100755 --- a/configure +++ b/configure @@ -88,6 +88,11 @@ parser.add_option("--openssl-no-asm", dest="openssl_no_asm", help="Do not build optimized assembly for OpenSSL") +parser.add_option("--openssl-fips", + action="store", + dest="openssl_fips", + help="Build OpenSSL using FIPS canister .o file in supplied folder") + shared_optgroup.add_option('--shared-http-parser', action='store_true', dest='shared_http_parser', @@ -720,6 +725,14 @@ def configure_openssl(o): o['variables']['node_use_openssl'] = b(not options.without_ssl) o['variables']['node_shared_openssl'] = b(options.shared_openssl) o['variables']['openssl_no_asm'] = 1 if options.openssl_no_asm else 0 + if options.openssl_fips: + o['variables']['openssl_fips'] = options.openssl_fips + o['make_global_settings'] = [ + ['LINK', '<(openssl_fips)/bin/fipsld'], + ] + else: + o['variables']['openssl_fips'] = '' + if options.without_ssl: return @@ -1025,10 +1038,21 @@ configure_fullystatic(output) # move everything else to target_defaults variables = output['variables'] del output['variables'] + +# make_global_settings should be a root level element too +if 'make_global_settings' in output: + make_global_settings = output['make_global_settings'] + del output['make_global_settings'] +else: + make_global_settings = False + output = { 'variables': variables, - 'target_defaults': output + 'target_defaults': output, } +if make_global_settings != False: + output['make_global_settings'] = make_global_settings + pprint.pprint(output, indent=2) write('config.gypi', do_not_edit + diff --git a/deps/openssl/fips/fipsld.diff b/deps/openssl/fips/fipsld.diff new file mode 100644 index 00000000000000..507f78b5ff7d6e --- /dev/null +++ b/deps/openssl/fips/fipsld.diff @@ -0,0 +1,60 @@ +diff --git a/out/bin/fipsld.bak b/out/bin/fipsld +index 62565fd..3e7ce4f 100755 +--- a/out/bin/fipsld.bak ++++ b/out/bin/fipsld +@@ -12,6 +12,7 @@ + + #set -x + ++CC=${CXX} + CC=${FIPSLD_CC:-${CC}} + [ -n "${CC}" ] || { echo '$CC is not defined'; exit 1; } + +@@ -36,9 +37,9 @@ TARGET=`(while [ "x$1" != "x" -a "x$1" != "x-o" ]; do shift; done; echo $2)` + # procedures are already embedded into and executed in shared library + # context. + case `basename "${TARGET}"` in +-libcrypto*|libfips*|*.dll) ;; ++libopenssl*|libcrypto*|libfips*|*.dll) ;; + *) case "$*" in +- *libcrypto.a*|*-lcrypto*|*fipscanister.o*) ;; ++ *libopenssl.a*|*libcrypto.a*|*-lcrypto*|*fipscanister.o*) ;; + *) exec ${CC} "$@" ;; + esac + esac +@@ -124,7 +125,7 @@ lib*|*.dll) # must be linking a shared lib... + + /bin/rm -f "${TARGET}" + ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ +- "${PREMAIN_C}" \ ++ -x c "${PREMAIN_C}" -x none \ + ${_WL_PREMAIN} "$@" + + if [ "x${FIPS_SIG}" != "x" ]; then +@@ -143,7 +144,7 @@ lib*|*.dll) # must be linking a shared lib... + + # recompile with signature... + ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ +- -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" \ ++ -DHMAC_SHA1_SIG=\"${SIG}\" -x c "${PREMAIN_C}" -x none \ + ${_WL_PREMAIN} "$@" + ;; + +@@ -172,7 +173,7 @@ lib*|*.dll) # must be linking a shared lib... + + /bin/rm -f "${TARGET}" + ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ +- "${PREMAIN_C}" \ ++ -x c "${PREMAIN_C}" -x none \ + ${_WL_PREMAIN} "$@" + + if [ "x${FIPS_SIG}" != "x" ]; then +@@ -191,7 +192,7 @@ lib*|*.dll) # must be linking a shared lib... + + # recompile with signature... + ${CC} ${CANISTER_O_CMD:+"${CANISTER_O_CMD}"} \ +- -DHMAC_SHA1_SIG=\"${SIG}\" "${PREMAIN_C}" \ ++ -DHMAC_SHA1_SIG=\"${SIG}\" -x c "${PREMAIN_C}" -x none \ + ${_WL_PREMAIN} "$@" + ;; + esac diff --git a/deps/openssl/openssl.gyp b/deps/openssl/openssl.gyp index 5a3dc9b6c74210..1422816453370e 100644 --- a/deps/openssl/openssl.gyp +++ b/deps/openssl/openssl.gyp @@ -9,6 +9,7 @@ 'openssl_no_asm%': 0, 'llvm_version%': 0, 'gas_version%': 0, + 'openssl_fips%': 'false', }, 'targets': [ { @@ -21,6 +22,25 @@ ['exclude', 'store/.*$'] ], 'conditions': [ + # FIPS + ['openssl_fips != ""', { + 'defines': [ + 'OPENSSL_FIPS', + ], + 'include_dirs': [ + '<(openssl_fips)/include', + ], + + 'direct_dependent_settings': { + 'defines': [ + 'OPENSSL_FIPS', + ], + 'include_dirs': [ + '<(openssl_fips)/include', + ], + }, + }], + ['openssl_no_asm!=0', { # Disable asm 'defines': [ diff --git a/src/node_crypto.cc b/src/node_crypto.cc index e2c478a510be84..ba2e804f0e78e6 100644 --- a/src/node_crypto.cc +++ b/src/node_crypto.cc @@ -5071,6 +5071,16 @@ void InitCryptoOnce() { CRYPTO_set_locking_callback(crypto_lock_cb); CRYPTO_THREADID_set_callback(crypto_threadid_cb); +#ifdef OPENSSL_FIPS + if (!FIPS_mode_set(1)) { + int r; + r = ERR_get_error(); + fprintf(stderr, "openssl fips failed: %s\n", ERR_error_string(r, NULL)); + UNREACHABLE(); + } +#endif /* BUD_FIPS_ENABLED */ + + // Turn off compression. Saves memory and protects against CRIME attacks. #if !defined(OPENSSL_NO_COMP) #if OPENSSL_VERSION_NUMBER < 0x00908000L