Search code examples
c#.netsslcompact-frameworkx509

Using a X509 Certificate in .Net Compact Framework for Client Authentication HTTPRequest


I'm working in Windows Mobile 6 and would like to have client authentication when talking to a Apache webserver. I have a certificate in my local certificate store and it should be rather straightforward:

X509Store myStore = new X509Store("MY", StoreLocation.CurrentUser);
myStore.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certificates = myStore.Certificates;
X509Certificate2 clientcertificate;
foreach (X509Certificate 2certificate in certificates) {
     clientcertificate = certificate; //omitted code to validate certificate
}
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(webPage);
req.AllowWriteStreamBuffering = true;
req.AllowAutoRedirect = false;
req.Method = "POST";
req.ContentType = "text/xml";
req.Accept = "text/xml";
req.ClientCertificates.Add(clientcertificate);
Stream stream = req.GetRequestStream();
stream.Write(buffer, 0, buffer.Length);
stream.Close();

This code segment works as long as I remove the "req.ClientCertificates.Add(clientcertificate)" line.

Once that's inserted, I get a "Could not establish secure channel for SSL/TLS". Maddeningly enough, when I use this exact code in the regular .Net Framework it transmits the certificate perfectly.

Does anyone know if this is possible in Compact Framework? If I can't present the X509Certificate for Client Authentication, what other ways should I pursue to ensure that authentication is proper (I should have access to CAPI or other Microsoft Cryptographic modules)

Thanks.


Solution

  • Good news: I solved it. It turned out not to have to do with the .Net Compact Framework. In 3.5 CF, HTTPWebRequest.ClientCertificates is supported as long as the X509 certificate can be accessed.

    The reason why the SSL Handshake failed was because of a trust issue with the server side certificate. Our server certificates were self-signed and we used certificates that were signed for the wrong URL, so the application rightly wouldn't trust the provided server certificate. For testing purposes, we put in place a Trust All Certificates policy, which will be removed for the production.

    sealed class AcceptAllCertificatePolicy : ICertificatePolicy
    {
        private const uint CERT_E_UNTRUSTEDROOT = 0x800B0109;
    
        public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate
        certificate, WebRequest request, int certificateProblem)
        {
            // Just accept.
            return true;
        }
        /*public bool CheckValidationResult(ServicePoint sp,
        X509Certificate cert, WebRequest req, int problem)
        {
            return true;  
        }*/
    }
    

    Referenced right before the HTTPWebRequest

    System.Net.ServicePointManager.CertificatePolicy = new AcceptAllCertificatePolicy();
    

    And this solves our problem with the SSL/TLS secure channel.