Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Tracking Issue] OpenSSL 3 #29817

Closed
jasnell opened this issue Oct 2, 2019 · 31 comments
Closed

[Tracking Issue] OpenSSL 3 #29817

jasnell opened this issue Oct 2, 2019 · 31 comments
Assignees
Labels
crypto Issues and PRs related to the crypto subsystem. openssl Issues and PRs related to the OpenSSL dependency.

Comments

@jasnell
Copy link
Member

jasnell commented Oct 2, 2019

Hey @nodejs/crypto (and in particular @sam-github). For the QUIC implementation, for a variety of reasons, it's going to better for us to be able to move up to OpenSSL 3 as soon as possible. Yes, I know it hasn't been released yet. I wanted to check in to see if anyone has started the exploration of 3.0 yet, and if so, what the issues so far have been.

For QUIC, the reason we need it is because the BoringSSL QUIC APIs are being ported to OpenSSL 3.0. Once those are available, our implementation will be greatly simplified by being able to take advantage of the ngtcp2_crypto helper library. As it stands right now, we have to overlay and support a patch on OpenSSL 1.1.1 for it to work.

@jasnell jasnell added crypto Issues and PRs related to the crypto subsystem. openssl Issues and PRs related to the OpenSSL dependency. labels Oct 2, 2019
@sam-github
Copy link
Contributor

Its been on my list of things to look at, because FIPS will require OpenSSL 3.x, but I haven't had the time to try a build yet.

OpenSSL 3.x is intended to be API compatible with OpenSSL 1.1.1 -- though NOT ABI compatible, but the proof of that will be in the build and testing.

@jasnell
Copy link
Member Author

jasnell commented Oct 2, 2019

Ok, I'll see if I can at least do a preliminary check on it in the coming few weeks. Let's leave this issue open as a tracking issue for it.

@jasnell jasnell changed the title OpenSSL 3 [Tracking Issue] OpenSSL 3 Oct 2, 2019
@sam-github
Copy link
Contributor

OpenSSL policy is to not release new features in patch releases, so OpenSSL 1.1.1 is feature frozen.

However, OpenSSL also decided not to have a new 1.1.x release.

So, QUIC support will only be possible on OpenSSL 3.x, or on our internal OpenSSL 1.1.1 with overlay patches. I'm not sure what to do about that.

Once we have QUIC and HTTP/3 support it might be worth bringing this up with OpenSSL, because no OpenSSL 1.1.1 ABI compatible release will ever support HTTP/3. That might become an issue important enough for them to do an OpenSSL 1.1.2 (or 1.2.0).

At this point, given lack of adoption or support for HTTP/3, I think its a bit early to try to get them to do a new release.

@jasnell
Copy link
Member Author

jasnell commented Apr 28, 2020

@nodejs/crypto @nodejs/tsc ... just a heads up.. the OpenSSL OMC has announced the first alpha of OpenSSL 3: https://www.openssl.org/blog/blog/2020/04/23/OpenSSL3.0Alpha1/

@jasnell
Copy link
Member Author

jasnell commented Apr 28, 2020

@sam-github ... I've been thinking that it would be a good idea to set up an openssl-canary branch where we can start working with compiling openssl 3 into nodejs master to work out any issues that may exist. Wanted to coordinate with you on that before moving forward tho.

@sam-github
Copy link
Contributor

Sure, so a branch like update-openssl-3.x pushed to github.com/nodejs/node, so it can be worked on cooperatively? Sounds good to me.

FYI, my first experience posted here, https://mta.openssl.org/pipermail/openssl-users/2020-April/012312.html (repeated below), but I used the configure flags to point to an out-of-tree openssl in order to do those tests.

In terms of dep update, the deps/openssl/conf scripts failed when openssl was replaced with openssl 3. How much it will take to make them work I have not looked at.


Fwiw, took a quick run at building and testing Node.js against the 3.x beta.

It was API compatible enough to build. The DH_, ECDH_, HMAC_, etc.
deprecations make sense, will look at those.

My assumption is that EVP versions of these exist in openssl 1.1.1,
and that if we switch our openssl 1.1.1 code to using the EVP APIs,
that that cod will then work unchanged when we update to openssl 3.x?

ERR_func_error_string, what is its replacement? I didn't see it
mentioned in the wiki, but its marked deprecated.

