mesh: Fix inOOB and outOOB agent handling on prov initiate

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"
This commit is contained in:
Brian Gix 2019-11-15 14:52:09 -08:00
parent 53a81750db
commit 4853937edd
4 changed files with 81 additions and 24 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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(

View File

@ -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;