Skip to content

Instantly share code, notes, and snippets.

@jaimejim
Last active August 15, 2018 10:31
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save jaimejim/82d53f97a9d011ef13c8750129b84cb1 to your computer and use it in GitHub Desktop.
Firmware Updates

FIRMWARE UPDATES FOR IOT

Image

Attendees:

  • Hannes Tschofenig
  • Jaime Jiménez
  • Thomas Fossatti
  • Bill Silverajan
  • Felipe Espinoza
  • Alexandra Ibarra
  • David Waltermire

Twitter: #IETFHackathon & #IETF102

Hackathon IETF102

This tutorial is available as a gist: https://gist.github.com/jaimejim/82d53f97a9d011ef13c8750129b84cb1

Etherpad: https://etherpad.tools.ietf.org/p/FUIETF102

Notes from previous hackathon at IETF101

Etherpad: https://etherpad.tools.ietf.org/p/FUIETF101

Formatted SUIT Tutorial: https://gist.github.com/jaimejim/3aa9c6e85e82a353c9fa90794c856d89

Manifest Generator: https://github.com/ARMmbed/suit-manifest-generator

Development board for the IETF suit workshop https://os.mbed.com/platforms/Mbed-WiFi-BLE/

TAKEAWAYS

  • To accelerate the setup process it would be good to (a) have everyone install the Keil uVision 5 IDE upfront (Windows-only), and (b) develop a COSE middleware for Keil. The COSE middleware package would allow integrating COSE without having to deal with the crypto configuration.

  • It would also be good to use and configure the Keil development board, http://www.keil.com/mcbstm32f400/, for use with SUIT. The primary reason is the great debugging support available for this board.

  • Setting a common virtual environment (i.e. nix) would help when locally compiling the mbed code. There are often small configuration issues that take a while to figure out (Toolchain, python env, gcc version...). @jaime: there is docker-based environment available at https://github.com/aschmidt75/docker-mbed-cli-gcc-arm

  • We bricked a couple of boards, still unsure as to the reason why...

It is pretty cool to use dedicated boards, more of that please: Image

Setting up the Environment

Online on the MBed site

Locally on your computer

On Mac the board is at /Volumes/DAPLINK not cd /Volumes/MBED as in IETF101. Note: Only python 2.7 is compatible. When using a Mac, usage of macOS High Sierra is recommended. Using Python 2.x in earlier versions of Mac OS X is problematic. In such cases using the Python virtualenv utility is recommended to install Python packages. Also pip would need to be reinstalled. See this article for details

mbed import mbed-os-example-blinky
  • Got into the project
cd mbed-os-example-blinky
  • You should have downloaded the GCC compiler, let's set up the right GCC path and other MBED variables. You can also set them as --global ones.
mbed config GCC_ARM_PATH ~/opt/gcc-arm-none-eabi-7-2017-q4-major/bin
mbed config TARGET MTB_MXCHIP_EMW3166

Note: If you encounter this error condition [mbed] ERROR: Could not find mbed program in current path.. execute the following command instead:

mbed config --global GCC_ARM_PATH ~/opt/gcc-arm-none-eabi-7-2017-q4-major/bin
  • Check that the configuration is correct:
mbed config --list

It should look similar to:

[mbed] Global config: ARM_PATH=/Users/jaime/opt/gcc-arm-none-eabi-7-2017-q4-major/ TOOLCHAIN=GCC_ARM TARGET=K64F 
GCC_ARM=Users/jaime/opt/gcc-arm-none-eabi-7-2017-q4-major/lib/ GCC_ARM_PATH=/Users/jaime/opt/gcc-arm-none-eabi-7-2017-q4-major/bin MBED_GCC_ARM_PATH=/Users/jaime/opt/gcc-arm-none-eabi-7-2017-q4-major/  

[mbed] Local config (/Users/jaime/code/mbed-cli/mbed-os-example-blinky): GCC_ARM_PATH=/Users/jaime/opt/gcc-arm-none-eabi-7-2017-q4-major/bin 
TARGET=MTB_MXCHIP_EMW3166
  • To compile it locally run
mbed compile -t GCC_ARM

That generates a binary at mbed-cli/mbed-os-example-blinky/BUILD/MTB_MXCHIP_EMW3166

  • The blinky will be generated at ./BUILD/MTB_MXCHIP_EMW3166/GCC_ARM/mbed-os-example-blinky.bin and the board is at /Volumes/DAPLINK on Mac.

  • Copy the binary to the board.

