static void gzp_process_encrypted_user_data(uint8_t* rx_payload, uint8_t length) { uint8_t tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH]; if(gzp_id_req_received()) { gzp_crypt_select_key(GZP_ID_EXCHANGE); } else { gzp_crypt_select_key(GZP_DATA_EXCHANGE); } gzp_crypt(&rx_payload[1], &rx_payload[1], length - 1); if(gzp_validate_id(&rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID])) { gzp_encrypted_user_data_length = length - GZP_USER_DATA_PACKET_OVERHEAD; memcpy((void*)gzp_encrypted_user_data, &rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], gzp_encrypted_user_data_length); } // Build response packet tx_payload[0] = GZP_CMD_ENCRYPTED_USER_DATA_RESP; gzp_add_validation_id(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]); gzp_crypt(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], &tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID], GZP_VALIDATION_ID_LENGTH); gzp_get_session_counter(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]); // Update "session token" only if no ID request is pending if(!gzp_id_req_received()) { gzp_crypt_set_session_token(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]); } gzp_preload_ack(tx_payload, GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE); }
static void gzp_process_id_req(uint8_t* rx_payload) { uint8_t temp_host_id[GZP_HOST_ID_LENGTH]; if(gzp_pairing_enabled_f) { if(!gzp_id_req_received()) { gzp_crypt_set_session_token(&rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]); gzp_id_req_stat = GZP_ID_REQ_PENDING; } // If host ID not generated yet if(!gzp_get_host_id(temp_host_id)) { // Generate new host ID from "session counter" and received "session token" gzp_get_session_counter(temp_host_id); if(GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH) { gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH); } else { gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_HOST_ID_LENGTH); } gzp_set_host_id(temp_host_id); } } }
static void gzp_process_id_fetch(uint8_t* rx_payload) { uint8_t tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH]; if(gzp_id_req_received()) { gzp_crypt_select_key(GZP_ID_EXCHANGE); gzp_crypt(&rx_payload[1], &rx_payload[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1); if(gzp_validate_id(&rx_payload[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID])) { switch(gzp_id_req_stat) { case GZP_ID_REQ_PENDING_AND_GRANTED: tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = GZP_ID_RESP_GRANTED; gzp_get_host_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]); gzp_id_req_stat = GZP_ID_REQ_IDLE; break; case GZP_ID_REQ_PENDING_AND_REJECTED: tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = GZP_ID_RESP_REJECTED; gzp_id_req_stat = GZP_ID_REQ_IDLE; break; case GZP_ID_REQ_PENDING: default: tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = GZP_ID_RESP_PENDING; break; } tx_payload[0] = GZP_CMD_HOST_ID_FETCH_RESP; gzp_add_validation_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]); gzp_crypt(&tx_payload[1], &tx_payload[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1); gzp_preload_ack(tx_payload, GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE); } } }
void gzp_id_req_cancel() { if(gzp_id_req_received()) { gzp_id_req_stat = GZP_ID_REQ_IDLE; } }
void gzp_id_req_grant() { if(gzp_id_req_received()) { gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_GRANTED; } }
void gzp_id_req_reject() { if(gzp_id_req_received()) { gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_REJECTED; } }
int main(void) { // Debug helper variables uint32_t length; // Data and acknowledgement payloads uint8_t payload[NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH]; ///< Payload to send to Host. // Setup user interface (buttons and LEDs) ui_init(); // Initialize Gazell Link Layer (void)nrf_gzll_init(NRF_GZLL_MODE_HOST); (void)nrf_gzll_set_timeslot_period(NRF_GZLLDE_RXPERIOD_DIV_2); // Half RX period on nRF24Lxx device // Initialize Gazell Pairing Library gzp_init(); (void)nrf_gzll_set_rx_pipes_enabled(nrf_gzll_get_rx_pipes_enabled() | (1 << UNENCRYPTED_DATA_PIPE)); gzp_pairing_enable(true); (void)nrf_gzll_enable(); for(;;) { gzp_host_execute(); // If Host ID request received if(gzp_id_req_received()) { // Always grant request gzp_id_req_grant(); } length = NRF_GZLL_CONST_MAX_PAYLOAD_LENGTH; if( nrf_gzll_get_rx_fifo_packet_count(UNENCRYPTED_DATA_PIPE) ) { if(nrf_gzll_fetch_packet_from_rx_fifo(UNENCRYPTED_DATA_PIPE, payload, &length)) { output_present(payload[0]); } } else if (gzp_crypt_user_data_received()) { if(gzp_crypt_user_data_read(payload, (uint8_t*)&length)) { output_present(payload[0]); } } } }
void main(void) { uint8_t payload[GZLL_MAX_PAYLOAD_LENGTH]; mcu_init(); gzll_init(); gzp_init(); gzp_pairing_enable(true); // Open pipe 2. (Pipe 0 and 1 are reserved by pairing library). gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << 2)); // Set P0 as output P0DIR = 0; EA = 1; // Enter host mode (start monitoring for data) gzll_rx_start(); for(;;) { // If gzpair_host_execute() returns true, a pairing request has been received gzp_host_execute(); // If Host ID request received if(gzp_id_req_received()) { // Always grant request gzp_id_req_grant(); } // If any data received (plaintext on pipe 2 or encrypted through Gazell pairing library) if((gzll_get_rx_data_ready_pipe_number() == 2) || (gzp_crypt_user_data_received())) { // Plaintext data received? if(gzll_rx_fifo_read(payload, NULL, NULL)) { // Write received payload[0] to port 0 P0 = payload[0]; } else { // Read data from Gazell pairing library gzp_crypt_user_data_read(payload, NULL); // Write received payload[0] to port 0 P0 = payload[0]; } } } }
static void gzp_process_key_update_prepare() { uint8_t tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH]; tx_payload[0] = GZP_CMD_KEY_UPDATE_PREPARE_RESP; gzp_get_session_counter(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]); // Update session token if no ID request is pending if(!gzp_id_req_received()) { gzp_crypt_set_session_token(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]); } gzp_preload_ack(tx_payload, GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE); }
static void gzp_process_key_update_prepare() { uint8_t tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH]; tx_payload[0] = (uint8_t)GZP_CMD_KEY_UPDATE_PREPARE_RESP; gzp_get_session_counter(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]); // Update session token if no ID request is pending if(!gzp_id_req_received()) { gzp_crypt_set_session_token(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]); } gzp_preload_ack(tx_payload, GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE); ASSERT(nrf_gzll_get_error_code() == NRF_GZLL_ERROR_CODE_NO_ERROR); }
static void gzp_process_id_req(uint8_t* rx_payload) { int i; uint8_t temp_host_id[GZP_HOST_ID_LENGTH]; if(gzp_pairing_enabled_f) { if(!gzp_id_req_received()) { gzp_crypt_set_session_token(&rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]); gzp_id_req_stat = GZP_ID_REQ_PENDING; } gzp_get_host_id(temp_host_id); // Added: for(i = 0; i < GZP_HOST_ID_LENGTH; i++) { if(temp_host_id[i] != 0xFF) { break; } } if(i == GZP_HOST_ID_LENGTH) // If host not generated yet { gzp_get_session_counter(temp_host_id); //lint -save -e506 Constantvalue Boolean if(GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH) { //lint -restore gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH); } else { gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_HOST_ID_LENGTH); } gzp_set_host_id(temp_host_id); } } }