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

Add support for TLSv1.3 when compiled against openssl 1.1.1 #389

Merged
merged 1 commit into from
Sep 20, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions openssl-dynamic/src/main/c/native_constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ TCN_IMPLEMENT_CALL(jint, NativeStaticallyReferencedJniMethods, sslOpNoTLSv12)(TC
return SSL_OP_NO_TLSv1_2;
}

TCN_IMPLEMENT_CALL(jint, NativeStaticallyReferencedJniMethods, sslOpNoTLSv13)(TCN_STDARGS) {
return SSL_OP_NO_TLSv1_3;
}

TCN_IMPLEMENT_CALL(jint, NativeStaticallyReferencedJniMethods, sslOpNoTicket)(TCN_STDARGS) {
return SSL_OP_NO_TICKET;
}
Expand Down Expand Up @@ -484,6 +488,7 @@ static const JNINativeMethod method_table[] = {
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv1, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv11, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv12, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTLSv13, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoTicket, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslOpNoCompression, ()I, NativeStaticallyReferencedJniMethods) },
{ TCN_METHOD_TABLE_ENTRY(sslSessCacheOff, ()I, NativeStaticallyReferencedJniMethods) },
Expand Down
30 changes: 22 additions & 8 deletions openssl-dynamic/src/main/c/ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1559,27 +1559,41 @@ TCN_IMPLEMENT_CALL(jobjectArray, SSL, getCiphers)(TCN_STDARGS, jlong ssl)
}

