Ok, so I figured out I could specify
sslContextBuilder.sslContextProvider(Security.getProvider("BCJSSE"));
Now it seems that I'm not configuring something correctly for EC
algorithms, or else Netty and BouncyCastle are not playing nicely together.
Below is a slightly modified EchoServer. It pre-loads the BouncyCastle
providers, and uses a pre-generated EC key and certificate, since
SelfSignedCertificate is hard coded to use RSA.
package io.netty.example.echo;
import java.io.ByteArrayInputStream;
import java.security.Security;
import javax.net.ssl.SSLEngine;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.jsse.provider.BouncyCastleJsseProvider;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.SslHandler;
/**
* Echoes back any received data from a client.
*/
public final class EchoServer {
private static byte[] KEY =
("-----BEGIN PRIVATE KEY-----\n"
+ "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgujVVI0eva1wiEgIK\n"
+ "lBon2bp0ZFnS8JCuYe3djnfvPG6hRANCAARXIyQz9p/u9IdnLX/hKokNTD5VLMTX\n"
+ "OwA+sTCBY4i2iyZBr0IJQ2ckcoOaljMIFDL/ZKsZKM0hJsoylUD9ZVW1\n"
+ "-----END PRIVATE KEY-----\n").getBytes();
private static byte[] CERT =
("-----BEGIN CERTIFICATE-----\n"
+ "MIIBHDCBwqADAgECAgRZ1gxLMAoGCCqGSM49BAMCMBYxFDASBgNVBAMMC2V4YW1w\n"
+ "bGUub3JnMB4XDTE3MTAwNTEwNDIxOFoXDTE4MTAwNTEwNDIxOFowFjEUMBIGA1UE\n"
+ "AwwLZXhhbXBsZS5vcmcwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARXIyQz9p/u\n"
+ "9IdnLX/hKokNTD5VLMTXOwA+sTCBY4i2iyZBr0IJQ2ckcoOaljMIFDL/ZKsZKM0h\n"
+ "JsoylUD9ZVW1MAoGCCqGSM49BAMCA0kAMEYCIQD2/7J9u4Cz5ewdgXAe7jM9B3w2\n"
+ "R8Cg4Tph4i9629mF1QIhAL59cMvwwEuN7HxYYZoZNB3nGOoMVFXwVvdZwuMhOo5Z\n"
+ "-----END CERTIFICATE-----").getBytes();
public static void main(String[] args) throws Exception {
// Configure SSL.
Security.addProvider(new BouncyCastleProvider());
BouncyCastleJsseProvider bcjsp = new BouncyCastleJsseProvider();
Security.addProvider(bcjsp);
ByteArrayInputStream cert = new ByteArrayInputStream(CERT);
ByteArrayInputStream key = new ByteArrayInputStream(KEY);
final SslContext sslCtx = SslContextBuilder.forServer(cert, key
).sslContextProvider(bcjsp).build();
// Configure the server.
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class
).option(ChannelOption.SO_BACKLOG, 100)
.handler(new LoggingHandler(LogLevel.INFO)).childHandler(new
ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline p = ch.pipeline();
SslHandler s = sslCtx.newHandler(ch.alloc());
SSLEngine e = s.engine();
e.setEnabledCipherSuites(e.getSupportedCipherSuites());
p.addLast(s);
p.addLast(new LoggingHandler(LogLevel.INFO));
p.addLast(new EchoServerHandler());
}
});
// Start the server.
ChannelFuture f = b.bind(4433).sync();
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} finally {
// Shut down all event loops to terminate all threads.
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
@Sharable
public static class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ctx.write(msg);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
// Close the connection when an exception is raised.
cause.printStackTrace();
ctx.close();
}
}
}
I try to connect to it using OpenSSL (1.1 has better support for EC
algorithms, it seems, in particular):
openssl s_client
And I get:
Oct 05, 2017 1:00:48 PM org.bouncycastle.jsse.provider.ProvTlsServer
notifyAlertRaised
INFO: Server raised fatal(2) handshake_failure(40) alert: Failed to read
record
org.bouncycastle.tls.TlsFatalAlert: handshake_failure(40)
at org.bouncycastle.tls.AbstractTlsServer.getSelectedCipherSuite(Unknown
Source)
at
org.bouncycastle.jsse.provider.ProvTlsServer.getSelectedCipherSuite(Unknown
Source)
at org.bouncycastle.tls.TlsServerProtocol.sendServerHelloMessage(Unknown
Source)
at org.bouncycastle.tls.TlsServerProtocol.handleHandshakeMessage(Unknown
Source)
at org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(Unknown Source)
at org.bouncycastle.tls.TlsProtocol.processRecord(Unknown Source)
at org.bouncycastle.tls.RecordStream.readRecord(Unknown Source)
at org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown Source)
at org.bouncycastle.tls.TlsProtocol.offerInput(Unknown Source)
at org.bouncycastle.jsse.provider.ProvSSLEngine.unwrap(Unknown Source)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(
SslHandler.java:281)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1215)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1127)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1162)
at
io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(
ByteToMessageDecoder.java:489)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(
ByteToMessageDecoder.java:428)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(
ByteToMessageDecoder.java:265)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(
AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(
AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(
AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(
DefaultChannelPipeline.java:1359)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(
AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(
AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(
DefaultChannelPipeline.java:935)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(
AbstractNioByteChannel.java:134)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(
NioEventLoop.java:645)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(
NioEventLoop.java:580)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(
NioEventLoop.java:497)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:459)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(
SingleThreadEventExecutor.java:858)
at
io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(
DefaultThreadFactory.java:138)
at java.lang.Thread.run(Thread.java:748)
I have confirmed that this works using old-style Threads, etc, and can
provide that code here if needed.
Any idea what I am doing wrong? If I remove the
"builder.sslContextProvider(bcjsp)", it also works, BUT only BouncyCastle
has support for "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8", which need! Sigh!
Rogan
On Tuesday, September 26, 2017 at 9:40:55 AM UTC+2, Rogan Dawes wrote:
>
> Hi,
>
> I'm trying to write a proxy to intercept COAP connections from an embedded
> device. I am able to clone the TLS certificates that it thinks it is
> connecting to, obviously using my own keys (for the TLS server side), and
> insert the CA cert into the firmware of this device. By this, I mean that
> an ASN.1 dump of my CA certificate and the "expected" CA certificate show
> differences only in the actual key values, not any other parameters of the
> keys or certificates.
>
> However, so far I have been unable to convince netty to negotiate a
> connection using the only supported algorithm offered by the device,
> being TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8. When I do, I get handshake errors
> that the handshaker was unable to establish a common cipher suite.
>
> I have tried using the native JDK 8 options (build 1.8.0_102-b14), as well
> as tried specifying use of the Openssl provider via
>
>
> sslContext = SslContextBuilder.forServer(km.getPrivateKey(target), km
> .getCertificateChain(target))
>
> .sslContextProvider(new BouncyCastleProvider()).build();
>
>
> I have also tried:
>
>
> sslContext = SslContextBuilder.forServer(km.getPrivateKey(target), km
> .getCertificateChain(target))
>
> .sslProvider(SslProvider.OPENSSL).build();
>
>
> where km is an X509KeyManager instance that holds the relevant keys.
>
>
> Any suggestions?
>
>
> Rogan
>
>
>
--
You received this message because you are subscribed to the Google Groups
"Netty discussions" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/netty/876f9cb6-9b29-43fa-9309-239b24661432%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.