Skip to content

SSLNTV-29 Add the ability to use a custom OpenSSL engine#16

Open
heyuanliu-intel wants to merge 1 commit intowildfly-security:mainfrom
heyuanliu-intel:custom_engine
Open

SSLNTV-29 Add the ability to use a custom OpenSSL engine#16
heyuanliu-intel wants to merge 1 commit intowildfly-security:mainfrom
heyuanliu-intel:custom_engine

Conversation

@heyuanliu-intel
Copy link
Copy Markdown

@heyuanliu-intel heyuanliu-intel commented Oct 9, 2022

Add support custom engine to fix the issue #15

Intel QAT can boost SSL/TLS performance and has been integrated into many popular open source frameworks.
Such as envoy and nginx. Please refer to envoyproxy/envoy#21984

And for the async mode nginx, it can get 4X performance boost with QAT.
Please refer to https://01.org/sites/default/files/downloads/intelr-quickassist-technology/intelquickassisttechnologyopensslperformance.pdf

So many applications can get benefit from QAT custom engine and other custom engines.

@fjuma
Copy link
Copy Markdown
Contributor

fjuma commented Dec 13, 2022

Thanks for the PR, @heyuanliu-intel!

Tests for WildFly OpenSSL are included in the wildfly-openssl project that depends on this wildfly-openssl-natives project. Do you think it would be possible to add a test case that makes use of a custom engine? Or is it possible to provide steps that can be used for testing this?

@heyuanliu-intel
Copy link
Copy Markdown
Author

I have verified this using Intel QAT engine and using Airlift sample as a testcase. Please refer to this project.
https://github.com/heyuanliu-intel/AirliftPerformance

@fjuma
Copy link
Copy Markdown
Contributor

fjuma commented Dec 19, 2022

Thanks, took a look at https://github.com/heyuanliu-intel/AirliftPerformance. I noticed the -Dorg.wildfly.openssl.engine being specified in run_server.sh. Do you have corresponding changes against the wildfly-openssl repo that adds support for this new org.wildfly.openssl.engine option?

In particular, it looks like corresponding changes would be needed in SSL.java to call the updated initialize method with the customEngine parameter.

@heyuanliu-intel
Copy link
Copy Markdown
Author

Yes. Below is the git commit

