0 votes
by (220 points)

Trying to evaluate if I can use Rebex dll to support TLS 1.2 on Wince 5.0 and PC.

Downloading the trial license on Feb 2, 2024, I followed the example to write a small test program (see below). Using 3 dll files in Rebex Components 7.0.8755\bin\net-3.5, the test program on PC returned the Result message in 2 seconds: "Result: Hello World from test.rebex.net. Server time is 2024-02-12 11:39:22."

14:39:21:009    WL: StartRebexTest is called
14:39:21:009    WL: MyRebexTest starts...
14:39:21:262    Registering Rebex HttpWebRequestCreator...  
14:39:21:262    Invoking web service at 
https://test.rebex.net/demowebservice.asmx  
14:39:21:262    WL:  MkRebex HelloWorld 
14:39:22:548    [PanelFlipper] Flipped panels for no-ID from indexes 0 to 1.
14:39:23:557    Result: Hello World from test.rebex.net. Server time is 2024-02-12 11:39:22.

Running the same test program with 3 dll files from "Rebex Components Legacy CF R5.14\bin\netcf-3.5" on Wince 5.0 dev Set-Top-Box, the TLS 1.2 call never returns the invoke results.

Why does the client fail to get TLS 1.2 test result on WinCE device? Is there any way to debug or fix?

[2024-02-12 11:20:46.929] WL: StartRebexTest is called
[2024-02-12 11:20:47.585] WL: MyRebexTest starts...
[2024-02-12 11:20:47.745] Rx Sense = 1
[2024-02-12 11:20:47.922] Registering Rebex HttpWebRequestCreator... 
[2024-02-12 11:20:48.015] Invoking web service at https://test.rebex.net/demowebservice.asmx
[2024-02-12 11:20:48.016] WL:  MkRebex HelloWorld 
[2024-02-12 11:20:49.712] [PanelFlipper] Flipped panels for no-ID from indexes 0 to 1.
[2024-02-12 11:20:49.744] Rx Sense = 1
[2024-02-12 11:20:51.752] Rx Sense = 1
[2024-02-12 11:20:53.750] Rx Sense = 1
[2024-02-12 11:20:55.750] Rx Sense = 1
[2024-02-12 11:20:56.719] [PanelFlipper] Flipped panels for no-ID from indexes 1 to 0.
[2024-02-12 11:20:57.759] Rx Sense = 1
[2024-02-12 11:20:59.770] Rx Sense = 1

Here is the Rebex https TLS 1.2 test sample code:

