IoT Lab 2

In this exercise you will learn how to implement basic crypto operations on constrained resources. We will use the same setup as we did for lab exercise 1. Ubuntu 18.04. (VM) with RIOT-OS and the IoT-Lab. The node is – again – IoT-Lab’s m3-node.

Group members: <Anna Kastlunger, Gaelle Knibbeler, Judyta Krzyzak>

RIOT Documentation Link:
https://riot-os.org/api/index.html

I. IoT-Security WrapUp

Describe the top 5 of the OWASP Top 10 IoT Vulnerabilities thoroughly (in your own words!).

  1. Weak Passwords

    • Characteristics:
      • Simple letter combinations - firstnamelastname, companyname
      • Publicly available
      • Hardcoded passwords
      • Guessable - birthday date, pet's names
      • Simple number combinations: 1234, 4321
  2. Insecure Network Services

    • Many network services that are running are unnecessary (or not required by the user). These are often insecure and require access to the Internet, which means that unauthorized people can access sensitive data. This often also leads to violations of the CIA principles.
  3. Insecure Ecosystem Interfaces

    • You can imagine that a device is surrounded by several services called the ecosystem. It contains of web API's, backend API's, cloud and mobile interfaces to this system. If one of them is insecure, it can lead to lack of authentication / authorization, weak encryption and / or lack of input and output filtering.
  4. Lack of Secure Update Mechanism

    • You should be able to securely update your device and its services. A lack of this important feature causes problems like: lack of firmware validation on device, unencrypted transitions which means no secure delivery, lack of anti-rollback mechanisms, and lack of notifications of security changes due to updates.
  5. Use of Insecure or Outdated Components

    • There is a reason for updates and new components and it is not always to frustrate the user. Attackers pretty easily find ways to hack services and devices therefore the use of deprecated or insecure software components/libraries leads to insecure customization of operating system platforms, and the use of third-party software or hardware components from a compromised supply chain.

II. Implement basic crypto operations on IoT-Lab’s m3-node

Download the zip files from Moodle:

  • lab2_01_shell.zip
  • lab2_02_crypto.zip

Move the unzipped directories into your /myRIOT/examples/ directory and follow the steps in

​	https://tinyurl.com/riotoslab2 

1) Warm up: shell exercise

1. Edit the file Makefile: add the shell module to the build

​​​​    USEMODULE += shell

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

2. Include the header(s) required at the beginning of the main.c file

​​​​    #include "shell.h"

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

3. In the main function, the shell can be started by adding the following code before return 0:

​​​​    char line_buf[SHELL_DEFAULT_BUFSIZE];
​​​​    shell_run(NULL, line_buf, SHELL_DEFAULT_BUFSIZE);

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

4. Now test the application on native:

​​​​    make
​​​​    make term

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

By default, the shell module provides the help command to list available commands. Try it. You should see that there is no available command at this stage.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

5. In main.c, add the callback functions for the board and cpu commands, just below the line #include "shell.h:

​​​​       /* board handler */
​​​​            static int _board_handler(int argc, char **argv)
​​​​            {
​​​​                /* These parameters are not used, avoid a warning during build */
​​​​                (void)argc;
​​​​                (void)argv;

​​​​    puts(RIOT_BOARD);

​​​​    return 0;
​​​​    }

​​​​    /* cpu handler */
​​​​    static int _cpu_handler(int argc, char **argv)
​​​​    {
​​​​        /* These parameters are not used, avoid a warning during build */
​​​​        (void)argc;
​​​​        (void)argv;

​​​​    puts(RIOT_CPU);

​​​​    return 0;
​​​​   }

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

6. Define the command name, the help message and the associated callback function in the list of available shell commands.

This is simply done by adding the following code between the function callbacks and the main function:

​​​​    static const shell_command_t shell_commands[] = {
​​​​        { "board", "Print the board name", _board_handler },
​​​​        { "cpu", "Print the cpu name", _cpu_handler },
​​​​        { NULL, NULL, NULL }
​​​​    };

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

7. Test your application on native & on the IoT-Lab testbed

If everything works fine create a new experiment at the IoT-Lab, build your application for the m3 node and upload it to your experiment. Run the experiment - interact with the shell to get the command output. Finally, make screenshots for your documentation.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Use the following command to create a connection to grenoble (to be able to create your own programms on RIOT):

​​​​export PATH=$PATH:/home/(your user)/gcc-arm-none-eabi-7-2018-q2-update/bin/

Now you can login to grenoble with ssh

​​​​ssh krzyzak@grenoble.iot-lab.info

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

