Introduction: Security With Arduino : Atecc608a

About: Hobbyist about programming and electonics. Security is life !

Topic

Hello everyone !

This is my first Instructables Article so I hope it will be interesting for all of you.

In this article, I will explain you how to use a micro chip called "ATECC608A" that provide multiple security tools.

This chip has been designed by MicroChip and it is the last version of "CryptoAuthentication chip". Before this version, there was "ATSHA204A" and the "ATECC508A".

Why did I decide to use the last version and not the previous version ?

This version is the most advanced chip and got functionalities that old version does not have (For example : AES module, IO protection module ...).

Why this project ?

I work in the domain of the CyberSecurity and as everyone I loved programming and electronics. During my studies, I get a conference with a specialist on IoT Security who showed us that Industrial does not use Security in their IoT object. I showed us a padlock that can be open with your smartphone by Bluetooth. On the padlock, a sentence said "This padlock is most secure than a key padlock !". This sentence make him smile and he modified the sentence "This padlock is the worst padlock ever build !".

He showed us with his own PC and a Bluetooth sniffer that every command sent by the smartphone are the same each time and it is very simple to copy this command and sent it with your smartphone. He explained us that "Security" for "Industrial" is not the main problem. He showed us chips (less than 0.60$) that could add a layer of security to these objects.

After this demonstration, I tried to find some Open source project that add security layer to IoT object but I never found it.

So I decided to work on a project that use security layer for communication between two IoT object.

What is my idea ?

During a communication between two IoT Object, multiple attacks can be exist : Man Of the mild, Copy of information and more .. So my idea is very simple :

  1. Utilization of encrypted data between two or more IoT object.
  2. Low cost supplies
  3. Can work with an Arduino UNO

Now I will explain you how I implemented this abstract picture with an Arduino and a Atecc608a chip. In this article, I will explain you how to use the Arduino UNO with the ATECC608A.

I will wrote an article about the communication of two object next time.

Supplies

You need some few things for this project :

  1. Arduino UNO or MEGA (Chip must be Atmega 328 or ATMEGA 2560)
  2. Atecc608A chip (cost less than 0.80$ each, easy to find on your supplier website)
  3. 8-Pin SOIC Adapter
  4. Some wires and resistors

The datasheet of the previous version of this chip (Atecc508a) is available here -> Datasheet Atecc508a

Step 1: Step by Step

In this article, I will show you how to modified the configuration of this chip and after how to encrypt data using the AES CBC Algorithme .

We will follow those steps :

  1. Design of the circuit
  2. Configuration of this chip
  3. Utilization of the AES CBC module
  4. Why do you need to use this chip

For each steps, I will details everything for you. Also, I added my code in my Github with comments for each functions. If you have some questions about my code or this project, I will be happy to answer it .

My Github : My Github

Step 2: Warning About the Atecc608a

The Atecc608a chip is not a "easy" chip.

First, the documentation of this chip is under NDA so you won't find it in complete on Internet. But no problem for this, the datasheet of the previous version is available on Internet Datasheet Complete ATECC508A.

Second, when you use this chip you need to lock its configuration and it is impossible to modify the configuration of the chip if it is locked. So be careful when you will lock the Config Zone and the Data Zone.

Third, the library wrote in C is very big and complete, so you have to read the documentation of the functions that you will use before.

Four, the library wrote for this chip not work for Arduino UNO, but It added the functionalities need it to work with Arduino UNO.

The chip ATECC608A

You can communicate with this chip by I2C. The address of this chip can be modify in the configuration.

This chip contains 16 different slots that can contains different type of data :

  1. ECC Key (private or public)
  2. AES Key
  3. Other data (like Sha hash or just words)

In our case, we will store AES Key in one slot.

Step 3: 1. Desing of the Circuit

1. Design of the circuit

The schema of this circuit is very simple!

You need to use 3.3V power because the recommendation is between 2.0V and 5.5V but I preferred use the 3.3V.

