From: Prathyusha N <prathyusha.n@xxxxxxxxxxx> In Public Key OOB case, when provisioner receives public key via OOB, provisioner has to send it's public key to remote node and and then proceed for authentication. Handle invalid keys case. --- mesh/prov-initiator.c | 231 +++++++++++++++++++++++++----------------- 1 file changed, 136 insertions(+), 95 deletions(-) diff --git a/mesh/prov-initiator.c b/mesh/prov-initiator.c index 7efd5b349..21f686264 100644 --- a/mesh/prov-initiator.c +++ b/mesh/prov-initiator.c @@ -186,7 +186,7 @@ static void int_prov_open(void *user_data, prov_trans_tx_t trans_tx, return; } -static void prov_calc_secret(const uint8_t *pub, const uint8_t *priv, +static bool prov_calc_secret(const uint8_t *pub, const uint8_t *priv, uint8_t *secret) { uint8_t tmp[64]; @@ -196,22 +196,27 @@ static void prov_calc_secret(const uint8_t *pub, const uint8_t *priv, swap_u256_bytes(tmp); swap_u256_bytes(tmp + 32); - ecdh_shared_secret(tmp, priv, secret); + if (!ecdh_shared_secret(tmp, priv, secret)) + return false; /* Convert to Mesh byte order */ swap_u256_bytes(secret); + return true; } -static void int_credentials(struct mesh_prov_initiator *prov) +static bool int_credentials(struct mesh_prov_initiator *prov) { - prov_calc_secret(prov->conf_inputs.dev_pub_key, - prov->private_key, prov->secret); + if (!prov_calc_secret(prov->conf_inputs.dev_pub_key, + prov->private_key, prov->secret)) + goto failure; - mesh_crypto_s1(&prov->conf_inputs, - sizeof(prov->conf_inputs), prov->salt); + if (!mesh_crypto_s1(&prov->conf_inputs, + sizeof(prov->conf_inputs), prov->salt)) + goto failure; - mesh_crypto_prov_conf_key(prov->secret, prov->salt, - prov->calc_key); + if (!mesh_crypto_prov_conf_key(prov->secret, prov->salt, + prov->calc_key)) + goto failure; l_getrandom(prov->rand_auth_workspace, 16); @@ -224,6 +229,11 @@ static void int_credentials(struct mesh_prov_initiator *prov) print_packet("LocalRandom", prov->rand_auth_workspace, 16); print_packet("ConfirmationSalt", prov->salt, 16); print_packet("ConfirmationKey", prov->calc_key, 16); + + return true; + +failure: + return false; } static uint8_t u16_high_bit(uint16_t mask) @@ -320,10 +330,21 @@ static void static_cb(void *user_data, int err, uint8_t *key, uint32_t len) send_confirm(prov); } +static void send_pub_key(struct mesh_prov_initiator *prov) +{ + struct prov_pub_key_msg msg; + + msg.opcode = PROV_PUB_KEY; + memcpy(msg.pub_key, prov->conf_inputs.prv_pub_key, 64); + prov->trans_tx(prov->trans_data, &msg, sizeof(msg)); + prov->state = INT_PROV_KEY_SENT; +} + static void pub_key_cb(void *user_data, int err, uint8_t *key, uint32_t len) { struct mesh_prov_initiator *rx_prov = user_data; struct prov_fail_msg msg; + uint8_t fail_code[2]; if (prov != rx_prov) return; @@ -338,20 +359,17 @@ static void pub_key_cb(void *user_data, int err, uint8_t *key, uint32_t len) memcpy(prov->conf_inputs.dev_pub_key, key, 64); prov->material |= MAT_REMOTE_PUBLIC; - if ((prov->material & MAT_SECRET) == MAT_SECRET) - int_credentials(prov); - - send_confirm(prov); -} - -static void send_pub_key(struct mesh_prov_initiator *prov) -{ - struct prov_pub_key_msg msg; + if ((prov->material & MAT_SECRET) == MAT_SECRET) { + if (!int_credentials(prov)) { + fail_code[0] = PROV_FAILED; + fail_code[1] = PROV_ERR_UNEXPECTED_ERR; + prov->trans_tx(prov->trans_data, fail_code, 2); + int_prov_close(prov, fail_code[1]); + return; + } + } - msg.opcode = PROV_PUB_KEY; - memcpy(msg.pub_key, prov->conf_inputs.prv_pub_key, 64); - prov->trans_tx(prov->trans_data, &msg, sizeof(msg)); - prov->state = INT_PROV_KEY_SENT; + send_pub_key(prov); } static void send_random(struct mesh_prov_initiator *prov) @@ -482,13 +500,99 @@ static void get_random_key(struct mesh_prov_initiator *prov, uint8_t action, l_put_be32(oob_key, prov->rand_auth_workspace + 44); } +static void int_prov_auth(void) +{ + uint8_t fail_code[2]; + uint32_t oob_key; + + prov->state = INT_PROV_KEY_ACKED; + + l_debug("auth_method: %d", prov->conf_inputs.start.auth_method); + memset(prov->rand_auth_workspace + 16, 0, 32); + + switch (prov->conf_inputs.start.auth_method) { + default: + case 0: + /* Auth Type 3c - No OOB */ + prov->material |= MAT_RAND_AUTH; + break; + case 1: + /* Auth Type 3c - Static OOB */ + /* Prompt Agent for Static OOB */ + fail_code[1] = mesh_agent_request_static(prov->agent, + static_cb, prov); + + if (fail_code[1]) + goto failure; + + break; + case 2: + /* Auth Type 3a - Output OOB */ + /* Prompt Agent for Output OOB */ + if (prov->conf_inputs.start.auth_action == + PROV_ACTION_OUT_ALPHA) { + fail_code[1] = mesh_agent_prompt_alpha( + prov->agent, true, + static_cb, prov); + } else { + fail_code[1] = mesh_agent_prompt_number( + prov->agent, true, + prov->conf_inputs.start.auth_action, + number_cb, prov); + } + + if (fail_code[1]) + goto failure; + + break; + + case 3: + /* Auth Type 3b - input OOB */ + get_random_key(prov, + prov->conf_inputs.start.auth_action, + prov->conf_inputs.start.auth_size); + oob_key = l_get_be32(prov->rand_auth_workspace + 28); + + /* Ask Agent to Display random key */ + if (prov->conf_inputs.start.auth_action == + PROV_ACTION_IN_ALPHA) { + + fail_code[1] = mesh_agent_display_string( + prov->agent, + (char *) prov->rand_auth_workspace + 16, + NULL, prov); + } else { + fail_code[1] = mesh_agent_display_number( + prov->agent, true, + prov->conf_inputs.start.auth_action, + oob_key, NULL, prov); + } + + if (fail_code[1]) + goto failure; + + break; + + } + + if (prov->material & MAT_RAND_AUTH) + send_confirm(prov); + + return; + +failure: + l_debug("Failing... %d", fail_code[1]); + fail_code[0] = PROV_FAILED; + prov->trans_tx(prov->trans_data, fail_code, 2); + int_prov_close(prov, fail_code[1]); +} + static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len) { struct mesh_prov_initiator *rx_prov = user_data; uint8_t *out; uint8_t type = *data++; uint8_t fail_code[2]; - uint32_t oob_key; if (rx_prov != prov || !prov->trans_tx) return; @@ -596,79 +700,12 @@ static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len) if ((prov->material & MAT_SECRET) != MAT_SECRET) return; - int_credentials(prov); - prov->state = INT_PROV_KEY_ACKED; - - l_debug("auth_method: %d", prov->conf_inputs.start.auth_method); - memset(prov->rand_auth_workspace + 16, 0, 32); - switch (prov->conf_inputs.start.auth_method) { - default: - case 0: - /* Auth Type 3c - No OOB */ - prov->material |= MAT_RAND_AUTH; - break; - case 1: - /* Auth Type 3c - Static OOB */ - /* Prompt Agent for Static OOB */ - fail_code[1] = mesh_agent_request_static(prov->agent, - static_cb, prov); - - if (fail_code[1]) - goto failure; - - break; - case 2: - /* Auth Type 3a - Output OOB */ - /* Prompt Agent for Output OOB */ - if (prov->conf_inputs.start.auth_action == - PROV_ACTION_OUT_ALPHA) { - fail_code[1] = mesh_agent_prompt_alpha( - prov->agent, true, - static_cb, prov); - } else { - fail_code[1] = mesh_agent_prompt_number( - prov->agent, true, - prov->conf_inputs.start.auth_action, - number_cb, prov); - } - - if (fail_code[1]) - goto failure; - - break; - - case 3: - /* Auth Type 3b - input OOB */ - get_random_key(prov, - prov->conf_inputs.start.auth_action, - prov->conf_inputs.start.auth_size); - oob_key = l_get_be32(prov->rand_auth_workspace + 28); - - /* Ask Agent to Display random key */ - if (prov->conf_inputs.start.auth_action == - PROV_ACTION_IN_ALPHA) { - - fail_code[1] = mesh_agent_display_string( - prov->agent, - (char *) prov->rand_auth_workspace + 16, - NULL, prov); - } else { - fail_code[1] = mesh_agent_display_number( - prov->agent, true, - prov->conf_inputs.start.auth_action, - oob_key, NULL, prov); - } - - if (fail_code[1]) - goto failure; - - break; - + if (!int_credentials(prov)) { + fail_code[1] = PROV_ERR_UNEXPECTED_ERR; + goto failure; } - if (prov->material & MAT_RAND_AUTH) - send_confirm(prov); - + int_prov_auth(); break; case PROV_INP_CMPLT: /* Provisioning Input Complete */ @@ -760,11 +797,15 @@ static void int_prov_ack(void *user_data, uint8_t msg_num) prov->state = INT_PROV_DATA_ACKED; break; + case INT_PROV_KEY_SENT: + if (prov->conf_inputs.caps.pub_type == 1) + int_prov_auth(); + break; + case INT_PROV_IDLE: case INT_PROV_INVITE_SENT: case INT_PROV_INVITE_ACKED: case INT_PROV_START_ACKED: - case INT_PROV_KEY_SENT: case INT_PROV_KEY_ACKED: case INT_PROV_CONF_SENT: case INT_PROV_CONF_ACKED: -- 2.17.1