Tests didn't go so well. Minor changes in error strings are to be
expected, but more than that changed.

I haven't looked at these yet other than scan the output, we might be
relying on internals, but just for anyone curious, here's the test
output:

https://gist.github.com/sam-github/5a3b3775029efb3d31109d7e6e390f85

@sam-github
Copy link
Contributor

nodejs/TSC#859

@danbev
Copy link
Contributor

danbev commented Jul 1, 2020

I've started to take a look at this and I've pushed the following branch:
https://github.com/nodejs/node/tree/update-openssl-3.x

I'm currently building this locally against OpenSSL 3.0 Alpha 3 as I ran into an issue with our snapshot building with Alpha 4 (I'll investigate that further once I got all the tests to pass). There are two tests that are failing at the moment which are a little more involved than just error message/code changes but I'm looking into them now.

I'm using the following configuration options to build:

$ ./configure --shared-openssl --shared-openssl-libpath=/work/security/openssl_build_master/lib --shared-openssl-includes=/work/security/openssl_build_master/include --shared-openssl-libname=crypto,ssl --debug

@danbev danbev self-assigned this Jul 1, 2020
@danbev

This comment has been minimized.

danbev added a commit to danbev/openssl that referenced this issue Oct 5, 2020
This commit sets the error mark before calling old_priv_decode and if
old_priv_decode returns false, and if EVP_PKCS82PKEY is successful, the
errors are popped to the previously set mark.

The motivation for this is an issue we found when linking Node.js
against OpenSSL 3.0. Details can be found in the link below and the
test case provided in this commit attempts cover this.

Refs: https://github.com/danbev/learning-libcrypto#asn1-wrong-tag-issue
Refs: nodejs/node#29817
openssl-machine pushed a commit to openssl/openssl that referenced this issue Oct 8, 2020
This commit sets the error mark before calling old_priv_decode and if
old_priv_decode returns false, and if EVP_PKCS82PKEY is successful, the
errors are popped to the previously set mark.

The motivation for this is an issue we found when linking Node.js
against OpenSSL 3.0. Details can be found in the link below and the
test case provided in this commit attempts cover this.

Refs: https://github.com/danbev/learning-libcrypto#asn1-wrong-tag-issue
Refs: nodejs/node#29817

Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from #13073)
danbev added a commit to danbev/openssl that referenced this issue Nov 24, 2020
This commit tries to address a locking issue in evp_pkey_reset_unlocked
which can occur when it is called from evp_pkey_downgrade.

evp_pkey_downgrade will acquire a lock for pk->lock and if successful
then call evp_pkey_reset_unlocked. evp_pkey_reset_unlocked will call
memset on pk, and then create a new lock and set pk->lock to point to
that new lock. I believe there are two problems with this.

The first is that after the call to memset, another thread would try to
acquire a lock for NULL as that is what the value of pk->lock would be
at that point.

The second issue is that after the new lock has been assigned to
pk->lock, that lock is different from the one currently locked so
another thread trying to acquire the lock will succeed which can lead to
strange behaviour. More details and a reproducer can be found in the
Refs link below.

This commit introduces a new function that is only called by
evp_pkey_downgrade which does not use memset but instead "manually"
sets the EVP_PKEY values to their default values, but does not modify
pk->lock. This could perhaps be updated to go back to only having one
function that is called for both evp_pkey_downgrade and EVP_PKEY_new
and only create a new lock if one does not already exist.

Refs:
https://github.com/danbev/learning-libcrypto/blob/master/notes/issues.md#openssl-investigationtroubleshooting
nodejs/node#29817
openssl-machine pushed a commit to openssl/openssl that referenced this issue Nov 26, 2020
This commit tries to address a locking issue in evp_pkey_reset_unlocked
which can occur when it is called from evp_pkey_downgrade.

evp_pkey_downgrade will acquire a lock for pk->lock and if successful
then call evp_pkey_reset_unlocked. evp_pkey_reset_unlocked will call
memset on pk, and then create a new lock and set pk->lock to point to
that new lock. I believe there are two problems with this.

The first is that after the call to memset, another thread would try to
acquire a lock for NULL as that is what the value of pk->lock would be
at that point.

The second issue is that after the new lock has been assigned to
pk->lock, that lock is different from the one currently locked so
another thread trying to acquire the lock will succeed which can lead to
strange behaviour. More details and a reproducer can be found in the
Refs link below.