For this chip, normally you have a dot on a corner of the chip, this dot is the Pin 1 of this board. I added the Top view of the Atecc608a with PIN Number because it is a 8-Lead SOIC so the chip is very small.

  1. ARDUINO 3.3V -> PIN 8 (Atecc608a)
  2. ARDUINO GND -> PIN 4 (Atecc608a)
  3. ARDUINO A4 (SDL) -> PIN 5 (Atecc608a)
  4. ARDUINO A5 (SCL) -> PIN 6 (Atecc608a)

You need to use 3.3V power because the recommendation is between 2.0V and 5.5V but I preferred use the 3.3V.

I added the Top view of the Atecc608a because it is a 8-Lead SOIC so the chip is very small. If you prefer, so suppliers build some board with the chip solder, it could be easier for you.


Warning : In my case, I have to add a resistor between the SDA of the Arduino and the Chip (also for the SDL). I added a 4.7Kohm resistor for each.

Step 4: 2. Configuration of the Chip (Atecc608a)

Before use the function of encryption or decryption you need to configure the chip. In this step, I will details every steps you need to do for the configuration of this chip.

Warning : this step is very import and if you lock the zones before the end you cannot modify them.

As explained before, this chip got two zone :

  1. Config Zone
  2. Data Zone

The configuration Zone got a size of 128 bytes but the first 16 bytes cannot be modified.

To configure this chip, you need two follow those step. It is very important to follow each steps in order or your configuration will not working, and your chip will be locked and unusable. Those steps are :

  1. Create a configuration template
  2. Write this template to the chip
  3. Lock the Config Zone
  4. Write your AES Key (128 Bits) in a slot
  5. Lock the Data Zone

Information

Below I details each step of the conifguration with my code, but no worries, I added a full example of configuration in my Github. I put comments on each functions, and a *.ino file is available with each step in order for you.


First step : Create a configuration template

As explained before, the configuration zone get a size of 128 bits, but the first 16 bits cannot be changed. This zone is composed of multiple parts, but you need to know only 3 parts of this configuration zone for this project :

  1. The Bytes 16 -> This is the I2C address of the chip
  2. The Bytes 20 to 51 -> You can modify here the type of Slot for the 16 slots of this chip
  3. The Bytes 96 to 127 -> You can set here the Type of key or data used in each slot.

(If you need more explication of all this zone, please read the documentation (page 13, section 2.2))

Here, I put in details each Bytes/Parts of the 112 bytes of the configuration of a Chip. This is a example, each chip bought can have a different configuration :

	0xC0, // I2C address
        0x00,
        0x00,
        0x00,
        0x83, 0x20, //  Slot Config Slot 1
        0x85, 0x20, //  Slot Config Slot 2
        0x8F, 0x20, //  Slot Config Slot 3
        0xC4, 0x8F, //  Slot Config Slot 4
        0x8F, 0x8F, //  Slot Config Slot 5
        0x8F, 0x8F, //  Slot Config Slot 6
        0x9F, 0x8F, //  Slot Config Slot 7
        0x0F, 0x0F, //  Slot Config Slot 8 
        0x8F, 0x0F, //  Slot Config Slot 9
        0x8F, 0x0F, //  Slot Config Slot 10
        0x8F, 0x0F, //  Slot Config Slot 11
        0x8F, 0x0F, //  Slot Config Slot 12
        0x8F, 0x0F, //  Slot Config Slot 13
        0x00, 0x00, //  Slot Config Slot 14
        0x00, 0x00, //  Slot Config Slot 15
        0xAF, 0x8F, //  Slot Config Slot 16
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
        0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
        0x00,
        0x00,
        0x00, 0x00,
        0x00,
        0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00,
        0x00,
        0x00,
        0x00,
        0xFF, 0xFF,
        0x00, 0x00,
        0x00, 0x00, 0x00, 0x00,
        0x33, 0x00, //  Key Config Slot 1
        0x33, 0x00, //  Key Config Slot 2
        0x33, 0x00, //  Key Config Slot 3
        0x1C, 0x00, //  Key Config Slot 4
        0x1C, 0x00, //  Key Config Slot 5
        0x1C, 0x00, //  Key Config Slot 6
        0x1C, 0x00, //  Key Config Slot 7
        0x3C, 0x00, //  Key Config Slot 8
        0x1A, 0x00, //  Key Config Slot 9 
        0x3A, 0x00, //  Key Config Slot 10 
        0x1A, 0x00, //  Key Config Slot 11 
        0x3A, 0x00, //  Key Config Slot 12
        0x3A, 0x00, //  Key Config Slot 13
        0x3C, 0x00, //  Key Config Slot 14
        0x3C, 0x00, //  Key Config Slot 15
        0x1C, 0x00  //  Key Config Slot 16

