Netduino 3 Wifi Azure Service Bus client certificate issue

A few months ago I wrote a post about using a Netduino 3 wifi device to push data to an Azure Event Hub. Last week I wanted to reuse some of the code for another gateway I was building but it didn’t appear to work. When my application made an HTTPS request to the service bus endpoint of my Event Hub it failed with an exception. Initially I though it might be a problem with wildcard certificates so I build a small demo program which makes three HTTPS requests to endpoints with different certificate configurations (for more detail see the code below).

using System;
using System.Net;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Net.NetworkInformation;

namespace devMobile.Netduino3WifiCertificateQuery
{
   public class Program
   {
      public static void Main()
      {
         // Wait for Network address if DHCP
         NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces()[0];
         if (networkInterface.IsDhcpEnabled)
         {
            Debug.Print(" Waiting for IP address ");
            while (NetworkInterface.GetAllNetworkInterfaces()[0].IPAddress == IPAddress.Any.ToString())
            {
               Debug.Print(".");
               Thread.Sleep(250);
            }
         }

         // Baseline check with google
         Debug.Print("https://www.google.co.nz");
         try
         {
            using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"https://www.google.co.nz"))
            {
               request.Method = "GET";
               request.KeepAlive = false;
               request.Timeout = 5000;
               request.ReadWriteTimeout = 5000;
               request.KeepAlive = false;

               using (var response = (HttpWebResponse)request.GetResponse())
               {
                  Debug.Print("HTTP Status:" + response.StatusCode + " : " + response.StatusDescription);
               }
            }
         }
         catch (Exception ex)
         {
            Debug.Print(ex.Message);
         }

         /*
         DNS Name=*.wordpress.com
         DNS Name=wordpress.com
         */
         Debug.Print("https://wordpress.wordpress.com/");
         try
         {
            using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"https://wordpress.wordpress.com/"))
            {
               //request.Proxy = proxy; 
               request.Method = "GET";
               request.KeepAlive = false;
               request.Timeout = 5000;
               request.ReadWriteTimeout = 5000;
               request.KeepAlive = false;


               using (var response = (HttpWebResponse)request.GetResponse())
               {
                  Debug.Print("HTTP Status:" + response.StatusCode + " : " + response.StatusDescription);
               }
            }
         }
         catch (Exception ex)
         {
            Debug.Print(ex.Message);
         }


         /*
         DNS Name=*.servicebus.windows.net
         DNS Name=servicebus.windows.net
         */
         Debug.Print(@"https://myhomemonitor.servicebus.windows.net/");
         try
         {
            using (HttpWebRequest request = (HttpWebRequest)WebRequest.Create(@"https://myhomemonitor.servicebus.windows.net/"))
            {
               //request.Proxy = proxy; 
               request.Method = "GET";
               request.KeepAlive = false;
               request.Timeout = 5000;
               request.ReadWriteTimeout = 5000;
               request.KeepAlive = false;

               using (var response = (HttpWebResponse)request.GetResponse())
               {
                  Debug.Print("HTTP Status:" + response.StatusCode + " : " + response.StatusDescription);
               }
            }
         }
         catch (Exception ex)
         {
            Debug.Print(ex.Message);
         }
      }
   }
}

I then noticed that when I looked at the certificate details of the endpoint where the requests were failing in Google Chrome (only occurred in Chrome) there was a warming about “obsolete cryptography”.

Google Chrome info about ok certificate

Google Chrome info about ok certificate

Google Chrome info about error causing certificate

Google Chrome info about possibly error causing certificate

I have downloaded the Netduino 3 Wifi IP stack code from github and have traced down to the native interop call which appears to be failing at the very bottom of the stack. My post at Netduino.com has additional detail about my debugging efforts.

Now I’m wondering if the crypto required by newish certificate for the service bus endpoint is not supported/needs to be enabled for the TI CC3100 SimpleLink Wifi network processor.

 

HTTPS with NetMF calling an Azure Service Bus endpoint

Back in Q1 of 2013 I posted a sample application which called an Azure Service Bus end point just to confirm that the certificate configuration etc. was good.

Since I published that sample the Azure Root certificate has been migrated so I have created a new project which uses the Baltimore Cyber Trust Root certificate.

The sample Azure ServiceBus client uses a wired LAN connection (original one used wifi module) and to run it locally you will have to update the Date information around line 24.

HTTPS with NetMF HTTP Client managing certificates

One of the services I needed to call from my Fez Spider required an HTTPS connection. The HTTP client sample located at

C:\Users\…\Documents\Microsoft .NET Micro Framework 4.2\Samples\HttpClient

