Skip to content

Instantly share code, notes, and snippets.

@jaimejim
Last active July 14, 2018 15:12
Show Gist options
  • Save jaimejim/3aa9c6e85e82a353c9fa90794c856d89 to your computer and use it in GitHub Desktop.
Save jaimejim/3aa9c6e85e82a353c9fa90794c856d89 to your computer and use it in GitHub Desktop.

FIRMWARE UPDATES FOR IOT

Hackathon IETF101

Image

Links

Etherpad: https://etherpad.tools.ietf.org/p/FUIETF101?p=courier

Draft: https://tools.ietf.org/html/draft-moran-suit-manifest-01

C implementation of the IETF CBOR Encoded Message Syntax (COSE): https://github.com/cose-wg/COSE-C

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

Tools for parsing CBOR generated files/ Diagnostic Tools: https://github.com/cabo/cbor-diag

1. Running the SUIT sample parser/interpreter.

Clone

git clone https://github.com/ARMmbed/suit-manifest-generator.git

Generate the test manifest in CBOR

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

If it complains about cbor then pip3 install cbor

Now you should have the following:

 .
 ├── LICENSE
 ├── README.md
 ├── draft-moran-suit-manifest-01.txt 
 ├── encode.py
 ├── sign.py
 ├── test-file.json
 └── test-out.cbor

The contents of test-out.cbor are xxd test-out.cbor:

00000000: 8a02 a401 6e54 6869 7320 6973 2061 2074  ....nThis is a t
00000010: 6573 7402 6e41 2074 6573 7420 7061 796c  est.nA test payl
00000020: 6f61 6403 6f41 2073 616d 706c 6520 7665  oad.oA sample ve 
00000030: 6e64 6f72 0475 416e 2065 7870 6572 696d  ndor.uAn experim 
00000040: 656e 7461 6c20 6d6f 6465 6c50 128f 7346  ental modelP..sF 
00000050: bdf1 8d59 ae8d 0601 7396 585e 1a5a acf3  ...Y....s.X^.Z.. 
00000060: 9d82 8201 50fa 6b4a 53d5 ad5f dfbe 9de6  ....P.kJS.._.... 
00000070: 63e4 d41f fe82 0250 1492 af14 2569 5e48  c......P....%i^H 
00000080: bf42 9b2d 51f2 ab45 f6f6 f6f6 8781 0110  .B.-Q..E........ 
00000090: 4366 6f6f 8182 6e68 7474 703a 2f2f 666f  Cfoo..nhttp://fo
000000a0: 6f2e 636f 6d01 8101 a101 5820 c312 11d1  o.com.....X .... 
000000b0: ff88 f77a 5aaf 6536 7789 5bfc a769 f06d  ...zZ.e6w.[..i.m 
000000c0: a198 a8fa 7115 6aa6 4acd 695d f6         ....q.j.J.i].

Generate the COSE signature file

openssl ecparam -name secp256r1 -out secp256r1.pem 
openssl ecparam -in secp256r1.pem -genkey -noout -out secp256r1-key.pem 
openssl ec -in secp256r1-key.pem -pubout -out ecpubkey.pem

python3 ./sign.py secp256r1-key.pem ecpubkey.pem ./test-out.cbor ./test-out-signed.cose 

Note: If you don't have the crypto library installed then pip3 install cryptography Add also the specific modules "ed25519", "pyasn1" pip3 install cryptography ed25519 pyasn1

Pass COSE binary to CBOR Diagnostic or CBOR pretty:

gem install cbor-diag
cbor2pretty.rb test-out.cbor > test-out.cbor.pretty

2. Hardware Setup - FRDM-K64F

Image

2.2 MbedOS Online IDE

On Windows & Linux: If you experience issues with the USB->UART you might have to update the Bootloader and DAPLink (1, 2).

  1. Create an account or log in to Mbed (if you already have an account): https://os.mbed.com

On Mac: When you plug the board it will appear under /Volumes/MBED

  1. Add this board to your Mbed Compiler: https://os.mbed.com/platforms/FRDM-K64F/
  2. Create/Select/Edit an example: https://os.mbed.com/compiler/#nav:/mbed-os-example-blinky/main.cpp;
  3. Click "Add to your MBED compiler"
  4. Click "Open MBed compiler"
  5. On the compiler, Click Compile and open the downloaded binary on Downloads.
  6. Drag and drop to the MBED folder. Now the binary is loaded.
  7. Unplug or reset the board.