As see, I put some comments in this code to understand more this configuration.

In your case to need to understand only three things :

  1. The Bytes 16 -> This is the I2C address of the chip
  2. The Bytes 20 to 51 -> You can modify here the type of Slot for the 16 slots of this chip
  3. The Byte 96 to 127 -> You can set here the Type of key or data used in each slot.

I won't explain the type of configuration and why I used this and not an other because it's complicated to explain everything. If you need more information go to the documentation, page 16 section 2.2.1 for the "SlotConfig" and page 19 section 2.2.5 for "KeyConfig"

For this example, you will use the slot 9 to store a AES key.

For this, we need to put (if you need, you can copy the example above, the modification has been done in it ):

  1. Byte 36 = 0x8F
  2. Byte 37 = 0x0F
  3. Byte 112 = 0x1A
  4. Byte 113 = 0x00

Why did I set this configuration : For each slot of this chip, you can set parameters to say to the chip what type of data will be store. You have multiple parameters :

  • Slot can be write or read (clear or encrypt action)
  • Type of data stored (ECC key, Public Key, SHA Hash, AES Key ...)
  • Slot can be lockable
  • Generation of key is allowed
  • ...

With the byte 36 and 37 set to "0x0F8F" :

  • Data can be written in the Clear
  • The contents of this slot are secret and cannot be read
  • Slot cannot be used for the CheckMac Copy command

With the byte 112 and 113 set to "0x001A" :

  • Slot can store up to four AES 128-bit symmetric keys (KeyType = 0x6)

Second step : Write this configuration

This step is very important because we will set the chip with our configuration and if this configuration is not good, you will use this chip.

But no worries, as long as the Configuration is not locked, you can modify your configuration.

Here, this the code used to write the configuration to the chip :

/** \brief Write a new configuration to the chip.
 *  \param[in] cfg  Logical interface configuration. Some predefined
 *                  configurations can be found in atca_cfgs.h
 *  \param[in] config Array uint8_t of configuration (length 112)
 *  \param[in] len Size of the configuration array
 *  \return ATCA_SUCCESS on success, otherwise an error code.
 */
ATCA_STATUS write_configuration(ATCAIfaceCfg *cfg, uint8_t *config, size_t len)
{
    if (len != 112)
        return ATCA_BAD_PARAM;
    ATCA_STATUS status;
    status = atcab_init(cfg);
    if (status == ATCA_SUCCESS)
    {
        // Write the configuration Array to the chip
        // Padding of 16 byte (16 first bytes cannot be writed)
        status = atcab_write_bytes_zone(ATCA_ZONE_CONFIG, 0, 16, (uint8_t *)config, len);
        return status;
    }
    return status;
}

This function will write your configuration in the chip.

Third step : lock the configuration Zone

Warning : be careful with this step, if you lock this Zone and your configuration is not good, the chip is unusable and you could not modify this zone.

For this action, we will use this function :

/** \brief Check if a the DATA_ZONE or CONFIG_ZONE is locked
 *  \param[in] cfg  Logical interface configuration. Some predefined
 *                  configurations can be found in atca_cfgs.h
 *  \param[in] zone LOCK_ZONE_DATA or LOCK_ZONE_CONFIG
 *  \return ATCA_SUCCESS on success, otherwise an error code.
 */
