/** \brief This function puts all devices to sleep. */ void sha204_sleep_all(void) { uint8_t i; for (i = 1; i < SHA204_DEVICE_COUNT; i++) { sha204p_set_device_id(sha204_i2c_address(i)); // Send Sleep command. sha204p_sleep(); } }
/** \brief This function is the entry function for an example application that uses the SHA204 ASF component. * \return result (0: success, otherwise failure) */ int main(void) { static uint8_t tx_buffer_command[CHECKMAC_COUNT]; // biggest command in this example static uint8_t rx_buffer[SHA204_RSP_SIZE_MAX]; static uint8_t challenge[MAC_CHALLENGE_SIZE]; static uint8_t other_data[CHECKMAC_OTHER_DATA_SIZE]; uint8_t sha204_lib_return = SHA204_SUCCESS; uint32_t loop_count = 0; uint8_t i2c_address_index = 0; uint8_t twi_address_client; uint8_t twi_address_host; // Initialize system clock. sysclk_init(); // Initialize board. board_init(); // Initialize logging (USART). log_init(); // Initialize interrupt vectors. irq_initialize_vectors(); // Send example info. log_sha204_title("ATSHA204 Mac / CheckMac Example\r\n"); // Indicate entering main loop. led_display_number(0xFF); sha204h_delay_ms(1000); // The main loop wakes up all four devices, sends a Mac command to one serving // as a client, and subsequently a CheckMac command with the Mac challenge and response data // to another SHA204 serving as a host. At the end of the loop, all four devices // are put back to sleep by sending a Sleep command to every one of them. while (true) { // Indicate success or error for some time. led_display_number(sha204_lib_return); sha204h_delay_ms(1000); log_sha204_title("----------------------"); sprintf((char *) tx_buffer_command, "loop count = %lu", loop_count++); log_sha204_title((char *) tx_buffer_command); // Indicate that Mac / CheckMac command sequence is running. led_display_number(0xFF); // Generate Wakeup pulse. All SHA204 devices that share SDA will wake up. log_sha204_title("generating 60 us Wakeup low pulse on TWI SDA"); sha204_lib_return = sha204p_wakeup(); if (sha204_lib_return != SHA204_SUCCESS) { // todo Indicate Wakeup failure. continue; } // Exercise all four devices. twi_address_client = sha204_i2c_address(i2c_address_index % 4); i2c_address_index++; twi_address_host = sha204_i2c_address(i2c_address_index % 4); i2c_address_index++; // --------------------------------------------------------------------------------- // Now let's send a Mac to one SHA204, and verify the generated Mac with a second // SHA204 serving as a host device. In this example, we are not using the Nonce // command but the least secure and simplest mode. // Let host generate a random number to use as Mac challenge. An unlocked SHA204 // will always generate "FFFF0000FFFF0000...". struct sha204_random_parameters random; random.mode = 0; random.tx_buffer = tx_buffer_command; random.rx_buffer = rx_buffer; sha204p_set_device_id(twi_address_host); log_sha204_title("sending Random command to host"); sha204_lib_return = sha204m_random(&random); log_sha204(random.tx_buffer[SHA204_COUNT_IDX], random.tx_buffer, false); if (sha204_lib_return != SHA204_SUCCESS) { sha204_sleep_all(); continue; } log_sha204(random.rx_buffer[SHA204_COUNT_IDX], random.rx_buffer, true); // Save challenge for subsequent CheckMac command. memcpy(challenge, &random.rx_buffer[SHA204_BUFFER_POS_DATA], sizeof(challenge)); // Send Mac command to client. struct sha204_mac_parameters mac; mac.mode = 0; mac.key_id = 0; mac.challenge = challenge; mac.tx_buffer = tx_buffer_command; mac.rx_buffer = rx_buffer; sha204p_set_device_id(twi_address_client); log_sha204_title("sending Mac command to client"); sha204_lib_return = sha204m_mac(&mac); log_sha204(mac.tx_buffer[SHA204_COUNT_IDX], mac.tx_buffer, false); if (sha204_lib_return != SHA204_SUCCESS) { sha204_sleep_all(); continue; } log_sha204(mac.rx_buffer[SHA204_COUNT_IDX], mac.rx_buffer, true); // Save first four bytes of Mac command for subsequent CheckMac command. memset(other_data, 0, CHECKMAC_OTHER_DATA_SIZE); memcpy(other_data, &tx_buffer_command[SHA204_OPCODE_IDX], CHECKMAC_CLIENT_COMMAND_SIZE); // Send CheckMac command to host. struct sha204_check_mac_parameters check_mac; check_mac.mode = 0; check_mac.key_id = 0; check_mac.client_challenge = challenge; check_mac.client_response = &rx_buffer[SHA204_BUFFER_POS_DATA]; check_mac.other_data = other_data; check_mac.tx_buffer = tx_buffer_command; check_mac.rx_buffer = rx_buffer; sha204p_set_device_id(twi_address_host); log_sha204_title("sending CheckMac command to host"); sha204_lib_return = sha204m_check_mac(&check_mac); log_sha204(check_mac.tx_buffer[SHA204_COUNT_IDX], check_mac.tx_buffer, false); if (sha204_lib_return != SHA204_SUCCESS) { sha204_sleep_all(); continue; } log_sha204(check_mac.rx_buffer[SHA204_COUNT_IDX], check_mac.rx_buffer, true); log_sha204_title("sending a Sleep command to all devices"); sha204_sleep_all(); // Display response status byte. sha204_lib_return = check_mac.rx_buffer[SHA204_BUFFER_POS_STATUS]; } return sha204_lib_return; }
/** * \brief This function runs a SHA204 Read test on all four devices. * * This test wakes up the devices, reads their TWI addresses from * their Config zone, and sends them back to sleep. The test fails if * there are communication failures or the TWI addresses do not match. * * \param test current test case */ static void test_all_devices(const struct test_case *test) { test_assert_true(test, success, "Previous test failed."); success = false; uint8_t sha204_status; uint8_t i; uint8_t twi_address; uint8_t twi_address_retrieved = 0; uint8_t command[READ_COUNT]; uint8_t response[READ_4_RSP_SIZE]; sha204_status = sha204p_wakeup(); test_assert_true(test, sha204_status == SHA204_SUCCESS, "Sending Wakeup token failed."); // Address 16 holds the TWI address. struct sha204_read_parameters args = {.tx_buffer = command, .rx_buffer = response, .zone = SHA204_ZONE_CONFIG, .address = 16}; // Read TWI address from all four devices that are mounted on the Security Xplained extension board. for (i = 0; i < SHA204_DEVICE_COUNT; i++) { twi_address = sha204_i2c_address(i); sha204p_set_device_id(twi_address); memset(response, 0, sizeof(response)); success = false; sha204_status = sha204m_read(&args); if (sha204_status != SHA204_SUCCESS) break; twi_address_retrieved = args.rx_buffer[SHA204_BUFFER_POS_DATA] & 0xFE; if (twi_address_retrieved != twi_address) break; sha204_status = sha204p_sleep(); if (sha204_status != SHA204_SUCCESS) break; success = true; } // Sleep remaining devices in case one of them failed. for (; i < SHA204_DEVICE_COUNT; i++) { twi_address = sha204_i2c_address(i); sha204p_set_device_id(twi_address); sha204p_sleep(); } test_assert_true(test, sha204_status == SHA204_SUCCESS, "Communication error."); test_assert_true(test, twi_address_retrieved == twi_address, "TWI address does not match."); success = true; } //! \name Unit test configuration //@{ /** * \def CONF_TEST_USART * \brief USART to redirect STDIO to */ /** * \def CONF_TEST_BAUDRATE * \brief Baudrate of USART */ /** * \def CONF_TEST_CHARLENGTH * \brief Character length (bits) of USART */ /** * \def CONF_TEST_PARITY * \brief Parity mode of USART */ /** * \def CONF_TEST_STOPBITS * \brief Stop bit configuration of USART */ //@} /** * \brief This function runs ATSHA204 component unit tests. */ int main (void) { const usart_serial_options_t usart_serial_options = { .baudrate = CONF_TEST_BAUDRATE, .charlength = CONF_TEST_CHARLENGTH, .paritytype = CONF_TEST_PARITY, .stopbits = CONF_TEST_STOPBITS, }; sysclk_init(); board_init(); pmic_init(); sleepmgr_init(); stdio_serial_init(CONF_TEST_USART, &usart_serial_options); // Enable low level interrupts pmic_enable_level(PMIC_LVL_LOW); // Enable interrupt requests cpu_irq_enable(); // Define all the test cases DEFINE_TEST_CASE(sha204_test1, NULL, test_sha204_wakeup, NULL, "Testing Wakeup / Sleep"); DEFINE_TEST_CASE(sha204_test2, NULL, test_all_devices, NULL, "Testing all devices"); // Put test case addresses in an array DEFINE_TEST_ARRAY(sha204_tests) = { &sha204_test1, &sha204_test2 }; // Define the test suite DEFINE_TEST_SUITE(sha204_suite, sha204_tests, "XMEGA ATSHA204 component test suite"); // Run all tests in the test suite test_suite_run(&sha204_suite); while (1) { // Loop for infinity } }