This code fixes the Provisioner Initiator role so that the following Out-of-Band agent calls are made correctly, and their results handled properly: "push", "twist", "blink", "beep", "vibrate", "in-numeric", "out-numeric", "in-alpha", "out-alpha" --- mesh/agent.c | 28 +++++++++++------ mesh/agent.h | 4 +-- mesh/prov-acceptor.c | 2 +- mesh/prov-initiator.c | 71 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 81 insertions(+), 24 deletions(-) diff --git a/mesh/agent.c b/mesh/agent.c index 4f99bad7b..5a5570ae5 100644 --- a/mesh/agent.c +++ b/mesh/agent.c @@ -363,7 +363,7 @@ static void key_reply(struct l_dbus_message *reply, void *user_data) mesh_agent_key_cb_t cb; struct l_dbus_message_iter iter_array; uint32_t n = 0, expected_len = 0; - uint8_t buf[64]; + uint8_t *buf; int err; if (!l_queue_find(agents, simple_match, agent) || !agent->req) @@ -376,13 +376,13 @@ static void key_reply(struct l_dbus_message *reply, void *user_data) if (err != MESH_ERROR_NONE) goto done; - if (!l_dbus_message_get_arguments(reply, "au", &iter_array)) { + if (!l_dbus_message_get_arguments(reply, "ay", &iter_array)) { l_error("Failed to retrieve key input"); err = MESH_ERROR_FAILED; goto done; } - if (!l_dbus_message_iter_get_fixed_array(&iter_array, buf, &n)) { + if (!l_dbus_message_iter_get_fixed_array(&iter_array, &buf, &n)) { l_error("Failed to retrieve key input"); err = MESH_ERROR_FAILED; goto done; @@ -390,7 +390,7 @@ static void key_reply(struct l_dbus_message *reply, void *user_data) if (req->type == MESH_AGENT_REQUEST_PRIVATE_KEY) expected_len = 32; - else if (MESH_AGENT_REQUEST_PUBLIC_KEY) + else if (req->type == MESH_AGENT_REQUEST_PUBLIC_KEY) expected_len = 64; else expected_len = 16; @@ -402,13 +402,13 @@ static void key_reply(struct l_dbus_message *reply, void *user_data) } done: - l_dbus_message_unref(req->msg); - if (req->cb) { cb = req->cb; cb(req->user_data, err, buf, n); } + l_dbus_message_unref(req->msg); + l_free(req); agent->req = NULL; } @@ -601,11 +601,19 @@ int mesh_agent_prompt_number(struct mesh_agent *agent, bool initiator, return prompt_input(agent, str_type, type, true, cb, user_data); } -int mesh_agent_prompt_alpha(struct mesh_agent *agent, mesh_agent_key_cb_t cb, - void *user_data) +int mesh_agent_prompt_alpha(struct mesh_agent *agent, bool initiator, + mesh_agent_key_cb_t cb, void *user_data) { - return prompt_input(agent, "in-alpha", MESH_AGENT_REQUEST_IN_ALPHA, - false, cb, user_data); + if (initiator) + return prompt_input(agent, + cap_table[MESH_AGENT_REQUEST_OUT_ALPHA].action, + MESH_AGENT_REQUEST_OUT_ALPHA, false, cb, + user_data); + else + return prompt_input(agent, + cap_table[MESH_AGENT_REQUEST_IN_ALPHA].action, + MESH_AGENT_REQUEST_IN_ALPHA, false, cb, + user_data); } int mesh_agent_request_static(struct mesh_agent *agent, mesh_agent_key_cb_t cb, diff --git a/mesh/agent.h b/mesh/agent.h index 0a499d2d5..80333acd5 100644 --- a/mesh/agent.h +++ b/mesh/agent.h @@ -54,8 +54,8 @@ int mesh_agent_display_number(struct mesh_agent *agent, bool initiator, int mesh_agent_prompt_number(struct mesh_agent *agent, bool initiator, uint8_t action, mesh_agent_number_cb_t cb, void *user_data); -int mesh_agent_prompt_alpha(struct mesh_agent *agent, mesh_agent_key_cb_t cb, - void *user_data); +int mesh_agent_prompt_alpha(struct mesh_agent *agent, bool initiator, + mesh_agent_key_cb_t cb, void *user_data); int mesh_agent_request_static(struct mesh_agent *agent, mesh_agent_key_cb_t cb, void *user_data); int mesh_agent_request_private_key(struct mesh_agent *agent, diff --git a/mesh/prov-acceptor.c b/mesh/prov-acceptor.c index 57eb1e750..bca019358 100644 --- a/mesh/prov-acceptor.c +++ b/mesh/prov-acceptor.c @@ -479,7 +479,7 @@ static void acp_prov_rx(void *user_data, const uint8_t *data, uint16_t len) if (prov->conf_inputs.start.auth_action == PROV_ACTION_IN_ALPHA) { fail.reason = mesh_agent_prompt_alpha( - prov->agent, + prov->agent, false, static_cb, prov); } else { fail.reason = mesh_agent_prompt_number( diff --git a/mesh/prov-initiator.c b/mesh/prov-initiator.c index 5e45d6813..7efd5b349 100644 --- a/mesh/prov-initiator.c +++ b/mesh/prov-initiator.c @@ -433,6 +433,54 @@ failure: /* TODO: Call Complete Callback (Fail)*/ } +static void get_random_key(struct mesh_prov_initiator *prov, uint8_t action, + uint8_t size) +{ + uint32_t oob_key; + int i; + + if (action >= PROV_ACTION_IN_ALPHA) { + uint8_t alpha; + char tmp[17]; + + memset(tmp, 0, sizeof(tmp)); + + if (size > 16) + size = 16; + + /* Create random alphanumeric string made of 0-9, a-z, A-Z */ + for (i = 0; i < size; i++) { + l_getrandom(&alpha, sizeof(alpha)); + alpha %= (10 + 26 + 26); + + if (alpha < 10) + alpha += '0'; + else if (alpha < 10 + 26) + alpha += 'a' - 10; + else + alpha += 'A' - 10 - 26; + + tmp[i] = (char) alpha; + } + memcpy(prov->rand_auth_workspace + 16, tmp, size); + memcpy(prov->rand_auth_workspace + 32, tmp, size); + return; + } + + l_getrandom(&oob_key, sizeof(oob_key)); + + if (action <= PROV_ACTION_TWIST) + oob_key %= size; + else + oob_key %= digit_mod(size); + + if (!oob_key) + oob_key = size; + + /* Save two copies, for two confirmation values */ + l_put_be32(oob_key, prov->rand_auth_workspace + 28); + l_put_be32(oob_key, prov->rand_auth_workspace + 44); +} static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len) { @@ -575,7 +623,7 @@ static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len) if (prov->conf_inputs.start.auth_action == PROV_ACTION_OUT_ALPHA) { fail_code[1] = mesh_agent_prompt_alpha( - prov->agent, + prov->agent, true, static_cb, prov); } else { fail_code[1] = mesh_agent_prompt_number( @@ -591,22 +639,22 @@ static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len) case 3: /* Auth Type 3b - input OOB */ - l_getrandom(&oob_key, sizeof(oob_key)); - oob_key %= digit_mod(prov->conf_inputs.start.auth_size); + 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); - /* Save two copies, for two confirmation values */ - l_put_be32(oob_key, prov->rand_auth_workspace + 28); - l_put_be32(oob_key, prov->rand_auth_workspace + 44); - prov->material |= MAT_RAND_AUTH; - /* Ask Agent to Display U32 */ + /* Ask Agent to Display random key */ if (prov->conf_inputs.start.auth_action == PROV_ACTION_IN_ALPHA) { - /* TODO: Construst NUL-term string to pass */ + fail_code[1] = mesh_agent_display_string( - prov->agent, NULL, NULL, prov); + prov->agent, + (char *) prov->rand_auth_workspace + 16, + NULL, prov); } else { fail_code[1] = mesh_agent_display_number( - prov->agent, false, + prov->agent, true, prov->conf_inputs.start.auth_action, oob_key, NULL, prov); } @@ -625,6 +673,7 @@ static void int_prov_rx(void *user_data, const uint8_t *data, uint16_t len) case PROV_INP_CMPLT: /* Provisioning Input Complete */ /* TODO: Cancel Agent prompt */ + prov->material |= MAT_RAND_AUTH; send_confirm(prov); break; -- 2.21.0