shows how to load a certificate and use it when making a request.

There wasn’t a lot of information about getting the required certificate so I decided to document how I did it. On my Windows Server 2k8 box I use either a web browser or the Certificate Manager for exporting certificates. The easiest way is to use your preferred browser to access the service endpoint (To enable the export functionality you need to “Run as administrator”).

1.IECertificate

View the certificate

2.CertificateDetails

Select the root certificate

3.CertificatePath

View the root certificate information

4.CertificateRoot

View the root certificate details

5.CertificateRootDetails

Export the certificate

6.CertificateRootExport

Save CER file in the resources directory of your NetMF Project and then add it to the application resources.

If you know the Root Certification Authority you can export the certificate using Certificate Manager

Certificate Manager

Don’t forget to Update the SSL Seed using MF Deploy and ensure that the device clock is correct.

I use either an Network Time Protocol (NTP) Client or an RTC (Realtime Clock) module to set the device clock.

Depending on the application and device you might need to set the device clock every so often.

HTTP Headers Payload encryption

So far the content of the messages has been sent as clear text which would not be acceptable for many applications. The requirement for data privacy causes a problem on the Netduino+ (Nov 2012) as the standard NetMF crypto libraries are not baked into the platform.

I then set about finding some crypto libraries which were NetMF friendly. RSA and Xtea are included in some of other NetMF platforms in the Microsoft.SPOT.Cryptography assembly so Xtea seemed like a reasonable choice to ensure interoperability.

When looking for crypto implementations one of the best sources is the Legion of the Bouncy Castle which was where I started. I downloaded the the V17.7 zip file had a look at the size of the Xtea code & all the associated support libraries and then parked that approach as I was worried about the size and performance of the resulting binaries.

I then looked at other possible tea, xtea & xxtea implementations (including porting the original C code to C#)

I am not a cryptographer so I can’t personally confirm the quality and correctness of an implementation. So after having interop problems I went back to the Legion of the Bouncy Castle which has been peer reviewed by experts and had another look. To get an Xtea implementation working on a .NetMF platform like the Netduino+ you need to include the following files…

  • CryptoException.cs
  • DataLengthException.cs
  • IBlockCipher.cs
  • ICipherParameters.cs
  • KeyParameter.cs
  • XTEAEngine.cs

On the Azure side of things where size is not so critical I just added a reference to the Bouncy Castle main project.

Xtea requires 128 bit blocks so you need to pad out the data on the client, then trim off the padding on the server.
// Pad out the data to a multiple of 8 bytes with spaces
if (xPosition.Length % 8 != 0)
{
xPosition += new string(' ', 8 - xPosition.Length % 8);
}

The key and the data need to be converted to byte arrarys, the Xtea engine initialised and a buffer for storing the encrypted data created.

byte[] dataBytes = Encoding.UTF8.GetBytes(xPosition);
byte[] keyBytes = Encoding.UTF8.GetBytes(key);

xteaEngine.Init(true, new KeyParameter(keyBytes));

Then the data can be encrypted in 8 byte chunks
byte[] cryptoBytes = new byte[dataBytes.Length];
for (int i = 0; i < dataBytes.Length; i += 8)
{
xteaEngine.ProcessBlock(dataBytes, i, cryptoBytes, i);
}

I hex encoded the encrypted data for transmission. Downside to this was it doubled the size of the payload
string hexEncodedCryptoBytes = ByteArrayToHex(cryptoBytes);

I added a StopWatch so I could measure the time taken to encrypt the position data (roughly 72 chars) on my Netduino+
285,342,277,345,282,345,342,350,278,343
Average 318mSec

The size of the payload had grown a bit
Request - Bytes Sent: 262
POST http://gpstrackerhttpheaders.cloudapp.net/posV7.aspx HTTP/1.1
Host: gpstrackerhttpheaders.cloudapp.net
x-Pos: 693A7AC6EBF4E5848CE8ABBA2BC6CAC1ED20574C1B2384E7E246A202C8A67E3DE14EE5231A5DF98C211F64F8402547F8BFDCC2241AAE3782A820086E5EF37AA2C50744941F588442
Content-Length: 0
Connection: Close

Response - Bytes Received: 132
HTTP/1.1 200 OK
Cache-Control: private
Content-Type: text/html
Date: Sun, 03 Feb 2013 04:53:30 GMT
Content-Length: 0

This increase in size had an impact on the time taken to send the message

1123,1144,1122,1142,1125,1125,1138,1111,1099,1141
Average 1127mSec

The binary downloaded to the Netduino+ had grown to 28K which still left plenty of space for additional functionality.