On RIOT start new experiment with the m3-node

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Working on Anna's machine:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Working on Anna's IoT-Lab:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Working on Judyta's IoT-Lab:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →


Damit wir den Exportpfad nicht jedes Mal neu eingeben müssen, schreiben wir ihn in ein Bash-Script:
nano .bashrc
export PATH=$PATH:/home/anna/gcc-arm-none-eabi-7-2018-q2-update/bin/
Speichern (Strg+X -> y)

Einspielen der Firmware für das Board mit dem wir im IoT-Lab arbeiten in den aktuellen Arbeitsordner:
cd myRIOT/examples/lab2_01_shell
make BOARD=iotlab-m3 all


2) Crypto Exercise

In this exercise, you will write 2 RIOT shell commands to encrypt and decrypt simple messages. The algorithm will use AES 128 symmetric encryption and more precisely, this exercise will use the CTR cipher mode which is able to encrypt/decrypt messages of arbitrary sizes.

AES encryption is provided by crypto module of RIOT and CTR cipher mode is provided by the cipher_modes module.

Document your steps here with screenshots (IoT-Lab) and thorough explanation. Provide a README for your application (don’t forget: no prosa, etc).

Message encryption/decryption

1. Add required modules to the build

Since the application is about to implement shell functions, the shell module must be added, as well as the fmt, crypto and cipher_modes modules.

Edit the file Makefile and add there the required modules to the build.

2. Add the required includes

Add the inculdes corresponding to the fmt, shell and crypto modules that will be used by the application:

​​​​    #include "shell.h"
​​​​    #include "fmt.h"
​​​​    #include "crypto/ciphers.h"
​​​​    #include "crypto/modes/ctr.h"

3. Define the symmetric key and the nonce:

​​​​    static const uint8_t key[] = {
​​​​    0x23, 0xA0, 0x18, 0x53, 0xFA, 0xB3, 0x89, 0x23,
​​​​    0x65, 0x89, 0x2A, 0xBC, 0x43, 0x99, 0xCC, 0x00
​​​​    };

​​​​    static const uint8_t ctr[] = {
​​​​    0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
​​​​    0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
​​​​    };

4. Implement the encrypt command handler function

This function will return the input message in its encrypted form. The encrypted message is printed as a string of hexadecimal characters:

In the _encrypt_handler function, call the functions that will encrypt the message:

​​​ cipher_t cipher;
​​​ cipher_init(&cipher, CIPHER_AES_128, key, sizeof(key));
​​​ size_t enc_len = cipher_encrypt_ctr(&cipher, ctr_copy, 0, (uint8_t *)argv[1], strlen(argv[1]), data);

We use a copy of the nonce buffer because it is modifed by the call to cypher_encrypt_ctr.

In the _encrypt_handler function, convert the encrypted message (a byte array) to its hexadecimal string representation:

size_t len = fmt_bytes_hex(buf_str, data, enc_len);
buf_str[len] = 0;
/* The hexadecimal string buffer must be closed to ensure a proper output. */

5. Implement the decrypt command handler function:

In the _decrypt_handler function, you must first convert the hexadecimal representation of the input encrypted message into a byte array:

​​​​    size_t len = fmt_hex_bytes(data, argv[1]);

Then, decrypt the content of the data buffer:

The output should directly be readable, so there's no need to convert it to hexadecimal.

In the 6th step we should test the application. We did not do it, since it would be necessary to uncomment the rest of the code which is a lot of work. Now, by entering 'make' we are getting a series of errors.

We checked the errors and realized they were only about the parts of code that we didn't write yet, e.g.:

We can say that there are no errors in the lines we have already written, since the compiler checks the file chronologically.

Sign & Verify Messages


In this exercise, you will write RIOT shell commands to sign and verify simple messages:

  • One command that signs and prints the signature
  • One command that verifies the signature
  • One command to generate the key pair used to sign/verify the message

1. Add required modules

Add the module random and the external package c25519 to your Makefile

2. Add the corresponding includes to the main.c file

For the c25519 you will need an additional header file: edsign.h besides the common header file.

3. Implement the key command handler function that will generate a new pair of key each time it is called

First, under the header includes, declare 2 buffers where the asymmetric keys are stored:

​​​​    static uint8_t secret_key[EDSIGN_SECRET_KEY_SIZE] = { 0 };
​​​​    static uint8_t public_key[EDSIGN_PUBLIC_KEY_SIZE] = { 0 };

In the _key_handler function, call the functions that will create the new keypair:

