Categories

[Little Brosers] DFU, Flash, and Heroku

Hello everyone. I’ve been working on various things for our project, here is a summary.

DFU

After struggling a lot, I succeeded performing a DFU in bootloader mode (in this mode, there is no app in the flash). Now I work on making a DFU in buttonless mode, where the DFU is performed with a GATT service with the application running.

We need to flash the bootloader and the softdevice to make it work. When there is a reset, the bootloader checks the apps present in the internal flash, it computes their crc32 and compare it to the checksum stored in a special internal flash page named bootloader_settings_page. So now when we flash our app, we also need to write the good checksum in this place. The program nrfutil can generate a hex file (a text file, basically with a list of address and their data) with the content of the bootloader settings page, and we can juste merge it with the application with the nordic mergehex program to make it work. I still need to write a script for the merge, and also handle the keys in the CI (with a protected secret key).

Flash

I made a basic code that check if the SPI external flash (AT45DB321E) is present and stop the execution otherwise. For that I used the “Manufacturer and Device ID Read”, I just send an opcode, and the flash has to answer correctly 5 bytes. 

After having made a board configuration header, and after having received the drop boards, I tested it, but it was not working. The logic analyser showed that the CS pin was not working and was kept low. I tested it on a second Drop, and surprisingly, it started working for some times, and then failed. At this time I suspected a hardware problem, for example the flash receives too much voltage and is destroyed. Hopefully with the help of Antony, we realised that the CS pin was by default used for NFC, and unlike other GPIO pins, needed to be explicitly configured as GPIO. I think it works one time because there is an undefined behaviour if the CS wire is always kept low.

Heroku

We migrate the certification authority to Heroku because my 15€ router didn’t work correctly (after ~20 hours of up time, it wasn’t connected to the internet anymore, and I had to plug out and plug in the RJ45 wire, and it would work again).