namespace Rebex.Samples
{
    /// <remarks/>
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Web.Services.WebServiceBindingAttribute(Name = "DemoWebServiceSoap", Namespace = "http://tempuri.org/")]
    public partial class MkRebexWebService : System.Web.Services.Protocols.SoapHttpClientProtocol
    {

        /// <remarks/>
        public MkRebexWebService()
        {
            this.Url = "http://test.rebex.net/demowebservice.asmx";
            // this.Url = "https://test-tls12.messagemedia.com";
        }

        /// <remarks/>
        [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace = "http://tempuri.org/", ResponseNamespace = "http://tempuri.org/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
        public string HelloWorld()
        {
            Console.WriteLine("WL:  MkRebex HelloWorld ");
            object[] results = this.Invoke("HelloWorld", new object[0]);
            return ((string)(results[0]));
        }
    }

    static class MkRebexCertificateVerifier
    {
        // list of trusted certificate thumbprints
        // (replace with a persistend storage if needed)
        static List<string> TrustedThumbprints = new List<string>();

        public static void MkRebexCertificateValidator(object sender, Rebex.Net.SslCertificateValidationEventArgs e)
        {
            // try using the default certificate validator (uses Windows certificate infrastructure
            // or custom Rebex certificate validator when needed (e.g. for SHA-2 based certificates on .NET CF)
            Rebex.Security.Certificates.ValidationResult res = e.CertificateChain.Validate(e.ServerName, 0);
            if (res.Valid)
            {
                e.Accept();
                return;
            }

            // get the server certificate
            Rebex.Security.Certificates.Certificate cert = e.CertificateChain.LeafCertificate;

            // check whether the certificate is already explicitly trusted
            if (TrustedThumbprints.Contains(cert.Thumbprint))
            {
                e.Accept();
                return;
            }

            // the certificate is not trusted yet - show it to the user
            StringBuilder sb = new StringBuilder();
            sb.Append("There was an error validating the certificate: '" + res.Status + "'.\r\n");
            sb.Append("Do you trust the following certificate?\r\n");
            sb.Append(" Common name:\t" + cert.GetCommonName() + "\r\n");
            sb.Append(" Thumbprint:\t" + cert.Thumbprint + "\r\n");
            sb.Append(" Expires on:\t" + cert.GetExpirationDate().ToString() + "\r\n");

            // ask user whether to trust this certificate
            DialogResult result = MessageBox.Show(
                sb.ToString(),
                "Do you trust this certificate?",
                MessageBoxButtons.YesNo,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button2
                );

            // accept or reject the certificate based on user response
            if (result == DialogResult.Yes)
            {
                e.Accept();

                // OPTIONALLY store the current certificate in a list of explicitly trusted certificates
                // WriteLine("Adding certificate thumbprint to trusted certificate store.");
                TrustedThumbprints.Add(cert.Thumbprint);
            }
            else
            {
                e.Reject();
            }
        }
    }

    static class Program
    {
        public static void MyRebexTest()
        {
            Console.WriteLine("WL: MyRebexTest starts...");
            Rebex.Licensing.Key = "...does not show temp license here...";

            // create an instance of Rebex HTTP request creator
            Rebex.Net.HttpRequestCreator creator = new Rebex.Net.HttpRequestCreator();

            // specify enabled TLS/SSL versions (TLS 1.2, 1.1 and 1.0 are enabled by default;
            // legacy SSL 3.0 is also supported, but it is no longer considered secure)
            // creator.Settings.SslAllowedVersions = TlsVersion.TLS12 | TlsVersion.TLS11 | TlsVersion.TLS10;

            creator.ValidatingCertificate += Rebex.Samples.MkRebexCertificateVerifier.MkRebexCertificateValidator;

            // register request creator to handle HTTP and HTTPS requests
            // (replaces .NET's default HttpWebRequest)
            Console.WriteLine("Registering Rebex HttpWebRequestCreator... ");
            creator.Register();

            MkRebexWebService client = new MkRebexWebService();
            client.Url = "https://test.rebex.net/demowebservice.asmx";
            // client.Url = "https://test-tls12.messagemedia.com";

            try
            {
                Console.WriteLine("Invoking web service at " + client.Url);
                Console.WriteLine("");
                Console.WriteLine("Result: " + client.HelloWorld());
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }
    }
}
Applies to: Rebex HTTPS, Rebex TLS
by (144k points)
Please create a debug log using HttpRequestCreator's LogWriter property - as described at https://www.rebex.net/kb/logging/ - and see what's actually going on.
It might be useful to compare logs from the test program on the PC with a log from WinCE 5.0. Ideally, post the logs here or mail them to us at support@rebex.net for analysis.

1 Answer

0 votes
by (220 points)
selected by
 
Best answer

Thanks for the debug trick. I sent the details to support@rebex.net.

It seems that Server certificate was rejected on WinCE device.

2024-02-13 11:41:01 INFO HttpRequest(1)[1702422970] TLS: Negotiating TLS 1.2, RSA, AES with 128-bit key in GCM mode, AEAD.
2024-02-13 11:41:01 DEBUG HttpRequest(1)[1702422970] TLS: The server supports secure renegotiation.
2024-02-13 11:41:01 DEBUG HttpRequest(1)[1702422970] TLS: HandshakeMessage:Certificate was received.
2024-02-13 11:41:01 DEBUG HttpRequest(1)[1702422970] TLS: HandshakeMessage:ServerHelloDone was received.
2024-02-13 11:41:02 DEBUG HttpRequest(1)[1702422970] TLS: Verifying server certificate ('CN=test.rebex.net').
2024-02-13 11:56:07 DEBUG HttpRequest(1)[1702422970] TLS: Certificate verification result: Other
2024-02-13 11:56:07 DEBUG HttpRequest(1)[1702422970] TLS: Rebex.Net.TlsException: Server certificate was rejected by the verifier because of other problem.
by (144k points)
Thanks!
To determine what went wrong during the certificate validtion, you might enable relevant logging as well:
    Rebex.Security.Certificates.CertificateEngine.SetCurrentEngine(CertificateEngine.Internal);
    Rebex.Security.Certificates.CertificateEngine.Internal.LogWriter = new FileLogWriter(path, LogLevel.Debug);
by (220 points)
Hi, Lukas:

Thanks again for the great suggestions. The setting seems to work on the WinCE device only.

After adding the 2 lines and running the test on the WinCE device, I found the TLS problem was related to "CERT: Verification result is 'IncompleteChain' (CRL not validated yet)"

    2024-02-14 15:54:21 DEBUG HttpRequest(1)[596780386] TLS: Verifying server certificate ('CN=test.rebex.net').
    2024-02-14 15:54:21 DEBUG EnhancedCertificateEngine(0)[596780386] CERT: Certificate chain building started ('CN=test.rebex.net').
    2024-02-14 15:54:21 DEBUG EnhancedCertificateEngine(0)[596780386] CERT: Certificate chain building started ('CN=test.rebex.net').
    2024-02-14 15:54:21 DEBUG EnhancedCertificateEngine(0)[596780386] CERT: Certificate chain validation started ('CN=test.rebex.net').
    2024-02-14 15:54:21 DEBUG EnhancedCertificateEngine(0)[596780386] CERT: Verifying certificate 'CN=R3, O=Let's Encrypt, C=US'.
    2024-02-14 15:54:21 DEBUG EnhancedCertificateEngine(0)[596780386] CERT: Verification result is 'IncompleteChain' (CRL not validated yet), certificate: 'CN=R3, O=Let's Encrypt, C=US'.
by (144k points)
This looks like Let's Encrypt's root CA certificate is not trusted at the WinCE device.
Try downloading it from https://letsencrypt.org/certs/isrgrootx1.pem and either (a) add it to the trusted root CA store on the device, or (b) configure Rebex certificate engine to trust it:

    using  Rebex.Security.Certificates;
    ...

    var letsEncrypt = Certificate.LoadDer("/some_path/isrgrootx1.pem");
    var extraCertificates = new Certificate[] { letsEncrypt };
    var customEngine = new EnhancedCertificateEngine(extraCertificates);
    //customEngine LogWriter = new FileLogWriter(path, LogLevel.Debug);
    CertificateEngine.SetCurrentEngine(customEngine);
by (220 points)
Hi, Lukas:

Thanks again for providing the solution. It works now.
...