[Mono-list] SSL Negotiation

Sebastien Pouliot sebastien.pouliot at gmail.com
Wed Apr 27 11:07:39 EDT 2011


Hello Chuck,

As stated in
http://www.mono-project.com/FAQ:_Security#Are_SSL_client_certificates_supported_.3F

client certificates are working with the older API (SslServerStream,
back from 1.2 beta days) that is present in Mono.Security.dll. You can
see examples in
http://www.mono-project.com/UsingClientCertificatesWithXSP
and look at xsp source code.

SslStream is newer than this (2.0 API) and is reusing the older code
(Ssl[Client|Server]Stream). I do not recall if client certificates are
supported (I did not write the SslStream layer code).

Further comments inline...

On Wed, 2011-04-27 at 10:32 -0400, Chuck Budzeak wrote:
> Greetings all,
> 
> 
> I have an SSL Server written for mono which needs to mutually
> authenticate with the clients that connect. As soon as a client
> connects I get:
> 
> 
> System.IO.IOException: The authentication or decryption has failed.
> ---> Mono.Security.Protocol.Tls.TlsException: Server certificate
> Private Key unavailable.
>   at
> Mono.Security.Protocol.Tls.Handshake.Server.TlsClientKeyExchange.ProcessAsTls1 () [0x00000] in <filename unknown>:0 
>   at Mono.Security.Protocol.Tls.Handshake.HandshakeMessage.Process ()
> [0x00000] in <filename unknown>:0 
>   at (wrapper remoting-invoke-with-check)
> Mono.Security.Protocol.Tls.Handshake.HandshakeMessage:Process ()
>   at
> Mono.Security.Protocol.Tls.ServerRecordProtocol.ProcessHandshakeMessage (Mono.Security.Protocol.Tls.TlsStream handMsg) [0x00000] in <filename unknown>:0 
>   at
> Mono.Security.Protocol.Tls.RecordProtocol.InternalReceiveRecordCallback (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
>   --- End of inner exception stack trace ---
>   at Mono.Security.Protocol.Tls.SslStreamBase.AsyncHandshakeCallback
> (IAsyncResult asyncResult) [0x00000] in <filename unknown>:0 
> 
> 
>  I have been at this for a couple days and have read
> through http://www.mono-project.com/Cryptography
> and http://www.mono-project.com/FAQ:_Security a dozen times. 
> 
> 
> Here is my code:
> 
> 
> TcpClient tcpClient = this.tcpListener.AcceptTcpClient();
> SslStream sslStream = new SslStream(tcpClient.GetStream(), true, new
> RemoteCertificateValidationCallback(Validator), new
> LocalCertificateSelectionCallback(SelectLocalCertificate));
> X509Certificate2 serverCert = new X509Certificate2("root.cer");

That won't work. A .cer file contains only a certificate, no private key
so it won't be able to decrypt anything (which means the server won't
work, client certs or not).

You should load a PKCS12 file (which includes both the certificate and
the private key) using the appropriate X509Certificate2 ctor.

Are you able to make your SSL server code working without client
certificates ? (i.e. one problem at the time ;-)

> sslStream.AuthenticateAsServer(serverCert, true, SslProtocols.Tls,
> true);
> 
> 
> It is failing during the RemoteCertificateValidationCallback, which it
> doesn't find the private key. 
> 
> 
> I have tried importing the p12 with the private key every way i could
> google with no result. 

You're not telling where you tried this and  I assume 'no result' likely
means 'no change' ?
> 
> If I try to manually add the p12 with X509Certificate2 cert = new
> X509Certificate2("foo.p12","pass") inside the remote callback, it will
> load the file fine, but then I don't know what to do with it.

If loaded properly then there should be nothing else to to (assuming
SslStream supports client certificates properly).

> 
> If i try to add it to the chain, (which is apparently not what I want
> to do) i get:
> 
> 
> System.IO.IOException: The authentication or decryption has failed.
> ---> System.NullReferenceException: Object reference not set to an
> instance of an object
> at Test.Validator (System.Object sender,
> System.Security.Cryptography.X509Certificates.X509Certificate
> certificate, System.Security.Cryptography.X509Certificates.X509Chain
> chain, SslPolicyErrors sslPolicyErrors) [0x00000] in <filename
> unknown>:0 
> at System.Net.Security.SslStream
> +<BeginAuthenticateAsServer>c__AnonStorey8.<>m__B
> (System.Security.Cryptography.X509Certificates.X509Certificate cert,
> System.Int32[] certErrors) [0x00000] in <filename unknown>:0 

when reporting errors / exceptions always compile with debug and execute
mono with --debug so we'll get file names and line numbers

> 
> The box it is running on is an openSUSE 11.3 with Mono 2.6.4 (which
> probably doesn't matter, but I am trying to give as much detail as
> possible).
> 
> 
> I have the exact opposite working as part of this server which makes
> an SSL/TLS connection to another server (AuthenticateAsClient) and it
> works great. There is just something in this process I am not
> getting...and it is probably really simple.

Client-side is a very different code path - which is why the original
design used 2 (client/server) classes.

You do not need to worry about keys (unless you use client certificates
- and even then the server must _require_ them) when doing client access
to SSL.

> 
> I made the certificate with makecert (as detailed in the links above),
> added it to the trust with certmgr (ditto), and am at a wall.
> 
> 
> Any help would be greatly appreciated!

If you're still having issues then please open a bug report (with a
self-contained test case) and I'll have a look at it.

Sebastien

p.s. an alternative is using the older, tested, API just like XSP





More information about the Mono-list mailing list