Seems like I'm talking to myself here :-(

Anyway, current status is that BouncyCastle requires use of the PKIX 
implementation of a KeyManager, and this is not the default. In order to do 
this, it looks like I have to replicate a whole lot of code that already 
exists in SslContextBuilder and SslContext, unless I do:

Security.setProperty("ssl.KeyManagerFactory.algorithm","PKIX");

But that feels like a "big stick" approach, being a global change! :-(

Also also noted that I have to change JdkSslServerContext (and place a copy 
in my own code), because when initialising the SSLContext, it passes a null 
value instead of a SecureRandom instance.:

            SSLContext ctx = sslContextProvider == null ? 
SSLContext.getInstance(PROTOCOL)

                : SSLContext.getInstance(PROTOCOL, sslContextProvider);

            ctx.init(keyManagerFactory.getKeyManagers(),

                     trustManagerFactory == null ? null : 
trustManagerFactory.getTrustManagers(),

                     null);

 
BouncyCastle does not like that at all.

Rogan

On Thursday, October 5, 2017 at 1:06:20 PM UTC+2, Rogan Dawes wrote:
>
> 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/08e97b0d-4be2-4ab3-8c6b-65455a0c5d57%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to