cp ./BUILD/MTB_MXCHIP_EMW3166/GCC_ARM/mbed-libcose.bin /Volumes/DAPLINK

Running the SUIT code on the SUIT IETF Hackathon Board.

Setting up libcose

The Mbed libcose repo is now at https://github.com/suit-wg/mbed-libcose

  • Clone & update submodules
git clone https://github.com/jaimejim/mbed-libcose.git
git submodule init
git submodule update

OR ALTERNATIVELY

git clone https://github.com/suit-wg/mbed-libcose.git 
git clone https://github.com/intel/tinycbor.git
git clone https://github.com/bergzand/libcose.git

You should have the following setup

.
├── BUILD 
├── README.md 
├── ecpubkey.pem 
├── libcose 
├── mbed-os 
├── mbed-os.lib 
├── mbed_app.json 
├── mbed_settings.py 
├── mbed_settings.pyc 
├── suit.c 
├── test.json 
└── tinycbor
cp tinycbor/src/cbor.h tinycbor/
sed -i'' -e 's|cbor.h|tinycbor/cbor.h|' libcose/include/cose/cbor.h
  • Set the mbed repository. Remember NOT to do "mbed deploy" this time.
mbed new .
mbed compile -m MTB_MXCHIP_EMW3166 -t GCC_ARM
  • Output should be:
Total Static RAM memory (data + bss): 12232 bytes 
Total Flash memory (text + data): 89186 bytes  
Image: ./BUILD/MTB_MXCHIP_EMW3166/GCC_ARM/mbed-libcose.bin

Note:

In order to fix the error

[Error] suit.c@115,33: 'keyid' undeclared (first use in this function); did you mean 'kid'? [ERROR] ./suit.c: In function 'main': ./suit.c:101:27: warning: statement with no effect [-Wunused-value]
CU_ASSERT_EQUAL_FATAL(decode_success, 0);

Comment out the following line on the suit.c file // CU_ASSERT_EQUAL(memcmp(kid, keyid, sizeof(keyid) - 1), 0);

Note for Windows users

Make sure that you read the README file since modifications to the cose code are needed. If you encounter problems compiling the code and it is related to a missing unistd.h file and the lack of definition of ssize_t then you need to add a dummary unistd.h file and put the definition of ssize_t in there (typedef size_t ssize_t;)

Creating the manifest

Clone into https://github.com/hannestschofenig/suit-manifest-generator For changes see https://github.com/hannestschofenig/suit-manifest-generator/commit/9ee0097b675abd47c156581ff3f618765dbde6de

The manifest-generator directory also contains the public key used to sign the manifest. The file is ecpubkey.pem. To parse the content use http://lapo.it/asn1js/

Here is another example JSON manifest file for use in our code:

{
    "manifestFormatVersion" : 1, 
    "nonce" : "c31211d1ff88", 
    "conditions" : {        
        "vendorId" : "fa6b4a53-d5ad-5fdf-be9d-e663e4d41ffe",
        "classId" : "1492af14-2569-5e48-bf42-9b2d51f2ab45"
    },
    "payloadInfo" : {
        "format" : {
            "type" : "binary"
        },
        "size" : 16,
        "digestAlgorithm" : "SHA-256",
        "digests" : {
            "raw" : "c31211d1ff88f77a5aaf653677895bfca769f06da198a8fa71156aa64acd695d",
            "ciphertext" : "f7e59db5d5ef2b6bbb732dec2e8ef33c285224cf7bad235910e402b5f5249c22"
        }
    }
}

To encode in CBOR use

python3 ./encode.py ./manifest-new.json ./manifest-new.cbor

If it complains about cbor then pip3 install cbor The contents of manifest-new.cbor are xxd manifest-new.cbor:

