In our HID module, MD5 hash function was used for a number of reasons. Previously we were using wolfSSL API to compute the MD5 hash, now I have replaced these function with bearSSL substitutes. Although Harmony has a crypto library providing MD5 hash, but that in fact is just merely a wrapper around the wolfSSL API.

We also need to generate RSA keys. The generation of device’s RSA key pair also rely on wolfSSL, but bearSSL do not support the generation of RSA keys (yet?). Of course, bearSSL does the encryption and decryption with RSA key pair but those functions are not provided as API for us to use. For now, I’ll leave them with wolfSSL until the day bearSSL release their support.

In our CORS module, for the searching of the start of the bitstream, Dr. Shawn questioned about the reliability of my method to dump the remaining header in a HTTP PUT request by simply clearing the remaining message in the first record. I was assuming that the request line and header of a PUT request is in one record and the body (which contains the bitstream) is in another since that is what I observed with Wireshark. The problem is that I have only tried to work with the PUT request sent by a curl client, it works perfectly fine, but does that holds true for all the major browser client (Chrome, Firefox, Safari, IE, Edge…)?

In order to check this out, I wrote AJAX code to send out PUT request to the board and run it with the browsers. Dr. Shawn is right. The browser can send out the body and header in the same records. In that case, I will lose the bitstream if I dump the first record. Hence, I modify the code to iterate through the request message to look for the start of the bitstream. Inside an HTTP request, there is an empty line between the header and body. In ASCII, “\r\n”, or LF(line feed) CR(carriage return), represent a new line. So what I need to do is to find a continuous “LF”(line feed) “CR”(carriage return) which will locate the empty line “CR LF CR LF” because there are a few “CR LF” in every new line of the request but only one “LF CR” right at the empty line. Then I dump one more bit (the LF afterward) and there it is, the start of the bitstream.

Next, I was assigned to work on the OTA over-the-air update of the board. Basically, its job is to check if our server has released a new update of the board’s firmware. If so, download the update, and run the new firmware right away on run-time. For now, the firmware is downloaded via TFTP protocol which originate from the file transfer between two nodes in a local area network. The OTA is working fine in local area network but has some issue on the internet. Thus, my task is to replace the TFTP service with HTTPS, in another word, build a bearSSL client to download the firmware.

Before I lay my hands on the code, I better first really understand what it is doing currently. So I start to study about the PIC32 Flash Live Update and Harmony Bootloader which involve the Boot Flash Memory(where the program start from), BFxSEQ3(which determine the BFM bank to get lower aliased) and the Configuration Space(where the configuration of the board is stored). Then I look into ota.c.

Before I build the bearSSL client on board, I need a bearSSL Server on the PC to test with. To make sure the bearSSL Server works, I also run a bearSSL client on PC to test with the bearSSL server (with the basic sample code provided). And it don’t. After some troubleshooting, I found the problem is on setting up the client context:
br_ssl_client_reset(&cc, host,0);

Here the second parameter specifies the server name, this will set up an SNI (Server Name Indication) extension which checks the server name contained in the certificate to make sure it matches with the IP address. But we just use an arbitrary name in the generation of the certificate so for sure it will fail the check. Simply pass in a NULL then the SNI extension won’t be executed.

Then, I start to work on ota.c: replace UDP(the transport layer used by TFTP) with TCP; replace TFTP with HTTP + bearSSL; and plant in trusted anchor corresponding to our bearSSL server’s certificate so that the certificate can be verified. Again, it did not works (as always). Client close connection after the server certificate was sent.

After some troubleshooting, I found that this time the problem is on the certificate verification of valid date. Each certificate has an allowed valid time limit like the expiry date we see on food. Although we have a huge range of valid date(since we sign our own cert), but the client needs the current time to validate it. BearSSL use the major environment (Linux, Mac, Windows) method to obtain the time, which is why the bearSSL client on PC works fine. But in PIC32, bearSSL could not obtain the time. Looking through the library I could not found the API to feed in the time or the callback function to obtain time to bearSSL. Hence what I do is directly assign the value into X509_context xc.days and xc.seconds. I need to add 719528 into the days because Unix time starts from 01-01-1970, 719528 is the days passed since year 0 to 1970. Then, voila it works! We are transmitting encrypted data between the PC and board.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.