Attendees:
- Hannes Tschofenig
- Jaime Jiménez
- Thomas Fossatti
- Bill Silverajan
- Felipe Espinoza
- Alexandra Ibarra
- David Waltermire
Twitter: #IETFHackathon & #IETF102
This tutorial is available as a gist: https://gist.github.com/jaimejim/82d53f97a9d011ef13c8750129b84cb1
Etherpad: https://etherpad.tools.ietf.org/p/FUIETF102
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/
-
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:
- Follow the tutorial on https://gist.github.com/jaimejim/3aa9c6e85e82a353c9fa90794c856d89 section 2.2
- You need to go to the mbed website for the board: https://os.mbed.com/platforms/Mbed-WiFi-BLE/
- Add the compiler.
- Change the led to led1(PA5)
To compile a program for this board using Mbed CLI, use
MTB_MXCHIP_EMW3166
as the target name, it is presented as "Mbed WiFi BLE". - Copy the binary to the board.
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
-
To begin with, follow the previous tutorial from IETF102section 2.3
-
Try to import blinky project
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
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
- Few modifications are required. We also updated the
suit.cpp
file has been modified to https://gist.github.com/fdns/bc3c05cffab99129ed73bff7a2d9ed63
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;)
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
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