This changes the evp_pkey_reset_unlocked to not touch the lock
and the creation of a new lock is done in EVP_PKEY_new.

Refs:
https://github.com/danbev/learning-libcrypto/blob/master/notes/issues.md#openssl-investigationtroubleshooting
nodejs/node#29817

Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from #13374)
danbev added a commit that referenced this issue Mar 16, 2021
This commit enables node to dynamically link against OpenSSL 3.0.

The motivation for opening this PR even though OpenSSL 3.0 has not been
released yet is to allow a nightly CI job to be created. This will
allow us stay on top of changes required for OpenSSL 3.0, and also to
make sure that changes to node crypto do not cause issues when linking
to OpenSSL 3.0.

PR-URL: #37669
Refs: #29817
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
danielleadams pushed a commit that referenced this issue Mar 16, 2021
This commit enables node to dynamically link against OpenSSL 3.0.

The motivation for opening this PR even though OpenSSL 3.0 has not been
released yet is to allow a nightly CI job to be created. This will
allow us stay on top of changes required for OpenSSL 3.0, and also to
make sure that changes to node crypto do not cause issues when linking
to OpenSSL 3.0.

PR-URL: #37669
Refs: #29817
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
danielleadams pushed a commit that referenced this issue Mar 16, 2021
This commit enables node to dynamically link against OpenSSL 3.0.

The motivation for opening this PR even though OpenSSL 3.0 has not been
released yet is to allow a nightly CI job to be created. This will
allow us stay on top of changes required for OpenSSL 3.0, and also to
make sure that changes to node crypto do not cause issues when linking
to OpenSSL 3.0.

PR-URL: #37669
Refs: #29817
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Michael Dawson <midawson@redhat.com>
@danbev
Copy link
Contributor

danbev commented Apr 8, 2021

Part of the work for this issue has been done with the updates made to be able to dynamically link with OpenSSL 3.0 and have the test suite pass. And @richardlau has set up a CI build so that we can keep track of any changes that break this 🎉

The next task is to take a look at what is required to be able to replace the statically linked OpenSSL version so that at some point the current version can be replaced. Not sure if I should continue updating this issue or create separate issues for each task. If anyone has a preference please let me know.

@jasnell
Copy link
Member Author

jasnell commented Apr 8, 2021

Just please be sure to source from the quictls/openssl repo, which has all the 3.0 bits. :)

@danbev
Copy link
Contributor

danbev commented Apr 8, 2021

@jasnell I actually just realized this today that we should be using quictls/openssl for 3.0 as well, while updating the OpenSSL-Strategy.md. I've been using openssl/openssl until now and that is what the CI job is using as that is what I specified. I'll update the CI config so that it is testing the right version as well.

@mayrbenjamin92
Copy link
Contributor

Part of the work for this issue has been done with the updates made to be able to dynamically link with OpenSSL 3.0 and have the test suite pass. And @richardlau has set up a CI build so that we can keep track of any changes that break this 🎉

The next task is to take a look at what is required to be able to replace the statically linked OpenSSL version so that at some point the current version can be replaced. Not sure if I should continue updating this issue or create separate issues for each task. If anyone has a preference please let me know.

Would you mind sharing the instructions to actually accomplish this? 🙃

@mayrbenjamin92
Copy link
Contributor

@danbev Would you mind giving me a quick response to my previous message? I am happy to assist and collaborate - I just want to avoid that I also start "from scratch"! We are eagerly trying to get node 16 and FIPS working as this is a requirement of one of our customers...

@richardlau
Copy link
Member

@mayrbenjamin92 Dan is currently on holiday and may not be checking notifications.
For dynamically linking OpenSSL 3 this is up to date: https://github.com/nodejs/node/blob/master/BUILDING.md#building-nodejs-with-fips-compliant-openssl
For static linking #38512 is the in progress PR.

@danbev
Copy link
Contributor

danbev commented Jul 8, 2021

@mayrbenjamin92 Like @richardlau mentioned I'm currently on PTO but I'll will be back next Friday and continue this work. The current state of #38512 is that I'm trying to get CI to pass for all architectures, and after that I'll iterate on this work (refactor and clean things up, and add some docs).

@mayrbenjamin92
Copy link
Contributor