ATCA_STATUS check_lock_zone(ATCAIfaceCfg *cfg, uint8_t zone)
{
    ATCA_STATUS status;
    bool lock = false;

    if (zone != (uint8_t)LOCK_ZONE_CONFIG && zone != (uint8_t)LOCK_ZONE_DATA)
        return ATCA_BAD_PARAM;


    status = atcab_init(cfg);
    if (status == ATCA_SUCCESS)
    {
        if (ATCA_SUCCESS != (status = atcab_is_locked(zone, &lock)))
        {
            return ATCA_FUNC_FAIL;
        }
        if (!lock)
        {
            return ATCA_NOT_LOCKED;
        }
        return ATCA_SUCCESS;
    }
    return ATCA_BAD_PARAM;
}

check_lock_zone(&cfg, LOCK_ZONE_CONFIG);

Fourth step : Write you AES Key in a slot

In this part you will set you personal AES key in the slot that you have defined in the configuration of the chip.

For this example, I will use the slot number 9 of the chip.

You need to know : A special feature of this chip is you can write data in slot only by 4 bytes or 32 bytes. For AES we need 128 bits Key so 16 bytes of data. So I decided to write to key of 16 bytes each in this slot to have 32 bytes data.

Now, I will show you the code used :

/** \brief Write AES key in a given slot.<br> *  \param[in] cfg      Logical interface configuration. Some predefined
 *                      configurations can be found in atca_cfgs.h
 *  \param[in] key      key slot number
 *  \param[in] datakey  key array uint8_t
 *  \param[in] len      Size of the key array
 *  \return ATCA_SUCCESS on success, otherwise an error code.
 */
ATCA_STATUS write_key_slot(ATCAIfaceCfg *cfg, uint8_t key, uint8_t *datakey, size_t len)
{
    if (key < 1 && key > 16)
        return ATCA_BAD_PARAM;

   if (len != 32)
        return ATCA_BAD_PARAM;

    ATCA_STATUS status = atcab_init(cfg);

    if (status == ATCA_SUCCESS)
    {
        status = atcab_write_zone(ATCA_ZONE_DATA, (uint16_t)key, 0, 0, datakey, 32);
        if (status != ATCA_SUCCESS)
            return status;
    }
    return status;
}

For this example, I will use two AES Keys of 16 bytes each :

// Example of AES KEY (len 32)<br>uint8_t example_of_key[32] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";

write_key_slot(&cfg, 9, example_of_key, sizeof(example_of_key));

If this action is good, now, you have to pass the last step "lock the data zone"

Last step : lock the Data Zone

Warning : be careful with this step, if you lock this Zone and your data are not set, the chip is unusable and you could not modify this zone.

For this action, we will use this function :

/** \brief Check if a the DATA_ZONE or CONFIG_ZONE is locked
 *  \param[in] cfg  Logical interface configuration. Some predefined
 *                  configurations can be found in atca_cfgs.h
 *  \param[in] zone LOCK_ZONE_DATA or LOCK_ZONE_CONFIG
 *  \return ATCA_SUCCESS on success, otherwise an error code.
 */
ATCA_STATUS check_lock_zone(ATCAIfaceCfg *cfg, uint8_t zone)
{
    ATCA_STATUS status;
    bool lock = false;

    if (zone != (uint8_t)LOCK_ZONE_CONFIG && zone != (uint8_t)LOCK_ZONE_DATA)
        return ATCA_BAD_PARAM;


    status = atcab_init(cfg);
    if (status == ATCA_SUCCESS)
    {
        if (ATCA_SUCCESS != (status = atcab_is_locked(zone, &lock)))
        {
            return ATCA_FUNC_FAIL;
        }
        if (!lock)
        {
            return ATCA_NOT_LOCKED;
        }
        return ATCA_SUCCESS;
    }
    return ATCA_BAD_PARAM;
}

check_lock_zone(&cfg, LOCK_ZONE_DATA);

If this action is good, your chip is ready to be use !

Step 5: 3. Utilization of the AES CBC Module

I will explain how to encrypt and decrypt data with the algorithm AES CBC and the chip Atecc608a.

Remember : Before use this function, you need to set up the chip. For this, follow the step 2 of this article