​​​​    random_bytes(secret_key, sizeof(secret_key));
​​​​    ed25519_prepare(secret_key);
​​​​    /* implement the derivation of the public_key here */

Then print the new keypair:

puts("New keypair generated:");
printf("  - Secret: ");
for (uint8_t i = 0; i < EDSIGN_SECRET_KEY_SIZE; ++i) 
{
  printf("%02X", secret_key[i]);
}

printf("\n  - Public: ");
for (uint8_t i = 0; i < EDSIGN_PUBLIC_KEY_SIZE; ++i) 
{
  printf("%02X", public_key[i]);
}
puts("");

4. Implement the sign command handler function that will generate a signature from an input message:

First, under the header includes, declare 2 buffers where the signatures (byte and hex representation) are stored:

​​​​    static uint8_t signature[EDSIGN_SIGNATURE_SIZE] = { 0 };
​​​​    static char signature_hex[EDSIGN_SIGNATURE_SIZE * 2 + 1] = { 0 };

Note: the size of the hexadecimal string signature buffer is twice as large as the signature buffer itself, because a single byte is represented by 2 hexadecimal characters.

In the _sign_handler function, call the functions that will generate the signature of the input command argument message in argv[1]:

​​​​    edsign_sign(signature, public_key, secret_key, (uint8_t *)argv[1], strlen(argv[1]));

Implement the conversion of the signature (a byte array) to its hexadecimal string representation:

​​​​    signature to signature_hex

5. Implement the verify command handler function

The message and the signature are provided as command line argument respectively in argv[1] and argv[2].

In the _verify_handler function, you must first convert the signature provided as a string of hex characters to a byte array, this is done with the hex_bytes function (from the fmt module):

​​​​    fmt_hex_bytes(signature, argv[2]);

Then call the functions that verify the signature:

if (edsign_verify(signature, public_key, (uint8_t *)argv[1], strlen(argv[1]))) 
{
  puts("Message verified");
}
else 
{
  puts("Message not verified");
}

6. Test your application

If everything works fine create got to next section "Hash Computation".

Not really:


But we continue anyway.


3) Hash Computation

In this exercise, you will write RIOT shell commands to compute the hash of a given input string:

  • One command that produces and prints the hash using the SHA256 algorithm
  • One command that produces and prints the hash using the SHA3-256 algorithm

In both cases, the hash is stored in memory in a byte array and, to print it, it must be converted to a string of hexadecimal characters. Use an appropriate module for the conversion.

Hash functions of several algorithms (SHA256, SHA3-256, SHA1, MD5, CMAC) are provided by the hashes module.

1. Add required modules

Add the hashes module.

2. Add the corresponding header files

Hint: You will need the header files for sha256 and sha3.

3. Implement the sha256 command handler function:

Declare 2 buffers, the first one for the computed hash itself, and the second one for its hexadecimal string representation:

​​​​    static uint8_t sha256_hash[SHA256_DIGEST_LENGTH];
​​​​    static char sha256_hash_hex[SHA256_DIGEST_LENGTH * 2 + 1];

Note: the size of the hexadecimal string buffer is twice as large as the hash itself, because a single byte is represented by 2 hexadecimal characters.

In the _sha256_handler function call the functions that will compute the hash from the command line argument argv[1]:

​​​​    implement the functions to compute a sha256 hash of a string (argv[1])

Convert the computed hash (a byte array) to its hexadecimal string representation:

​​​​    you know what to use by now ;) (sha256_hash to sha256_hash_hex)

4. Implement the sha3 command handler function

Declare 2 buffers, the first one for the computed hash itself, and the second one for its hexadecimal string representation:

​​​​    static uint8_t sha3_hash[SHA3_256_DIGEST_LENGTH];
​​​​    static char sha3_hash_hex[SHA3_256_DIGEST_LENGTH * 2 + 1];

Call the functions that will compute the hash from the command line argument argv[1]:

​​​​    implement the functions to compute a sha256 hash of a string (argv[1])

Convert the computed hash (a byte array) to its hexadecimal string representation:

Since we are programming in C and don't like to see something like:

we need to THINK and declare the functions in the last step:

5. Test your application on native & on the IoT-Lab testbed

If everything works fine create a new experiment at the IoT-Lab, build your application for the m3 node and upload it to your experiment. Run the experiment - interact with the shell to get the command output. Finally, make screenshots for your documentation.

Enter 'make'

Make term and trying out the functions:

It works!
On native:

And on the IoT-Server:

And another IoT-Server:

III. Upload to Moodle

Submit 1 zip file for the crypto exercise containing your app’s main.c, Makefile, and README.