uint8_t atsha204Class::sha204c_wakeup(uint8_t *response)
{
    uint8_t ret_code = sha204p_wakeup();
    if (ret_code != SHA204_SUCCESS)
        return ret_code;

    ret_code = sha204p_receive_response(SHA204_RSP_SIZE_MIN, response);
    if (ret_code != SHA204_SUCCESS)
        return ret_code;

    // Verify status response.
    Serial.print("Buffer pos: ");
    Serial.println(response[SHA204_BUFFER_POS_COUNT]);
    if (response[SHA204_BUFFER_POS_COUNT] != SHA204_RSP_SIZE_MIN)
        ret_code = SHA204_INVALID_SIZE;
    else if (response[SHA204_BUFFER_POS_STATUS] != SHA204_STATUS_BYTE_WAKEUP)
        ret_code = SHA204_COMM_FAIL;
    else
    {
        if ((response[SHA204_RSP_SIZE_MIN - SHA204_CRC_SIZE] != 0x33)
                || (response[SHA204_RSP_SIZE_MIN + 1 - SHA204_CRC_SIZE] != 0x43))
            ret_code = SHA204_BAD_CRC;
    }
    if (ret_code != SHA204_SUCCESS)
        delay(SHA204_COMMAND_EXEC_MAX);

    return ret_code;
}
/** \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;
}
Exemple #3
0
/**
 * \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
	}
}
Exemple #4
0
uint8_t encrypted_read(int fd, uint16_t key_id, uint8_t *key_value,uint16_t slot, uint8_t *readdata) {
	int i;
	static uint8_t status = SHA204_SUCCESS;
	static uint8_t tmpdata[0x20] = {0};
	static uint8_t random_number[0x20] = {0};		// Random number returned by Random NONCE command
	static uint8_t computed_response[0x20] = {0};	// Host computed expected response

	struct sha204h_decrypt_in_out decrypt_param;	// Parameter for decrypt helper function
	struct sha204h_nonce_in_out nonce_param;		// Parameter for nonce helper function
	struct sha204h_gen_dig_in_out gendig_param;	// Parameter for gen_dig helper function
	struct sha204h_temp_key computed_tempkey;		// TempKey parameter for nonce and gen_dig helper function

	//add by jli :That before every executing  cmd sent to ATSHA204 chip  should have waked it up once!
	sha204p_wakeup(fd);
	
	printf("ATSHA204A encrypted read  !\n");
	//nonce operation
	cmd_args.op_code = SHA204_NONCE;
	cmd_args.param_1 = NONCE_MODE_SEED_UPDATE;
	cmd_args.param_2 = NONCE_PARAM2;
	cmd_args.data_len_1 = NONCE_NUMIN_SIZE;
	cmd_args.data_1 = read_num_in;
	cmd_args.data_len_2 = 0;
	cmd_args.data_2 = NULL;
	cmd_args.data_len_3 = 0;
	cmd_args.data_3 = NULL;
	cmd_args.tx_size = NONCE_COUNT_SHORT;			
	cmd_args.tx_buffer = global_tx_buffer;
	cmd_args.rx_size = NONCE_RSP_SIZE_LONG;			 
	cmd_args.rx_buffer = global_rx_buffer;
	status = sha204m_execute(fd,&cmd_args);
	//sha204p_idle(fd);
	if(status != SHA204_SUCCESS) { printf(" Mathine NONCE  FAILED! \n"); return -1; }
	// Capture the random number from the NONCE command if it were successful
	memcpy(random_number,&global_rx_buffer[1],0x20);

	//host nonce operation
	nonce_param.mode = NONCE_MODE_SEED_UPDATE;
	nonce_param.num_in = read_num_in;
	nonce_param.rand_out = random_number;
	nonce_param.temp_key = &computed_tempkey;
	status = sha204h_nonce(nonce_param);
	if(status != SHA204_SUCCESS) { printf("HOST   NONCE  FAILED! \n"); return -1; }
	
	//gendig operation
	cmd_args.op_code = SHA204_GENDIG;
	cmd_args.param_1 = GENDIG_ZONE_DATA;
	cmd_args.param_2 = key_id;
	cmd_args.data_len_1 = 0; 
	cmd_args.data_1 = NULL;
	cmd_args.data_len_2 = 0;
	cmd_args.data_2 = NULL;
	cmd_args.data_len_3 = 0;
	cmd_args.data_3 = NULL;
	cmd_args.tx_size = SHA204_CMD_SIZE_MIN;
	cmd_args.tx_buffer = global_tx_buffer;
	cmd_args.rx_size = GENDIG_RSP_SIZE;
	cmd_args.rx_buffer = global_rx_buffer;
	status = sha204m_execute(fd,&cmd_args);
	//sha204p_sleep(fd);
	if(status != SHA204_SUCCESS) { printf("Mathine  GENGID  FAILED! \n"); return -1; }
	
	//Host gengid operation
	memcpy(tmpdata,key_value,0x20);	
	gendig_param.zone = GENDIG_ZONE_DATA;
	gendig_param.key_id = key_id;
	gendig_param.stored_value = tmpdata;
	gendig_param.temp_key = &computed_tempkey;
	status = sha204h_gen_dig(gendig_param);
	if(status != SHA204_SUCCESS) { printf("HOST   GENDIG  FAILED! \n"); return -1; }

	//Read operation
	cmd_args.op_code = SHA204_READ;
	cmd_args.param_1 = SHA204_ZONE_DATA|SHA204_ZONE_COUNT_FLAG;
	cmd_args.param_2 =  (uint16_t)(slot * 8);
	cmd_args.data_len_1 = 0;
	cmd_args.data_1 = NULL;
	cmd_args.data_len_2 = 0;
	cmd_args.data_2 = NULL;
	cmd_args.data_len_3 = 0;
	cmd_args.data_3 = NULL;
	cmd_args.tx_size = 0x30;
	cmd_args.tx_buffer = global_tx_buffer;
	cmd_args.rx_size = 0x30;
	cmd_args.rx_buffer = global_rx_buffer;
	//sha204p_wakeup(fd);	
	status = sha204m_execute(fd,&cmd_args);
	//sha204p_sleep(fd);
	memcpy(tmpdata,&global_rx_buffer[1],0x20);
	if(status != SHA204_SUCCESS) { printf("FAILED! e_read_data\n"); return -1 ; }

	decrypt_param.data = tmpdata;
	decrypt_param.temp_key = &computed_tempkey;
	status = sha204h_decrypt(decrypt_param);
	if(status != SHA204_SUCCESS) { printf("HOST   DECRYPT  FAILED! \n"); return -1; }
	memcpy(readdata,tmpdata,0x20);
	return status;
}
void random_challenge_response_authentication(int fd, uint16_t key_id, uint8_t *secret_key_value) {
	
	static uint8_t status = SHA204_SUCCESS;
	static uint8_t random_number[0x20] = {0};		// Random number returned by Random NONCE command
	static uint8_t computed_response[0x20] = {0};	// Host computed expected response
	static uint8_t atsha204_response[0x20] = {0};	// Actual response received from the ATSHA204 device
	struct sha204h_nonce_in_out nonce_param;		// Parameter for nonce helper function
	struct sha204h_mac_in_out mac_param;			// Parameter for mac helper function
	struct sha204h_temp_key computed_tempkey;		// TempKey parameter for nonce and mac helper function

	//add by jli :That before every executing  cmd sent to ATSHA204 chip  should have waked it up once!
	sha204p_wakeup(fd);
	
	printf("Random Chal_Response r\n");
	
	// Notes: 
	// 1.	Random Challenge-Response involves the use of a random
	//		challenge for EVERY authentication process. A host with a good
	//		source of random number generation can simply ensure the challenge
	//		is random while making a simple MAC command call.  
	//
	// 2.	A host without a good random generator may be tempted to use the
	//		ATSHA204 random command to obtain a random number from the device.
	//		While the random number obtained through this process is of the 
	//		highest quality, the process is susceptible to man-in-the-middle
	//		attack, whereby the attacker simply intercepts the random number
	//		and sent the host a non-random number.
	//
	// 3.	Host systems without good random number generators and wanting to
	//		avoid the susceptibility to man-in-the-middle attack described in
	//		note #2 above can use the authentication process involving the
	//		ATSHA204 NONCE command in Random Mode.  The NONCE command guarantees
	//		an internal random state within the ATSHA204 device that is virtually
	//		impossible to fake.  This is the process exemplified in this exercise.
	
	
	// *** STEP 1:	ISSUE A NONCE WITH NO EEPROM SEED UPDATE ***
	// 
	//				The NONCE command generates an internal random state
	//				in the ATSHA204 device. Note that the actual random NONCE is 
	//				a value computed using an internally generated random number
	//				and other device parameters.  The NONCE command emits this
	//				random value for the host to use for host side computation of
	//				an equivalent NONCE.  Capture this random number and keep for
	//				use with computing the equivalent NONCE on the host side.
	
	// Issue the NONCE command
	cmd_args.op_code = SHA204_NONCE;
	cmd_args.param_1 = NONCE_MODE_NO_SEED_UPDATE;
	cmd_args.param_2 = NONCE_PARAM2;
	cmd_args.data_len_1 = NONCE_NUMIN_SIZE;
	cmd_args.data_1 = num_in;
	cmd_args.data_len_2 = 0;
	cmd_args.data_2 = NULL;
	cmd_args.data_len_3 = 0;
	cmd_args.data_3 = NULL;
	cmd_args.tx_size = NONCE_COUNT_SHORT;			
	cmd_args.tx_buffer = global_tx_buffer;
	cmd_args.rx_size = NONCE_RSP_SIZE_LONG;			 
	cmd_args.rx_buffer = global_rx_buffer;
	status = sha204m_execute(fd,&cmd_args);
	//sha204p_idle(fd);
	if(status != SHA204_SUCCESS) { printf(" Mathine NONCE  FAILED! \n"); return; }
	
	// Capture the random number from the NONCE command if it were successful
	memcpy(random_number,&global_rx_buffer[1],0x20);
	
	// *** STEP 2:	COMPUTE THE EQUIVALENT NONCE ON THE HOST SIDE
	//
	//				Go the easy way using the host helper functions provided with 
	//				the ATSHA204 library.
	
	nonce_param.mode = NONCE_MODE_NO_SEED_UPDATE;
	nonce_param.num_in = num_in;
	nonce_param.rand_out = random_number;
	nonce_param.temp_key = &computed_tempkey;
	status = sha204h_nonce(nonce_param);
	if(status != SHA204_SUCCESS) { printf("HOST   NONCE  FAILED! \n"); return; }

	
	// *** STEP 3:	ISSUE THE MAC COMMAND
	//
	//				Starting from a randomized internal state of the ATSHA204 device
	//				guarantees that this MAC command call is executing a random
	//				challenge-response authentication. 
	
	// Issue the MAC command
	cmd_args.op_code = SHA204_MAC;
	cmd_args.param_1 = MAC_MODE_BLOCK2_TEMPKEY;
	cmd_args.param_2 = key_id;
	cmd_args.data_len_1 = 0; 
	cmd_args.data_1 = NULL;
	cmd_args.data_len_2 = 0;
	cmd_args.data_2 = NULL;
	cmd_args.data_len_3 = 0;
	cmd_args.data_3 = NULL;
	cmd_args.tx_size = MAC_COUNT_SHORT;
	cmd_args.tx_buffer = global_tx_buffer;
	cmd_args.rx_size = MAC_RSP_SIZE;
	cmd_args.rx_buffer = global_rx_buffer;
	status = sha204m_execute(fd,&cmd_args);
	//sha204p_sleep(fd);
	if(status != SHA204_SUCCESS) { printf("Mathine  MACFAILED! \n"); return; }
	
	// Capture actual response from the ATSHA204 device
	memcpy(atsha204_response,&global_rx_buffer[1],0x20);
	
	
	// *** STEP 4:	DYNAMICALLY VALIDATE THE (MAC) RESPONSE
	//				
	//				Note that this requires knowledge of the actual secret key
	//				value.
	
	mac_param.mode = MAC_MODE_BLOCK2_TEMPKEY;
	mac_param.key_id = key_id;
	mac_param.challenge = NULL;
	mac_param.key = secret_key_value;
	mac_param.otp = NULL;
	mac_param.sn = NULL;
	mac_param.response = computed_response;
	mac_param.temp_key = &computed_tempkey;
	status = sha204h_mac(mac_param);
	if(status != SHA204_SUCCESS) { printf("HOST   MAC  FAILED! \n"); return; }
	
	
	// Moment of truth: Compare the received response with the dynamically computed expected response.
	status = memcmp(computed_response,atsha204_response,0x20);
	if ( !status ) {	
		printf("Authentication  SUCCESS!\n");
	} else {
		 printf("Authentication   FAILED! \n"); 
		 return; 
	}
	
	return;
}