This chip got multiple type of AES module (AES 128 bits), only AES 128 bits is possible :

  1. AES normal
  2. AES CBC
  3. AES GCM (with GFM hash) (see wikipedia for more explication)

To make it easier to use, I created two functions:

  1. aes_cbc_encrypt
  2. aes_cbc_decrypt

Those two functions are available on my Github.

Explication

I choose to use the AES CBC Algorithm because it is safer than the basic AES 128 bits. This algorithm use an Initial Vector to encrypt your data.

Information

Below I details each step of the encryption and decryption method. But I wrote a code for the Arduino that use those both functions. You can see this code in my Github :

First step : Encrypt your data

In this part, I will show you how to encrypt your data.

First you will need this function :

/** \brief Encrypt data using AES CBC algorithme<br> *  \param[in] cfg          Logical interface configuration. Some predefined
 *                          configurations can be found in atca_cfgs.h
 *  \param[in] data         Words to encypt (must be divided by 16, max length 240)
 *  \param[in] len          length of Words to encypt (must be divided by 16, max length 240)
 *  \param[out] iv          Initial Vector used in the AES CBC (return the vector in this var)
 *  \param[out] ciphertext  return here the Cypher text
 *  \param[in] key          Slot number of the key
 *  \return ATCA_SUCCESS on success, otherwise an error code.
 */
ATCA_STATUS aes_cbc_encrypt(ATCAIfaceCfg *cfg, uint8_t *data, int len, uint8_t *iv, uint8_t *ciphertext, uint8_t key)
{

    atca_aes_cbc_ctx_t ctx;

    if (len > LIMIT_DATA_SIZE_CBC && len % 16 != 0)
    {
        Serial.print(F("ERROR : ATCA_BAD_PARAM"));
        return ATCA_BAD_PARAM;
    }
    uint8_t tmp_iv[IV_LENGTH_CBC];
    uint8_t tmp_data[len];

    ATCA_STATUS status = atcab_init(cfg);
    if (status == ATCA_SUCCESS)
    {
        status = atcab_aes_cbc_init(&ctx, key, 0, tmp_iv);

        if (status != ATCA_SUCCESS)
        {
            Serial.print(F("ERROR Encrypt : atcab_aes_cbc_init, Code Error 0x"));
            Serial.println(status, HEX);
            return;
        }
        memcpy(iv, tmp_iv, IV_LENGTH_CBC);
        memcpy(tmp_data, data, len);

        int max = len / 16;

        for (int j = 0; j < max; j++)
        {
            status = atcab_aes_cbc_encrypt_block(&ctx, &tmp_data[j * 16], &ciphertext[j * 16]);
        }
        if (status != ATCA_SUCCESS)
        {
            Serial.print(F("ERROR Encrypt : atcab_aes_cbc_encrypt_block, Code Error 0x"));
            Serial.println(status, HEX);
        }
        return status;
    }
    return status;
}

This function is simple to use, you have to set two things:

  1. An empty IV (Initial Vector) of 16 Bytes
  2. Data to encrypt (max size 240 Bytes)

Here an example "how to use this function".

I want to encrypt the word "AAAAAAAAAAAAAAA", with my key wrote in the slot number "9":

    ATCA_STATUS status = atcab_init(&cfg);<br>    if (status != ATCA_SUCCESS)
    {
        Serial.println(F("atcab_init() failed : Code -> 0x"));
        Serial.println(status, HEX);
    }

    uint8_t plaintext[16] = "AAAAAAAAAAAAAAA"; // Original text

    uint8_t iv[IV_LENGTH_CBC]; // Initial Vector
    uint8_t cypherdata[sizeof(plaintext)]; // Data encrypted

    status = aes_cbc_encrypt(&cfg, plaintext, sizeof(plaintext), iv, cypherdata, 9);

If the action is good, you will have the encrypted data in the variable "cypherdata" and the Initial Vector in the variable "IV".

Keep those two variables to decrypt your text !

Second step : decrypt your data

To decrypt your data you will need two things :

  1. The Initial Vector
  2. The Cypher data (encrypted data)

To decrypt your data, you will need this function :

/** \brief Decrypt data using AES CBC algorithme<br> *  \param[in] cfg          Logical interface configuration. Some predefined
 *                          configurations can be found in atca_cfgs.h
 *  \param[in] ciphertext   Words to decypt (must be divided by 16, max length 240)
 *  \param[in] len          length of Words to decypt (must be divided by 16, max length 240)
 *  \param[in] iv           Initial Vector to use in the AES CBC 
 *  \param[out] plaintext   return here the decrypted text
 *  \param[in] key          Slot number of the key
 *  \return ATCA_SUCCESS on success, otherwise an error code.
 */
ATCA_STATUS aes_cbc_decrypt(ATCAIfaceCfg *cfg, uint8_t *ciphertext, int len, uint8_t *iv, uint8_t *plaintext, uint8_t key)
{

    atca_aes_cbc_ctx_t ctx;

    if (len > LIMIT_DATA_SIZE_CBC || len % 16 != 0)
    {
        Serial.print(F("ERROR Decrypt : ATCA_BAD_PARAM"));
        return ATCA_BAD_PARAM;
    }

    ATCA_STATUS status = atcab_init(cfg);
    if (status == ATCA_SUCCESS)
    {
        status = atcab_aes_cbc_init(&ctx, key, 0, iv);

        if (status != ATCA_SUCCESS)
        {
            Serial.print(F("ERROR Decrypt: atcab_aes_cbc_init, Code Error 0x"));
            Serial.println(status, HEX);
            return;
        }
        int max = len / 16;

        for (int j = 0; j < max; j++)
        {
            status = atcab_aes_cbc_decrypt_block(&ctx, &ciphertext[j * 16], &plaintext[j * 16]);
        }
        if (status != ATCA_SUCCESS)
        {
            Serial.print(F("ERROR Decrypt : atcab_aes_cbc_encrypt_block, Code Error 0x"));
            Serial.println(status, HEX);
        }
        return status;
    }
    return status;
}

I want to decrypt my previous data (see below, First step). For this I will do this:


    uint8_t plaintext[16] = "AAAAAAAAAAAAAAA";<br>
    uint8_t iv[IV_LENGTH_CBC];
    uint8_t cypherdata[sizeof(plaintext)];
    uint8_t decryptdata[sizeof(plaintext)];


        status = aes_cbc_decrypt(&cfg, cypherdata, sizeof(cypherdata), iv, decryptdata, 9);<br>        if (status == ATCA_SUCCESS)
        {
            Serial.print("Decrypted text is : ");
            for (size_t i = 0; i < sizeof(decryptdata); i++)
            {
                Serial.print((char)decryptdata[i]);
            }
            Serial.println("");
        }
        else
        {
            // See file atca_status.h for the code Error
            Serial.print(F("Impossible do the decryption | Code Error 0x"));
            Serial.println(status, HEX);
            return;
        }

If the action is good, you will have the decrypted data in the variable "decryptdata".

Now you know how to use encryption and decryption with the chip Atecc608a !

Step 6: 5. Why Do You Need to Use This Chip

Encrypted data are very useful because you can hide your information and send it by Wireless or just store it.

Here some example of utilization :

  1. Stored data to an external EEPROM : You can secure data of an external EEPROM and if someone still this EEPROM, he will need the Key and the IV for the decryption
  2. Send Wireless data : You can send this encrypted data by Wireless (nrf24L01, RFM95W...) and if somebody intercept your data, this data will be secure
  3. Stored password
  4. ...

You can do multiple things with this chip. It can be used in multiple project. If you have time, say me in what project you will use this chip ?

One last advice, if you build some wireless project or store some raw data, be careful, security is very important and if you know how it is simple for a "noob" to intercept or steal your data. Now with Internet, everyone can have scripts to launch on their computer just to "hack" you !

Step 7: Conclusion

I hope this article will be useful for you. Sorry if I did mistake in my text but English is not my main language and I speak better than I write.

Thanks for reading everything.

Enjoy it.

First Time Author Contest

Participated in the
First Time Author Contest