Hi @richardlau thanks for your response! I am still running into issues when following the provided docs - this is how far I got so far:

The openssl stuff works - I can build it (I have setup a pipeline for that). My "openssl" checkout is located in:
/root/openssl

My configured build path is /root/ossl containing:

  • lib
  • SSL

subdirectories. My openssl.cnf file is located under root/openssl/ssl/openssl.cnf and I have added (concatenated) the additional FIPS specific module - these are the last 20 lines of my openssl.conf file:

[kur]
# Certificate update
cmd = kur
oldcert = $insta::certout # insta.cert.pem

[rr]
# Certificate revocation
cmd = rr
oldcert = $insta::certout # insta.cert.pem
.include fipsmodule.cnf

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included /path/to/install/dir/ssl/fipsmodule.cnf.
fips = fips_sect

[default_sect]
activate = 1

As far as I understood, this is what I should suppose to do - adding the .include ... stuff and append it to this file - correct?

I then exported the following env variables:

export OPENSSL_CONF=/root/openssl/ssl/openssl.cnf
export OPENSSL_MODULES=/root/ossl/lib/ossl-modules

So far so good. I then cloned the "nodejs" source, checked-out the latest v16.X.X version explicitly and ran the following:

cd node

./configure \
--shared-openssl \
--shared-openssl-libpath=/root/ossl/lib \
--shared-openssl-includes=/root/openssl/include \
--shared-openssl-libname=crypto,ssl \
--openssl-is-fips

export LD_LIBRARY_PATH=/root/ossl/lib

I first looked okay:

Node.js configure: Found Python 3.8.10...
INFO: configure completed successfully

But when I actually then try to start compiling node, I will get the following linker error at the end:

/usr/bin/ld: cannot find -lcrypto
/usr/bin/ld: cannot find -lssl

I am not sure whether I have missed something or whether the docs could be improved.

@mayrbenjamin92
Copy link
Contributor

Hi guys,

maybe I am also confused, but what is meant with /path/to/install/dir/? Should this path point to the "clone-directory" of openssl or of node?

@richardlau
Copy link
Member

@mayrbenjamin92 Are you on Linux? If you are not then instead of setting LD_LIBRARY_PATH you would need to set, e.g.