TCN_IMPLEMENT_CALL(jboolean, SSL, setCipherSuites)(TCN_STDARGS, jlong ssl,
jstring ciphers)
jstring ciphers, jboolean tlsv13)
{
jboolean rv = JNI_TRUE;
TCN_ALLOC_CSTRING(ciphers);
SSL *ssl_ = J2P(ssl, SSL *);

TCN_CHECK_NULL(ssl_, ssl, JNI_FALSE);

UNREFERENCED(o);
#ifdef OPENSSL_NO_TLS1_3
if (tlsv13 == JNI_TRUE) {
tcn_Throw(e, "TLSv1.3 not supported");
return JNI_FALSE;
}
#endif

TCN_ALLOC_CSTRING(ciphers);
UNREFERENCED(o);
if (!J2S(ciphers)) {
return JNI_FALSE;
}

if (!SSL_set_cipher_list(ssl_, J2S(ciphers))) {
char err[ERR_LEN];
#ifdef OPENSSL_NO_TLS1_3
rv = SSL_set_cipher_list(ssl_, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
#else
if (tlsv13 == JNI_TRUE) {
rv = SSL_set_ciphersuites(ssl_, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
} else {
rv = SSL_set_cipher_list(ssl_, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
}
#endif

if (rv == JNI_FALSE) {
char err[256];
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
rv = JNI_FALSE;
}

TCN_FREE_CSTRING(ciphers);
return rv;
}
Expand Down Expand Up @@ -2307,7 +2321,7 @@ static const JNINativeMethod method_table[] = {
{ TCN_METHOD_TABLE_ENTRY(getMode, (J)I, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getMaxWrapOverhead, (J)I, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getCiphers, (J)[Ljava/lang/String;, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuites, (JLjava/lang/String;)Z, SSL) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuites, (JLjava/lang/String;Z)Z, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getSessionId, (J)[B, SSL) },
{ TCN_METHOD_TABLE_ENTRY(getHandshakeCount, (J)I, SSL) },
{ TCN_METHOD_TABLE_ENTRY(clearError, ()V, SSL) },
Expand Down
16 changes: 16 additions & 0 deletions openssl-dynamic/src/main/c/ssl_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,22 @@ extern const char* TCN_UNKNOWN_AUTH_METHOD;
#define TLS1_3_VERSION 0x0304
#endif

#ifndef SSL_OP_NO_TLSv1_3
// TLSV1_3 is not really supported by the underlying OPENSSL version
#ifndef OPENSSL_NO_TLS1_3
#define OPENSSL_NO_TLS1_3
#endif // OPENSSL_NO_TLS1_3

#define SSL_OP_NO_TLSv1_3 0x20000000U
#endif // SSL_OP_NO_TLSv1_3

// BoringSSL does not support TLSv1.3 for now
#ifdef OPENSSL_IS_BORINGSSL
#ifndef OPENSSL_NO_TLS1_3
#define OPENSSL_NO_TLS1_3
#endif // OPENSSL_NO_TLS1_3
#endif // OPENSSL_IS_BORINGSSL

/* OpenSSL 1.0.2 compatibility */
#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
#define TLS_method SSLv23_method
Expand Down
36 changes: 23 additions & 13 deletions openssl-dynamic/src/main/c/sslcontext.c
Original file line number Diff line number Diff line change
Expand Up @@ -422,24 +422,40 @@ TCN_IMPLEMENT_CALL(void, SSLContext, clearOptions)(TCN_STDARGS, jlong ctx,
}

TCN_IMPLEMENT_CALL(jboolean, SSLContext, setCipherSuite)(TCN_STDARGS, jlong ctx,
jstring ciphers)
jstring ciphers, jboolean tlsv13)
{
tcn_ssl_ctxt_t *c = J2P(ctx, tcn_ssl_ctxt_t *);
jboolean rv = JNI_TRUE;

TCN_CHECK_NULL(c, ctx, JNI_FALSE);

TCN_ALLOC_CSTRING(ciphers);
#ifdef OPENSSL_NO_TLS1_3
if (tlsv13 == JNI_TRUE) {
tcn_Throw(e, "TLSv1.3 not supported");
return JNI_FALSE;
}
#endif

TCN_ALLOC_CSTRING(ciphers);
UNREFERENCED(o);
if (!J2S(ciphers))
if (!J2S(ciphers)) {
return JNI_FALSE;
}

#ifdef OPENSSL_NO_TLS1_3
rv = SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
#else
if (tlsv13 == JNI_TRUE) {
rv = SSL_CTX_set_ciphersuites(c->ctx, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
} else {
rv = SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers)) == 0 ? JNI_FALSE : JNI_TRUE;
}
#endif

if (!SSL_CTX_set_cipher_list(c->ctx, J2S(ciphers))) {
if (rv == JNI_FALSE) {
char err[256];
ERR_error_string(ERR_get_error(), err);
tcn_Throw(e, "Unable to configure permitted SSL ciphers (%s)", err);
rv = JNI_FALSE;
}
TCN_FREE_CSTRING(ciphers);
return rv;
Expand Down Expand Up @@ -1434,13 +1450,12 @@ TCN_IMPLEMENT_CALL(void, SSLContext, setCertVerifyCallback)(TCN_STDARGS, jlong c
}
}


static jbyteArray keyTypes(JNIEnv* e, SSL* ssl) {
jbyte* ctype_bytes;
jbyteArray types;
int ctype_num = tcn_SSL_get0_certificate_types(ssl, (const uint8_t **) &ctype_bytes);
if (ctype_num <= 0) {
// Use no certificate
// No idea what we should use... Let the caller handle it.
return NULL;
}
types = (*e)->NewByteArray(e, ctype_num);
Expand All @@ -1451,7 +1466,6 @@ static jbyteArray keyTypes(JNIEnv* e, SSL* ssl) {
return types;
}


/**
* Returns an array containing all the X500 principal's bytes.
*
Expand Down Expand Up @@ -1527,10 +1541,6 @@ static int cert_requested(SSL* ssl, X509** x509Out, EVP_PKEY** pkeyOut) {
tcn_get_java_env(&e);

types = keyTypes(e, ssl);
if (types == NULL) {
return 0;
}

issuers = principalBytes(e, SSL_get_client_CA_list(ssl));

// Execute the java callback
Expand Down Expand Up @@ -1870,7 +1880,7 @@ static const JNINativeMethod fixed_method_table[] = {
{ TCN_METHOD_TABLE_ENTRY(setOptions, (JI)V, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(getOptions, (J)I, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(clearOptions, (JI)V, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuite, (JLjava/lang/String;)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCipherSuite, (JLjava/lang/String;Z)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCertificateChainFile, (JLjava/lang/String;Z)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCertificateChainBio, (JJZ)Z, SSLContext) },
{ TCN_METHOD_TABLE_ENTRY(setCACertificateBio, (JJ)Z, SSLContext) },
Expand Down
6 changes: 6 additions & 0 deletions openssl-dynamic/src/main/c/sslutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ const char* tcn_SSL_cipher_authentication_method(const SSL_CIPHER* cipher){
default:
return TCN_UNKNOWN_AUTH_METHOD;
}
#ifndef OPENSSL_NO_TLS1_3
case NID_kx_any:
// Let us just pick one as we could use whatever we want.
// See https://www.openssl.org/docs/man1.1.1/man3/SSL_CIPHER_get_kx_nid.html
return "ECDHE_" SSL_TXT_RSA;
#endif
default:
return TCN_UNKNOWN_AUTH_METHOD;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ private NativeStaticallyReferencedJniMethods() {
static native int sslOpNoTLSv1();
static native int sslOpNoTLSv11();
static native int sslOpNoTLSv12();
static native int sslOpNoTLSv13();
static native int sslOpNoTicket();

/**
Expand Down
31 changes: 28 additions & 3 deletions openssl-dynamic/src/main/java/io/netty/internal/tcnative/SSL.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ private SSL() { }
public static final int SSL_PROTOCOL_TLSV1 = (1<<2);
public static final int SSL_PROTOCOL_TLSV1_1 = (1<<3);
public static final int SSL_PROTOCOL_TLSV1_2 = (1<<4);
public static final int SSL_PROTOCOL_TLSV1_3 = (1<<5);

/** TLS_*method according to <a href="https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_new.html">SSL_CTX_new</a> */
public static final int SSL_PROTOCOL_TLS = (SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2);
public static final int SSL_PROTOCOL_TLS = (SSL_PROTOCOL_SSLV3 | SSL_PROTOCOL_TLSV1 | SSL_PROTOCOL_TLSV1_1 | SSL_PROTOCOL_TLSV1_2 | SSL_PROTOCOL_TLSV1_3);
public static final int SSL_PROTOCOL_ALL = (SSL_PROTOCOL_SSLV2 | SSL_PROTOCOL_TLS);

/*
Expand All @@ -69,6 +70,7 @@ private SSL() { }
public static final int SSL_OP_NO_TLSv1 = sslOpNoTLSv1();
public static final int SSL_OP_NO_TLSv1_1 = sslOpNoTLSv11();
public static final int SSL_OP_NO_TLSv1_2 = sslOpNoTLSv12();
public static final int SSL_OP_NO_TLSv1_3 = sslOpNoTLSv13();
public static final int SSL_OP_NO_TICKET = sslOpNoTicket();

public static final int SSL_OP_NO_COMPRESSION = sslOpNoCompression();
Expand Down Expand Up @@ -500,10 +502,33 @@ private SSL() { }
* @param ciphers an SSL cipher specification
* @return {@code true} if successful
* @throws Exception if an error happened
* @deprecated Use {@link #setCipherSuites(long, String, boolean)}
*/
public static native boolean setCipherSuites(long ssl, String ciphers)
throws Exception;
@Deprecated
public static boolean setCipherSuites(long ssl, String ciphers)
throws Exception {
return setCipherSuites(ssl, ciphers, false);
}

/**
* Returns the cipher suites available for negotiation in SSL handshake.
* <p>
* This complex directive uses a colon-separated cipher-spec string consisting
* of OpenSSL cipher specifications to configure the Cipher Suite the client
* is permitted to negotiate in the SSL handshake phase. Notice that this
* directive can be used both in per-server and per-directory context.
* In per-server context it applies to the standard SSL handshake when a
* connection is established. In per-directory context it forces a SSL
* renegotiation with the reconfigured Cipher Suite after the HTTP request
* was read but before the HTTP response is sent.
* @param ssl the SSL instance (SSL *)
* @param ciphers an SSL cipher specification
* @param tlsv13 {@code true} if the ciphers are for TLSv1.3
* @return {@code true} if successful
* @throws Exception if an error happened
*/
public static native boolean setCipherSuites(long ssl, String ciphers, boolean tlsv13)
throws Exception;
/**
* Returns the ID of the session as byte array representation.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,31 @@ public static native long make(int protocol, int mode)
* @param ciphers An SSL cipher specification.
* @return {@code true} if successful
* @throws Exception if an error happened
* @deprecated Use {@link #setCipherSuite(long, String, boolean)}.
*/
public static native boolean setCipherSuite(long ctx, String ciphers) throws Exception;
@Deprecated
public static boolean setCipherSuite(long ctx, String ciphers) throws Exception {
return setCipherSuite(ctx, ciphers, false);
}

/**
* Cipher Suite available for negotiation in SSL handshake.
* <br>
* This complex directive uses a colon-separated cipher-spec string consisting
* of OpenSSL cipher specifications to configure the Cipher Suite the client
* is permitted to negotiate in the SSL handshake phase. Notice that this
* directive can be used both in per-server and per-directory context.
* In per-server context it applies to the standard SSL handshake when a
* connection is established. In per-directory context it forces a SSL
* renegotiation with the reconfigured Cipher Suite after the HTTP request
* was read but before the HTTP response is sent.
* @param ctx Server or Client context to use.
* @param ciphers An SSL cipher specification.
* @param tlsv13 {@code true} if the ciphers are for TLSv1.3
* @return {@code true} if successful
* @throws Exception if an error happened
*/
public static native boolean setCipherSuite(long ctx, String ciphers, boolean tlsv13) throws Exception;

/**
* Set File of PEM-encoded Server CA Certificates
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,10 @@
- Record the sha256: sha1sum -a 256 libressl-{libresslVersion}.tar.gz (shasum on osx)
-->
<libresslSha256>1e3a9fada06c1c060011470ad0ff960de28f9a0515277d7336f7e09362517da6</libresslSha256>
<opensslMinorVersion>1.1.0</opensslMinorVersion>
<opensslPatchVersion>i</opensslPatchVersion>
<opensslMinorVersion>1.1.1</opensslMinorVersion>
<opensslPatchVersion></opensslPatchVersion>
<opensslVersion>${opensslMinorVersion}${opensslPatchVersion}</opensslVersion>
<opensslSha256>50a98e07b1a89eb8f6a99477f262df71c6fa7bef77df4dc83025a2845c827d00</opensslSha256>
<opensslSha256>2836875a0f89c03d0fdf483941512613a50cfb421d6fd94b9f41d7279d586a3d</opensslSha256>
<aprHome>${project.build.directory}/apr</aprHome>
<aprBuildDir>${project.build.directory}/apr-${aprVersion}</aprBuildDir>
<archBits>64</archBits>
Expand Down