diff --git a/java/src/main/java/org/wildfly/openssl/SSLImpl.java b/java/src/main/java/org/wildfly/openssl/SSLImpl.java
index 2dbe55e..c7ab32a 100644
--- a/java/src/main/java/org/wildfly/openssl/SSLImpl.java
+++ b/java/src/main/java/org/wildfly/openssl/SSLImpl.java
@@ -27,10 +27,10 @@ public class SSLImpl extends SSL {
public SSLImpl() {
}

  • static native void initialize0(String libCryptoPath, String libSslPath);
  • static native void initialize0(String libCryptoPath, String libSslPath, String customEngine);
  • protected void initialize(String libCryptoPath, String libSslPath) {
  •    SSLImpl.initialize0(libCryptoPath, libSslPath);
    
  • protected void initialize(String libCryptoPath, String libSslPath, String customEngine) {
  •    SSLImpl.initialize0(libCryptoPath, libSslPath, customEngine);
    
    }

diff --git a/java/src/main/java/org/wildfly/openssl/SSL.java b/java/src/main/java/org/wildfly/openssl/SSL.java
index d103474..534c7d3 100644
--- a/java/src/main/java/org/wildfly/openssl/SSL.java
+++ b/java/src/main/java/org/wildfly/openssl/SSL.java
@@ -41,6 +41,7 @@ public abstract class SSL {
public static final String MAC_HOMEBREW_OPENSSL_PATH = "/usr/local/opt/openssl/lib/";
private static SSL instance;

  • public static final String ORG_WILDFLY_OPENSSL_ENGINE = "org.wildfly.openssl.engine";
    public static final String ORG_WILDFLY_OPENSSL_PATH = "org.wildfly.openssl.path";
    public static final String ORG_WILDFLY_OPENSSL_PATH_LIBSSL = "org.wildfly.openssl.path.ssl";
    public static final String ORG_WILDFLY_OPENSSL_PATH_LIBCRYPTO = "org.wildfly.openssl.path.crypto";
    @@ -191,7 +192,8 @@ public abstract class SSL {
    if (cryptoPath == null) {
    throw new RuntimeException(Messages.MESSAGES.couldNotFindLibCrypto(ORG_WILDFLY_OPENSSL_PATH, attemptedCrypto.toString()));
    }
  •                instance.initialize(cryptoPath, sslPath);
    
  •                String sslEngine = System.getProperty(ORG_WILDFLY_OPENSSL_ENGINE);
    
  •                instance.initialize(cryptoPath, sslPath, sslEngine);
                   String version = instance.version();
                   logger.info(Messages.MESSAGES.openSSLVersion(version));
    

@@ -289,7 +291,7 @@ public abstract class SSL {
}
}

  • protected abstract void initialize(String libCryptoPath, String libSslPath);
  • protected abstract void initialize(String libCryptoPath, String libSslPath, String customEngine);

@fjuma
Copy link
Copy Markdown
Contributor

fjuma commented Dec 20, 2022

@heyuanliu-intel Thanks! Would you be able to submit a PR against wildfly-openssl and indicate in the description that it depends on this PR?

@fjuma
Copy link
Copy Markdown
Contributor

fjuma commented Dec 20, 2022

When creating the PR against wildfly-openssl, please reference WFSSL-111 in the commit message. Thanks!

@heyuanliu-intel
Copy link
Copy Markdown
Author

Create a new PR on wildfly-openssl.
The PR is wildfly-security/wildfly-openssl#127

@heyuanliu-intel
Copy link
Copy Markdown
Author

Throw exceptions when error occurs during initialize custom engine.

Copy link
Copy Markdown
Contributor

@fjuma fjuma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heyuanliu-intel Thanks for the updates! I've added some comments, feel free to let me know if you have any questions.

One more small thing, please update the commits in this PR so they reference SSLNTV-29.

Thanks!

Comment thread libwfssl/src/ssl.c Outdated
return 0;
TCN_FREE_CSTRING(customEngine);
throwIllegalStateException(e, "Could not load openssl dynamic methods.");
goto init_failed;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any changes made to load_openssl_dynamic_methods. Is there a reason for introducing the above two lines? These change the behaviour compared to what was done before so am curious about the need for this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Previous logic doesn't contains this. I added this exception to keep the consistent with the other error processing. As you know, I added the logic to throw exception when the error occurs during loading custom engine. So If you think this isn't necessary, I can remove this line.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this would mean a change in behaviour compared to what was happening before, for backwards compatibility, I think we should remove these two lines.

Comment thread libwfssl/src/ssl.c

/* Check if already initialized */
if (ssl_initialized++) {
TCN_FREE_CSTRING(customEngine);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we are missing a call to TCN_FREE_CSTRING(customEngine) after the changes below.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. You are right. I can move TCN_FREE_CSTRING(customEngine) to init_failed.

Comment thread libwfssl/src/ssl.c
return (jint)0;

init_failed:
return 0;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be a call to TCN_FREE_CSTRING(customEngine) before returning.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think ssl_initialized should also be set to 0 here.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. You are right. I will do the code change.

Comment thread libwfssl/src/ssl.c
}
}

if (ssl_engine) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this case, it looks like both the Netty and Tomcat OpenSSL implementations also do this before attempting to set the default:

#ifdef ENGINE_CTRL_CHIL_SET_FORKCHECK
                if (strcmp(J2S(engine), "chil") == 0)
                    ENGINE_ctrl(tcn_ssl_engine, ENGINE_CTRL_CHIL_SET_FORKCHECK, 1, 0, 0);
#endif

See https://github.com/netty/netty-tcnative/blob/main/openssl-dynamic/src/main/c/ssl.c#L804-L810 and https://github.com/apache/tomcat-native/blob/main/native/src/ssl.c#L540-L547.

Do you think we could do something similar here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know the real reason to add this logic. So I need to check.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is specifically for the "chil" engine. It's not strictly required to add this for your changes but since both the Netty and Tomcat OpenSSL implementations have this, I think we might as well add the same logic here as well.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ENGINE_CTRL_CHIL_SET_FORKCHECK is never going to be defined, so adding the lines like they are now is doing nothing. Note that wildfly-openssl works using dlopen without any openssl include at compilation. If we really want to set this option for chil like in the other implementations we need to add the define in wfssl.h:

+/* Flags specific to the nCipher "chil" engine */
+# define ENGINE_CTRL_CHIL_SET_FORKCHECK          100

And always execute the ENGINE_ctrl in case of the chil engine.

Nit-picky request, please add the brackets to the if. 😄

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heyuanliu-intel The #ifdef is not needed now, it's going to be always defined. All the rest LGTM now. Thanks!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay. I will remove it.

@fjuma
Copy link
Copy Markdown
Contributor

fjuma commented Jan 10, 2023

Note that the test failures in this CI job are expected because the corresponding changes to SSL.java and SSLImpl.java from wildfly-security/wildfly-openssl#127 are needed for things to work properly.

@heyuanliu-intel heyuanliu-intel force-pushed the custom_engine branch 2 times, most recently from 6a17ec9 to e8914f5 Compare January 12, 2023 04:48
Copy link
Copy Markdown
Contributor

@rmartinc rmartinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heyuanliu-intel I have added a few more comments.

Thanks!

Comment thread libwfssl/src/ssl.c Outdated
if (!crypto_methods.ENGINE_ctrl_cmd_string(ssl_engine, "SO_PATH", engine, 0) || !crypto_methods.ENGINE_ctrl_cmd_string(ssl_engine, "LOAD", NULL, 0)) {
crypto_methods.ENGINE_free(ssl_engine);
ssl_engine = NULL;
tcn_Throw(e, "Could not load openssl custom engine (%s) .so library file", engine);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@heyuanliu-intel What do you think about returning the openssl error too?
Something like the following:

char err[2048];
crypto_methods.ENGINE_free(ssl_engine);
ssl_engine = NULL;
generate_openssl_stack_error(e, err, sizeof(err));
tcn_Throw(e, "Could not load openssl custom engine (%s) .so library file: %s", engine, err);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good suggestion. It will help software developer get more detailed error message. I will add this to the code change.

Comment thread libwfssl/src/ssl.c Outdated
if (!crypto_methods.ENGINE_set_default(ssl_engine, ENGINE_METHOD_ALL)) {
crypto_methods.ENGINE_free(ssl_engine);
ssl_engine = NULL;
tcn_Throw(e, "Could not set custom engine (%s) to default engine.", engine);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, I would add the openssl error like in the previous throw.

Comment thread libwfssl/src/ssl.c
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The customEngine is not freed in non-error return, you can add TCN_FREE_CSTRING(customEngine); here after the if.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right and I will fix this.

Comment thread libwfssl/src/ssl.c
}
}

if (ssl_engine) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ENGINE_CTRL_CHIL_SET_FORKCHECK is never going to be defined, so adding the lines like they are now is doing nothing. Note that wildfly-openssl works using dlopen without any openssl include at compilation. If we really want to set this option for chil like in the other implementations we need to add the define in wfssl.h:

+/* Flags specific to the nCipher "chil" engine */
+# define ENGINE_CTRL_CHIL_SET_FORKCHECK          100

And always execute the ENGINE_ctrl in case of the chil engine.

Nit-picky request, please add the brackets to the if. 😄

@heyuanliu-intel heyuanliu-intel changed the title support custom engine SSLNTV-29 Add the ability to use a custom OpenSSL engine Jan 13, 2023
Copy link
Copy Markdown
Contributor

@rmartinc rmartinc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM now, thanks @heyuanliu-intel !

@fjuma
Copy link
Copy Markdown
Contributor

fjuma commented Jan 17, 2023

Thanks for the updates @heyuanliu-intel! Would you be able to squash the commits into a single commit?

@heyuanliu-intel
Copy link
Copy Markdown
Author

I have squashed the commits into a singe commit, please review it again.

Copy link
Copy Markdown
Contributor

@fjuma fjuma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks @heyuanliu-intel!

@fjuma
Copy link
Copy Markdown
Contributor

fjuma commented Feb 3, 2023

@heyuanliu-intel Just to keep you updated, we are planning on doing a WildFly OpenSSL release next month so will get this merged in the next few weeks (we are currently working on some updates to our CI environments). Will keep you posted on the release date. Thanks.

@heyuanliu-intel
Copy link
Copy Markdown
Author

Great! Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants