Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
M

meddie

@meddie
About
Posts
106
Topics
9
Shares
0
Groups
0
Followers
0
Following
0

Posts

Recent Best Controversial

  • 💬 Sensebender Gateway
    M meddie

    @alexsh1
    hi, yes it was very simple :-D the gateway has worked fine in this time, i thought that when nothing shown in serial monitor that the gateway dont work, but it did it, after i connected the gateway to FHEM (my controller) i saw that FHEM connects t mys Gateway.
    So it worked all the time

    Greets Eddie

    OpenHardware.io mysensors gateway samd

  • Sensebender Micro Battery Code
    M meddie

    Hello together,

    i have bought a sensebender micro to test as temp and humidity sensor. I use the example sketch from sensebender, and for test i used a cd2032 battery but the battery is after 14 days empty.
    So i have to optimize my code and would like to ask you which settings are you using for battery nodes.

    How often do you transmit the temp / humidity?
    Which threshold for changing the temp / humidity?

    Thanks a lot
    Greets Eddie

    Development

  • 💬 Sensebender Micro
    M meddie

    @Michiel-van-der-Wulp
    thank you i will test it the next few days

    OpenHardware.io temperature atmega328 atsha204a humidity flash mysensors

  • 💬 Sensebender Micro
    M meddie

    @Michiel-van-der-Wulp
    Can you tell me where in the code is the switch to 1 MHz? I still have the problems that my node dosnt send anymore. It works for several hours but after then it dont send anything.

    In programming i am not good, and so i cant find the switch.
    Thank you very much.
    Greets Eddie

    OpenHardware.io temperature atmega328 atsha204a humidity flash mysensors

  • 💬 Sensebender Micro
    M meddie

    @qqlapraline
    oh yes it does! It explains why i get the € signs in the serial monitor. But why does the node not send to my FHEM Controller? Depends it also on it, that the node switch to 1 Mhz and cant send anymore?
    Thank you very much for your answer, its very helpfull.
    Greets Eddie

    OpenHardware.io temperature atmega328 atsha204a humidity flash mysensors

  • 💬 Sensebender Micro
    M meddie

    i have just tried it again, it worked for 20 minutes. After them i get this output:

    Sensebender Micro FW 1.4 - Online!
    isMetric: 1
    TempDiff :122.28
    HumDiff  :154.00
    T: 22.28
    H: 54
    TempDiff :0.00
    HumDiff  :0.00
    TempDiff :0.10
    HumDiff  :0.50
    TempDiff :0.11
    HumDiff  :0.50
    TempDiff :0.12
    HumDiff  :0.00
    €€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€€
    
    

    ok one more thing i found, when i close the serial monitor and start it again, i get the correctly output again, and i see in fhem the new readings.

    but i cant understand what happens why stop the node to transmit the correct readings

    OpenHardware.io temperature atmega328 atsha204a humidity flash mysensors

  • 💬 Sensebender Micro
    M meddie

    Hey together,

    i have an problem, i had some troubles with the space on the sb micro, i have removed the #define my_debug that solved my space problem, but now i have observed that the node is starting and sends few times the temp and humidity but after the few times nothing happens anymore.
    i observed, when i hold the sensor in the fingers so that it will be worm, and start the node then it sends all minute the temp, but when the temp goes down to the room temperature then the node should send only when the humidity or temp changes over the threshhold, so in the room i dont have much changes and i think that when the node does not send about a longer time, that the the problem comes up.
    I tested it in some different distances, on another floor but in very short distance too. I dont think that is a radio problem.
    What do you think about?
    The Problem is, that i cant debug the node because i disabled it because of space problems.
    Thank you

    OpenHardware.io temperature atmega328 atsha204a humidity flash mysensors

  • [security] Introducing signing support to MySensors
    M meddie

    i observed, when i hold the sensor in the fingers so that it will be worm, and start the node then it sends all minute the temp, but when the temp goes donw to the room temperature the the node sends only when the humidity or temp changes over the threshhold, but in the room i dont have much changes and i think that when the node does not send about longer time, that the the problem comes up.
    I tested it in some different distances, on another floor but in very short distance too. I dont think that is a radio problem.
    What do you think about?
    The Problem is, that i cant debug the node because i disabled it because of space problems.
    Thank you

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    sorry i didnt let hear anything from me for the last few days.
    i had the same problems with compiling the sketch. It depends on the signing. When you remove the #define MY_SIGNING_ATSHA204 the you can compile but when the singning is defined you get an error until you remove this line:
    #include <drivers/ATSHA204/ATSHA204.cpp>

    i have removed the line and defined the signing and for me works the singing and encryption.

    but i have an another problem, i dont know if i am right here or i better have to post in the sensebender micro forum, i posted that i had some troubles with the space on the sb micro, i have removed the #define my_debug that solved my space problem, but now i have observed that the node is starting and sends few times the temp and humidity but after the few times nothing happens anymore.

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    i used the stable lib and comiled the sketch both features are now working encryption and signing! Thank you very much!!!!! I will try to update the example lib and try again.

    I got just the next problem the space from sensebender micro is not enought to use all three features signing, encryption and ota. When i use AES and Signing i get over 109%, when i use the example sketch temp and humidty meassure.

    Greets Eddie

    Development security

  • 💬 Sensebender Micro
    M meddie

    Hey together,
    i have a question, because i have some capacity troubles. I used the example sketch from sensebender micro that meassures the temperature and humidity but i have additional activated the signing and encryption and now i got over the availible space 109%.
    use anybody from you all the features? what i have to do?
    thank you

    OpenHardware.io temperature atmega328 atsha204a humidity flash mysensors

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    its combined from two example sketches sensebendergateway and gatewayw5100 example sketch

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    Hi, i just tried it out and now it and it has worked! The Aes key is stored correctly! BUT i get now an error on compile the gateway sketch

    C:\Users\meddie\Documents\Arduino\SenseebnderGW_LAN_NRF24\SenseebnderGW_LAN_NRF24.ino\SenseebnderGW_LAN_NRF24.ino.ino: In function 'bool testEEProm()':
    
    SenseebnderGW_LAN_NRF24.ino:315: error: 'i2c_eeprom_read_byte' was not declared in this scope
    
       eeprom_d1 = i2c_eeprom_read_byte(EEPROM_VERIFICATION_ADDRESS);
    
                                                                   ^
    
    SenseebnderGW_LAN_NRF24.ino:318: error: 'i2c_eeprom_write_byte' was not declared in this scope
    
       i2c_eeprom_write_byte(EEPROM_VERIFICATION_ADDRESS, eeprom_d1);
    

    i could use the stable lib again then it should compile, but i think you would like to know that an error occours.
    Greets Eddie

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    thank you very much for your support and for your patience with me!!!!
    i just tried and the signing is working fine!!!!
    i look forward to try the encryption! i

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    and this is the serial output:

    This key will be stored in EEPROM as AES key:
    #define MY_AES_KEY 0x6A,0x2B,0xF7,0xFB,0x03,0x8D,0x03,0x85,0x4D,0xDA,0x2D,0x89,0x9F,0xAD,0x8B,0x4F
    EEPROM configuration:
    SOFT_HMAC_KEY | 01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0BFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    SOFT_SERIAL   | 10FFFFFFFFFFFFFFFF
    AES_KEY       | 6AFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
    --------------------------------
    Personalization is now complete.
    
    
    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    yes of course!!!
    here is the sketch:

    #include "sha204_library.h"
    #include "sha204_lib_return_codes.h"
    #define MY_CORE_ONLY
    #include <MySensors.h>
    
    // Doxygen specific constructs, not included when built normally
    // This is used to enable disabled macros/definitions to be included in the documentation as well.
    #if DOXYGEN
    #define LOCK_CONFIGURATION
    #define LOCK_DATA
    #define SKIP_KEY_STORAGE
    #define USER_KEY
    #define SKIP_UART_CONFIRMATION
    #define USE_SOFT_SIGNING
    #define STORE_SOFT_KEY
    #define USER_SOFT_KEY
    #define STORE_SOFT_SERIAL
    #define USER_SOFT_SERIAL
    #define STORE_AES_KEY
    #define USER_AES_KEY
    #endif
    
    #define LOCK_CONFIGURATION
    
    
    //#define LOCK_DATA
    
    
    //#define SKIP_KEY_STORAGE
    
    
    //#define USER_KEY
    
    
    //#define SKIP_UART_CONFIRMATION
    
    
    #define USE_SOFT_SIGNING
    
    
    #define STORE_SOFT_KEY
    
    
    #define USER_SOFT_KEY
    
    
    #define STORE_SOFT_SERIAL
    
    
    #define USER_SOFT_SERIAL
    
    
    #define STORE_AES_KEY
    
    
    //#define USER_AES_KEY
    
    #if defined(SKIP_UART_CONFIRMATION) && !defined(USER_KEY)
    #error You have to define USER_KEY for boards that does not have UART
    #endif
    
    #ifdef USER_KEY
    /** @brief The user-defined HMAC key to use for personalization */
    #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
    /** @brief The data to store in key slot 0 */
    const uint8_t user_key_data[32] = {MY_HMAC_KEY};
    #endif
    
    #ifdef USER_SOFT_KEY
    /** @brief The user-defined soft HMAC key to use for EEPROM personalization */
    #define MY_SOFT_HMAC_KEY 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x010,0x11,0x12,0x13,0x14,0x15,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F,0xAA,0xAB,0xBA,0xBB,0xAC,0xAD,0xAE,0xEB,0xEC,0xED,0xDD
    /** @brief The data to store as soft HMAC key in EEPROM */
    const uint8_t user_soft_key_data[32] = {MY_SOFT_HMAC_KEY};
    #endif
    
    #ifdef USER_SOFT_SERIAL
    /** @brief The user-defined soft serial to use for EEPROM personalization */
    #define MY_SOFT_SERIAL 0x10,0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x02
    /** @brief The data to store as soft serial in EEPROM */
    const uint8_t user_soft_serial[9] = {MY_SOFT_SERIAL};
    #endif
    
    #ifdef USER_AES_KEY
    /** @brief The user-defined AES key to use for EEPROM personalization */
    #define MY_AES_KEY 0x15,0x14,0x13,0x12,0x11,0x10,0x09,0x08,0x07,0x06,0x05,0x05,0x04,0x03,0x14,0x15
    /** @brief The data to store as AES key in EEPROM */
    const uint8_t user_aes_key[16] = {MY_AES_KEY};
    #endif
    
    #ifndef USE_SOFT_SIGNING
    const int sha204Pin = MY_SIGNING_ATSHA204_PIN; //!< The IO pin to use for ATSHA204A
    atsha204Class sha204(sha204Pin);
    #endif
    
    /** @brief Print a error notice and halt the execution */
    void halt()
    {
    	Serial.println(F("Halting!"));
    	while(1);
    }
    
    #ifndef USE_SOFT_SIGNING
    
    uint16_t write_config_and_get_crc()
    {
    	uint16_t crc = 0;
    	uint8_t config_word[4];
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    	bool do_write;
    
    	
    	for (int i=0; i < 88; i += 4) {
    		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 {
    			// All other configs are untouched
    			ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Failed to read config. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    			// Set config_word to the read data
    			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;
    		}
    
    		// Update crc with CRC for the current word
    		crc = sha204.calculateAndUpdateCrc(4, config_word, crc);
    
    		// Write config word
    		if (do_write) {
    			ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_CONFIG,
    			                                  i >> 2, 4, config_word, 0, NULL, 0, NULL,
    			                                  WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Failed to write config word at address "));
    				Serial.print(i);
    				Serial.print(F(". Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    		}
    	}
    	return crc;
    }
    
    
    void write_key(uint8_t* key)
    {
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    
    	// Write key to slot 0
    	ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG,
    	                                  0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL,
    	                                  WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to write key to slot 0. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	}
    }
    #endif // not USE_SOFT_SIGNING
    
    /** @brief Dump current configuration to UART */
    void dump_configuration()
    {
    	uint8_t buffer[32];
    #ifndef USE_SOFT_SIGNING
    	Serial.println(F("EEPROM DATA:"));
    #endif
    	hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32);
    	Serial.print(F("SOFT_HMAC_KEY | "));
    	for (int j=0; j<32; j++) {
    		if (buffer[j] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(buffer[j], HEX);
    	}
    	Serial.println();
    	hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
    	Serial.print(F("SOFT_SERIAL   | "));
    	for (int j=0; j<9; j++) {
    		if (buffer[j] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(buffer[j], HEX);
    	}
    	Serial.println();
    	hwReadConfigBlock((void*)buffer, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
    	Serial.print(F("AES_KEY       | "));
    	for (int j=0; j<16; j++) {
    		if (buffer[j] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(buffer[j], HEX);
    	}
    	Serial.println();
    #ifndef USE_SOFT_SIGNING
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    	Serial.println(F("ATSHA204A DATA:"));
    	for (int i=0; i < 88; i += 4) {
    		ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i);
    		if (ret_code != SHA204_SUCCESS) {
    			Serial.print(F("Failed to read config. Response: "));
    			Serial.println(ret_code, HEX);
    			halt();
    		}
    		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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		}
    	}
    #endif // not USE_SOFT_SIGNING
    }
    
    /** @brief Sketch setup code */
    void setup()
    {
    	// Delay startup a bit for serial consoles to catch up
    	unsigned long enter = hwMillis();
    	while (hwMillis() - enter < (unsigned long)500);
    #ifndef USE_SOFT_SIGNING
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    	uint8_t lockConfig = 0;
    	uint8_t lockValue = 0;
    	uint16_t crc;
    	(void)crc;
    #else
    	// initialize pseudo-RNG
    	randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN));
    #endif
    	uint8_t key[32];
    	(void)key;
    
    	Serial.begin(9600);
    	hwInit();
    	Serial.println(F("Personalization sketch for MySensors usage."));
    	Serial.println(F("-------------------------------------------"));
    
    #ifndef USE_SOFT_SIGNING
    	// Wake device before starting operations
    	ret_code = sha204.sha204c_wakeup(rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to wake device. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	}
    	// Read out lock config bits to determine if locking is possible
    	ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to determine device lock status. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3];
    		lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2];
    	}
    #endif
    
    #ifdef STORE_SOFT_KEY
    #ifdef USER_SOFT_KEY
    	memcpy(key, user_soft_key_data, 32);
    	Serial.println(F("Using this user supplied soft HMAC key:"));
    #else
    	// Retrieve random value to use as soft HMAC key
    #ifdef USE_SOFT_SIGNING
    	for (int i = 0; i < 32; i++) {
    		key[i] = random(256) ^ micros();
    		unsigned long enter = hwMillis();
    		while (hwMillis() - enter < (unsigned long)2);
    	}
    	Serial.println(F("This value will be stored in EEPROM as soft HMAC key:"));
    #else
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random key generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("This value will be stored in EEPROM as soft HMAC key:"));
    	} else {
    		Serial.println(F("Key is not randomized (configuration not locked):"));
    	}
    #endif // not USE_SOFT_SIGNING
    #endif // not USER_SOFT_KEY
    	Serial.print("#define MY_SOFT_HMAC_KEY ");
    	for (int i=0; i<32; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 31) {
    			Serial.print(',');
    		}
    	}
    	Serial.println();
    	hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32);
    #endif // STORE_SOFT_KEY
    
    #ifdef STORE_SOFT_SERIAL
    #ifdef USER_SOFT_SERIAL
    	memcpy(key, user_soft_serial, 9);
    	Serial.println(F("Using this user supplied soft serial:"));
    #else
    	// Retrieve random value to use as serial
    #ifdef USE_SOFT_SIGNING
    	for (int i = 0; i < 9; i++) {
    		key[i] = random(256) ^ micros();
    		unsigned long enter = hwMillis();
    		while (hwMillis() - enter < (unsigned long)2);
    	}
    	Serial.println(F("This value will be stored in EEPROM as soft serial:"));
    #else
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random serial generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 9);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("This value will be stored in EEPROM as soft serial:"));
    	} else {
    		Serial.println(F("Serial is not randomized (configuration not locked):"));
    	}
    #endif // not USE_SOFT_SIGNING
    #endif // not USER_SOFT_SERIAL
    	Serial.print("#define MY_SOFT_SERIAL ");
    	for (int i=0; i<9; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 8) {
    			Serial.print(',');
    		}
    	}
    	Serial.println();
    	hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
    #endif // STORE_SOFT_SERIAL
    
    #ifdef STORE_AES_KEY
    #ifdef USER_AES_KEY
    	memcpy(key, user_aes_key, 16);
    	Serial.println(F("Using this user supplied AES key:"));
    #else
    	// Retrieve random value to use as key
    #ifdef USE_SOFT_SIGNING
    	for (int i = 0; i < 16; i++) {
    		key[i] = random(256) ^ micros();
    		unsigned long enter = hwMillis();
    		while (hwMillis() - enter < (unsigned long)2);
    	}
    	Serial.println(F("This key will be stored in EEPROM as AES key:"));
    #else
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random key generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("This key will be stored in EEPROM as AES key:"));
    	} else {
    		Serial.println(F("Key is not randomized (configuration not locked):"));
    	}
    #endif // not USE_SOFT_SIGNING
    #endif // not USER_AES_KEY
    	Serial.print("#define MY_AES_KEY ");
    	for (int i=0; i<16; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 15) {
    			Serial.print(',');
    		}
    	}
    	Serial.println();
    	hwWriteConfigBlock((void*)key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
    #endif // STORE_AES_KEY
    
    #ifdef USE_SOFT_SIGNING
    	Serial.println(F("EEPROM configuration:"));
    	dump_configuration();
    #else
    	// Output device revision on console
    	ret_code = sha204.sha204m_dev_rev(tx_buffer, rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to determine device revision. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		Serial.print(F("Device revision: "));
    		for (int i=0; i<4; i++) {
    			if (rx_buffer[SHA204_BUFFER_POS_DATA+i] < 0x10) {
    				Serial.print('0'); // Because Serial.print does not 0-pad HEX
    			}
    			Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+i], HEX);
    		}
    		Serial.println();
    	}
    
    	// Output serial number on console
    	ret_code = sha204.getSerialNumber(rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to obtain device serial number. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		Serial.print(F("Device serial:   "));
    		Serial.print('{');
    		for (int i=0; i<9; i++) {
    			Serial.print(F("0x"));
    			if (rx_buffer[i] < 0x10) {
    				Serial.print('0'); // Because Serial.print does not 0-pad HEX
    			}
    			Serial.print(rx_buffer[i], HEX);
    			if (i < 8) {
    				Serial.print(',');
    			}
    		}
    		Serial.print('}');
    		Serial.println();
    		for (int i=0; i<9; i++) {
    			if (rx_buffer[i] < 0x10) {
    				Serial.print('0'); // Because Serial.print does not 0-pad HEX
    			}
    			Serial.print(rx_buffer[i], HEX);
    		}
    		Serial.println();
    	}
    
    	if (lockConfig != 0x00) {
    		// Write config and get CRC for the updated config
    		crc = write_config_and_get_crc();
    
    		// List current configuration before attempting to lock
    		Serial.println(F("Chip configuration:"));
    		dump_configuration();
    
    #ifdef LOCK_CONFIGURATION
    		// Purge serial input buffer
    #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.println(F("Locking configuration..."));
    
    			// Correct sequence, resync chip
    			ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer);
    			if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) {
    				Serial.print(F("Resync failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    
    			// Lock configuration zone
    			ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_CONFIG,
    			                                  crc, 0, NULL, 0, NULL, 0, NULL,
    			                                  LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Configuration lock failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			} else {
    				Serial.println(F("Configuration locked."));
    
    				// Update lock flags after locking
    				ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
    				if (ret_code != SHA204_SUCCESS) {
    					Serial.print(F("Failed to determine device lock status. Response: "));
    					Serial.println(ret_code, HEX);
    					halt();
    				} 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 lock."));
    		}
    #endif //not SKIP_UART_CONFIRMATION
    #else //LOCK_CONFIGURATION
    		Serial.println(F("Configuration not locked. Define LOCK_CONFIGURATION to lock for real."));
    #endif
    	} else {
    		Serial.println(F("Skipping configuration write and lock (configuration already locked)."));
    		Serial.println(F("Chip configuration:"));
    		dump_configuration();
    	}
    
    #ifdef SKIP_KEY_STORAGE
    	Serial.println(F("Disable SKIP_KEY_STORAGE to store key."));
    #else
    #ifdef USER_KEY
    	memcpy(key, user_key_data, 32);
    	Serial.println(F("Using this user supplied HMAC key:"));
    #else
    	// Retrieve random value to use as key
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random key generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("Take note of this key, it will never be the shown again:"));
    	} else {
    		Serial.println(F("Key is not randomized (configuration not locked):"));
    	}
    #endif
    	Serial.print("#define MY_HMAC_KEY ");
    	for (int i=0; i<32; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 31) {
    			Serial.print(',');
    		}
    		if (i+1 == 16) {
    			Serial.print("\\\n                    ");
    		}
    	}
    	Serial.println();
    
    	// It will not be possible to write the key if the configuration zone is unlocked
    	if (lockConfig == 0x00) {
    		// Write the key to the appropriate slot in the data zone
    		Serial.println(F("Writing key to slot 0..."));
    		write_key(key);
    	} else {
    		Serial.println(F("Skipping key storage (configuration not locked)."));
    		Serial.println(F("The configuration must be locked to be able to write a key."));
    	}
    #endif
    
    	if (lockValue != 0x00) {
    #ifdef LOCK_DATA
    #ifndef SKIP_UART_CONFIRMATION
    		while (Serial.available()) {
    			Serial.read();
    		}
    		Serial.println(F("Send SPACE character to lock data..."));
    		while (Serial.available() == 0);
    		if (Serial.read() == ' ')
    #endif //not SKIP_UART_CONFIRMATION
    		{
    			// Correct sequence, resync chip
    			ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer);
    			if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) {
    				Serial.print(F("Resync failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    
    			// If configuration is unlocked, key is not updated. Locking data in this case will cause
    			// slot 0 to contain an unknown (or factory default) key, and this is in practically any
    			// usecase not the desired behaviour, so ask for additional confirmation in this case.
    			if (lockConfig != 0x00) {
    				while (Serial.available()) {
    					Serial.read();
    				}
    				Serial.println(F("*** ATTENTION ***"));
    				Serial.println(F("Configuration is not locked. Are you ABSULOUTELY SURE you want to lock data?"));
    				Serial.println(F("Locking data at this stage will cause slot 0 to contain a factory default key"));
    				Serial.println(
    				    F("which cannot be change after locking is done. This is in practically any usecase"));
    				Serial.println(F("NOT the desired behavour. Send SPACE character now to lock data anyway..."));
    				while (Serial.available() == 0);
    				if (Serial.read() != ' ') {
    					Serial.println(F("Unexpected answer. Skipping lock."));
    					halt();
    				}
    			}
    
    			// Lock data zone
    			ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_DATA | LOCK_ZONE_NO_CRC,
    			                                  0x0000, 0, NULL, 0, NULL, 0, NULL,
    			                                  LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Data lock failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			} else {
    				Serial.println(F("Data locked."));
    
    				// Update lock flags after locking
    				ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
    				if (ret_code != SHA204_SUCCESS) {
    					Serial.print(F("Failed to determine device lock status. Response: "));
    					Serial.println(ret_code, HEX);
    					halt();
    				} 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 lock."));
    		}
    #endif //not SKIP_UART_CONFIRMATION
    #else //LOCK_DATA
    		Serial.println(F("Data not locked. Define LOCK_DATA to lock for real."));
    #endif
    	} else {
    		Serial.println(F("Skipping OTP/data zone lock (zone already locked)."));
    	}
    #endif // not USE_SOFT_SIGNING
    
    	Serial.println(F("--------------------------------"));
    	Serial.println(F("Personalization is now complete."));
    #ifndef USE_SOFT_SIGNING
    	Serial.print(F("Configuration is "));
    	if (lockConfig == 0x00) {
    		Serial.println("LOCKED");
    	} else {
    		Serial.println("UNLOCKED");
    	}
    	Serial.print(F("Data is "));
    	if (lockValue == 0x00) {
    		Serial.println("LOCKED");
    	} else {
    		Serial.println("UNLOCKED");
    	}
    #endif
    }
    
    /** @brief Sketch execution code */
    void loop()
    {
    }
    
    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @tbowmo
    sorry can you say me please what i have to add to the sketch that will store my aes key on the sensebender gateway?
    I am a very very noob
    thanks

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    the troubles i have on sensebender gateway its a samd. On the micro (avr based) works fine.
    On the gateway i didnt upload a sketch between. I have uploaded the personalizer sketch and after them i tried the unmoded personalizer.

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    the interesting thing is when i upload the same sketch to the sensebender micro it works the AES Key will be stored correctly.
    But on the Sensebender Gateway only the first two digits

    Development security

  • [security] Introducing signing support to MySensors
    M meddie

    @Anticimex
    i checked the sketch already few times but i dont see an error.
    here is the code i have only change my key with XX

    
    
    #include "sha204_library.h"
    #include "sha204_lib_return_codes.h"
    #define MY_CORE_ONLY
    #include <MySensors.h>
    
    #if DOXYGEN
    #define LOCK_CONFIGURATION
    #define LOCK_DATA
    #define SKIP_KEY_STORAGE
    #define USER_KEY
    #define SKIP_UART_CONFIRMATION
    #define USE_SOFT_SIGNING
    #define STORE_SOFT_KEY
    #define USER_SOFT_KEY
    #define STORE_SOFT_SERIAL
    #define USER_SOFT_SERIAL
    #define STORE_AES_KEY
    #define USER_AES_KEY
    #endif
    
    #define LOCK_CONFIGURATION
    
    //#define LOCK_DATA
    
    //#define SKIP_KEY_STORAGE
    
    #define USER_KEY
    
    //#define SKIP_UART_CONFIRMATION
    
    //#define USE_SOFT_SIGNING
    
    //#define STORE_SOFT_KEY
    
    //#define USER_SOFT_KEY
    
    //#define STORE_SOFT_SERIAL
    
    //#define USER_SOFT_SERIAL
    
    #define STORE_AES_KEY
    
    #define USER_AES_KEY
    
    #if defined(SKIP_UART_CONFIRMATION) && !defined(USER_KEY)
    #error You have to define USER_KEY for boards that does not have UART
    #endif
    
    #ifdef USER_KEY
    /** @brief The user-defined HMAC key to use for personalization */
    #define MY_HMAC_KEY 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX
    /** @brief The data to store in key slot 0 */
    const uint8_t user_key_data[32] = {MY_HMAC_KEY};
    #endif
    
    #ifdef USER_SOFT_KEY
    /** @brief The user-defined soft HMAC key to use for EEPROM personalization */
    #define MY_SOFT_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
    /** @brief The data to store as soft HMAC key in EEPROM */
    const uint8_t user_soft_key_data[32] = {MY_SOFT_HMAC_KEY};
    #endif
    
    #ifdef USER_SOFT_SERIAL
    /** @brief The user-defined soft serial to use for EEPROM personalization */
    #define MY_SOFT_SERIAL 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
    /** @brief The data to store as soft serial in EEPROM */
    const uint8_t user_soft_serial[9] = {MY_SOFT_SERIAL};
    #endif
    
    #ifdef USER_AES_KEY
    /** @brief The user-defined AES key to use for EEPROM personalization */
    #define MY_AES_KEY 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX
    /** @brief The data to store as AES key in EEPROM */
    const uint8_t user_aes_key[16] = {MY_AES_KEY};
    #endif
    
    #ifndef USE_SOFT_SIGNING
    const int sha204Pin = MY_SIGNING_ATSHA204_PIN; //!< The IO pin to use for ATSHA204A
    atsha204Class sha204(sha204Pin);
    #endif
    
    /** @brief Print a error notice and halt the execution */
    void halt()
    {
    	Serial.println(F("Halting!"));
    	while(1);
    }
    
    #ifndef USE_SOFT_SIGNING
    
    uint16_t write_config_and_get_crc()
    {
    	uint16_t crc = 0;
    	uint8_t config_word[4];
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    	bool do_write;
    
    	for (int i=0; i < 88; i += 4) {
    		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 {
    			// All other configs are untouched
    			ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Failed to read config. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    			// Set config_word to the read data
    			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;
    		}
    
    		// Update crc with CRC for the current word
    		crc = sha204.calculateAndUpdateCrc(4, config_word, crc);
    
    		// Write config word
    		if (do_write) {
    			ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_CONFIG,
    			                                  i >> 2, 4, config_word, 0, NULL, 0, NULL,
    			                                  WRITE_COUNT_SHORT, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Failed to write config word at address "));
    				Serial.print(i);
    				Serial.print(F(". Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    		}
    	}
    	return crc;
    }
    
    /**
     * @brief Write provided key to slot 0
     * @param key The key data to write
     */
    void write_key(uint8_t* key)
    {
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    
    	// Write key to slot 0
    	ret_code = sha204.sha204m_execute(SHA204_WRITE, SHA204_ZONE_DATA | SHA204_ZONE_COUNT_FLAG,
    	                                  0, SHA204_ZONE_ACCESS_32, key, 0, NULL, 0, NULL,
    	                                  WRITE_COUNT_LONG, tx_buffer, WRITE_RSP_SIZE, rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to write key to slot 0. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	}
    }
    #endif // not USE_SOFT_SIGNING
    
    /** @brief Dump current configuration to UART */
    void dump_configuration()
    {
    	uint8_t buffer[32];
    #ifndef USE_SOFT_SIGNING
    	Serial.println(F("EEPROM DATA:"));
    #endif
    	hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32);
    	Serial.print(F("SOFT_HMAC_KEY | "));
    	for (int j=0; j<32; j++) {
    		if (buffer[j] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(buffer[j], HEX);
    	}
    	Serial.println();
    	hwReadConfigBlock((void*)buffer, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
    	Serial.print(F("SOFT_SERIAL   | "));
    	for (int j=0; j<9; j++) {
    		if (buffer[j] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(buffer[j], HEX);
    	}
    	Serial.println();
    	hwReadConfigBlock((void*)buffer, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
    	Serial.print(F("AES_KEY       | "));
    	for (int j=0; j<16; j++) {
    		if (buffer[j] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(buffer[j], HEX);
    	}
    	Serial.println();
    #ifndef USE_SOFT_SIGNING
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    	Serial.println(F("ATSHA204A DATA:"));
    	for (int i=0; i < 88; i += 4) {
    		ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, i);
    		if (ret_code != SHA204_SUCCESS) {
    			Serial.print(F("Failed to read config. Response: "));
    			Serial.println(ret_code, HEX);
    			halt();
    		}
    		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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j == 1) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				Serial.print(F("   "));
    			}
    			Serial.println();
    		} 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'); // Because Serial.print does not 0-pad HEX
    				}
    				Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+j], HEX);
    				if (j < 3) {
    					Serial.print(F(" | "));
    				} else {
    					Serial.print(F("   "));
    				}
    			}
    			Serial.println();
    		}
    	}
    #endif // not USE_SOFT_SIGNING
    }
    
    /** @brief Sketch setup code */
    void setup()
    {
    	// Delay startup a bit for serial consoles to catch up
    	unsigned long enter = hwMillis();
    	while (hwMillis() - enter < (unsigned long)500);
    #ifndef USE_SOFT_SIGNING
    	uint8_t tx_buffer[SHA204_CMD_SIZE_MAX];
    	uint8_t rx_buffer[SHA204_RSP_SIZE_MAX];
    	uint8_t ret_code;
    	uint8_t lockConfig = 0;
    	uint8_t lockValue = 0;
    	uint16_t crc;
    	(void)crc;
    #else
    	// initialize pseudo-RNG
    	randomSeed(analogRead(MY_SIGNING_SOFT_RANDOMSEED_PIN));
    #endif
    	uint8_t key[32];
    	(void)key;
    
      Serial.begin(9600);
    	hwInit();
    	Serial.println(F("Personalization sketch for MySensors usage."));
    	Serial.println(F("-------------------------------------------"));
    
    #ifndef USE_SOFT_SIGNING
    	// Wake device before starting operations
    	ret_code = sha204.sha204c_wakeup(rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to wake device. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	}
    	// Read out lock config bits to determine if locking is possible
    	ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to determine device lock status. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		lockConfig = rx_buffer[SHA204_BUFFER_POS_DATA+3];
    		lockValue = rx_buffer[SHA204_BUFFER_POS_DATA+2];
    	}
    #endif
    
    #ifdef STORE_SOFT_KEY
    #ifdef USER_SOFT_KEY
    	memcpy(key, user_soft_key_data, 32);
    	Serial.println(F("Using this user supplied soft HMAC key:"));
    #else
    	// Retrieve random value to use as soft HMAC key
    #ifdef USE_SOFT_SIGNING
    	for (int i = 0; i < 32; i++) {
    		key[i] = random(256) ^ micros();
    		unsigned long enter = hwMillis();
    		while (hwMillis() - enter < (unsigned long)2);
    	}
    	Serial.println(F("This value will be stored in EEPROM as soft HMAC key:"));
    #else
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random key generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("This value will be stored in EEPROM as soft HMAC key:"));
    	} else {
    		Serial.println(F("Key is not randomized (configuration not locked):"));
    	}
    #endif // not USE_SOFT_SIGNING
    #endif // not USER_SOFT_KEY
    	Serial.print("#define MY_SOFT_HMAC_KEY ");
    	for (int i=0; i<32; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 31) {
    			Serial.print(',');
    		}
    	}
    	Serial.println();
    	hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32);
    #endif // STORE_SOFT_KEY
    
    #ifdef STORE_SOFT_SERIAL
    #ifdef USER_SOFT_SERIAL
    	memcpy(key, user_soft_serial, 9);
    	Serial.println(F("Using this user supplied soft serial:"));
    #else
    	// Retrieve random value to use as serial
    #ifdef USE_SOFT_SIGNING
    	for (int i = 0; i < 9; i++) {
    		key[i] = random(256) ^ micros();
    		unsigned long enter = hwMillis();
    		while (hwMillis() - enter < (unsigned long)2);
    	}
    	Serial.println(F("This value will be stored in EEPROM as soft serial:"));
    #else
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random serial generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 9);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("This value will be stored in EEPROM as soft serial:"));
    	} else {
    		Serial.println(F("Serial is not randomized (configuration not locked):"));
    	}
    #endif // not USE_SOFT_SIGNING
    #endif // not USER_SOFT_SERIAL
    	Serial.print("#define MY_SOFT_SERIAL ");
    	for (int i=0; i<9; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 8) {
    			Serial.print(',');
    		}
    	}
    	Serial.println();
    	hwWriteConfigBlock((void*)key, (void*)EEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9);
    #endif // STORE_SOFT_SERIAL
    
    #ifdef STORE_AES_KEY
    #ifdef USER_AES_KEY
    	memcpy(key, user_aes_key, 16);
    	Serial.println(F("Using this user supplied AES key:"));
    #else
    	// Retrieve random value to use as key
    #ifdef USE_SOFT_SIGNING
    	for (int i = 0; i < 16; i++) {
    		key[i] = random(256) ^ micros();
    		unsigned long enter = hwMillis();
    		while (hwMillis() - enter < (unsigned long)2);
    	}
    	Serial.println(F("This key will be stored in EEPROM as AES key:"));
    #else
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random key generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("This key will be stored in EEPROM as AES key:"));
    	} else {
    		Serial.println(F("Key is not randomized (configuration not locked):"));
    	}
    #endif // not USE_SOFT_SIGNING
    #endif // not USER_AES_KEY
    	Serial.print("#define MY_AES_KEY ");
    	for (int i=0; i<16; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 15) {
    			Serial.print(',');
    		}
    	}
    	Serial.println();
    	hwWriteConfigBlock((void*)key, (void*)EEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16);
    #endif // STORE_AES_KEY
    
    #ifdef USE_SOFT_SIGNING
    	Serial.println(F("EEPROM configuration:"));
    	dump_configuration();
    #else
    	// Output device revision on console
    	ret_code = sha204.sha204m_dev_rev(tx_buffer, rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to determine device revision. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		Serial.print(F("Device revision: "));
    		for (int i=0; i<4; i++) {
    			if (rx_buffer[SHA204_BUFFER_POS_DATA+i] < 0x10) {
    				Serial.print('0'); // Because Serial.print does not 0-pad HEX
    			}
    			Serial.print(rx_buffer[SHA204_BUFFER_POS_DATA+i], HEX);
    		}
    		Serial.println();
    	}
    
    	// Output serial number on console
    	ret_code = sha204.getSerialNumber(rx_buffer);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Failed to obtain device serial number. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		Serial.print(F("Device serial:   "));
    		Serial.print('{');
    		for (int i=0; i<9; i++) {
    			Serial.print(F("0x"));
    			if (rx_buffer[i] < 0x10) {
    				Serial.print('0'); // Because Serial.print does not 0-pad HEX
    			}
    			Serial.print(rx_buffer[i], HEX);
    			if (i < 8) {
    				Serial.print(',');
    			}
    		}
    		Serial.print('}');
    		Serial.println();
    		for (int i=0; i<9; i++) {
    			if (rx_buffer[i] < 0x10) {
    				Serial.print('0'); // Because Serial.print does not 0-pad HEX
    			}
    			Serial.print(rx_buffer[i], HEX);
    		}
    		Serial.println();
    	}
    
    	if (lockConfig != 0x00) {
    		// Write config and get CRC for the updated config
    		crc = write_config_and_get_crc();
    
    		// List current configuration before attempting to lock
    		Serial.println(F("Chip configuration:"));
    		dump_configuration();
    
    #ifdef LOCK_CONFIGURATION
    		// Purge serial input buffer
    #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.println(F("Locking configuration..."));
    
    			// Correct sequence, resync chip
    			ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer);
    			if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) {
    				Serial.print(F("Resync failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    
    			// Lock configuration zone
    			ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_CONFIG,
    			                                  crc, 0, NULL, 0, NULL, 0, NULL,
    			                                  LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Configuration lock failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			} else {
    				Serial.println(F("Configuration locked."));
    
    				// Update lock flags after locking
    				ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
    				if (ret_code != SHA204_SUCCESS) {
    					Serial.print(F("Failed to determine device lock status. Response: "));
    					Serial.println(ret_code, HEX);
    					halt();
    				} 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 lock."));
    		}
    #endif //not SKIP_UART_CONFIRMATION
    #else //LOCK_CONFIGURATION
    		Serial.println(F("Configuration not locked. Define LOCK_CONFIGURATION to lock for real."));
    #endif
    	} else {
    		Serial.println(F("Skipping configuration write and lock (configuration already locked)."));
    		Serial.println(F("Chip configuration:"));
    		dump_configuration();
    	}
    
    #ifdef SKIP_KEY_STORAGE
    	Serial.println(F("Disable SKIP_KEY_STORAGE to store key."));
    #else
    #ifdef USER_KEY
    	memcpy(key, user_key_data, 32);
    	Serial.println(F("Using this user supplied HMAC key:"));
    #else
    	// Retrieve random value to use as key
    	ret_code = sha204.sha204m_random(tx_buffer, rx_buffer, RANDOM_SEED_UPDATE);
    	if (ret_code != SHA204_SUCCESS) {
    		Serial.print(F("Random key generation failed. Response: "));
    		Serial.println(ret_code, HEX);
    		halt();
    	} else {
    		memcpy(key, rx_buffer+SHA204_BUFFER_POS_DATA, 32);
    	}
    	if (lockConfig == 0x00) {
    		Serial.println(F("Take note of this key, it will never be the shown again:"));
    	} else {
    		Serial.println(F("Key is not randomized (configuration not locked):"));
    	}
    #endif
    	Serial.print("#define MY_HMAC_KEY ");
    	for (int i=0; i<32; i++) {
    		Serial.print("0x");
    		if (key[i] < 0x10) {
    			Serial.print('0'); // Because Serial.print does not 0-pad HEX
    		}
    		Serial.print(key[i], HEX);
    		if (i < 31) {
    			Serial.print(',');
    		}
    		if (i+1 == 16) {
    			Serial.print("\\\n                    ");
    		}
    	}
    	Serial.println();
    
    	// It will not be possible to write the key if the configuration zone is unlocked
    	if (lockConfig == 0x00) {
    		// Write the key to the appropriate slot in the data zone
    		Serial.println(F("Writing key to slot 0..."));
    		write_key(key);
    	} else {
    		Serial.println(F("Skipping key storage (configuration not locked)."));
    		Serial.println(F("The configuration must be locked to be able to write a key."));
    	}
    #endif
    
    	if (lockValue != 0x00) {
    #ifdef LOCK_DATA
    #ifndef SKIP_UART_CONFIRMATION
    		while (Serial.available()) {
    			Serial.read();
    		}
    		Serial.println(F("Send SPACE character to lock data..."));
    		while (Serial.available() == 0);
    		if (Serial.read() == ' ')
    #endif //not SKIP_UART_CONFIRMATION
    		{
    			// Correct sequence, resync chip
    			ret_code = sha204.sha204c_resync(SHA204_RSP_SIZE_MAX, rx_buffer);
    			if (ret_code != SHA204_SUCCESS && ret_code != SHA204_RESYNC_WITH_WAKEUP) {
    				Serial.print(F("Resync failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			}
    
    			// If configuration is unlocked, key is not updated. Locking data in this case will cause
    			// slot 0 to contain an unknown (or factory default) key, and this is in practically any
    			// usecase not the desired behaviour, so ask for additional confirmation in this case.
    			if (lockConfig != 0x00) {
    				while (Serial.available()) {
    					Serial.read();
    				}
    				Serial.println(F("*** ATTENTION ***"));
    				Serial.println(F("Configuration is not locked. Are you ABSULOUTELY SURE you want to lock data?"));
    				Serial.println(F("Locking data at this stage will cause slot 0 to contain a factory default key"));
    				Serial.println(
    				    F("which cannot be change after locking is done. This is in practically any usecase"));
    				Serial.println(F("NOT the desired behavour. Send SPACE character now to lock data anyway..."));
    				while (Serial.available() == 0);
    				if (Serial.read() != ' ') {
    					Serial.println(F("Unexpected answer. Skipping lock."));
    					halt();
    				}
    			}
    
    			// Lock data zone
    			ret_code = sha204.sha204m_execute(SHA204_LOCK, SHA204_ZONE_DATA | LOCK_ZONE_NO_CRC,
    			                                  0x0000, 0, NULL, 0, NULL, 0, NULL,
    			                                  LOCK_COUNT, tx_buffer, LOCK_RSP_SIZE, rx_buffer);
    			if (ret_code != SHA204_SUCCESS) {
    				Serial.print(F("Data lock failed. Response: "));
    				Serial.println(ret_code, HEX);
    				halt();
    			} else {
    				Serial.println(F("Data locked."));
    
    				// Update lock flags after locking
    				ret_code = sha204.sha204m_read(tx_buffer, rx_buffer, SHA204_ZONE_CONFIG, 0x15<<2);
    				if (ret_code != SHA204_SUCCESS) {
    					Serial.print(F("Failed to determine device lock status. Response: "));
    					Serial.println(ret_code, HEX);
    					halt();
    				} 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 lock."));
    		}
    #endif //not SKIP_UART_CONFIRMATION
    #else //LOCK_DATA
    		Serial.println(F("Data not locked. Define LOCK_DATA to lock for real."));
    #endif
    	} else {
    		Serial.println(F("Skipping OTP/data zone lock (zone already locked)."));
    	}
    #endif // not USE_SOFT_SIGNING
    
    	Serial.println(F("--------------------------------"));
    	Serial.println(F("Personalization is now complete."));
    #ifndef USE_SOFT_SIGNING
    	Serial.print(F("Configuration is "));
    	if (lockConfig == 0x00) {
    		Serial.println("LOCKED");
    	} else {
    		Serial.println("UNLOCKED");
    	}
    	Serial.print(F("Data is "));
    	if (lockValue == 0x00) {
    		Serial.println("LOCKED");
    	} else {
    		Serial.println("UNLOCKED");
    	}
    #endif
    }
    
    /** @brief Sketch execution code */
    void loop()
    {
    }```
    Development security
  • Login

  • Don't have an account? Register

  • Login or register to search.
  • First post
    Last post
0
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular