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

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

heyuanliu-intel
Copy link

@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
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
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
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
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
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
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
Author

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

@heyuanliu-intel
Copy link
Author

Throw exceptions when error occurs during initialize custom engine.

Copy link
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!

return 0;
TCN_FREE_CSTRING(customEngine);
throwIllegalStateException(e, "Could not load openssl dynamic methods.");
goto init_failed;
Copy link
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
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
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.

}
TCN_FREE_CSTRING(libCryptoPath);
TCN_FREE_CSTRING(libSSLPath);

/* Check if already initialized */
if (ssl_initialized++) {
TCN_FREE_CSTRING(customEngine);
Copy link
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
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.

@@ -548,6 +587,9 @@ WF_OPENSSL(jint, initialize) (JNIEnv *e, jobject o, jstring libCryptoPath, jstri
session_init(e);

return (jint)0;

init_failed:
return 0;
Copy link
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
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
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.

}
}

if (ssl_engine) {
Copy link
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
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
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
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
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
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
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
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!

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
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
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.

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
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.

}
}
}
}

Copy link
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
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.

}
}

if (ssl_engine) {
Copy link
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
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
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
Author

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

Copy link
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
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
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