00000000: 8a01 f646 c312 11d1 ff88 1a5b 4a7a be82  ...F.......[Jz.. 
00000010: 8201 50fa 6b4a 53d5 ad5f dfbe 9de6 63e4  ..P.kJS.._....c. 
00000020: d41f fe82 0250 1492 af14 2569 5e48 bf42  .....P....%i^H.B 
00000030: 9b2d 51f2 ab45 f6f6 f6f6 8781 0110 f6f6  .-Q..E.......... 
00000040: 8101 a201 5820 c312 11d1 ff88 f77a 5aaf  ....X .......zZ. 
00000050: 6536 7789 5bfc a769 f06d a198 a8fa 7115  e6w.[..i.m....q. 
00000060: 6aa6 4acd 695d 0358 20f7 e59d b5d5 ef2b  j.J.i].X ......+ 
00000070: 6bbb 732d ec2e 8ef3 3c28 5224 cf7b ad23  k.s-....<(R$.{.# 
00000080: 5910 e402 b5f5 249c 22f6                 Y.....$.".

Another example is:

00000000: 8a01 f646 c312 11d1 ff88 1a5b 4a42 f982  ...F.......[JB..
00000010: 8201 50fa 6b4a 53d5 ad5f dfbe 9de6 63e4  ..P.kJS.._....c.
00000020: d41f fe82 0250 1492 af14 2569 5e48 bf42  .....P....%i^H.B
00000030: 9b2d 51f2 ab45 f6f6 f6f6 8781 0110 f6f6  .-Q..E..........
00000040: 8101 a201 5820 c312 11d1 ff88 f77a 5aaf  ....X .......zZ.
00000050: 6536 7789 5bfc a769 f06d a198 a8fa 7115  e6w.[..i.m....q.
00000060: 6aa6 4acd 695d 0358 20f7 e59d b5d5 ef2b  j.J.i].X ......+
00000070: 6bbb 732d ec2e 8ef3 3c28 5224 cf7b ad23  k.s-....<(R$.{.#
00000080: 5910 e402 b5f5 249c 22f6                 Y.....$.".

Curiosity: Note that both files are slightly different, one has 4a7a be82 and the other 4a42 f982. If you pass it on to "pretty" formatting you will see that there is an unsigned value: 1531607742 . That is the timestamp when the cbor file was made: Saturday, July 14, 2018 10:58:47 PM

  • Mac users: You can run screen /dev/cu.usbmodem1422 9600 or minicom.

  • Windows users: For debugging over the serial boards you can use Tera Term

Next you need to create a certificate and the corresponding private key. For the manifest signing the public key needs to be extracted from the certificate and it is passed as a function call to the sign.py

openssl x509 -pubkey -noout -in server.crt  > server-pubkey.pem
cat server-pubkey.pem 

-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAETvsWNlmwhq0iJ0jt5kQKEOY6hmzs
bAhmcqQtgxn50oFL7D8iGFGCGspY2IuyezvYJ+BKcOcfLWaBajoIHgS6Sg==
-----END PUBLIC KEY-----

When using the encode on the JSON manifest input file the Python program will produce a CBOR output, as described at https://github.com/ARMmbed/suit-manifest-generator. The example could look like as follows (depending on how you want to call your input & output files).

encode.py ./test-file.json ./test-out.cbor

To print the resulting output file using the Ruby program cbor2pretty use:

cbor2pretty.rb test-out.cbor > test-out.cbor.pretty

The ec_key_to_mbedtls_points.py pubkey.pem prints the x/y coordinates of the public key in a C structure, as follows:

const unsigned char pk_x [MBEDTLS_ECP_MAX_BYTES] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0xfb,
    0x16, 0x36, 0x59, 0xb0, 0x86, 0xad, 0x22, 0x27, 0x48, 0xed, 0xe6, 0x44,
    0x0a, 0x10, 0xe6, 0x3a, 0x86, 0x6c, 0xec, 0x6c, 0x08, 0x66, 0x72, 0xa4,
    0x2d, 0x83, 0x19, 0xf9, 0xd2, 0x81,
};
const unsigned char pk_y [MBEDTLS_ECP_MAX_BYTES] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4b, 0xec,
    0x3f, 0x22, 0x18, 0x51, 0x82, 0x1a, 0xca, 0x58, 0xd8, 0x8b, 0xb2, 0x7b,
    0x3b, 0xd8, 0x27, 0xe0, 0x4a, 0x70, 0xe7, 0x1f, 0x2d, 0x66, 0x81, 0x6a,
    0x3a, 0x08, 0x1e, 0x04, 0xba, 0x4a,
};

In addition to the public key, we also have to convert the signed manifest into a C structure since we are currently not providing a way to communicate the binary to the device.

  • Windows users: you can use the bin2c program:
bin2c.exe -i test-out-signed4.cose -o test-out-signed4.h -a cose_suite

Here is the result:

// Imported from file 'test-out-signed4.cose'
const unsigned char cose_suite[] = {
        0xd8,0x62,0x84,0x44,0xa1,0x03,0x18,0x2a,0xa0,0x58,0x8a,0x8a,0x01,0xf6,0x46,0xc3,0x12,0x11,0xd1,0xff,0x88,0x1a,0x5b,0x4a,0x42,0xf9,0x82,0x82,0x01,0x50,0xfa,0x6b,0x4a,0x53,0xd5,0xad,0x5f,0xdf,0xbe,0x9d,0xe6,0x63,0xe4,0xd4,0x1f,0xfe,0x82,0x02,0x50,0x14,0x92,0xaf,0x14,0x25,0x69,0x5e,0x48,0xbf,0x42,0x9b,0x2d,0x51,0xf2,0xab,0x45,0xf6,0xf6,0xf6,0xf6,0x87,0x81,0x01,0x10,0xf6,0xf6,0x81,0x01,0xa2,0x01,0x58,
        0x20,0xc3,0x12,0x11,0xd1,0xff,0x88,0xf7,0x7a,0x5a,0xaf,0x65,0x36,0x77,0x89,0x5b,0xfc,0xa7,0x69,0xf0,0x6d,0xa1,0x98,0xa8,0xfa,0x71,0x15,0x6a,0xa6,0x4a,0xcd,0x69,0x5d,0x03,0x58,0x20,0xf7,0xe5,0x9d,0xb5,0xd5,0xef,0x2b,0x6b,0xbb,0x73,0x2d,0xec,0x2e,0x8e,0xf3,0x3c,0x28,0x52,0x24,0xcf,0x7b,0xad,0x23,0x59,0x10,0xe4,0x02,0xb5,0xf5,0x24,0x9c,0x22,0xf6,0x81,0x83,0x58,0x26,0xa2,0x01,0x26,0x04,0x58,0x20,0x9e,
        0x85,0x76,0x97,0xb2,0xd7,0x50,0x68,0xb0,0xea,0x13,0x04,0x7f,0xba,0x82,0xfb,0xe2,0x32,0x48,0x19,0xbf,0x30,0xe0,0xea,0xec,0xf5,0xa6,0xbb,0x6e,0xb6,0x8a,0x5a,0xa0,0x58,0x48,0x30,0x46,0x02,0x21,0x00,0xbd,0xa3,0x26,0xf6,0xd8,0x6c,0x87,0x6c,0xb9,0xae,0xdd,0xd3,0xe9,0x45,0xf1,0x7a,0x65,0x0a,0xae,0x39,0x46,0xea,0x24,0x73,0xce,0xea,0x9a,0x47,0x3b,0x5d,0x86,0xf8,0x02,0x21,0x00,0xfb,0xed,0x42,0x08,0xdd,0x54,
        0x50,0x83,0x8a,0x6f,0xdf,0x59,0xe4,0x2b,0x04,0x4e,0xb7,0x97,0x1f,0xe4,0x53,0xf0,0xd2,0x81,0x8c,0x41,0x3d,0xc8,0xd3,0x0c,0x44,0x3f
};
const unsigned int cose_suite_len = 266;

If you are just doing printf debug, remember to create an explicit serial object in your suit.cpp e.g.

Serial pc(PC6, PC7);
pc.printf("debug message\n");

Here is the updated mbed-libcose code https://github.com/hannestschofenig/mbed-libcose

@bsilverajan
Copy link

For adding mbed variables, modify:

mbed config --global GCC_ARM_PATH ~/opt/gcc-arm-none-eabi-7-2017-q4-major/bin

to

mbed config --global GCC_ARM_PATH ~/opt/gcc-arm-none-eabi-7-2017-q4-major/bin
mbed config --global TARGET MTB_MXCHIP_EMW3166

@bsilverajan
Copy link

When using a Mac, usage of macOS High Sierra is recommended. Using Python 2.x in earlier versions of Mac OS X is problematic. In such cases using the Python virtualenv utility is recommended to install Python packages. Also pip would need to be reinstalled. See this article for details

@bsilverajan
Copy link

Possible comment:

  • To compile it locally run
mbed compile -t GCC_ARM

Note: For older Mac OS X versions, errors may arise when the mbed script is executed. you may need to use "sudo" to allow compiling to proceed normally.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment