This sketch will personalize either none-volatile memory or ATSHA204A for security functions available in the MySensors library.
 Details on personalization procedure is given in personalization.
 This sketch will when executed without modifications also print a guided workflow on the UART.
#include "sha204_library.h"
#define MY_CORE_ONLY
 
 
#define MY_HMAC_KEY 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
 
#define MY_AES_KEY 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
 
#define MY_SOFT_SERIAL 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
#ifdef GENERATE_KEYS_ATSHA204A
#define LOCK_ATSHA204A_CONFIGURATION // We have to lock configuration to enable random number generation
#define GENERATE_HMAC_KEY // Generate random HMAC key
#define GENERATE_AES_KEY // Generate random AES key
#define SKIP_UART_CONFIRMATION // This is an automated mode
#endif
 
#ifdef GENERATE_KEYS_SOFT
#define USE_SOFT_SIGNING // Use software backend
#define GENERATE_HMAC_KEY // Generate random HMAC key
#define GENERATE_AES_KEY // Generate random AES key
#define SKIP_UART_CONFIRMATION // This is an automated mode
#endif
 
#ifdef PERSONALIZE_ATSHA204A
#define LOCK_ATSHA204A_CONFIGURATION // We have to lock configuration to enable random number generation
#define STORE_HMAC_KEY // Store the HMAC key
#define STORE_AES_KEY // Store the AES key
#define SKIP_UART_CONFIRMATION // This is an automated mode
#endif
 
#ifdef PERSONALIZE_SOFT_RANDOM_SERIAL
#define GENERATE_SOFT_SERIAL // Generate a soft serial number
#define PERSONALIZE_SOFT // Do the rest as PERSONALIZE_SOFT
#endif
 
#ifdef PERSONALIZE_SOFT
#define USE_SOFT_SIGNING // Use software backend
#define STORE_HMAC_KEY // Store the HMAC key
#define STORE_AES_KEY // Store the AES key
#define STORE_SOFT_SERIAL // Store the soft serial number
#define SKIP_UART_CONFIRMATION // This is an automated mode
#endif
 
#if defined(GENERATE_HMAC_KEY) || defined(GENERATE_AES_KEY) || defined(GENERATE_SOFT_SERIAL)
#define GENERATE_SOMETHING
#endif
 
#if defined(MY_LOCK_MCU)
#undefine MY_LOCK_MCU  // The Sketch after SecurityPersonaliter should lock the MCU
#endif
 
#if defined(GENERATE_SOFT_SERIAL) && !defined(USE_SOFT_SIGNING)
#error Cannot generate soft serial using ATSHA204A, use USE_SOFT_SINGING for this
#endif
#if defined(STORE_SOFT_SERIAL) && !defined(USE_SOFT_SIGNING)
#error Cannot store soft serial to ATSHA204A, use USE_SOFT_SINGING for this
#endif
#if defined(PRINT_DETAILED_ATSHA204A_CONFIG) && defined(USE_SOFT_SIGNING)
#error Cannot print ATSHA204A config using software signing flag, disable USE_SOFT_SINGING for this
#endif
#if defined(LOCK_ATSHA204A_CONFIGURATION) && defined(USE_SOFT_SIGNING)
#error Cannot lock ATSHA204A config using software signing flag, disable USE_SOFT_SINGING for this
#endif
#ifdef GENERATE_KEYS_ATSHA204A
#ifdef USE_SOFT_SIGNING
#error You cannot select soft signing if you want to generate keys using ATSHA204A
#endif
#ifdef STORE_HMAC_KEY
#error Disable STORE_SOFT_KEY, you should not store keys in this mode
#endif
#ifdef STORE_SOFT_SERIAL
#error Disable STORE_SOFT_SERIAL, you should not store serial in this mode
#endif
#ifdef STORE_AES_KEY
#error Disable STORE_AES_KEY, you should not store keys in this mode
#endif
#if defined(GENERATE_KEYS_SOFT) ||\
        defined (PERSONALIZE_ATSHA204A) ||\
        defined (PERSONALIZE_SOFT) ||\
        defined (PERSONALIZE_SOFT_RANDOM_SERIAL)
#error You can not enable GENERATE_KEYS_ATSHA204A together with other guided modes
#endif
#endif // GENERATE_KEYS_ATSHA204A
#ifdef GENERATE_KEYS_SOFT
#ifdef STORE_HMAC_KEY
#error Disable STORE_SOFT_KEY, you should not store keys in this mode
#endif
#ifdef STORE_SOFT_SERIAL
#error Disable STORE_SOFT_SERIAL, you should not store serial in this mode
#endif
#ifdef STORE_AES_KEY
#error Disable STORE_AES_KEY, you should not store keys in this mode
#endif
#ifndef MY_SIGNING_SOFT_RANDOMSEED_PIN
#error You have to set MY_SIGNING_SOFT_RANDOMSEED_PIN to a suitable value in this mode
#endif
#if defined(GENERATE_KEYS_ATSHA204A) ||\
        defined (PERSONALIZE_ATSHA204A) ||\
        defined (PERSONALIZE_SOFT) ||\
        defined (PERSONALIZE_SOFT_RANDOM_SERIAL)
#error You can not enable GENERATE_KEYS_SOFT together with other guided modes
#endif
#endif // GENERATE_KEYS_SOFT
#ifdef PERSONALIZE_ATSHA204A
#ifdef USE_SOFT_SIGNING
#error You cannot select soft signing if you want to personalize an ATSHA204A
#endif
#if defined(GENERATE_KEYS_ATSHA204A) ||\
        defined (GENERATE_KEYS_SOFT) ||\
        defined (PERSONALIZE_SOFT) ||\
        defined (PERSONALIZE_SOFT_RANDOM_SERIAL)
#error You can not enable PERSONALIZE_ATSHA204A together with other guided modes
#endif
#ifdef RESET_EEPROM_PERSONALIZATION
#error You cannot reset EEPROM personalization when personalizing a device
#endif
#endif // PERSONALIZE_ATSHA204A
#ifdef PERSONALIZE_SOFT
#if defined(GENERATE_KEYS_ATSHA204A) ||\
        defined (GENERATE_KEYS_SOFT) ||\
        defined (PERSONALIZE_ATSHA204A)
#error You can not enable PERSONALIZE_SOFT together with other guided modes
#endif
#ifdef RESET_EEPROM_PERSONALIZATION
#error You cannot reset EEPROM personalization when personalizing a device
#endif
#endif // PERSONALIZE_SOFT
#ifdef PERSONALIZE_SOFT_RANDOM_SERIAL
#if defined(GENERATE_KEYS_SOFT) ||\
        defined (PERSONALIZE_ATSHA204A) ||\
        defined (GENERATE_KEYS_ATSHA204A)
#error You can only enable one of the guided modes at a time
#endif
#ifdef RESET_EEPROM_PERSONALIZATION
#error You cannot reset EEPROM personalization when personalizing a device
#endif
#endif // PERSONALIZE_SOFT_RANDOM_SERIAL
 
#if !defined(GENERATE_KEYS_ATSHA204A) &&\
        !defined(GENERATE_KEYS_SOFT) &&\
        !defined(PERSONALIZE_ATSHA204A) &&\
        !defined(PERSONALIZE_SOFT) &&\
        !defined(PERSONALIZE_SOFT_RANDOM_SERIAL) &&\
        !defined(USE_SOFT_SIGNING) &&\
        !defined(LOCK_ATSHA204A_CONFIGURATION) &&\
        !defined(SKIP_UART_CONFIRMATION) &&\
        !defined(GENERATE_HMAC_KEY) &&\
        !defined(STORE_HMAC_KEY) &&\
        !defined(GENERATE_SOFT_SERIAL) &&\
        !defined(STORE_SOFT_SERIAL) &&\
        !defined(GENERATE_AES_KEY) &&\
        !defined(STORE_AES_KEY) &&\
        !defined(PRINT_DETAILED_ATSHA204A_CONFIG) &&\
        !defined(RESET_EEPROM_PERSONALIZATION)
 
#define NO_SETTINGS_DEFINED
#endif
 
#if defined(GENERATE_KEYS_ATSHA204A) ||\
        defined(GENERATE_KEYS_SOFT) ||\
        defined(PERSONALIZE_ATSHA204A) ||\
        defined(PERSONALIZE_SOFT) ||\
        defined(PERSONALIZE_SOFT_RANDOM_SERIAL)
 
#define GUIDED_MODE
#endif
 
static void halt(bool success);
#ifdef GENERATE_SOMETHING
static bool generate_random_data(uint8_t* 
data, 
size_t sz);
 
#endif
static void generate_keys(void);
static void store_keys(void);
static void print_hex_buffer(uint8_t* 
data, 
size_t sz);
 
static void print_c_friendly_hex_buffer(uint8_t* 
data, 
size_t sz);
 
#ifdef STORE_HMAC_KEY
static bool store_hmac_key_data(uint8_t* 
data, 
size_t sz);
 
#endif
#ifdef STORE_AES_KEY
static bool store_aes_key_data(uint8_t* 
data, 
size_t sz);
 
#endif
#ifdef STORE_SOFT_SERIAL
static bool store_soft_serial_data(uint8_t* 
data, 
size_t sz);
 
#endif
#ifndef USE_SOFT_SIGNING
static void init_atsha204a_state(void);
#ifdef LOCK_ATSHA204A_CONFIGURATION
static void lock_atsha204a_config(void);
static uint16_t write_atsha204a_config_and_get_crc(void);
#endif
static bool get_atsha204a_serial(uint8_t* 
data);
 
#ifdef STORE_HMAC_KEY
static bool write_atsha204a_key(uint8_t* key);
#endif
#endif // not USE_SOFT_SIGNING
static void print_greeting(void);
static void print_ending(void);
static void probe_and_print_peripherals(void);
static void print_eeprom_data(void);
static void print_whitelisting_entry(void);
#ifdef PRINT_DETAILED_ATSHA204A_CONFIG
static void dump_detailed_atsha204a_configuration(void);
#endif
#ifdef RESET_EEPROM_PERSONALIZATION
static void reset_eeprom(void);
#endif
static void write_eeprom_checksum(void);
 
#if defined(GENERATE_HMAC_KEY) || defined(STORE_HMAC_KEY)
 
#endif
 
#if defined(GENERATE_SOFT_SERIAL) || defined(STORE_SOFT_SERIAL)
 
#endif
 
#if defined(GENERATE_AES_KEY) || defined(STORE_AES_KEY)
#endif
 
#ifndef USE_SOFT_SIGNING
static uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
static uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
static uint8_t ret_code;
static uint8_t lockConfig = 0;
static uint8_t lockValue = 0;
#endif
static bool has_device_unique_id = false;
static const uint8_t reset_buffer[32] = {
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
 
 
{
    
    uint32_t enter = hwMillis();
    while (hwMillis() - enter < (uint32_t)500);
#ifdef USE_SOFT_SIGNING
    
    hwRandomNumberInit();
#endif
 
    while(!Serial); 
 
    print_greeting();
 
#ifndef USE_SOFT_SIGNING
    init_atsha204a_state();
    
#ifdef LOCK_ATSHA204A_CONFIGURATION
    lock_atsha204a_config();
#endif
#endif
    
    generate_keys();
 
#ifdef RESET_EEPROM_PERSONALIZATION
    
    reset_eeprom();
#endif
 
    
    store_keys();
 
    
    write_eeprom_checksum();
 
    
    print_eeprom_data();
    print_whitelisting_entry();
    Serial.println();
 
    print_ending();
    halt(true);
}
 
{
}
 
static void halt(bool success)
{
    Serial.println();
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                                  Execution result                                  |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    if (success) {
        Serial.println(F(
                           "| SUCCESS                                                                            |"));
    } else {
        Serial.print(F(
                         "| FAILURE "));
#ifdef USE_SOFT_SIGNING
        Serial.println(F("                                                                           |"));
#else
            Serial.print(F("(last ATSHA204A return code: 0x"));
            if (ret_code < 0x10) {
                Serial.print('0'); 
            }
            Serial.print(ret_code, HEX);
            Serial.println(F(")                                         |"));
        } else {
            Serial.println(F("                                                                           |"));
        }
#endif
    }
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    while(1) {
    }
}
 
#ifdef GENERATE_SOMETHING
 
static bool generate_random_data(uint8_t* 
data, 
size_t sz)
 
{
#if defined(USE_SOFT_SIGNING) && ! defined(MY_HW_HAS_GETENTROPY)
    for (size_t i = 0; i < sz; i++) {
        data[i] = random(256) ^ micros();
 
        uint32_t enter = hwMillis();
        while (hwMillis() - enter < (uint32_t)2);
    }
    return true;
#elif defined(USE_SOFT_SIGNING) && defined(MY_HW_HAS_GETENTROPY)
#else
        return false;
    } else {
        memcpy(
data, rx_buffer+SHA204_BUFFER_POS_DATA, sz);
 
        return true;
    }
#endif // not USE_SOFT_SIGNING
}
#endif // GENERATE_SOMETHING
 
static void generate_keys(void)
{
#ifdef GENERATE_SOMETHING
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                                   Key generation                                   |"));
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.println(
        F("| Key ID | Status | Key                                                              |"));
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
#endif
#ifdef GENERATE_HMAC_KEY
    Serial.print(F("| HMAC   | "));
    if (!generate_random_data(user_hmac_key, 32)) {
        memset(user_hmac_key, 0xFF, 32);
        Serial.print(F("FAILED | "));
    } else {
        Serial.print(F("OK     | "));
    }
    print_hex_buffer(user_hmac_key, 32);
    Serial.println(F(" |"));
#endif
#ifdef GENERATE_AES_KEY
    Serial.print(F("| AES    | "));
    if (!generate_random_data(user_aes_key, 16)) {
        memset(user_aes_key, 0xFF, 16);
        Serial.print(F("FAILED | "));
    } else {
        Serial.print(F("OK     | "));
    }
    print_hex_buffer(user_aes_key, 16);
    Serial.println(F("                                 |"));
#endif
#ifdef GENERATE_SOFT_SERIAL
    Serial.print(F("| SERIAL | "));
    if (has_device_unique_id) {
        Serial.println(F("N/A    | MCU has a unique serial which will be used instead.              |"));
    } else {
        if (!generate_random_data(user_soft_serial, 9)) {
            memset(user_soft_serial, 0xFF, 9);
            Serial.print(F("FAILED | "));
        } else {
            Serial.print(F("OK     | "));
        }
        print_hex_buffer(user_soft_serial, 9);
        Serial.println(F("                                               |"));
    }
#endif
#if defined(GENERATE_SOMETHING) && !defined(PERSONALIZE_SOFT_RANDOM_SERIAL)
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.println();
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                                  Key copy section                                  |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
#ifdef GENERATE_HMAC_KEY
    Serial.print(F("#define MY_HMAC_KEY "));
    print_c_friendly_hex_buffer(user_hmac_key, 32);
    Serial.println();
#endif
#ifdef GENERATE_AES_KEY
    Serial.print(F("#define MY_AES_KEY "));
    print_c_friendly_hex_buffer(user_aes_key, 16);
    Serial.println();
#endif
#ifdef GENERATE_SOFT_SERIAL
    Serial.print(F("#define MY_SOFT_SERIAL "));
    print_c_friendly_hex_buffer(user_soft_serial, 9);
    Serial.println();
#endif
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println();
#elif defined(PERSONALIZE_SOFT_RANDOM_SERIAL)
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.println();
#endif
}
 
#ifdef RESET_EEPROM_PERSONALIZATION
 
static void reset_eeprom(void)
{
    uint8_t validation_buffer[32];
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                                   EEPROM reset                                     |"));
    Serial.println(
        F("+--------+---------------------------------------------------------------------------+"));
    Serial.println(
        F("| Key ID | Status                                                                    |"));
    Serial.println(
        F("+--------+---------------------------------------------------------------------------+"));
    Serial.print(F("| HMAC   | "));
    
    if (memcmp(validation_buffer, reset_buffer, 32) != 0) {
        Serial.println(F("FAILED                                                                    |"));
    } else {
        Serial.println(F("OK                                                                        |"));
    }
    Serial.print(F("| AES    | "));
    
    if (memcmp(validation_buffer, reset_buffer, 16) != 0) {
        Serial.println(F("FAILED                                                                    |"));
    } else {
        Serial.println(F("OK                                                                        |"));
    }
    Serial.print(F("| SERIAL | "));
    
    if (memcmp(validation_buffer, reset_buffer, 9) != 0) {
        Serial.println(F("FAILED                                                                    |"));
    } else {
        Serial.println(F("OK                                                                        |"));
    }
    Serial.println(
        F("+--------+---------------------------------------------------------------------------+"));
}
#endif // RESET_EEPROM_PERSONALIZATION
 
static void write_eeprom_checksum(void)
{
    uint8_t hash[32];
    uint8_t checksum;
 
    SHA256(hash, buffer, sizeof(buffer));
}
 
static void store_keys(void)
{
#if defined(STORE_HMAC_KEY) || defined(STORE_AES_KEY) || defined(STORE_SOFT_SERIAL)
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                                    Key storage                                     |"));
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.println(
        F("| Key ID | Status | Key                                                              |"));
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
#endif
#ifdef STORE_HMAC_KEY
    Serial.print(F("| HMAC   | "));
    if (!store_hmac_key_data(user_hmac_key)) {
        Serial.print(F("FAILED | "));
    } else {
        Serial.print(F("OK     | "));
    }
    print_hex_buffer(user_hmac_key, 32);
    Serial.println(F(" |"));
#endif
#ifdef STORE_AES_KEY
    Serial.print(F("| AES    | "));
    if (!store_aes_key_data(user_aes_key)) {
        Serial.print(F("FAILED | "));
    } else {
        Serial.print(F("OK     | "));
    }
    print_hex_buffer(user_aes_key, 16);
    Serial.println(F("                                 |"));
#endif
#ifdef STORE_SOFT_SERIAL
    Serial.print(F("| SERIAL | "));
    if (has_device_unique_id) {
        memset(user_soft_serial, 0xFF, 9);
    }
    if (!store_soft_serial_data(user_soft_serial)) {
        Serial.print(F("FAILED | "));
    } else {
        Serial.print(F("OK     | "));
    }
    if (has_device_unique_id) {
        Serial.println(F("EEPROM reset. MCU has a unique serial which will be used instead.|"));
    } else {
        print_hex_buffer(user_soft_serial, 9);
        Serial.println(F("                                               |"));
    }
#endif
#if defined(STORE_HMAC_KEY) || defined(STORE_AES_KEY) || defined(STORE_SOFT_SERIAL)
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.println();
#endif
}
 
static void print_hex_buffer(uint8_t* 
data, 
size_t sz)
 
{
    for (size_t i=0; i<sz; i++) {
            Serial.print('0'); 
        }
        Serial.print(
data[i], HEX);
 
    }
}
 
static void print_c_friendly_hex_buffer(uint8_t* 
data, 
size_t sz)
 
{
    for (size_t i=0; i<sz; i++) {
        Serial.print("0x");
            Serial.print('0'); 
        }
        Serial.print(
data[i], HEX);
 
        if (i < sz-1) {
            Serial.print(',');
        }
    }
}
 
#ifdef STORE_HMAC_KEY
 
static bool store_hmac_key_data(uint8_t* 
data)
 
{
#ifdef USE_SOFT_SIGNING
    static uint8_t validation_buffer[32];
    
    if (memcmp(validation_buffer, 
data, 32) != 0) {
 
        return false;
    } else {
        return true;
    }
#else
    
    if (lockConfig == 0x00) {
        
        if (!write_atsha204a_key(
data)) {
 
            return false;
        } else {
            return true;
        }
    } else {
        return false;
    }
#endif
}
#endif
 
#ifdef STORE_AES_KEY
 
static bool store_aes_key_data(uint8_t* 
data)
 
{
    static uint8_t validation_buffer[16];
    
    if (memcmp(validation_buffer, 
data, 16) != 0) {
 
        return false;
    } else {
        return true;
    }
}
#endif // STORE_AES_KEY
 
#ifdef STORE_SOFT_SERIAL
 
static bool store_soft_serial_data(uint8_t* 
data)
 
{
    static uint8_t validation_buffer[9];
    
    if (memcmp(validation_buffer, 
data, 9) != 0) {
 
        return false;
    } else {
        return true;
    }
}
#endif // STORE_SOFT_SERIAL
 
#ifndef USE_SOFT_SIGNING
 
static void init_atsha204a_state(void)
{
    
        halt(false);
    } else {
        lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3];
        lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2];
    }
}
 
#ifdef LOCK_ATSHA204A_CONFIGURATION
static void lock_atsha204a_config(void)
{
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                           ATSHA204A configuration locking                          |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    if (lockConfig != 0x00) {
        uint16_t crc;
        (void)crc;
 
        
        crc = write_atsha204a_config_and_get_crc();
 
        
#ifdef PRINT_DETAILED_ATSHA204A_CONFIG
        Serial.println(
            F("|                             New ATSHA204A Configuration                            |"));
        dump_detailed_atsha204a_configuration();
#endif // PRINT_DETAILED_ATSHA204A_CONFIG
 
#ifndef SKIP_UART_CONFIRMATION
        
        while (Serial.available()) {
            Serial.read();
        }
        Serial.println(
            F("| * Send SPACE character now to lock the configuration...                            |"));
 
        while (Serial.available() == 0);
        if (Serial.read() == ' ')
#endif //not SKIP_UART_CONFIRMATION
        {
            Serial.print(F("| * Locking configuration..."));
 
            
                Serial.println(
                    F("+------------------------------------------------------------------------------------+"));
                halt(false);
            }
 
            
                                              crc, 0, NULL, 0, NULL, 0, NULL,
                                              LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer);
                Serial.println(F("Failed                                                   |"));
                Serial.println(
                    F("+------------------------------------------------------------------------------------+"));
                halt(false);
            } else {
                Serial.println(F("Done                                                     |"));
 
                
                    Serial.println(
                        F("+------------------------------------------------------------------------------------+"));
                    halt(false);
                } else {
                    lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3];
                    lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2];
                }
            }
        }
#ifndef SKIP_UART_CONFIRMATION
        else {
            Serial.println(
                F("| * Unexpected answer. Skipping locking.                                             |"));
            Serial.println(
                F("+------------------------------------------------------------------------------------+"));
        }
#endif //not SKIP_UART_CONFIRMATION
    } else {
        Serial.println(
            F("| * Skipping configuration write and lock (configuration already locked).            |"));
        Serial.println(
            F("+------------------------------------------------------------------------------------+"));
    }
    Serial.println();
}
 
static uint16_t write_atsha204a_config_and_get_crc(void)
{
    uint16_t crc = 0;
    uint8_t config_word[4];
 
    
    
    
    
 
    for (int i=0; i < 88; i += 4) {
        bool do_write = true;
        if (i == 20) {
            config_word[0] = 0x8F;
            config_word[1] = 0x80;
            config_word[2] = 0x80;
            config_word[3] = 0xA1;
        } else if (i == 24) {
            config_word[0] = 0x82;
            config_word[1] = 0xE0;
            config_word[2] = 0xA3;
            config_word[3] = 0x60;
        } else if (i == 28) {
            config_word[0] = 0x94;
            config_word[1] = 0x40;
            config_word[2] = 0xA0;
            config_word[3] = 0x85;
        } else if (i == 32) {
            config_word[0] = 0x86;
            config_word[1] = 0x40;
            config_word[2] = 0x87;
            config_word[3] = 0x07;
        } else if (i == 36) {
            config_word[0] = 0x0F;
            config_word[1] = 0x00;
            config_word[2] = 0x89;
            config_word[3] = 0xF2;
        } else if (i == 40) {
            config_word[0] = 0x8A;
            config_word[1] = 0x7A;
            config_word[2] = 0x0B;
            config_word[3] = 0x8B;
        } else if (i == 44) {
            config_word[0] = 0x0C;
            config_word[1] = 0x4C;
            config_word[2] = 0xDD;
            config_word[3] = 0x4D;
        } else if (i == 48) {
            config_word[0] = 0xC2;
            config_word[1] = 0x42;
            config_word[2] = 0xAF;
            config_word[3] = 0x8F;
        } else if (i == 52 || i == 56 || i == 60 || i == 64) {
            config_word[0] = 0xFF;
            config_word[1] = 0x00;
            config_word[2] = 0xFF;
            config_word[3] = 0x00;
        } else if (i == 68 || i == 72 || i == 76 || i == 80) {
            config_word[0] = 0xFF;
            config_word[1] = 0xFF;
            config_word[2] = 0xFF;
            config_word[3] = 0xFF;
        } else {
            
                Serial.println(
                    F("+------------------------------------------------------------------------------------+"));
                halt(false);
            }
            
            config_word[0] = rx_buffer[SHA204_BUFFER_POS_DATA+0];
            config_word[1] = rx_buffer[SHA204_BUFFER_POS_DATA+1];
            config_word[2] = rx_buffer[SHA204_BUFFER_POS_DATA+2];
            config_word[3] = rx_buffer[SHA204_BUFFER_POS_DATA+3];
            do_write = false;
        }
 
        
 
        
        if (do_write) {
                                              i >> 2, 4, config_word, 0, NULL, 0, NULL,
                                              WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
                Serial.println(
                    F("+------------------------------------------------------------------------------------+"));
                halt(false);
            }
        }
    }
    return crc;
}
#endif
 
static bool get_atsha204a_serial(uint8_t* 
data)
 
{
        return false;
    } else {
        memcpy(
data, rx_buffer, 9);
 
        return true;
    }
}
 
#ifdef STORE_HMAC_KEY
 
static bool write_atsha204a_key(uint8_t* key)
{
    
                                      0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL,
                                      WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
        return false;
    } else {
        return true;
    }
}
#endif // STORE_HMAC_KEY
#endif // not USE_SOFT_SIGNING
 
