00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00019 #include "gzp.h"
00020 #include "gzll.h"
00021 #include "string.h"
00022 #include "stdint.h"
00023 #include "stdbool.h"
00024 #include "hal_aes.h"
00025 #include "hal_flash.h"
00026 #include "memdefs.h"
00027
00028
00029
00030
00031
00032
00033
00037 typedef enum
00038 {
00039 GZP_ID_REQ_IDLE,
00040 GZP_ID_REQ_PENDING,
00041 GZP_ID_REQ_PENDING_AND_GRANTED,
00042 GZP_ID_REQ_PENDING_AND_REJECTED,
00043 } gzp_id_req_stat_t;
00044
00045
00046
00047
00048
00052 static void gzp_session_counter_inc();
00053
00057 static void gzp_get_session_counter(uint8_t* dst);
00058
00065 static bool gzp_set_host_id(const uint8_t* dst);
00066
00070 static void gzp_process_address_req(uint8_t* gzp_req);
00071
00075 static void gzp_process_id_req(uint8_t* rx_payload);
00076 static void gzp_process_id_fetch(uint8_t* rx_payload);
00077 static void gzp_process_key_update_prepare();
00078 static void gzp_process_key_update(uint8_t* rx_payload);
00079 static void gzp_process_encrypted_user_data(uint8_t* rx_payload, uint8_t length);
00080
00084 static void gzp_preload_ack(uint8_t* src, uint8_t length, uint8_t pipe);
00085
00089 void gzp_host_chip_id_read(uint8_t *dst, uint8_t n);
00090
00091
00092
00093
00094
00095 static gzp_id_req_stat_t gzp_id_req_stat;
00096 static xdata bool gzp_pairing_enabled_f;
00097 static xdata bool gzp_address_exchanged_f;
00098 static xdata uint8_t gzp_session_counter[GZP_SESSION_TOKEN_LENGTH];
00099 static xdata uint8_t gzp_encrypted_user_data_length;
00100 static xdata bool gzp_encrypted_user_data[GZP_ENCRYPTED_USER_DATA_MAX_LENGTH];
00101 extern __no_init uint8_t gzp_dyn_key[GZP_DYN_KEY_LENGTH];
00102
00103
00104
00105
00106
00107 void gzp_init()
00108 {
00109 uint8_t system_address[GZP_SYSTEM_ADDRESS_WIDTH];
00110
00111
00112
00113 gzp_host_chip_id_read(system_address, GZP_SYSTEM_ADDRESS_WIDTH);
00114
00115
00116 gzp_update_radio_params(system_address);
00117
00118
00119 gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_DATA_PIPE));
00120
00121 gzp_pairing_enabled_f = false;
00122 gzp_address_exchanged_f = false;
00123 gzp_id_req_stat = GZP_ID_REQ_IDLE;
00124 gzp_encrypted_user_data_length = 0;
00125
00126
00127 gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0);
00128 }
00129
00130 void gzp_pairing_enable(bool enable)
00131 {
00132 gzll_states_t temp_gzll_state;
00133
00134 temp_gzll_state = gzll_get_state();
00135
00136 if(gzp_pairing_enabled_f != enable)
00137 {
00138 gzll_goto_idle();
00139
00140 if(enable)
00141 {
00142 gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_PAIRING_PIPE));
00143 }
00144 else
00145 {
00146 gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) & ~(1 << GZP_PAIRING_PIPE));
00147 gzp_id_req_stat = GZP_ID_REQ_IDLE;
00148 }
00149
00150 gzp_pairing_enabled_f = enable;
00151
00152 if(temp_gzll_state == GZLL_HOST_ACTIVE)
00153 {
00154 gzll_rx_start();
00155 }
00156 }
00157 }
00158
00159 void gzp_host_execute()
00160 {
00161 uint8_t rx_pipe;
00162 uint8_t payload_length;
00163 uint8_t rx_payload[GZLL_MAX_FW_PAYLOAD_LENGTH];
00164
00165 gzp_address_exchanged_f = false;
00166
00167 rx_pipe = gzll_get_rx_data_ready_pipe_number();
00168
00169 if((rx_pipe == GZP_PAIRING_PIPE) || ((rx_pipe == GZP_DATA_PIPE) && (gzp_encrypted_user_data_length == 0)))
00170 {
00171 gzll_rx_fifo_read(rx_payload, &payload_length, NULL);
00172
00173 switch(rx_payload[0])
00174 {
00175 case GZP_CMD_HOST_ADDRESS_REQ:
00176 gzp_process_address_req(rx_payload);
00177 break;
00178
00179 #ifndef GZP_CRYPT_DISABLE
00180
00181 case GZP_CMD_HOST_ID_REQ:
00182 gzp_process_id_req(rx_payload);
00183 break;
00184 case GZP_CMD_HOST_ID_FETCH:
00185 gzp_process_id_fetch(rx_payload);
00186 break;
00187 case GZP_CMD_KEY_UPDATE_PREPARE:
00188 gzp_process_key_update_prepare();
00189 break;
00190 case GZP_CMD_KEY_UPDATE:
00191 gzp_process_key_update(rx_payload);
00192 break;
00193 case GZP_CMD_ENCRYPTED_USER_DATA:
00194 gzp_process_encrypted_user_data(rx_payload, payload_length);
00195 break;
00196
00197 #endif
00198
00199 case GZP_CMD_FETCH_RESP:
00200 default:
00201 break;
00202 }
00203 }
00204
00205
00206 if(gzll_get_state() == GZLL_IDLE)
00207 {
00208 gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0);
00209 if(gzp_pairing_enabled_f)
00210 {
00211 gzll_set_param(GZLL_PARAM_RX_PIPES, gzll_get_param(GZLL_PARAM_RX_PIPES) | (1 << GZP_PAIRING_PIPE));
00212 }
00213 gzll_rx_start();
00214 }
00215
00216 #ifndef GZP_CRYPT_DISABLE
00217 gzp_session_counter_inc();
00218 #endif
00219 }
00220
00221 static void gzp_process_address_req(uint8_t* gzp_req)
00222 {
00223 uint8_t temp_rx_pipes, temp_host_mode;
00224 uint8_t pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH];
00225
00226 gzp_address_exchanged_f = false;
00227
00228 gzll_goto_idle();
00229 temp_rx_pipes = gzll_get_param(GZLL_PARAM_RX_PIPES);
00230 temp_host_mode = gzll_get_param(GZLL_PARAM_HOST_MODE);
00231
00232
00233 if(gzll_rx_power_high())
00234 {
00235 gzll_set_param(GZLL_PARAM_RX_PIPES, 0);
00236 gzll_set_param(GZLL_PARAM_HOST_MODE, 0);
00237 gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_CLOSE_PROXIMITY_BACKOFF_RX_TIMEOUT);
00238 gzll_rx_fifo_flush();
00239
00240
00241 gzll_rx_start();
00242
00243 while(gzll_get_state() != GZLL_IDLE)
00244 ;
00245
00246
00247 pairing_resp[0] = GZP_CMD_HOST_ADDRESS_RESP;
00248 gzp_host_chip_id_read(&pairing_resp[GZP_CMD_HOST_ADDRESS_RESP_ADDRESS], GZP_SYSTEM_ADDRESS_WIDTH);
00249 gzll_ack_payload_write(&pairing_resp[0], GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH, 0);
00250 gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_STEP1_RX_TIMEOUT);
00251
00252
00253 gzll_set_param(GZLL_PARAM_RX_PIPES, (1 << GZP_PAIRING_PIPE));
00254 gzll_rx_start();
00255
00256 while(gzll_get_state() != GZLL_IDLE)
00257 {
00258 if(gzll_rx_fifo_read(&gzp_req[0], NULL, NULL))
00259 {
00260
00261 if(gzp_req[0] == GZP_CMD_HOST_ADDRESS_FETCH)
00262 {
00263 gzp_address_exchanged_f = true;
00264 }
00265 }
00266 }
00267
00268 gzll_tx_fifo_flush();
00269 gzll_rx_fifo_flush();
00270 gzll_set_param(GZLL_PARAM_RX_TIMEOUT, 0);
00271 gzll_set_param(GZLL_PARAM_RX_PIPES, temp_rx_pipes);
00272 gzll_set_param(GZLL_PARAM_HOST_MODE, temp_host_mode);
00273
00274
00275 gzll_rx_start();
00276 }
00277 else
00278 {
00279 gzll_set_param(GZLL_PARAM_RX_PIPES, temp_rx_pipes & ~(1 << GZP_PAIRING_PIPE));
00280 gzll_set_param(GZLL_PARAM_RX_TIMEOUT, GZP_NOT_PROXIMITY_BACKOFF_RX_TIMEOUT);
00281
00282 gzll_rx_start();
00283 }
00284 }
00285
00286 static void gzp_preload_ack(uint8_t* src, uint8_t length, uint8_t pipe)
00287 {
00288 gzll_goto_idle();
00289 gzll_tx_fifo_flush();
00290 gzll_ack_payload_write(src, length, pipe);
00291 gzll_rx_start();
00292 }
00293
00294 bool gzp_address_exchanged()
00295 {
00296 return gzp_address_exchanged_f;
00297 }
00298
00299 #ifndef GZP_CRYPT_DISABLE
00300
00301 bool gzp_crypt_user_data_received()
00302 {
00303 return (gzp_encrypted_user_data_length > 0);
00304 }
00305
00306 bool gzp_crypt_user_data_read(uint8_t* dst, uint8_t* length)
00307 {
00308 if(gzp_encrypted_user_data_length > 0)
00309 {
00310 memcpy(dst, (void*)gzp_encrypted_user_data, gzp_encrypted_user_data_length);
00311
00312 if(length != NULL)
00313 {
00314 *length = gzp_encrypted_user_data_length;
00315 }
00316 gzp_encrypted_user_data_length = 0;
00317
00318 return true;
00319 }
00320 else
00321 {
00322 return false;
00323 }
00324 }
00325
00326 bool gzp_id_req_received()
00327 {
00328 return (gzp_id_req_stat != GZP_ID_REQ_IDLE);
00329 }
00330
00331 void gzp_id_req_reject()
00332 {
00333 if(gzp_id_req_received())
00334 {
00335 gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_REJECTED;
00336 }
00337 }
00338
00339 void gzp_id_req_grant()
00340 {
00341 if(gzp_id_req_received())
00342 {
00343 gzp_id_req_stat = GZP_ID_REQ_PENDING_AND_GRANTED;
00344 }
00345 }
00346
00347 void gzp_id_req_cancel()
00348 {
00349 if(gzp_id_req_received())
00350 {
00351 gzp_id_req_stat = GZP_ID_REQ_IDLE;
00352 }
00353 }
00354
00355 static void gzp_session_counter_inc()
00356 {
00357 uint8_t i;
00358
00359 for(i = 0; i < GZP_SESSION_TOKEN_LENGTH; i++)
00360 {
00361 gzp_session_counter[i]++;
00362 if(gzp_session_counter[i] != 0)
00363 {
00364 break;
00365 }
00366 }
00367 }
00368
00369 static void gzp_get_session_counter(uint8_t* dst)
00370 {
00371 memcpy(dst, (void*)gzp_session_counter, GZP_SESSION_TOKEN_LENGTH);
00372 }
00373
00374 static bool gzp_set_host_id(const uint8_t* src)
00375 {
00376 if(hal_flash_byte_read(GZP_PARAMS_STORAGE_ADR) == 0xff)
00377 {
00378 hal_flash_byte_write(GZP_PARAMS_STORAGE_ADR, 0x00);
00379 hal_flash_bytes_write(GZP_PARAMS_STORAGE_ADR + 1, src, GZP_HOST_ID_LENGTH);
00380 return true;
00381 }
00382 else
00383 {
00384 return false;
00385 }
00386 }
00387
00388 bool gzp_get_host_id(uint8_t* dst)
00389 {
00390 if(hal_flash_byte_read(GZP_PARAMS_STORAGE_ADR) == 0)
00391 {
00392 hal_flash_bytes_read(GZP_PARAMS_STORAGE_ADR + 1, dst, GZP_HOST_ID_LENGTH);
00393 return true;
00394 }
00395 else
00396 {
00397 return false;
00398 }
00399 }
00400
00401 static void gzp_process_id_req(uint8_t* rx_payload)
00402 {
00403 uint8_t temp_host_id[GZP_HOST_ID_LENGTH];
00404
00405 if(gzp_pairing_enabled_f)
00406 {
00407 if(!gzp_id_req_received())
00408 {
00409 gzp_crypt_set_session_token(&rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN]);
00410 gzp_id_req_stat = GZP_ID_REQ_PENDING;
00411 }
00412
00413
00414 if(!gzp_get_host_id(temp_host_id))
00415 {
00416
00417 gzp_get_session_counter(temp_host_id);
00418 if(GZP_HOST_ID_LENGTH > GZP_SESSION_TOKEN_LENGTH)
00419 {
00420 gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_SESSION_TOKEN_LENGTH);
00421 }
00422 else
00423 {
00424 gzp_xor_cipher(temp_host_id, temp_host_id, &rx_payload[GZP_CMD_HOST_ID_REQ_SESSION_TOKEN], GZP_HOST_ID_LENGTH);
00425 }
00426
00427 gzp_set_host_id(temp_host_id);
00428 }
00429 }
00430 }
00431
00432 static void gzp_process_id_fetch(uint8_t* rx_payload)
00433 {
00434 uint8_t tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH];
00435
00436 if(gzp_id_req_received())
00437 {
00438 gzp_crypt_select_key(GZP_ID_EXCHANGE);
00439 gzp_crypt(&rx_payload[1], &rx_payload[1], GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH - 1);
00440 if(gzp_validate_id(&rx_payload[GZP_CMD_HOST_ID_FETCH_VALIDATION_ID]))
00441 {
00442 switch(gzp_id_req_stat)
00443 {
00444 case GZP_ID_REQ_PENDING_AND_GRANTED:
00445 tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = GZP_ID_RESP_GRANTED;
00446 gzp_get_host_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID]);
00447 gzp_id_req_stat = GZP_ID_REQ_IDLE;
00448 break;
00449 case GZP_ID_REQ_PENDING_AND_REJECTED:
00450 tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = GZP_ID_RESP_REJECTED;
00451 gzp_id_req_stat = GZP_ID_REQ_IDLE;
00452 break;
00453 case GZP_ID_REQ_PENDING:
00454 default:
00455 tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_STATUS] = GZP_ID_RESP_PENDING;
00456 break;
00457 }
00458
00459 tx_payload[0] = GZP_CMD_HOST_ID_FETCH_RESP;
00460 gzp_add_validation_id(&tx_payload[GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID]);
00461 gzp_crypt(&tx_payload[1], &tx_payload[1], GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH - 1);
00462 gzp_preload_ack(tx_payload, GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
00463 }
00464 }
00465 }
00466
00467 static void gzp_process_key_update_prepare()
00468 {
00469 uint8_t tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH];
00470
00471 tx_payload[0] = GZP_CMD_KEY_UPDATE_PREPARE_RESP;
00472
00473 gzp_get_session_counter(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
00474
00475
00476 if(!gzp_id_req_received())
00477 {
00478 gzp_crypt_set_session_token(&tx_payload[GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN]);
00479 }
00480
00481 gzp_preload_ack(tx_payload, GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
00482 }
00483
00484 static void gzp_process_key_update(uint8_t* rx_payload)
00485 {
00486 gzp_crypt_select_key(GZP_KEY_EXCHANGE);
00487 gzp_crypt(&rx_payload[1], &rx_payload[1], GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH - 1);
00488 if(gzp_validate_id(&rx_payload[GZP_CMD_KEY_UPDATE_VALIDATION_ID]))
00489 {
00490 gzp_crypt_set_dyn_key(&rx_payload[GZP_CMD_KEY_UPDATE_NEW_KEY]);
00491 }
00492 }
00493
00494 static void gzp_process_encrypted_user_data(uint8_t* rx_payload, uint8_t length)
00495 {
00496 uint8_t tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH];
00497
00498 if(gzp_id_req_received())
00499 {
00500 gzp_crypt_select_key(GZP_ID_EXCHANGE);
00501 }
00502 else
00503 {
00504 gzp_crypt_select_key(GZP_DATA_EXCHANGE);
00505 }
00506
00507 gzp_crypt(&rx_payload[1], &rx_payload[1], length - 1);
00508 if(gzp_validate_id(&rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID]))
00509 {
00510 gzp_encrypted_user_data_length = length - GZP_USER_DATA_PACKET_OVERHEAD;
00511 memcpy((void*)gzp_encrypted_user_data, &rx_payload[GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD], gzp_encrypted_user_data_length);
00512 }
00513
00514
00515 tx_payload[0] = GZP_CMD_ENCRYPTED_USER_DATA_RESP;
00516 gzp_add_validation_id(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID]);
00517 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);
00518 gzp_get_session_counter(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
00519
00520
00521 if(!gzp_id_req_received())
00522 {
00523 gzp_crypt_set_session_token(&tx_payload[GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN]);
00524 }
00525
00526 gzp_preload_ack(tx_payload, GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH, GZP_DATA_PIPE);
00527 }
00528
00529 #endif