The heroku migration was not so easy, the reason was that heroku has ephemeral filesystems, it was generating the keys at each app startup (often in the free version of Heroku). So I put all the keys in environnement variables. Heroku also doesn’t provide database, I need to find a free MongoDB Heroku plugin to make it work, and Heroku ask for your CB even if it’s free. I updated the continuous deployment, it is now easier (I was doing a git filter-branch to keep only the ca folder history before) and use a ruby util named dpl (https://github.com/travis-ci/dpl).

I also put the Heroku API_KEY  as a protected secret variable in GitLab (Accessible only in the master branch, otherwise my coworkers could just write a CI script “echo $API_KEY” in one of their branch and would be able to steal the API_KEY).

DFU

This week, I worked on the DFU (or Device firmware update) over BLE. I succeeded in doing a dfu with our firmware, now I need to automatise it.

How it works

To make a DFU, we need another application called the DFU bootloader, it does this:

  • Check if a valid app is present (it will check a crc32 checksum)
  • If it’s the case it will run it, unless someone is pressing on button 4 (of course we will change it)
  • If there is no valid app or someone is pressing on button 4, the bootloader will enter dfu mode and wait for a dfu signed packet (there is a public key somewhere in the bootloader code)
  • If nobody is doing a DFU, and there was a valid application, it will run it after a timeout
  • If someone is doing a DFU, it will write the new code to the flash, check the content, and run it.

So the steps to make it work are:

  • Compile the bootloader and flash it
  • Compile the firmware
  • Create a zip packet with nrfutil : nrfutil pkg generate –application _build/nrf52832_xxaa.bin app.zip –debug-mode –hw-version 52 –sd-req 0xFFFE –key-file bootloader/key
  • Send it to your phone, and start nrf connect, launch the dfu

The dfu took 30 seconds (our app is not stripped, so it should be 15 seconds actually),

The softdevice update took 1 min 30.

Now I need to make the CI create the zip package, with a good private key handling, and see how we will work locally (on our laptops) with it.

Https backend

Currently, I’m working on the backend, which will mainly register user by signing their certificates.

Technologies

I work with Flask because everybody in our group know Python and they will be able to understand and review my code !

I chose MongoDB because our db has no relation, it just stores usernames, public keys, and ids.

I work with the cryptography python package, it uses openssl and I found it to be really great (I tried pyOpenSSL, and pycrypto before).

Certificate format

I decided to use x509 certificates because they have already everything we need in them, and they give different serialisation options.

Advancement

My server can already generate and sign a certificate based on the username and the public key given in a http post, but it’s still far from being ready.

I still need to work on:

  • Write the API documentation
  • Write more tests
  • Find the best way to handle CA private key storage
  • Handle User ids
  • Deployment, we will use Heroku for development (of course if there is a real production one day, we will not use it)
  • Get a https certificate (Let’s encrypt !)

We will maybe create a github mirror so everyone will be able to see and try our code !

[Little-Brosers] Encryption[#2] and Compression

Encryption

(context: everyone should be able to verify every message)

We changed our encryption, we decided to use RSA only (with 2048 bit keys).

With the padding scheme (OEAP), we have approximately 190 bytes of plaintext.

The total size of a message is 368 bytes.

The overhead seems huge, we will maybe implement an hybrid encryption with AES, but the overhead would still be big: 16 bytes IV, ~8 bytes padding (mean), 32 bytes MAC, 64 bytes signature)

We hash the encryption key and transmit it to let the receiver know which key was used to encrypt (or we would lose the plaintext non-repudiation property).

Because of the small allowed message size, we can try to compress them.

Compression

I tested two compression software: gzip (with default options) and smaz (source). Smaz is optimised for english, and is only 200 lines of c.

Results:

(sentences about BLE are from wikipedia BLE articles)

Sentence 1: “Les modes BLE (bande passante plus limitée et très faible consommation) et Bluetooth standard (niveau d’émission plus élevé et portée plus grande) sont donc des technologies complémentaires.”

Smaz: 76 % (output size on input size, smaller is better)

gzip (default options): 91 %

 

Sentence 2: “Borrowing from the original Bluetooth specification, the Bluetooth SIG defines several profiles — specifications for how a device works in a particular application — for low energy devices.”

Smaz: 65 %

gzip: 84 %

 

Sentence 3: “eiv9TaecCei3tah9quahJe 7aaCha8AinaewaZ1errait0Koizuo9ahQuikooQu6ahy air3saMeee LiPh8aieWae3HoaiThahb4Eer1dooGwu4Rae2aaichoe5F” (high entropy string)

Smaz: 117 %

gzip: 113 %

Conclusion

Smaz looks pretty good, it is better than gzip even in french. We will try to adapt it for the french language.

[Little Brosers] Crypto thoughts #1

[Little Brosers] Crypto thoughts

Please read the description of Little brosers to understand this post.

Whereas my teammates focused on merkle trees or android, I worked a little bit on encryption.

Goals

  • End to end encryption
  • authentication of both sides

Contraints

  • There is no handshake possible between two people before sending a message
  • Small key size (less BLE transfer => more battery life) (bye bye PGP)
  • Fast (actually low power consuming ) signature verification
  • each mobile app and drop must be able to verify each message, because we will have small memories in our drops, and thus we must be able to refuse every message which is not properly signed (or a denial of service would be too easy)

So we must encrypt then sign (It doesn’t work so easily, see later).

Using an existing protocol

Encrypt then sign not a common thing, and I don’t know any existing encryption protocol which does that (if you know one, please let me know).

I would like to use the Signal protocol (like Signal, WhatsApp,…), it features (wikipedia):

  • confidentiality
  • integrity
  • authentication
  • participant consistency
  • destination validation
  • forward secrecy
  • backward secrecy (aka future secrecy)
  • causality preservation
  • message unlinkability
  • message repudiation
  • participation repudiation
  • asynchronicity

I don’t think we could integrate it because of our constraints, and I believe it would be too hard to adapt it, but I will re-think about it.

Home-brewed crypto

It would be 100 times better to use an existing protocol, but I didn’t find one that satisfies our constraints. Hopefully we are in an academic context and we can make mistakes (and we will), so we can try to create our own crypto protocol.

For now, forget about features like forward secrecy.

We can’t encrypt then sign, because someone could re-sign the encrypted part and say it was his message. There are another problems (and sign then encrypt is also not completely safe), see http://world.std.com/~dtd/sign_encrypt/sign_encrypt7.html.

A solution is to sign, encrypt and then re-sign the message, the drop will only check the outer signature, whereas a phone will check the two signatures and verify that they are signed by the same person.

The other parts are common: AES with a mode of operation, RSA with a padding scheme (or another asymmetrical encryption algorithm), and a signature algorithm (RSA or ECDSA,  RSA has huge keys but is faster to verify a signature).

For now, the encryption looks like this:

Mode of operation and algorithms could change. I will add the size of keys later (it will be  approximately 128 bits of security).

I don’t think we need to use a MAC because the message is already signed.

For the public key infrastructure, we will use a certification authority which signs user certificates (through https) based on the username uniqueness, and another backend server will distribute the public keys to everybody. (more on that in a future post).

The drop will not have the time, we will talk of the implications and solutions later.

Please let me know if you have any idea of an existing protocol we could use, or any criticisms of our home-brewed crypto.