diff --git a/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java b/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java index 5a297614a9..4daa1d8ceb 100644 --- a/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java +++ b/handler/src/main/java/io/netty/handler/ssl/OpenSslKeyMaterialManager.java @@ -15,6 +15,7 @@ */ package io.netty.handler.ssl; +import io.netty.buffer.ByteBufAllocator; import org.apache.tomcat.jni.SSL; import javax.net.ssl.SSLException; @@ -27,6 +28,10 @@ import java.util.HashSet; import java.util.Map; import java.util.Set; +import static io.netty.handler.ssl.ReferenceCountedOpenSslContext.freeBio; +import static io.netty.handler.ssl.ReferenceCountedOpenSslContext.newBIO; +import static io.netty.handler.ssl.ReferenceCountedOpenSslContext.toBIO; + /** * Manages key material for {@link OpenSslEngine}s and so set the right {@link PrivateKey}s and * {@link X509Certificate}s. @@ -88,32 +93,39 @@ class OpenSslKeyMaterialManager { private void setKeyMaterial(long ssl, String alias) throws SSLException { long keyBio = 0; long keyCertChainBio = 0; + long keyCertChainBio2 = 0; + try { // TODO: Should we cache these and so not need to do a memory copy all the time ? PrivateKey key = keyManager.getPrivateKey(alias); X509Certificate[] certificates = keyManager.getCertificateChain(alias); if (certificates != null && certificates.length != 0) { - keyCertChainBio = OpenSslContext.toBIO(certificates); - if (key != null) { - keyBio = OpenSslContext.toBIO(key); - } - SSL.setCertificateBio(ssl, keyCertChainBio, keyBio, password); + // Only encode one time + PemEncoded encoded = PemX509Certificate.toPEM(ByteBufAllocator.DEFAULT, true, certificates); + try { + keyCertChainBio = newBIO(encoded.content().retainedSlice()); + keyCertChainBio2 = newBIO(encoded.content().retainedSlice()); - // We may have more then one cert in the chain so add all of them now. - SSL.setCertificateChainBio(ssl, keyCertChainBio, false); + if (key != null) { + keyBio = toBIO(key); + } + SSL.setCertificateBio(ssl, keyCertChainBio, keyBio, password); + + // We may have more then one cert in the chain so add all of them now. + SSL.setCertificateChainBio(ssl, keyCertChainBio2, false); + } finally { + encoded.release(); + } } } catch (SSLException e) { throw e; } catch (Exception e) { throw new SSLException(e); } finally { - if (keyBio != 0) { - SSL.freeBIO(keyBio); - } - if (keyCertChainBio != 0) { - SSL.freeBIO(keyCertChainBio); - } + freeBio(keyBio); + freeBio(keyCertChainBio); + freeBio(keyCertChainBio2); } } diff --git a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java index 19035d7698..5f5deb0667 100644 --- a/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java +++ b/handler/src/main/java/io/netty/handler/ssl/ReferenceCountedOpenSslContext.java @@ -637,29 +637,43 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen /* Load the certificate file and private key. */ long keyBio = 0; long keyCertChainBio = 0; - + long keyCertChainBio2 = 0; + PemEncoded encoded = null; try { - keyCertChainBio = toBIO(keyCertChain); - keyBio = toBIO(key); + // Only encode one time + encoded = PemX509Certificate.toPEM(ByteBufAllocator.DEFAULT, true, keyCertChain); + keyCertChainBio = newBIO(encoded.content().retainedSlice()); + keyCertChainBio2 = newBIO(encoded.content().retainedSlice()); + + if (key != null) { + keyBio = toBIO(key); + } SSLContext.setCertificateBio( ctx, keyCertChainBio, keyBio, keyPassword == null ? StringUtil.EMPTY_STRING : keyPassword); // We may have more then one cert in the chain so add all of them now. - SSLContext.setCertificateChainBio(ctx, keyCertChainBio, false); + SSLContext.setCertificateChainBio(ctx, keyCertChainBio2, false); } catch (SSLException e) { throw e; } catch (Exception e) { throw new SSLException("failed to set certificate and key", e); } finally { - if (keyBio != 0) { - SSL.freeBIO(keyBio); - } - if (keyCertChainBio != 0) { - SSL.freeBIO(keyCertChainBio); + freeBio(keyBio); + freeBio(keyCertChainBio); + freeBio(keyCertChainBio2); + if (encoded != null) { + encoded.release(); } } } + + static void freeBio(long bio) { + if (bio != 0) { + SSL.freeBIO(bio); + } + } + /** * Return the pointer to a in-memory BIO * or {@code 0} if the {@code key} is {@code null}. The BIO contains the content of the {@code key}. @@ -730,7 +744,7 @@ public abstract class ReferenceCountedOpenSslContext extends SslContext implemen } } - private static long newBIO(ByteBuf buffer) throws Exception { + static long newBIO(ByteBuf buffer) throws Exception { try { long bio = SSL.newMemBIO(); int readable = buffer.readableBytes();