static void print_greeting(void)
{
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                           MySensors security personalizer                          |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println();
#ifdef NO_SETTINGS_DEFINED
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("| You are running without any configuration flags set.                               |"));
    Serial.println(
        F("| No changes will be made to ATSHA204A or EEPROM except for the EEPROM checksum      |"));
    Serial.println(
        F("| which will be updated.                                                             |"));
    Serial.println(
        F("|                                                                                    |"));
    Serial.println(
        F("| If you want to personalize your device, you have two options.                      |"));
    Serial.println(
        F("|                                                                                    |"));
    Serial.println(
        F("| 1. a. Enable either GENERATE_KEYS_ATSHA204A or GENERATE_KEYS_SOFT                  |"));
    Serial.println(
        F("|       This will generate keys for ATSHA204A or software signing.                   |"));
    Serial.println(
        F("|    b. Execute the sketch. You will be guided through the steps below under         |"));
    Serial.println(
        F("|       WHAT TO DO NEXT?                                                             |"));
    Serial.println(
        F("|    c. Copy the generated keys and replace the topmost definitions in this file.    |"));
    Serial.println(
        F("|    d. Save the sketch and then disable the flag you just enabled.                  |"));
    Serial.println(
        F("|    e. Enable PERSONALIZE_ATSHA204A to personalize the ATSHA204A device.            |"));
    Serial.println(
        F("|       or                                                                           |"));
    Serial.println(
        F("|       Enable PERSONALIZE_SOFT to personalize the EEPROM for software signing.      |"));
    Serial.println(
        F("|       If you want to use whitelisting you need to pick a unique serial number      |"));
    Serial.println(
        F("|       for each device you run the sketch on and fill in MY_SOFT_SERIAL.            |"));
    Serial.println(
        F("|       or                                                                           |"));
    Serial.println(
        F("|       Enable PERSONALIZE_SOFT_RANDOM_SERIAL to personalzie the EEPROM and          |"));
    Serial.println(
        F("|       include a new random serial number every time the sketch is executed.        |"));
    Serial.println(
        F("|       Take note of each saved serial number if you plan to use whitelisting.       |"));
    Serial.println(
        F("|    f. Execute the sketch on each device you want to personalize that is supposed   |"));
    Serial.println(
        F("|       to communicate securely.                                                     |"));
    Serial.println(
        F("|                                                                                    |"));
    Serial.println(
        F("| 2. Enable any configuration flag as you see fit.                                   |"));
    Serial.println(
        F("|    It is assumed that you know what you are doing.                                 |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println();
#else
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                               Configuration settings                               |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
#if defined(GENERATE_KEYS_ATSHA204A)
    Serial.println(
        F("| * Guided key generation for ATSHA204A using ATSHA024A                              |"));
#endif
#if defined(GENERATE_KEYS_SOFT)
    Serial.println(
        F("| * Guided key generation for EEPROM using software                                  |"));
#endif
#if defined(PERSONALIZE_ATSHA204A)
    Serial.println(
        F("| * Guided personalization/storage of keys in ATSHA204A                              |"));
#endif
#if defined(PERSONALIZE_SOFT)
    Serial.println(
        F("| * Guided personalization/storage of keys in EEPROM                                 |"));
#endif
#if defined(PERSONALIZE_SOFT_RANDOM_SERIAL)
    Serial.println(
        F("| * Guided storage and generation of random serial in EEPROM                         |"));
#endif
#if defined(USE_SOFT_SIGNING)
    Serial.println(
        F("| * Software based personalization (no ATSHA204A usage whatsoever)                   |"));
#else
    Serial.println(
        F("| * ATSHA204A based personalization                                                  |"));
#endif
#if defined(LOCK_ATSHA204A_CONFIGURATION)
    Serial.println(
        F("| * Will lock ATSHA204A configuration                                                |"));
#endif
#if defined(SKIP_UART_CONFIRMATION)
    Serial.println(
        F("| * Will not require any UART confirmations                                          |"));
#endif
#if defined(GENERATE_HMAC_KEY)
    Serial.print(
        F("| * Will generate HMAC key using "));
#if defined(USE_SOFT_SIGNING)
    Serial.println(
        F("software                                            |"));
#else
    Serial.println(
        F("ATSHA204A                                           |"));
#endif
#endif
#if defined(STORE_HMAC_KEY)
    Serial.print(F("| * Will store HMAC key to "));
#if defined(USE_SOFT_SIGNING)
    Serial.println(
        F("EEPROM                                                    |"));
#else
    Serial.println(
        F("ATSHA204A                                                 |"));
#endif
#endif
#if defined(GENERATE_AES_KEY)
    Serial.print(
        F("| * Will generate AES key using "));
#if defined(USE_SOFT_SIGNING)
    Serial.println(
        F("software                                             |"));
#else
    Serial.println(
        F("ATSHA204A                                            |"));
#endif
#endif
#if defined(STORE_AES_KEY)
    Serial.println(
        F("| * Will store AES key to EEPROM                                                     |"));
#endif
#if defined(GENERATE_SOFT_SERIAL)
    Serial.println(
        F("| * Will generate soft serial using software                                         |"));
#endif
#if defined(STORE_SOFT_SERIAL)
    Serial.println(
        F("| * Will store soft serial to EEPROM                                                 |"));
#endif
#if defined(PRINT_DETAILED_ATSHA204A_CONFIG)
    Serial.println(
        F("| * Will print detailed ATSHA204A configuration                                      |"));
#endif
#if defined(RESET_EEPROM_PERSONALIZATION)
    Serial.println(
        F("| * Will reset EEPROM personalization data                                           |"));
#endif
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println();
#endif // not NO_SETTINGS_DEFINED
    probe_and_print_peripherals();
}
 
static void print_ending(void)
{
#if defined(GUIDED_MODE) || defined(NO_SETTINGS_DEFINED)
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                                  WHAT TO DO NEXT?                                  |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
#ifdef NO_SETTINGS_DEFINED
    Serial.println(
        F("| To proceed with the personalization, enable GENERATE_KEYS_ATSHA204A or             |"));
    Serial.println(
        F("| GENERATE_KEYS_SOFT depending on what type of signing backend you plan to use.      |"));
    Serial.println(
        F("| Both options will generate an AES key for encryption if you plan to use that.      |"));
    Serial.println(
        F("| Recompile, upload and run the sketch again for further instructions.               |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
#endif
#ifdef GENERATE_KEYS_ATSHA204A
    Serial.println(
        F("| To proceed with the personalization, copy the keys shown in the Key copy section,  |"));
    Serial.println(
        F("| and replace the corresponding definitions in the top of the sketch, then disable   |"));
    Serial.println(
        F("| GENERATE_KEYS_ATSHA204A and enable PERSONALIZE_ATSHA204A.                          |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
#endif
#ifdef GENERATE_KEYS_SOFT
    Serial.println(
        F("| To proceed with the personalization, copy the keys shown in the Key copy section,  |"));
    Serial.println(
        F("| and replace the corresponding definitions in the top of the sketch, then disable   |"));
    Serial.println(
        F("| GENERATE_KEYS_SOFT and enable PERSONALIZE_SOFT or PERSONALIZE_SOFT_RANDOM_SERIAL.  |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
#endif
#if defined(PERSONALIZE_ATSHA204A) ||\
    defined(PERSONALIZE_SOFT) ||\
    defined(PERSONALIZE_SOFT_RANDOM_SERIAL)
    Serial.println(
        F("| This device has now been personalized. Run this sketch with its current settings   |"));
    Serial.println(
        F("| on all the devices in your network that have security enabled.                     |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
#endif
#endif // GUIDED_MODE or NO_SETTINGS_DEFINED
}
 
static void probe_and_print_peripherals(void)
{
 
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                           Hardware security peripherals                            |"));
    Serial.println(
        F("+--------------+--------------+--------------+------------------------------+--------+"));
    Serial.println(
        F("| Device       | Status       | Revision     | Serial number                | Locked |"));
    Serial.println(
        F("+--------------+--------------+--------------+------------------------------+--------+"));
#if defined(ARDUINO_ARCH_AVR)
    Serial.print(F("| AVR          | DETECTED     | N/A          | "));
#elif defined(ARDUINO_ARCH_MEGAAVR)
    Serial.print(F("| megaAVR      | DETECTED     | N/A          | "));
#elif defined(ARDUINO_ARCH_ESP8266)
    Serial.print(F("| ESP8266      | DETECTED     | N/A          | "));
#elif defined(ARDUINO_ARCH_SAMD)
    Serial.print(F("| SAMD         | DETECTED     | N/A          | "));
#elif defined(ARDUINO_ARCH_STM32F1)
    Serial.print(F("| STM32F1      | DETECTED     | N/A          | "));
#elif defined(__linux__)
    Serial.print(F("| Linux        | DETECTED     | N/A          | "));
#else
    Serial.print(F("| Unknown      | DETECTED     | N/A          | "));
#endif
        has_device_unique_id = true;
        print_hex_buffer(uniqueID, 9);
        Serial.println(F("           | N/A    |"));
    } else {
        Serial.println(F("N/A (generation required)    | N/A    |"));
    }
    Serial.println(
        F("+--------------+--------------+--------------+------------------------------+--------+"));
#ifndef USE_SOFT_SIGNING
    Serial.print(F("| ATSHA204A    | "));
        Serial.println(F("NOT DETECTED | N/A          | N/A                          | N/A    |"));
    } else {
        uint8_t buffer[9];
        Serial.print(F("DETECTED     | "));
            Serial.print(F("FAILED       | "));
        } else {
            print_hex_buffer(&rx_buffer[SHA204_BUFFER_POS_DATA], 4);
            Serial.print(F("     | "));
        }
        if (!get_atsha204a_serial(buffer)) {
            memset(buffer, 0xFF, 9);
            Serial.print(F("FAILED                       | "));
        } else {
            print_hex_buffer(buffer, 9);
            Serial.print(F("           | "));
        }
            Serial.println("FAILED |");
        } else {
            if (rx_buffer[SHA204_BUFFER_POS_DATA+3] == 0x00) {
                Serial.println("YES    |");
            } else {
                Serial.println("NO     |");
            }
        }
    }
    Serial.println(
        F("+--------------+--------------+--------------+------------------------------+--------+"));
#ifdef PRINT_DETAILED_ATSHA204A_CONFIG
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                          Current ATSHA204A Configuration                           |"));
    dump_detailed_atsha204a_configuration();
#endif
#endif // not USE_SOFT_SIGNING
    Serial.println();
}
 
static void print_eeprom_data(void)
{
    uint8_t buffer[32];
 
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                                       EEPROM                                       |"));
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.println(
        F("| Key ID | Status | Key                                                              |"));
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.print(F("| HMAC   | "));
    if (!memcmp(buffer, reset_buffer, 32)) {
        Serial.print(F("RESET  | "));
    } else {
        Serial.print(F("OK     | "));
    }
    print_hex_buffer(buffer, 32);
    Serial.println(F(" |"));
    Serial.print(F("| AES    | "));
    if (!memcmp(buffer, reset_buffer, 16)) {
        Serial.print(F("RESET  | "));
    } else {
        Serial.print(F("OK     | "));
    }
    print_hex_buffer(buffer, 16);
    Serial.println(F("                                 |"));
    Serial.print(F("| SERIAL | "));
    if (!memcmp(buffer, reset_buffer, 9)) {
        if (has_device_unique_id) {
            Serial.println(F("N/A    | Device unique serial, not stored in EEPROM                       |"));
        } else {
            Serial.print(F("RESET  | "));
            print_hex_buffer(buffer, 9);
            Serial.println(F("                                               |"));
        }
    } else {
        Serial.print(F("OK     | "));
        print_hex_buffer(buffer, 9);
        Serial.println(F("                                               |"));
    }
    Serial.println(
        F("+--------+--------+------------------------------------------------------------------+"));
    Serial.println();
}
 
static void print_whitelisting_entry(void)
{
    uint8_t buffer[9];
#ifdef USE_SOFT_SIGNING
    if (!memcmp(buffer, reset_buffer, 9)) {
        
            memcpy(buffer, uniqueID, 9);
        }
    }
#else
    
    if (!get_atsha204a_serial(buffer)) {
        memset(buffer, 0xFF, 9);
    }
#endif
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.println(
        F("|                      This nodes whitelist entry on other nodes                     |"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
    Serial.print(F("{.nodeId = <ID of this node>,.serial = {"));
    print_c_friendly_hex_buffer(buffer, 9);
    Serial.println(F("}}"));
    Serial.println(
        F("+------------------------------------------------------------------------------------+"));
}
 
#ifdef PRINT_DETAILED_ATSHA204A_CONFIG
 
static void dump_detailed_atsha204a_configuration(void)
{
    Serial.println(
        F("+---------------------------------------------------------------++-------------------+"));
    Serial.println(
        F("|                           Fieldname                           ||       Data        |"));
    Serial.println(
        F("+-------------------------------+-------------------------------++---------+---------+"));
    for (int i=0; i < 88; i += 4) {
            Serial.println(
                F("+------------------------------------------------------------------------------------+"));
            halt(false);
        }
        if (i == 0x00) {
            Serial.print(F("|            SN[0:1]            |            SN[2:3]            || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x04) {
            Serial.print(F("|                            Revnum                             || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+---------------------------------------------------------------++-------------------+"));
        } else if (i == 0x08) {
            Serial.print(F("|                            SN[4:7]                            || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x0C) {
            Serial.print(F("|     SN[8]     |  Reserved13   |   I2CEnable   |  Reserved15   || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F(" | "));
                } else {
                    Serial.println(F(" |"));
                }
            }
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x10) {
            Serial.print(F("|  I2CAddress   |  TempOffset   |    OTPmode    | SelectorMode  || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F(" | "));
                } else {
                    Serial.println(F(" |"));
                }
            }
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x14) {
            Serial.print(F("|          SlotConfig00         |         SlotConfig01          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x18) {
            Serial.print(F("|          SlotConfig02         |         SlotConfig03          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x1C) {
            Serial.print(F("|          SlotConfig04         |         SlotConfig05          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x20) {
            Serial.print(F("|          SlotConfig06         |         SlotConfig07          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x24) {
            Serial.print(F("|          SlotConfig08         |         SlotConfig09          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x28) {
            Serial.print(F("|          SlotConfig0A         |         SlotConfig0B          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x2C) {
            Serial.print(F("|          SlotConfig0C         |         SlotConfig0D          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+-------------------------------+-------------------------------++---------+---------+"));
        } else if (i == 0x30) {
            Serial.print(F("|          SlotConfig0E         |         SlotConfig0F          || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j == 1) {
                    Serial.print(F(" | "));
                } else if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x34) {
            Serial.print(F("|   UseFlag00   | UpdateCount00 |   UseFlag01   | UpdateCount01 || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F(" | "));
                } else {
                    Serial.println(F(" |"));
                }
            }
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x38) {
            Serial.print(F("|   UseFlag02   | UpdateCount02 |   UseFlag03   | UpdateCount03 || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F(" | "));
                } else {
                    Serial.println(F(" |"));
                }
            }
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x3C) {
            Serial.print(F("|   UseFlag04   | UpdateCount04 |   UseFlag05   | UpdateCount05 || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F(" | "));
                } else {
                    Serial.println(F(" |"));
                }
            }
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x40) {
            Serial.print(F("|   UseFlag06   | UpdateCount06 |   UseFlag07   | UpdateCount07 || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F(" | "));
                } else {
                    Serial.println(F(" |"));
                }
            }
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x44) {
            Serial.print(F("|                        LastKeyUse[0:3]                        || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+---------------------------------------------------------------++-------------------+"));
        } else if (i == 0x48) {
            Serial.print(F("|                        LastKeyUse[4:7]                        || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+---------------------------------------------------------------++-------------------+"));
        } else if (i == 0x4C) {
            Serial.print(F("|                        LastKeyUse[8:B]                        || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+---------------------------------------------------------------++-------------------+"));
        } else if (i == 0x50) {
            Serial.print(F("|                        LastKeyUse[C:F]                        || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F("   "));
                }
            }
            Serial.println(F(" |"));
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        } else if (i == 0x54) {
            Serial.print(F("|   UserExtra   |    Selector   |   LockValue   |  LockConfig   || "));
            for (int j=0; j<4; j++) {
                if (rx_buffer[SHA204_BUFFER_POS_DATA+j] < 0x10) {
                    Serial.print('0'); 
                }
                Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
                if (j < 3) {
                    Serial.print(F(" | "));
                } else {
                    Serial.println(F(" |"));
                }
            }
            Serial.println(
                F("+---------------+---------------+---------------+---------------++----+----+----+----+"));
        }
    }
}
#endif // PRINT_DETAILED_ATSHA204A_CONFIG
 
#if DOXYGEN
#define GENERATE_KEYS_ATSHA204A
#define GENERATE_KEYS_SOFT
#define PERSONALIZE_ATSHA204A
#define PERSONALIZE_SOFT
#define PERSONALIZE_SOFT_RANDOM_SERIAL
#define USE_SOFT_SIGNING
#define LOCK_ATSHA204A_CONFIGURATION
#define SKIP_UART_CONFIRMATION
#define GENERATE_HMAC_KEY
#define STORE_HMAC_KEY
#define GENERATE_AES_KEY
#define STORE_AES_KEY
#define GENERATE_SOFT_SERIAL
#define STORE_SOFT_SERIAL
#define PRINT_DETAILED_ATSHA204A_CONFIG
#define RESET_EEPROM_PERSONALIZATION
#endif