2.3 Local MBed Command Line Interface (CLI)

1. Install MBED CLI

Detailed instructions at mbed CLI.

pip install mbed-cli

or

git clone https://github.com/ARMmbed/mbed-cli
cd mbed-cli
python setup.py install

Note: Python seems broken for Mac. Check the python path on the mbed compiler and change it to YOUR python 2.7 (won't work on 3.4). Mine is /usr/local/bin/python and not usr/bin/python Note2: It might be that you want to run your local python installation, if so run brew link --overwrite python

2. Install the ARM toolchain:

  • Download the appropriate toolchain from https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads
  • Follow the instructions
  • On Mac, copy to the directory you wish (e.g. ~/opt/gcc-arm-none-eabi-7-2017-q4-major)
  • Set the environment variable for your project:
    • In the directory mbed-os-example-blinky run the command: mbed config GCC_ARM_PATH ~/opt/gcc-arm-none-eabi-7-2017-q4-major/bin

Note: This example is with the GCC-ARM toolchain. Change accordingly if you are not using the GCC toolchain.

Verify that you configuraton is correct mbed config --list:

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

3. Import the example application

mbed import mbed-os-example-blinky 
cd mbed-os-example-blinky

You can set the configuration manually You can try to edit the main.cpp file to see the changes.

Note: you may need to execute #mbed new . to clone the mBed code

4. Compile

mbed compile -m K64F -t GCC_ARM

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

The compilation should terminate with success:
Link: mbed-os-example-blinky Elf2Bin: mbed-os-example-blinky 
+------------------+-------+-------+------+ 
| Module           | .text | .data | .bss | 
+------------------+-------+-------+------+ 
| [fill]           |   118 |     4 | 2066 | 
| [lib]/c.a        | 22745 |  2472 |   89 | 
| [lib]/gcc.a      |  3112 |     0 |    0 | 
| [lib]/misc       |   204 |     4 |   28 | 
| [lib]/nosys.a    |    32 |     0 |    0 | 
| main.o           |    56 |     0 |    4 | 
| mbed-os/features |    42 |     0 |  184 | 
| mbed-os/hal      |  1419 |     4 |   66 | 
| mbed-os/platform |  1404 |     4 |  270 | 
| mbed-os/rtos     |  8502 |   168 | 5989 | 
| mbed-os/targets  |  8151 |    12 |  384 | 
| Subtotals        | 45785 |  2668 | 9080 | 
+------------------+-------+-------+------+ 
Total Static RAM memory (data + bss): 11748 bytes 
Total Flash memory (text + data): 48453 bytes  
Image: ./BUILD/K64F/GCC_ARM/mbed-os-example-blinky.bin

5. Copy and reset

cp BUILD/K64F/GCC_ARM/mbed-os-example-blinky.bin /Volumes/MBED/

Unplug or reset the board.

3. Building COSE-C

git clone https://github.com/cose-wg/COSE-C

On Mac:

OPENSSL_ROOT_DIR=/usr/local/opt/openssl/ cmake .
make

Then you find the binaries in COSE-C/dist

Before you can run the test in dist/test with ./cose_test do the following You have to set a variable, In the COSE-C directory type:

export LD_LIBRARY_PATH=$PWD/build/dist/lib:$LD_LIBRARY_PATH:

Others used:

export LD_LIBRARY_PATH=$PWD/dist/lib/:$LD_LIBRARY_PATH:

Next Clone the Test Examples (not included in the git repository of the COSE-C project), In the COSE-C directory type:

git clone --depth 1 git://github.com/cose-wg/Examples Examples

In the Build Directoy build with test:

make all test 

In the dist/test Directory you can now run at thest with ECDSA Examples

./cose_test --dir ../../../Examples/ecdsa-examples/

For me it run with: ./cose_test --dir ../../Examples/ecdsa-examples/

4. Simple UART Bootloader

This code is a sample bootloader for the SUIT manifest. The target is to send the manifest file to th device, and validate it. It is still Work in progress.

Mbed SUIT pseude bootloader project:

https://os.mbed.com/users/iOperator/code/uart_pseudo_bootloader/

main cpp gist

https://gist.github.com/jaimejim/a129979b01dbf7489b300a536938c313 

and the Bootloader Host for the PC side:

https://gist.github.com/iOperator/e2fc911f1ce46efd60e8d3f6bb3e1659

On mac run ls /dev/tty.usb* to see where is it

Generate the mbed binary mbed compile -m K64F -t GCC_ARM

Copy to the board

cp BUILD/K64F/GCC_ARM/uart-pseudo-bootloader.bin /Volumes/MBED

Reset the board. The color should be green

Now we try to send the manifest to the board

python3 bl-host.py /dev/tty.usbmodem1412 /Users/jaime/code/suit-manifest-generator/test-out-signed1.cose

Follow the instructions, the output should be the manifest:

python3 bl-host.py /dev/tty.usbmodem1412 
/Users/jaime/code/suit-manifest-generator/test-out-signed1.cose

Manifest size is 289 bytes.  
Press the reset button on the development board now.  

***Welcome to SUIT pseudo bootloader!***  

Waiting for 289 bytes...  

b'\xd2\x84D\xa1\x03\x18*\xa0X\xcd\x8a\x02\xa4\x01n  etc etc

Building CN-CBOR on ARM

NOTE - That DOESNT work yet

Get it from github: git clone https://github.com/cabo/cn-cbor

Get the CMake configuration file from https://raw.githubusercontent.com/vpetrigo/arm-cmake-toolchains/master/arm-gcc-toolchain.cmake (e.g. wget or curl) and put it in the directory of CN-CBOR

Build for the ARM target (assuming you have installed the ARM GCC Toolkit /opt/gcc-arm-none-eabi-7-2017-q4-major/bin/ ): PATH=(DOLLAR)PATH:/opt/gcc-arm-none-eabi-7-2017-q4-major/bin/ cmake DCMAKE_TOOLCHAIN_FILE=arm-gcc-toolchain.cmake mkdir build make

Unsorted notes

We need to convert the X.509 ECC cert and private key to a JWK format for use with Jim's tool. 

https://www.npmjs.com/package/pem-to-jwk
https://www.npmjs.com/package/jwk-to-pem

Install the tool with
>  npm install -g pem-to-jwk

Here is an example invocation: 

> openssl ecparam -genkey -name secp256r1 -out example.key
> cat example.key | pem-to-jwk > key.jwk

Here is the result: 
    
{ kty: 'EC',
  crv: 'P-256',
  d: '4029ciM3SKuQD3QZ8CvKxRNGqEXOfSx51juBsoXjWnA',
  x: '3G7HKArn6yjJrADGi5ydz9kZBfzr70hVBXt9AUetG4Q',
  y: 'csycHuqeHiQMl6aMlREze262xM3QOtvlfYC3wGv2hPg' }

Presentation from ELC from Intel about tinyCBOR 
https://schd.ws/hosted_files/elciotna18/12/Tiny_Efficient_Library.pdf


If you want to convert any binary (e.g. signed manifest) to an C array you can use this Python:

handle = open('test-out-signed.cose', 'rb')
manifest = handle.read()
handle.close()

c_string = ""
C_HEAD = "uint8_t manifest[] = {"
C_FOOT = "};"
C_SEP = ", "

c_string += C_HEAD
for i in manifest:
    c_string += hex(i) + C_SEP
c_string += C_FOOT

print(c_string)


Example: C array representation of signed manifest:
uint8_t manifest[] = {0xd8, 0x62, 0x84, 0x44, 0xa1, 0x3, 0x18, 0x2a, 0xa0, 0x58, 0xcd, 0x8a, 0x2, 0xa4, 0x1, 0x6e, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61, 0x20, 0x74, 0x65, 0x73, 0x74, 0x2, 0x6e, 0x41, 0x20, 0x74, 0x65, 0x73, 0x74, 0x20, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x3, 0x6f, 0x41, 0x20, 0x73, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x20, 0x76, 0x65, 0x6e, 0x64, 0x6f, 0x72, 0x4, 0x75, 0x41, 0x6e, 0x20, 0x65, 0x 78, 0x70, 0x65, 0x72, 0x69, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x6c, 0x20, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x50, 0x41, 0x4c, 0x9d, 0x9f, 0x26, 0x65, 0xed, 0xf9, 0x92, 0x85, 0xd7, 0xaa, 0x23, 0xb7, 0x83, 0x12, 0x1a, 0x5a, 0xad, 0x46, 0xf5, 0x82, 0x82, 0x1, 0x50, 0xfa, 0x6b, 0x4a, 0x53, 0xd5, 0xad, 0x5f, 0xdf, 0xbe, 0x9d, 0xe6, 0x63, 0xe4, 0xd4, 0x1f, 0xfe, 0x82, 0x2, 0x50, 0x14, 0x92, 0xaf, 0x14, 0x25, 0x69, 0x5e, 0x48, 0xbf, 0x42, 0x9b, 0x2d, 0x51, 0xf2, 0xab, 0x45, 0xf6, 0xf6, 0xf6, 0xf6, 0x87, 0x81, 0x1, 0x10, 0x43, 0x66, 0x6f, 0x6f, 0x81, 0x82, 0x6e, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x66, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x1, 0x81, 0x1, 0xa1, 0x1, 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, 0xf6, 0x81, 0x83, 0x58, 0x26, 0xa2, 0x1, 0x26, 0x4, 0x58, 0x20, 0xdb, 0x8f, 0x3e, 0xaa, 0xd6, 0x3d, 0xa5, 0xbd, 0xc7, 0xb7, 0x60, 0xdb, 0xb2, 0xdf, 0x98, 0xb1, 0xc6, 0x2f, 0xf4, 0xb2, 0xc9, 0x56, 0x3b, 0xc4, 0xce, 0x80, 0xf8, 0x55, 0x17, 0x6e, 0xdb, 0x40, 0xa0, 0x58, 0x47, 0x30, 0x45, 0x2, 0x21, 0x0, 0xb4, 0x11, 0x4, 0x70, 0x52, 0x4b, 0x9a, 0xd6, 0x70, 0xdf, 0xa1, 0x9f, 0x4e, 0xa, 0xac, 0xdb, 0x53, 0x8d, 0xb5, 0x1b, 0x7a, 0xf2, 0x4f, 0x5d, 0xfd, 0x88, 0x22, 0x74, 0x97, 0x23, 0x96, 0x65, 0x2, 0x20, 0x43, 0xe7, 0xa7, 0xc6, 0x15, 0x54, 0xd, 0xff, 0xd0, 0x65, 0xeb, 0xe4, 0x3d, 0xf4, 0xed, 0x24, 0x2e, 0xb1, 0x2, 0xf2, 0x81, 0x91, 0xd4, 0xf0, 0x81, 0x96, 0xb6, 0x3b, 0x5c, 0xc8, 0x71, 0x3d, };

It seems that the trust anchor needed for use with the code is the SubjectPublicKeyInfo, which can be obtained from the example.key file using the following command

openssl ec -in example.key -pubout -outform der -out example.pub

To turn the resulting binary into a C structure this tool can be used: https://github.com/megastep/bin2c

For example, the following invokation

./bin2c.exe -i ../../example.pub -o ../../example.struct -a trust_anchor produces the following structure:

        const uint8_t raw_trust_anchor[] = {
                0x30,0x59,0x30,0x13,0x06,0x07,0x2a,0x86,0x48,0xce,0x3d,0x02,0x01,0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x03,0x42,0x00,0x04,0xdc,0x6e,0xc7,0x28,0x0a,0xe7,0xeb,0x28,0xc9,0xac,0x00,0xc6,0x8b,0x9c,0x9d,0xcf,0xd9,0x19,0x05,0xfc,0xeb,0xef,0x48,0x55,0x05,0x7b,0x7d,0x01,0x47,0xad,0x1b,0x84,0x72,0xcc,0x9c,0x1e,0xea,0x9e,0x1e,0x24,0x0c,0x97,0xa6,0x8c,0x95,0x11,0x33,0x7b,0x6e,0xb6,0xc4,0xcd,0xd0,
                0x3a,0xdb,0xe5,0x7d,0x80,0xb7,0xc0,0x6b,0xf6,0x84,0xf8
        };
        const size_t raw_trust_anchor_len = 91;

I edited the sign.py, this is the code: https://gist.github.com/jaimejim/67429d8ddc36d1dde1c8787251793e4b This is the cose output https://gist.github.com/jaimejim/ba2a07a8129061eab0d5c2aea1b60f06

@bsilverajan
Copy link

For coping with crypto errors when generating COSE signature file in Section 1, please amend the pip3 package installation to:

pip3 install cryptography ed25519 pyasn1

@jaimejim
Copy link
Author

Fixed! Good catch, I also edited few other typos.

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