If you are on Linux, then the linker error is strange... you should have libcyrpto.* and libssl.* files under /root/ossl/lib (or whatever you've set LD_LIBRARY_PATH to).

maybe I am also confused, but what is meant with /path/to/install/dir/? Should this path point to the "clone-directory" of openssl or of node?

This is what you pass to the configure command for building OpenSSL (i.e. ./config --prefix=/path/to/install/dir/ shared enable-fips linux-x86_64). The "install" directory can be anywhere you can write to -- it is where the OpenSSL commands

$ make install_ssldirs
$ make install_fips

"install" the built OpenSSL libraries.

I am not sure whether I have missed something or whether the docs could be improved.

Docs are always something that can be improved -- pull requests always welcome 🙂.

@mayrbenjamin92
Copy link
Contributor

@richardlau thanks for making this more clear. I will definitely improve the documentation as something is not "perfect" - I will create a pull request, soon.

One other short question - it looks like that I am partially successful. I am at the following step (I called make -j8 - I am on an 8 core machine):

...
  g++ -o /root/node/out/Release/node_mksnapshot -pthread -rdynamic -m64 -Wl,--whole-archive /root/node/out/Release/obj.target/deps/zlib/libzlib.a -Wl,--no-whole-archive -Wl,--whole-archive /root/node/out/Release/obj.target/deps/uv/libuv.a -Wl,--no-whole-archive -Wl,-z,noexecstack -Wl,--whole-archive /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_snapshot.a -Wl,--no-whole-archive -Wl,-z,relro -Wl,-z,now -pthread  -Wl,--start-group /root/node/out/Release/obj.target/node_mksnapshot/src/node_snapshot_stub.o /root/node/out/Release/obj.target/node_mksnapshot/src/node_code_cache_stub.o /root/node/out/Release/obj.target/node_mksnapshot/tools/snapshot/node_mksnapshot.o /root/node/out/Release/obj.target/libnode.a /root/node/out/Release/obj.target/deps/histogram/libhistogram.a /root/node/out/Release/obj.target/deps/uvwasi/libuvwasi.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_snapshot.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_libplatform.a /root/node/out/Release/obj.target/tools/icu/libicui18n.a /root/node/out/Release/obj.target/deps/zlib/libzlib.a /root/node/out/Release/obj.target/deps/llhttp/libllhttp.a /root/node/out/Release/obj.target/deps/cares/libcares.a /root/node/out/Release/obj.target/deps/uv/libuv.a /root/node/out/Release/obj.target/deps/nghttp2/libnghttp2.a /root/node/out/Release/obj.target/deps/brotli/libbrotli.a /root/node/out/Release/obj.target/tools/icu/libicuucx.a /root/node/out/Release/obj.target/tools/icu/libicudata.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_base_without_compiler.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_libbase.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_zlib.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_compiler.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_initializers.a -L/root/openssl -lcrypto -lssl -lm -ldl -Wl,--end-group
  LD_LIBRARY_PATH=/root/node/out/Release/lib.host:/root/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /root/node/out/Release/obj/gen; "/root/node/out/Release/mkcodecache" "/root/node/out/Release/obj/gen/node_code_cache.cc"
  LD_LIBRARY_PATH=/root/node/out/Release/lib.host:/root/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /root/node/out/Release/obj/gen; "/root/node/out/Release/node_mksnapshot" "/root/node/out/Release/obj/gen/node_snapshot.cc"

So it looks like that I am stuck in this step - nothing happens for more than 20 minutes. Is it really that heavy?

@mayrbenjamin92
Copy link
Contributor

I am one step further - I am, meanwhile, trying all of this on a big 16 CPU/30GB virtual machine on AWS. I think that I get quite far, but then I run into this:

OpenSSL configuration error:
0060AA80077F0000:error:80000002:system library:BIO_new_file:No such file or directory:crypto/bio/bss_file.c:67:calling fopen(/home/ubuntu/openssl/ssl/openssl.cnf, rb)
0060AA80077F0000:error:10000080:BIO routines:BIO_new_file:no such file:crypto/bio/bss_file.c:75:
0060AA80077F0000:error:07000072:configuration file routines:def_load:no such file:crypto/conf/conf_def.c:179:
/home/ubuntu/node/out/Release/node_mksnapshot[81737]: ../tools/snapshot/node_mksnapshot.cc:49:int main(int, char**): Assertion `!result.early_return' failed.
 1: 0x55c7633a8f84 node::Abort() [/home/ubuntu/node/out/Release/node_mksnapshot]
 2: 0x55c7633a9018  [/home/ubuntu/node/out/Release/node_mksnapshot]
 3: 0x55c76320f6ac main [/home/ubuntu/node/out/Release/node_mksnapshot]
 4: 0x7f0780ace0b3 __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
 5: 0x55c763217c7e _start [/home/ubuntu/node/out/Release/node_mksnapshot]
Aborted (core dumped)
make[1]: *** [node.target.mk:26: /home/ubuntu/node/out/Release/obj/gen/node_snapshot.cc] Error 134
make[1]: *** Waiting for unfinished jobs....
rm b686d532291c88b4026914f8ee87fcc458d9bbf7.intermediate 1d4311d5329fc69c1bf42791f159aee2725574ef.intermediate f38ec128c97cc68e650351c8a59ffecdb08aa5b9.intermediate f64dd52776e946cbb0911c33d749744cc49df032.intermediate
make: *** [Makefile:110: node] Error 2

@richardlau
Copy link
Member

...
  g++ -o /root/node/out/Release/node_mksnapshot -pthread -rdynamic -m64 -Wl,--whole-archive /root/node/out/Release/obj.target/deps/zlib/libzlib.a -Wl,--no-whole-archive -Wl,--whole-archive /root/node/out/Release/obj.target/deps/uv/libuv.a -Wl,--no-whole-archive -Wl,-z,noexecstack -Wl,--whole-archive /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_snapshot.a -Wl,--no-whole-archive -Wl,-z,relro -Wl,-z,now -pthread  -Wl,--start-group /root/node/out/Release/obj.target/node_mksnapshot/src/node_snapshot_stub.o /root/node/out/Release/obj.target/node_mksnapshot/src/node_code_cache_stub.o /root/node/out/Release/obj.target/node_mksnapshot/tools/snapshot/node_mksnapshot.o /root/node/out/Release/obj.target/libnode.a /root/node/out/Release/obj.target/deps/histogram/libhistogram.a /root/node/out/Release/obj.target/deps/uvwasi/libuvwasi.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_snapshot.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_libplatform.a /root/node/out/Release/obj.target/tools/icu/libicui18n.a /root/node/out/Release/obj.target/deps/zlib/libzlib.a /root/node/out/Release/obj.target/deps/llhttp/libllhttp.a /root/node/out/Release/obj.target/deps/cares/libcares.a /root/node/out/Release/obj.target/deps/uv/libuv.a /root/node/out/Release/obj.target/deps/nghttp2/libnghttp2.a /root/node/out/Release/obj.target/deps/brotli/libbrotli.a /root/node/out/Release/obj.target/tools/icu/libicuucx.a /root/node/out/Release/obj.target/tools/icu/libicudata.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_base_without_compiler.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_libbase.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_zlib.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_compiler.a /root/node/out/Release/obj.target/tools/v8_gypfiles/libv8_initializers.a -L/root/openssl -lcrypto -lssl -lm -ldl -Wl,--end-group
  LD_LIBRARY_PATH=/root/node/out/Release/lib.host:/root/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /root/node/out/Release/obj/gen; "/root/node/out/Release/mkcodecache" "/root/node/out/Release/obj/gen/node_code_cache.cc"
  LD_LIBRARY_PATH=/root/node/out/Release/lib.host:/root/node/out/Release/lib.target:$LD_LIBRARY_PATH; export LD_LIBRARY_PATH; cd ../.; mkdir -p /root/node/out/Release/obj/gen; "/root/node/out/Release/node_mksnapshot" "/root/node/out/Release/obj/gen/node_snapshot.cc"

So it looks like that I am stuck in this step - nothing happens for more than 20 minutes. Is it really that heavy?

That does feel long. We did see a hang here with earlier alpha builds of OpenSSL 3.0.0 due to openssl/openssl#12290. I also hit a hang with a misconfigured .include path.

You could try building with (Node.js) configure --without-node-snapshot to skip the snaphot (at the cost of Node.js start up time) -- it may just shift the problem to later when you try to run node if it successfully builds if the issue is in OpenSSL or the OpenSSL config.

I am one step further - I am, meanwhile, trying all of this on a big 16 CPU/30GB virtual machine on AWS. I think that I get quite far, but then I run into this:

OpenSSL configuration error:
0060AA80077F0000:error:80000002:system library:BIO_new_file:No such file or directory:crypto/bio/bss_file.c:67:calling fopen(/home/ubuntu/openssl/ssl/openssl.cnf, rb)

Does /home/ubuntu/openssl/ssl/openssl.cnf match what OPENSSL_CONF was set to? If it does, does that file exist and is it readable by the user?

@mayrbenjamin92
Copy link
Contributor

Okay I think that I still have some fundamental issue. So I am doing all of this on an Ubuntu 20.04 server on AWS - 16CPU/30GB memory.

Kernel is: 5.4.0-1045-aws

My "script" does the following:

cd /home/ubuntu
git clone https://github.com/quictls/openssl.git

cd openssl
./config \
    --prefix=/home/ubuntu/ossl \
    shared \
    enable-fips \
    linux-x86_64

make -j16
make install_ssldirs
make install_fips

Running all of this gives me a "standard" GIT checkout of "openssl" located under /home/ubuntu/openssl and running the "install" commands gives me an additional path (based on my prefix) of /home/ubuntu/ossl with the following contents:

ls /home/ubuntu/ossl

Output is:

lib  ssl

Contents of "lib":

ls /home/ubuntu/ossl/lib/

Output is:

ossl-modules

The "ossl-modules" folder only contains a single file: fips.so.

The ssl path contains more files:

ls /home/ubuntu/ossl/ssl

Output is:

certs            ct_log_list.cnf.dist  misc         openssl.cnf.dist
ct_log_list.cnf  fipsmodule.cnf        openssl.cnf  private

The content of the fipsmodule.cnf file is:

[fips_sect]
activate = 1
conditional-errors = 1
security-checks = 1
module-mac = 0C:DE:AE:7F:F8:9F:61:04:83:BE:58:74:E2:9F:85:16:7A:AB:9E:AC:E2:79:B1:CC:A3:03:71:82:DB:D2:5A:86

As far as I understand, I should now alter the openssl.cnf file which is also located in this "SSL" folder and "append":

.include fipsmodule.cnf

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included /path/to/install/dir/ssl/fipsmodule.cnf.
fips = fips_sect

[default_sect]
activate = 1

So this is the content of my openssl.cnf file located under /home/ubuntu/ossl/ssl (abbreviated, just the last couple of lines):

...
[signature] # Signature-based protection for Insta CA
# Server authentication
trusted = insta.ca.crt # does not include keyUsage digitalSignature

# Client authentication
secret = # disable PBM
key = $insta::newkey # insta.priv.pem
cert = $insta::certout # insta.cert.pem

[ir]
cmd = ir

[cr]
cmd = cr

[kur]
# Certificate update
cmd = kur
oldcert = $insta::certout # insta.cert.pem

[rr]
# Certificate revocation
cmd = rr
oldcert = $insta::certout # insta.cert.pem

.include fipsmodule.cnf

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included /path/to/install/dir/ssl/fipsmodule.cnf.
fips = fips_sect

[default_sect]
activate = 1

Whats next? There is also an "SSL" folder in /home/ubuntu/openssl. Should I simply replace the content in the "openssl" GIT repos SSL folder with the contents of my /home/ubuntu/ossl/ssl path?

Where should I place fips.so which is located under /home/ubuntu/ossl/lib/ossl-modules? Should I copy the "fips.so" file and simply place it into the "openssl" directory? Because there I can also see other modules like:

  • libcrypto.so -> libcrypto.so.81.3
  • libssl.so -> libssl.so.81.3

Does that make sense?

@richardlau
Copy link
Member

Ah this might be a gap in the docs 😞 (or maybe something changed in OpenSSL). Can you try

make install

between make -j16 and make install_ssldirs? Hopefully you should then end up with

engines-3  libcrypto.a  libcrypto.so  libcrypto.so.3  libssl.a  libssl.so  libssl.so.3  ossl-modules  pkgconfig

in lib.

For reference, we run the CI builds in a Docker container where we build OpenSSL 3.0.0 when we create the container, https://github.com/nodejs/build/blob/001a5725c136d472c565a6b6fe90eac143956098/ansible/roles/docker/templates/ubuntu1804_sharedlibs.Dockerfile.j2#L83-L90. The FIPS build steps in the docs are then run via Jenkins inside the built container.

Thanks for persevering with this -- it's always good to get new eyes on docs.

@mayrbenjamin92
Copy link
Contributor

So this is what I now came up with - sorry for the "repeating content":

OpenSSL

Clone

cd /home/ubuntu
git clone https://github.com/quictls/openssl.git

Build

cd openssl

./config \
    --prefix=/home/ubuntu/ossl \
    shared \
    enable-fips \
    linux-x86_64

make -j16
make install
make install_ssldirs
make install_fips

Alter OpenSSL config and "enable" fips

cat <<EOT >> /home/ubuntu/ossl/ssl/openssl.cnf
.include fipsmodule.cnf

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included /path/to/install/dir/ssl/fipsmodule.cnf.
fips = fips_sect

[default_sect]
activate = 1
EOT

Configure environment

export OPENSSL_CONF=/home/ubuntu/ossl/ssl/openssl.cnf
export OPENSSL_MODULES=/home/ubuntu/ossl/lib/ossl-modules

Node

Clone

cd /home/ubuntu
git clone -b master https://github.com/nodejs/node.git

Build

cd node
git checkout tags/v16.4.2

./configure \
    --shared-openssl \
    --shared-openssl-libpath=/home/ubuntu/ossl/lib \
    --shared-openssl-includes=/home/ubuntu/ossl/include \
    --shared-openssl-libname=crypto,ssl \
    --openssl-is-fips

export LD_LIBRARY_PATH=/home/ubuntu/ossl/lib

make -j16

So I actually end up with the following contents in /home/ubuntu/ossl:

bin  include  lib  share  ssl

That actually looks good. Please also check the "build steps" for NodeJS (above). I, sadly, still end up with:

...

OpenSSL configuration error:
0000C47BFF7E0000:error:80000002:system library:process_include:No such file or directory:crypto/conf/conf_def.c:803:calling stat(fipsmodule.cnf)
0000C47BFF7E0000:error:07800069:common libcrypto routines:provider_conf_load:provider section error:crypto/provider_conf.c:124:section=fips_sect not found
0000C47BFF7E0000:error:0700006D:configuration file routines:module_run:module initialization error:crypto/conf/conf_mod.c:243:module=providers, value=provider_sect retcode=-1      
/home/ubuntu/node/out/Release/node_mksnapshot[242411]: ../tools/snapshot/node_mksnapshot.cc:49:int main(int, char**): Assertion `!result.early_return' failed.
 1: 0x55e8ad030824 node::Abort() [/home/ubuntu/node/out/Release/node_mksnapshot]
 2: 0x55e8ad0308b8  [/home/ubuntu/node/out/Release/node_mksnapshot]
 3: 0x55e8ace9761c main [/home/ubuntu/node/out/Release/node_mksnapshot]
 4: 0x7eff7bc680b3 __libc_start_main [/lib/x86_64-linux-gnu/libc.so.6]
 5: 0x55e8ace9fbbe _start [/home/ubuntu/node/out/Release/node_mksnapshot]
Aborted (core dumped)
make[1]: *** [node.target.mk:26: /home/ubuntu/node/out/Release/obj/gen/node_snapshot.cc] Error 134
make[1]: *** Waiting for unfinished jobs....
rm b686d532291c88b4026914f8ee87fcc458d9bbf7.intermediate 1d4311d5329fc69c1bf42791f159aee2725574ef.intermediate f38ec128c97cc68e650351c8a59ffecdb08aa5b9.intermediate f64dd52776e946cbb0911c33d749744cc49df032.intermediate
make: *** [Makefile:110: node] Error 2

So something is still wrong :/.

@mayrbenjamin92
Copy link
Contributor

@richardlau My assumption that appending to the openssl.cnf file is correct, right?

...

# Client authentication
secret = # disable PBM
key = $insta::newkey # insta.priv.pem
cert = $insta::certout # insta.cert.pem

[ir]
cmd = ir

[cr]
cmd = cr

[kur]
# Certificate update
cmd = kur
oldcert = $insta::certout # insta.cert.pem

[rr]
# Certificate revocation
cmd = rr
oldcert = $insta::certout # insta.cert.pem
.include fipsmodule.cnf

# List of providers to load
[provider_sect]
default = default_sect
# The fips section name should match the section name inside the
# included /path/to/install/dir/ssl/fipsmodule.cnf.
fips = fips_sect

[default_sect]
activate = 1

So since the environment variables (OPENSSL_MODULES and OPENSSL_CONF) now point to the ossl directory on my system, this should work, right?

@richardlau
Copy link
Member

@richardlau My assumption that appending to the openssl.cnf file is correct, right?

So since the environment variables (OPENSSL_MODULES and OPENSSL_CONF) now point to the ossl directory on my system, this should work, right?

Yes (to both questions). I don't see anything obvious that would explain why OpenSSL couldn't open/find fipsmodule.cnf 😞 (at least we know it's attempted to load the updated openssl.cnf). Maybe try a full path to fipsmodule.cnf in the .include statement?

@mayrbenjamin92
Copy link
Contributor

@richardlau ohhh my god! That did the trick! I hate relative file-paths... Thank you soo much for your assistance! I will create a pull request and improve/update the documentation with my latest findings! Works as expected:

ubuntu@ip-172-31-17-25:~/node/out/Release$ ./node --enable-fips -p 'crypto.getFips()'
1

@dschepler
Copy link

Currently, if I try a build on Linux using system OpenSSL 3.0.0 and passing --shared-openssl on the configure command line, I get a compiler error that looks like a const issue. Is that known? (I was just quickly looking through this issue and didn't see anything related, but I could easily have missed something.) If it isn't a known issue, would it be appropriate to report it here, or would it be something I should open as a new issue?

@targos
Copy link
Member

targos commented Sep 29, 2021

@dschepler opening a new issue is probably a good idea 👍🏻

@danbev
Copy link
Contributor

danbev commented Oct 18, 2021

Closing this issue as OpenSSL 3.0 has been released now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto Issues and PRs related to the crypto subsystem. openssl Issues and PRs related to the OpenSSL dependency.
Projects
None yet
Development

No branches or pull requests

7 participants