summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.mesh19
-rw-r--r--mesh/btmesh.c181
-rw-r--r--mesh/config/composition.json44
-rw-r--r--mesh/display.c64
-rw-r--r--mesh/display.h28
-rw-r--r--mesh/prov.c722
-rw-r--r--mesh/provision.c1162
8 files changed, 6 insertions, 2215 deletions
diff --git a/.gitignore b/.gitignore
index 24587305a..d145ccdcd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -130,7 +130,6 @@ emulator/hfp
client/bluetoothctl
tools/meshctl
mesh/meshd
-mesh/btmesh
src/bluetoothd.8
src/bluetooth.service
diff --git a/Makefile.mesh b/Makefile.mesh
index 8b5af4cf6..ea6c5e939 100644
--- a/Makefile.mesh
+++ b/Makefile.mesh
@@ -3,35 +3,28 @@ if MESH
mesh_sources = mesh/mesh.h mesh/mesh.c \
mesh/net_keys.h mesh/net_keys.c \
mesh/mesh-io.h mesh/mesh-io.c \
- mesh/mesh-io-api.h \
+ mesh/error.h mesh/mesh-io-api.h \
mesh/mesh-io-generic.h \
mesh/mesh-io-generic.c \
mesh/storage.h mesh/storage.c \
mesh/net.h mesh/net.c \
- mesh/display.h mesh/display.c \
mesh/crypto.h mesh/crypto.c \
mesh/friend.h mesh/friend.c \
mesh/appkey.h mesh/appkey.c \
mesh/node.h mesh/node.c \
- mesh/prov.h mesh/prov.c \
- mesh/provision.h mesh/provision.c \
+ mesh/provision.h mesh/prov.h \
mesh/model.h mesh/model.c \
mesh/cfgmod.h mesh/cfgmod-server.c \
mesh/mesh-db.h mesh/mesh-db.c \
mesh/util.h mesh/util.c \
+ mesh/dbus.h mesh/dbus.c \
+ mesh/agent.h mesh/agent.c \
+ mesh/prov-acceptor.c mesh/prov-initiator.c \
+ mesh/pb-adv.h mesh/pb-adv.c \
mesh/mesh-defs.h
libexec_PROGRAMS += mesh/meshd
mesh_meshd_SOURCES = $(mesh_sources) mesh/main.c
mesh_meshd_LDADD = src/libshared-ell.la $(ell_ldadd) -ljson-c
mesh_meshd_DEPENDENCIES = $(ell_dependencies) src/libshared-ell.la
-
-noinst_PROGRAMS += mesh/btmesh
-
-mesh_btmesh_SOURCES = $(mesh_sources) mesh/agent.h \
- mesh/agent.c \
- mesh/btmesh.c
-mesh_btmesh_LDADD = src/libshared-mainloop.la $(ell_ldadd) -lreadline -ljson-c
-mesh_btmesh_DEPENDENCIES = $(ell_dependencies)
-
endif
diff --git a/mesh/btmesh.c b/mesh/btmesh.c
deleted file mode 100644
index 5b724239c..000000000
--- a/mesh/btmesh.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2018 Intel Corporation. All rights reserved.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#define _GNU_SOURCE
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#include <ell/ell.h>
-
-#include "src/shared/shell.h"
-#include "src/shared/mainloop.h"
-
-#include "mesh/mesh.h"
-#include "mesh/net.h"
-
-#define PROMPT COLOR_BLUE "[btmesh]" COLOR_OFF "# "
-
-static struct bt_mesh *mesh;
-
-static const struct option main_options[] = {
- { "index", 1, 0, 'i' },
- { "config", 1, 0, 'c' },
- { "save", 1, 0, 's' },
- { 0, 0, 0, 0 }
-};
-
-static const char *index_option;
-static const char *config_option;
-static const char *save_option;
-
-static const char **optargs[] = {
- &index_option,
- &config_option,
- &save_option,
-};
-
-static const char *help[] = {
- "Specify adapter index",
- "Specify input configuration file",
- "Specify output configuration file"
-};
-
-static const struct bt_shell_opt opt = {
- .options = main_options,
- .optno = sizeof(main_options) / sizeof(struct option),
- .optstr = "i:c:s:",
- .optarg = optargs,
- .help = help,
-};
-
-static int get_arg_on_off(int argc, char *argv[])
-{
- if (!strcmp(argv[1], "on") || !strcmp(argv[1], "yes"))
- return 1;
-
- if (!strcmp(argv[1], "off") || !strcmp(argv[1], "no"))
- return 0;
-
- bt_shell_printf("Invalid argument %s\n", argv[1]);
- return -1;
-}
-
-static void cmd_beacon(int argc, char *argv[])
-{
- bool res;
- int enable;
-
- enable = get_arg_on_off(argc, argv);
- if (enable < 0)
- return;
-
- res = mesh_net_set_beacon_mode(mesh_get_net(mesh), enable);
- if (res)
- bt_shell_printf("Local beacon mode is %s\n",
- enable > 0 ? "enabled" : "disabled");
- else
- bt_shell_printf("Failed to set local beacon mode to %s\n",
- enable > 0 ? "enabled" : "disabled");
-}
-
-static const struct bt_shell_menu main_menu = {
- .name = "main",
- .entries = {
- { "beacon", "<enable>", cmd_beacon, "Enable/disable beaconing"},
- { } },
-};
-
-static int get_index(const char *arg)
-{
- if (strlen(arg) > 3 && !strncasecmp(arg, "hci", 3))
- return atoi(&arg[3]);
- else
- return atoi(arg);
-}
-
-static void ell_event(int fd, uint32_t events, void *user_data)
-{
- int timeout = l_main_prepare();
-
- l_main_iterate(timeout);
-}
-
-int main(int argc, char *argv[])
-{
- int index;
- int fd;
- int status;
-
- l_log_set_stderr();
- l_debug_enable("*");
-
- if (!l_main_init())
- return -1;
-
- bt_shell_init(argc, argv, &opt);
- bt_shell_set_menu(&main_menu);
-
- if (!index_option) {
- l_info("Controller index is required");
- goto fail;
- }
-
- if (config_option)
- l_info("Reading local configuration from %s\n", config_option);
-
- if (save_option)
- l_info("Saving local configuration to %s\n", save_option);
-
- bt_shell_set_prompt(PROMPT);
-
- index = get_index(index_option);
-
- l_info("Starting mesh on hci%d\n", index);
-
- mesh = mesh_new(index, config_option);
- if (!mesh) {
- l_info("Failed to create mesh\n");
- goto fail;
- }
-
- if (save_option)
- mesh_set_output(mesh, save_option);
-
- fd = l_main_get_epoll_fd();
- mainloop_add_fd(fd, EPOLLIN, ell_event, NULL, NULL);
-
- status = bt_shell_attach(fileno(stdin));
- bt_shell_run();
-
- mesh_unref(mesh);
- mesh_cleanup();
- l_main_exit();
- return status;
-
-fail:
- bt_shell_cleanup();
- return EXIT_FAILURE;
-}
diff --git a/mesh/config/composition.json b/mesh/config/composition.json
deleted file mode 100644
index 20c0d0c3a..000000000
--- a/mesh/config/composition.json
+++ /dev/null
@@ -1,44 +0,0 @@
-{
- "$schema":"file:\/\/\/BlueZ\/MeshD\/local_schema\/mesh.jsonschema",
- "meshName":"BT Mesh sample node",
- "UUID":"E0ED0F0200000000203C100200000000",
- "cid":"0002",
- "pid":"0010",
- "vid":"0001",
- "crpl":"000a",
- "proxy":"unsupported",
- "friend":"disabled",
- "lowPower":"disabled",
- "relay":{
- "mode":"enabled"
- },
- "elements":[
- {
- "elementIndex":0,
- "location":"0001",
- "models":[
- {
- "modelId":"0000"
- },
- {
- "modelId":"1001"
- }
- ]
- }
- ],
- "provision": {
- "privateKey": "729aa0670d72cd6497502ed473502b037e8803b5c60829a5a3caa219505530ba",
- "algorithms": [ 0 ],
- "inputOOB": {
- "size": 8,
- "actions": [ 2, 3]
- },
- "outputOOB": {
- "size": 8,
- "actions": [ 3, 4]
- },
- "publicType": false,
- "staticType": false
- },
- }
-}
diff --git a/mesh/display.c b/mesh/display.c
deleted file mode 100644
index 8238ae849..000000000
--- a/mesh/display.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2018 Intel Corporation. All rights reserved.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- */
-
-#include <stdio.h>
-#include <unistd.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
-#include <ell/ell.h>
-
-#include "display.h"
-
-static unsigned int cached_num_columns;
-
-unsigned int num_columns(void)
-{
- struct winsize ws;
-
- if (cached_num_columns > 0)
- return cached_num_columns;
-
- if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) < 0 || ws.ws_col == 0)
- cached_num_columns = 80;
- else
- cached_num_columns = ws.ws_col;
-
- return cached_num_columns;
-}
-
-void print_packet(const char *label, const void *data, uint16_t size)
-{
- struct timeval pkt_time;
-
- gettimeofday(&pkt_time, NULL);
-
- if (size > 0) {
- char *str;
-
- str = l_util_hexstring(data, size);
- l_debug("%05d.%03d %s: %s",
- (uint32_t) pkt_time.tv_sec % 100000,
- (uint32_t) pkt_time.tv_usec/1000, label, str);
- l_free(str);
- } else
- l_debug("%05d.%03d %s: empty",
- (uint32_t) pkt_time.tv_sec % 100000,
- (uint32_t) pkt_time.tv_usec/1000, label);
-}
diff --git a/mesh/display.h b/mesh/display.h
deleted file mode 100644
index f5d1f7f79..000000000
--- a/mesh/display.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2018 Intel Corporation. All rights reserved.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- */
-
-#define COLOR_OFF "\x1B[0m"
-#define COLOR_RED "\x1B[0;91m"
-#define COLOR_GREEN "\x1B[0;92m"
-#define COLOR_YELLOW "\x1B[0;93m"
-#define COLOR_BLUE "\x1B[0;94m"
-
-unsigned int num_columns(void);
-
-void print_packet(const char *label, const void *data, uint16_t size);
diff --git a/mesh/prov.c b/mesh/prov.c
deleted file mode 100644
index 45ced404c..000000000
--- a/mesh/prov.c
+++ /dev/null
@@ -1,722 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2018 Intel Corporation. All rights reserved.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/time.h>
-#include <ell/ell.h>
-
-#include "mesh/mesh-defs.h"
-
-#include "mesh/mesh-io.h"
-#include "mesh/display.h"
-#include "mesh/crypto.h"
-#include "mesh/net.h"
-#include "mesh/prov.h"
-
-#define PB_ADV_MTU 24
-
-#define DEFAULT_CONN_ID 0x00000000
-#define DEFAULT_PROV_MSG_NUM 0x00
-#define DEFAULT_DEV_MSG_NUM 0x80
-
-#define TX_TIMEOUT 30
-
-struct mesh_prov *mesh_prov_new(struct mesh_net *net, uint16_t remote)
-{
- struct mesh_prov *prov;
-
- prov = l_new(struct mesh_prov, 1);
-
- prov->remote = remote;
- prov->net = net;
-
- return mesh_prov_ref(prov);
-}
-
-struct mesh_prov *mesh_prov_ref(struct mesh_prov *prov)
-{
- if (!prov)
- return NULL;
-
- __sync_fetch_and_add(&prov->ref_count, 1);
-
- return prov;
-}
-
-void mesh_prov_unref(struct mesh_prov *prov)
-{
- struct mesh_io *io;
- uint8_t type;
-
- if (!prov)
- return;
-
- if (__sync_sub_and_fetch(&prov->ref_count, 1))
- return;
-
- io = mesh_net_get_io(prov->net);
- type = MESH_AD_TYPE_BEACON;
- mesh_io_send_cancel(io, &type, 1);
- type = MESH_AD_TYPE_PROVISION;
- mesh_io_send_cancel(io, &type, 1);
- mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_PROV);
- mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_BEACON);
- l_timeout_remove(prov->tx_timeout);
-
-
- l_info("Freed Prov Data");
- l_free(prov);
-}
-
-static void packet_received(struct mesh_prov *prov, const void *data,
- uint16_t size, uint8_t fcs)
-{
- if (prov->receive_callback)
- prov->receive_callback(data, size, prov);
-}
-
-static void send_open_req(struct mesh_prov *prov)
-{
- struct mesh_io *io;
- uint8_t open_req[23] = { MESH_AD_TYPE_PROVISION };
- struct mesh_io_send_info info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.interval = 50,
- .u.gen.cnt = 1,
- .u.gen.min_delay = 0,
- .u.gen.max_delay = 0,
- };
-
- if (!prov)
- return;
-
- io = mesh_net_get_io(prov->net);
- if (!io)
- return;
-
- l_put_be32(prov->conn_id, open_req + 1);
- open_req[1 + 4] = prov->local_msg_num = 0;
- open_req[1 + 4 + 1] = 0x03; /* OPEN_REQ */
- memcpy(open_req + 1 + 4 + 1 + 1, prov->uuid, 16);
-
- /* print_packet("PB-TX", open_req + 1, sizeof(open_req) - 1); */
- mesh_io_send_cancel(io, open_req, 1);
- mesh_io_send(io, &info, open_req, sizeof(open_req));
-}
-
-static void send_open_cfm(struct mesh_prov *prov)
-{
- struct mesh_io *io;
- uint8_t open_cfm[7] = { MESH_AD_TYPE_PROVISION };
- struct mesh_io_send_info info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.interval = 50,
- .u.gen.cnt = 1,
- .u.gen.min_delay = 0,
- .u.gen.max_delay = 0,
- };
-
- if (!prov)
- return;
-
- io = mesh_net_get_io(prov->net);
- if (!io)
- return;
-
- l_put_be32(prov->conn_id, open_cfm + 1);
- open_cfm[1 + 4] = 0;
- open_cfm[1 + 4 + 1] = 0x07; /* OPEN_CFM */
-
- /* print_packet("PB-TX", open_cfm + 1, sizeof(open_cfm) - 1); */
-
- mesh_io_send_cancel(io, open_cfm, 1);
- mesh_io_send(io, &info, open_cfm, sizeof(open_cfm));
-}
-
-static void send_close_ind(struct mesh_prov *prov, uint8_t reason)
-{
- uint8_t buf[8] = { MESH_AD_TYPE_PROVISION };
- struct mesh_io *io;
- struct mesh_io_send_info info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.interval = 50,
- .u.gen.cnt = 3,
- .u.gen.min_delay = 0,
- .u.gen.max_delay = 0,
- };
-
- if (!prov)
- return;
-
- if (prov->bearer == MESH_BEARER_ADV) {
- io = mesh_net_get_io(prov->net);
- if (!io)
- return;
-
- l_put_be32(prov->conn_id, buf + 1);
- buf[5] = 0;
- buf[6] = 0x0B; /* CLOSE_IND */
- buf[7] = reason;
-
- /* print_packet("PB-TX", buf + 1, sizeof(buf) - 1); */
-
- mesh_io_send_cancel(io, buf, 1);
- mesh_io_send(io, &info, buf, sizeof(buf));
- }
-
- prov->bearer = MESH_BEARER_IDLE;
-}
-
-static void tx_timeout(struct l_timeout *timeout, void *user_data)
-{
- struct mesh_prov *prov = user_data;
- uint8_t cancel[] = { MESH_AD_TYPE_PROVISION };
- struct mesh_io *io;
-
- if (!prov)
- return;
-
- l_timeout_remove(prov->tx_timeout);
- prov->tx_timeout = NULL;
-
- io = mesh_net_get_io(prov->net);
- if (!io)
- return;
-
- mesh_io_send_cancel(io, cancel, sizeof(cancel));
-
- l_info("TX timeout");
- mesh_prov_close(prov, 1);
-}
-
-static void send_adv_segs(struct mesh_prov *prov)
-{
- struct mesh_io *io = mesh_net_get_io(prov->net);
- struct mesh_io_send_info info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.interval = 50,
- .u.gen.cnt = MESH_IO_TX_COUNT_UNLIMITED,
- .u.gen.min_delay = 0,
- .u.gen.max_delay = 0,
- };
- const void *data = prov->packet_buf;
- uint16_t size = prov->packet_len;
- uint16_t init_size;
- uint8_t buf[1 + PB_ADV_MTU + 5] = { MESH_AD_TYPE_PROVISION };
- uint8_t max_seg;
- uint8_t consumed;
- int i;
-
- if (!size)
- return;
-
- mesh_io_send_cancel(io, buf, 1);
-
- l_put_be32(prov->conn_id, buf + 1);
- buf[1 + 4] = prov->local_msg_num;
-
- if (size > PB_ADV_MTU - 4) {
- max_seg = 1 +
- (((size - (PB_ADV_MTU - 4)) - 1) / (PB_ADV_MTU - 1));
- init_size = PB_ADV_MTU - 4;
- } else {
- max_seg = 0;
- init_size = size;
- }
-
- /* print_packet("FULL-TX", data, size); */
-
- l_debug("Sending %u fragments for %u octets", max_seg + 1, size);
-
- buf[1 + 4 + 1] = max_seg << 2;
- l_put_be16(size, buf + 1 + 4 + 1 + 1);
- buf[9] = mesh_crypto_compute_fcs(data, size);
- memcpy(buf + 1 + 4 + 1 + 1 + 2 + 1, data, init_size);
-
- l_debug("max_seg: %2.2x", max_seg);
- l_debug("size: %2.2x, CRC: %2.2x", size, buf[9]);
-
- /* print_packet("PB-TX", buf + 1, init_size + 9); */
- mesh_io_send(io, &info, buf, init_size + 10);
-
- consumed = init_size;
-
- for (i = 1; i <= max_seg; i++) {
- uint8_t seg_size; /* Amount of payload data being sent */
-
- if (size - consumed > PB_ADV_MTU - 1)
- seg_size = PB_ADV_MTU - 1;
- else
- seg_size = size - consumed;
-
- buf[6] = (i << 2) | 0x02;
- memcpy(buf + 7, data + consumed, seg_size);
-
- /* print_packet("PB-TX", buf + 1, seg_size + 6); */
-
- mesh_io_send(io, &info, buf, seg_size + 7);
-
- consumed += seg_size;
- }
-}
-
-static void send_adv_msg(struct mesh_prov *prov, const void *data,
- uint16_t size)
-{
- l_timeout_remove(prov->tx_timeout);
- prov->tx_timeout = l_timeout_create(TX_TIMEOUT, tx_timeout, prov, NULL);
-
- memcpy(prov->packet_buf, data, size);
- prov->packet_len = size;
-
- send_adv_segs(prov);
-}
-
-static void send_ack(struct mesh_prov *prov)
-{
- struct mesh_io *io = mesh_net_get_io(prov->net);
- struct mesh_io_send_info info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.interval = 50,
- .u.gen.cnt = 1,
- .u.gen.min_delay = 0,
- .u.gen.max_delay = 0,
- };
- uint8_t ack[7] = { MESH_AD_TYPE_PROVISION };
-
- l_put_be32(prov->conn_id, ack + 1);
- ack[1 + 4] = prov->last_peer_msg_num;
- ack[1 + 4 + 1] = 0x01; /* ACK */
-
- /* print_packet("ADV-ACK", ack + 1, sizeof(ack) - 1); */
- mesh_io_send(io, &info, ack, sizeof(ack));
-}
-
-static void adv_data_pkt(uint8_t type, const void *pkt, uint8_t size,
- void *user_data)
-{
- const uint8_t *data = pkt;
- struct mesh_prov *prov = user_data;
- uint16_t offset = 0;
-
- if ((type & 0x03) == 0x00) {
- uint8_t last_seg = type >> 2;
-
- prov->expected_len = l_get_be16(data);
- prov->expected_fcs = l_get_u8(data + 2);
-
- /* print_packet("Pkt", pkt, size); */
- data += 3;
- size -= 3;
-
- prov->trans = MESH_TRANS_RX;
-
- if (prov->expected_len > sizeof(prov->peer_buf)) {
- l_info("Incoming pkt exceeds storage %d > %ld",
- prov->expected_len, sizeof(prov->peer_buf));
- return;
- } else if (last_seg == 0)
- prov->trans = MESH_TRANS_IDLE;
-
- prov->expected_segs = 0xff >> (7 - last_seg);
- prov->got_segs |= 1;
- memcpy(prov->peer_buf, data, size);
-
- } else if ((type & 0x03) == 0x02) {
- offset = (PB_ADV_MTU - 4) + ((type >> 2) - 1) *
- (PB_ADV_MTU - 1);
-
- if (offset + size > prov->expected_len) {
- l_info("Incoming pkt exceeds agreed len %d + %d > %d",
- offset, size, prov->expected_len);
- return;
- }
-
- prov->trans = MESH_TRANS_RX;
-
- l_debug("Processing fragment %u", type & 0x3f);
-
- prov->got_segs |= 1 << (type >> 2);
- memcpy(prov->peer_buf + offset, data, size);
-
- } else if (type == 0x01) {
- if (prov->send_callback) {
- void *data = prov->send_data;
- mesh_prov_send_func_t cb = prov->send_callback;
-
- prov->trans = MESH_TRANS_IDLE;
- prov->send_callback = NULL;
- prov->send_data = NULL;
-
- cb(true, data);
- }
- return;
- } else
- return;
-
- if (prov->got_segs != prov->expected_segs)
- return;
-
- /* Validate RXed packet and pass up to Provisioning */
- if (!mesh_crypto_check_fcs(prov->peer_buf,
- prov->expected_len,
- prov->expected_fcs)) {
- l_debug("Invalid FCS");
- return;
- }
-
- prov->last_peer_msg_num = prov->peer_msg_num;
- send_ack(prov);
-
- prov->trans = MESH_TRANS_IDLE;
-
- packet_received(prov, prov->peer_buf,
- prov->expected_len, prov->expected_fcs);
-
- /* Reset Re-Assembly for next packet */
- prov->expected_len = sizeof(prov->peer_buf);
- prov->expected_fcs = 0;
- prov->expected_segs = 0;
- prov->got_segs = 0;
-
-}
-
-static void adv_bearer_packet(void *user_data, struct mesh_io_recv_info *info,
- const uint8_t *pkt, uint16_t len)
-{
- struct mesh_prov *prov = user_data;
- uint32_t conn_id;
- uint8_t msg_num;
- uint8_t type;
-
- if (len < 6) {
- l_info(" Too short packet");
- return;
- }
-
- conn_id = l_get_be32(pkt + 1);
- msg_num = l_get_u8(pkt + 1 + 4);
- type = l_get_u8(pkt + 1 + 4 + 1);
-
- /*if (prov->conn_id == conn_id) print_packet("ADV-RX", pkt, len); */
-
- if (prov->conn_id != DEFAULT_CONN_ID) {
- if (prov->conn_id != conn_id) {
- l_debug("rxed unknown conn_id: %8.8x != %8.8x",
- conn_id, prov->conn_id);
- return;
- }
- } else if (type != 0x03)
- return;
-
- /* print_packet("PB-ADV-RX", pkt, len); */
-
- /* Normalize pkt to start of PROV pkt payload */
- pkt += 7;
- len -= 7;
-
- if (type == 0x07) { /* OPEN_CFM */
- if (conn_id != prov->conn_id)
- return;
-
- if (msg_num != prov->local_msg_num)
- return;
-
- l_info("Link open confirmed");
-
- prov->bearer = MESH_BEARER_ADV;
- if (prov->open_callback)
- prov->open_callback(prov->receive_data);
- } else if (type == 0x01) {
- if (conn_id != prov->conn_id)
- return;
-
- if (msg_num != prov->local_msg_num)
- return;
-
- l_debug("Got ACK %d", msg_num);
- adv_data_pkt(type, pkt, len, user_data);
- } else if (type == 0x03) {
- /*
- * Ignore if:
- * 1. We are already provisioning
- * 2. We are not advertising that we are unprovisioned
- * 3. Open request not addressed to us
- */
- if (prov->conn_id != DEFAULT_CONN_ID &&
- prov->conn_id != conn_id)
- return;
-
- if (prov->local_msg_num != (DEFAULT_DEV_MSG_NUM - 1))
- return;
-
- if (memcmp(pkt, prov->uuid, 16))
- return;
-
- l_info("Link open request");
-
- prov->last_peer_msg_num = 0xFF;
- prov->bearer = MESH_BEARER_ADV;
- if (prov->open_callback && prov->conn_id == DEFAULT_CONN_ID)
- prov->open_callback(prov->receive_data);
-
- prov->conn_id = conn_id;
- prov->peer_msg_num = msg_num;
- send_open_cfm(prov);
- } else if (type == 0x0B) {
- if (prov->conn_id != conn_id)
- return;
-
- prov->conn_id = DEFAULT_CONN_ID;
- prov->local_msg_num = 0xFF;
- prov->peer_msg_num = 0xFF;
- prov->last_peer_msg_num = 0xFF;
-
- l_timeout_remove(prov->tx_timeout);
- prov->tx_timeout = NULL;
-
- l_info("Link closed notification: %2.2x", pkt[0]);
-
- if (prov->close_callback)
- prov->close_callback(prov->receive_data, pkt[0]);
- } else if ((type & 0x03) == 0x00) {
- if (prov->conn_id != conn_id)
- return;
-
- if (msg_num == prov->last_peer_msg_num) {
- send_ack(prov);
- return;
- }
-
- prov->peer_msg_num = msg_num;
-
- l_debug("Processing Data with %u fragments,%d octets",
- type >> 2, l_get_be16(pkt));
- adv_data_pkt(type, pkt, len, user_data);
-
- } else if ((type & 0x03) == 0x02) {
- if (prov->conn_id != conn_id)
- return;
-
- if (msg_num == prov->last_peer_msg_num) {
- send_ack(prov);
- return;
- }
-
- prov->peer_msg_num = msg_num;
-
- l_debug("Processing fragment %u", type >> 2);
- adv_data_pkt(type, pkt, len, user_data);
- }
-}
-
-static void beacon_packet(void *user_data, struct mesh_io_recv_info *info,
- const uint8_t *pkt, uint16_t len)
-{
- struct mesh_prov *prov = user_data;
- struct mesh_io *io;
-
- pkt++;
- len--;
-
- if (len < 19)
- return;
-
- if (!pkt[0])
- print_packet("UnProv-BEACON-RX", pkt, len);
-
- /* Ignore devices not matching UUID */
- if (pkt[0] || memcmp(pkt + 1, prov->uuid, 16))
- return;
-
- io = mesh_net_get_io(prov->net);
- mesh_io_deregister_recv_cb(io, MESH_IO_FILTER_BEACON);
-
- if ((prov->conn_id != DEFAULT_CONN_ID) ||
- (prov->bearer != MESH_BEARER_IDLE)) {
- l_info("PB-ADV: Already Provisioning");
- return;
- }
-
- l_getrandom(&prov->conn_id, sizeof(prov->conn_id));
- prov->bearer = MESH_BEARER_ADV;
- send_open_req(prov);
-}
-
-static bool mesh_prov_enable(struct mesh_prov *prov, enum mesh_prov_mode mode,
- uint8_t uuid[16])
-{
- const uint8_t pb_adv_data[] = { MESH_AD_TYPE_BEACON, 0 };
- uint8_t adv_data[62];
- uint8_t adv_len, type;
- struct mesh_io *io;
- struct mesh_io_send_info tx_info = {
- .type = MESH_IO_TIMING_TYPE_GENERAL,
- .u.gen.interval = 1000, /* ms */
- .u.gen.cnt = 0, /* 0 == Infinite */
- .u.gen.min_delay = 0, /* no delay */
- .u.gen.max_delay = 0, /* no delay */
- };
-
- if (!prov || !prov->net)
- return false;
-
-
- prov->mode = mode;
- memcpy(prov->uuid, uuid, 16);
- prov->conn_id = DEFAULT_CONN_ID;
- io = mesh_net_get_io(prov->net);
-
- switch (mode) {
- case MESH_PROV_MODE_NONE:
- break;
- case MESH_PROV_MODE_INITIATOR:
- print_packet("Searching for uuid", uuid, 16);
- prov->local_msg_num = DEFAULT_PROV_MSG_NUM;
- prov->peer_msg_num = DEFAULT_DEV_MSG_NUM;
- mesh_io_register_recv_cb(io, MESH_IO_FILTER_PROV,
- adv_bearer_packet, prov);
- mesh_io_register_recv_cb(io, MESH_IO_FILTER_BEACON,
- beacon_packet, prov);
- break;
-
- case MESH_PROV_MODE_ADV_ACCEPTOR:
- prov->local_msg_num = DEFAULT_DEV_MSG_NUM - 1;
- prov->peer_msg_num = DEFAULT_PROV_MSG_NUM;
-
- print_packet("Beaconing as unProvisioned uuid", uuid, 16);
- adv_len = sizeof(pb_adv_data);
- memcpy(adv_data, pb_adv_data, adv_len);
- memcpy(adv_data + adv_len, uuid, 16);
- adv_len += 16;
- adv_len += 2;
- mesh_io_register_recv_cb(io, MESH_IO_FILTER_PROV,
- adv_bearer_packet, prov);
- type = MESH_AD_TYPE_BEACON;
- mesh_io_send_cancel(io, &type, 1);
- mesh_io_send(io, &tx_info, adv_data, adv_len);
- break;
-
- case MESH_PROV_MODE_GATT_CLIENT:
- case MESH_PROV_MODE_MESH_GATT_CLIENT:
- case MESH_PROV_MODE_GATT_ACCEPTOR:
- case MESH_PROV_MODE_MESH_SERVER:
- case MESH_PROV_MODE_MESH_CLIENT:
- default:
- l_error("Unimplemented Prov Mode: %d", mode);
- break;
- }
-
- return true;
-}
-
-bool mesh_prov_listen(struct mesh_net *net, uint8_t uuid[16], uint8_t caps[12],
- mesh_prov_open_func_t open_callback,
- mesh_prov_close_func_t close_callback,
- mesh_prov_receive_func_t recv_callback,
- void *user_data)
-{
- struct mesh_prov *prov = mesh_net_get_prov(net);
-
- if (!prov) {
- prov = mesh_prov_new(net, 0);
- if (!prov)
- return false;
-
- mesh_net_set_prov(net, prov);
- }
-
- prov->open_callback = open_callback;
- prov->close_callback = close_callback;
- prov->receive_callback = recv_callback;
- prov->receive_data = prov; /* TODO: retink the callback placement */
- memcpy(prov->caps, caps, sizeof(prov->caps));
-
- prov->trans = MESH_TRANS_IDLE;
-
-
- return mesh_prov_enable(prov, MESH_PROV_MODE_ADV_ACCEPTOR, uuid);
-}
-
-unsigned int mesh_prov_send(struct mesh_prov *prov,
- const void *ptr, uint16_t size,
- mesh_prov_send_func_t send_callback,
- void *user_data)
-{
- const uint8_t *data = ptr;
-
- if (!prov)
- return 0;
-
- if (prov->trans != MESH_TRANS_IDLE)
- return 0;
-
- if (prov->remote) {
- /* TODO -- PB-Remote */
- } else {
- prov->send_callback = send_callback;
- prov->send_data = user_data;
- prov->trans = MESH_TRANS_TX;
- prov->local_msg_num++;
- send_adv_msg(prov, data, size);
- }
-
- return 1;
-}
-
-bool mesh_prov_close(struct mesh_prov *prov, uint8_t reason)
-{
- if (!prov)
- return false;
-
- prov->local_msg_num = 0;
- send_close_ind(prov, reason);
-
- prov->conn_id = DEFAULT_CONN_ID;
- prov->local_msg_num = 0xFF;
- prov->peer_msg_num = 0xFF;
- prov->last_peer_msg_num = 0xFF;
-
- if (prov->tx_timeout) {
- l_timeout_remove(prov->tx_timeout);
-
- /* If timing out, give Close indication 1 second of
- * provisioning timing to get final Close indication out
- */
- prov->tx_timeout = l_timeout_create(1, tx_timeout, prov, NULL);
- }
-
- if (prov->close_callback)
- prov->close_callback(prov->receive_data, reason);
-
- return false;
-}
-
-void mesh_prov_set_addr(struct mesh_prov *prov, uint16_t addr)
-{
- prov->addr = addr;
-}
-
-uint16_t mesh_prov_get_idx(struct mesh_prov *prov)
-{
- return prov->net_idx;
-}
diff --git a/mesh/provision.c b/mesh/provision.c
deleted file mode 100644
index 17422ce0a..000000000
--- a/mesh/provision.c
+++ /dev/null
@@ -1,1162 +0,0 @@
-/*
- *
- * BlueZ - Bluetooth protocol stack for Linux
- *
- * Copyright (C) 2018 Intel Corporation. All rights reserved.
- *
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sys/select.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <termios.h>
-
-#include <ctype.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <time.h>
-#include <ell/ell.h>
-
-#include "mesh/mesh-defs.h"
-#include "src/shared/ecc.h"
-
-#include "mesh/display.h"
-#include "mesh/net_keys.h"
-#include "mesh/crypto.h"
-#include "mesh/net.h"
-#include "mesh/prov.h"
-#include "mesh/provision.h"
-#include "mesh/node.h"
-
-#define PROV_INVITE 0x00
-#define PROV_CAPS 0x01
-#define PROV_START 0x02
-#define PROV_PUB_KEY 0x03
-#define PROV_INP_CMPLT 0x04
-#define PROV_CONFIRM 0x05
-#define PROV_RANDOM 0x06
-#define PROV_DATA 0x07
-#define PROV_COMPLETE 0x08
-#define PROV_FAILED 0x09
-
-#define PROV_ERR_INVALID_PDU 0x01
-#define PROV_ERR_INVALID_FORMAT 0x02
-#define PROV_ERR_UNEXPECTED_PDU 0x03
-#define PROV_ERR_CONFIRM_FAILED 0x04
-#define PROV_ERR_INSUF_RESOURCE 0x05
-#define PROV_ERR_DECRYPT_FAILED 0x06
-#define PROV_ERR_UNEXPECTED_ERR 0x07
-#define PROV_ERR_CANT_ASSIGN_ADDR 0x08
-
-/* Expected Provisioning PDU sizes */
-static const uint16_t expected_pdu_size[] = {
- 1 + 1, /* PROV_INVITE */
- 1 + 1 + 2 + 1 + 1 + 1 + 2 + 1 + 2, /* PROV_CAPS */
- 1 + 1 + 1 + 1 + 1 + 1, /* PROV_START */
- 1 + 64, /* PROV_PUB_KEY */
- 1, /* PROV_INP_CMPLT */
- 1 + 16, /* PROV_CONFIRM */
- 1 + 16, /* PROV_RANDOM */
- 1 + 16 + 2 + 1 + 4 + 2 + 8, /* PROV_DATA */
- 1, /* PROV_COMPLETE */
- 1 + 1, /* PROV_FAILED */
-};
-
-static enum {
- PUB_KEY_TYPE_ephemeral,
- PUB_KEY_TYPE_available,
-} pub_key_type = PUB_KEY_TYPE_ephemeral;
-
-static enum {
- AUTH_TYPE_3a,
- AUTH_TYPE_3b,
- AUTH_TYPE_3c,
-} prov_auth_type = AUTH_TYPE_3c;
-
-enum {
- INT_PROV_IDLE,
- INT_PROV_INVITE_SENT,
- INT_PROV_INVITE_ACKED,
- INT_PROV_START_SENT,
- INT_PROV_START_ACKED,
- INT_PROV_KEY_SENT,
- INT_PROV_KEY_ACKED,
- INT_PROV_CONF_SENT,
- INT_PROV_CONF_ACKED,
- INT_PROV_RAND_SENT,
- INT_PROV_RAND_ACKED,
- INT_PROV_DATA_SENT,
- INT_PROV_DATA_ACKED,
-} int_prov_state = INT_PROV_IDLE;
-
-enum {
- ACP_PROV_IDLE,
- ACP_PROV_CAPS_SENT,
- ACP_PROV_CAPS_ACKED,
- ACP_PROV_KEY_SENT,
- ACP_PROV_KEY_ACKED,
- ACP_PROV_INP_CMPLT_SENT,
- ACP_PROV_INP_CMPLT_ACKED,
- ACP_PROV_CONF_SENT,
- ACP_PROV_CONF_ACKED,
- ACP_PROV_RAND_SENT,
- ACP_PROV_RAND_ACKED,
- ACP_PROV_CMPLT_SENT,
- ACP_PROV_FAIL_SENT,
-} acp_prov_state = ACP_PROV_IDLE;
-
-static uint8_t prov_expected;
-static int8_t prov_last = -1;
-
-static void int_prov_send_cmplt(bool success, struct mesh_prov *prov);
-static void acp_prov_send_cmplt(bool success, struct mesh_prov *prov);
-
-static void swap_u256_bytes(uint8_t *u256)
-{
- int i;
-
- /* End-to-End byte reflection of 32 octet buffer */
- for (i = 0; i < 16; i++) {
- u256[i] ^= u256[31 - i];
- u256[31 - i] ^= u256[i];
- u256[i] ^= u256[31 - i];
- }
-}
-
-static uint8_t u16_highest_bit(uint16_t mask)
-{
- uint8_t cnt = 0;
-
- if (!mask)
- return 0xff;
-
- while (mask & 0xfffe) {
- cnt++;
- mask >>= 1;
- }
-
- return cnt;
-}
-
-static void send_prov_start(struct mesh_prov *prov)
-{
- struct mesh_net *net = prov->net;
- struct mesh_net_prov_caps *caps = mesh_net_prov_caps_get(net);
- uint8_t prov_start[6] = { PROV_START };
-
- memset(prov_start + 1, 0, 1 + 1 + 1 + 1 + 1);
- if (!(caps->algorithms & 0x0001)) {
- /* We only support FIPS P-256 Elliptic Curve */
- l_error("Unrecognized Algorithm %4.4x", caps->algorithms);
- return;
- }
-
- if (caps->pub_type) {
- /* Prov Step 2b: New device exposed PublicKey OOB */
- prov_start[2] = 0x01;
- pub_key_type = PUB_KEY_TYPE_available;
- } else {
- pub_key_type = PUB_KEY_TYPE_ephemeral;
- }
-
- if (caps->output_size &&
- caps->output_action) {
- /* Prov Step 3a: Output OOB used */
- prov_start[3] = 0x02;
- prov_start[4] = u16_highest_bit(caps->output_action);
- prov_start[5] = caps->output_size > 8 ?
- 8 : caps->output_size;
-
- prov_auth_type = AUTH_TYPE_3a;
-
- } else if (caps->input_size &&
- caps->input_action) {
- /* Prov Step 3b: Input OOB used */
- prov_start[3] = 0x03;
- prov_start[4] = u16_highest_bit(caps->input_action);
- prov_start[5] = caps->input_size > 8 ?
- 8 : caps->input_size;
-
- prov_auth_type = AUTH_TYPE_3b;
-
- } else {
- if (caps->static_type)
- prov_start[3] = 0x01;
-
- /* Prov Step 3c: Static OOB used (or no OOB available) */
- prov_auth_type = AUTH_TYPE_3c;
- }
-
- memcpy(&prov->conf_inputs.start, prov_start + 1,
- sizeof(prov->conf_inputs.start));
-
- int_prov_state = INT_PROV_START_SENT;
- if (pub_key_type == PUB_KEY_TYPE_ephemeral)
- prov_expected = PROV_PUB_KEY;
- else if (prov_auth_type == AUTH_TYPE_3b)
- prov_expected = PROV_INP_CMPLT;
- else
- prov_expected = PROV_CONFIRM;
-
- mesh_prov_send(prov, prov_start, 6,
- int_prov_send_cmplt, prov);
-
-}
-
-static void calculate_secrets(struct mesh_prov *prov, bool initiator)
-{
- struct mesh_net *net = prov->net;
- uint8_t *priv_key = mesh_net_priv_key_get(net);
- bool test_mode = mesh_net_test_mode(net);
- uint8_t tmp[64];
-
- if (initiator) {
- memcpy(prov->conf_inputs.prv_pub_key,
- prov->l_public, sizeof(prov->l_public));
- memcpy(prov->conf_inputs.dev_pub_key,
- prov->r_public, sizeof(prov->r_public));
- } else {
- memcpy(prov->conf_inputs.prv_pub_key,
- prov->r_public, sizeof(prov->r_public));
- memcpy(prov->conf_inputs.dev_pub_key,
- prov->l_public, sizeof(prov->l_public));
- }
-
- /* Convert to Mesh byte order */
- memcpy(tmp, prov->r_public, 64);
- swap_u256_bytes(tmp);
- swap_u256_bytes(tmp + 32);
-
- ecdh_shared_secret(tmp, priv_key, prov->secret);
-
- /* Convert to Mesh byte order */
- swap_u256_bytes(prov->secret);
-
- mesh_crypto_s1(&prov->conf_inputs,
- sizeof(prov->conf_inputs), prov->conf_salt);
-
-
- mesh_crypto_prov_conf_key(prov->secret, prov->conf_salt,
- prov->conf_key);
-
- if (test_mode) {
- print_packet("PublicKeyRemote", prov->r_public, 64);
- print_packet("PublicKeyLocal", prov->l_public, 64);
- print_packet("PrivateKeyLocal", priv_key, 32);
- print_packet("ConfirmationInputs", &prov->conf_inputs,
- sizeof(prov->conf_inputs));
- print_packet("ECDHSecret", prov->secret,
- sizeof(prov->secret));
- print_packet("ConfirmationSalt", prov->conf_salt, 16);
- print_packet("ConfirmationKey", prov->conf_key,
- sizeof(prov->conf_key));
- }
-}
-
-static void send_prov_key(struct mesh_prov *prov,
- mesh_prov_send_func_t send_callback)
-{
- uint8_t send_pub_key[65] = { PROV_PUB_KEY };
-
- memcpy(send_pub_key + 1, prov->l_public, 64);
- mesh_prov_send(prov, send_pub_key, 65,
- send_callback, prov);
-}
-
-static void send_prov_data(struct mesh_prov *prov)
-{
- struct mesh_net *net = prov->net;
- struct mesh_net_prov_caps *caps = mesh_net_prov_caps_get(net);
- uint64_t mic;
- uint32_t iv_index;
- uint32_t net_key_id;
- uint8_t snb_flags;
- uint16_t net_idx = mesh_prov_get_idx(prov);
- uint8_t prov_data[1 + 16 + 2 + 1 + 4 + 2 + sizeof(mic)] = { PROV_DATA };
- uint16_t uni_addr = mesh_net_prov_uni(net, caps->num_ele);
- bool test_mode = mesh_net_test_mode(net);
-
- /* Calculate Provisioning Data */
- prov_expected = PROV_COMPLETE;
- mesh_net_get_snb_state(net, &snb_flags, &iv_index);
-
- mesh_net_get_key(net, !!(snb_flags & 0x01), net_idx, &net_key_id);
- net_key_retrieve(net_key_id, prov_data + 1);
- l_put_be16(net_idx, prov_data + 1 + 16);
- l_put_u8(snb_flags, prov_data + 1 + 16 + 2);
- l_put_be32(iv_index, prov_data + 1 + 16 + 2 + 1);
- l_put_be16(uni_addr, prov_data + 1 + 16 + 2 + 1 + 4);
-
- if (test_mode)
- print_packet("Data", prov_data + 1, 16 + 2 + 1 + 4 + 2);
-
- mesh_crypto_device_key(prov->secret, prov->prov_salt, prov->dev_key);
- if (test_mode) {
- print_packet("DevKey", prov->dev_key, 16);
- print_packet("NetworkKey", prov_data + 1, 16);
- print_packet("NetworkKey Index", prov_data + 1 + 16, 2);
- print_packet("SNB Flags", prov_data + 1 + 16 + 2, 1);
- print_packet("IVindex", prov_data + 1 + 16 + 2 + 1, 4);
- print_packet("Unicast Addr", prov_data + 1 + 16 + 2 + 1 + 4, 2);
- }
-
- mesh_crypto_aes_ccm_encrypt(prov->s_nonce, prov->s_key,
- NULL, 0,
- &prov_data[1],
- sizeof(prov_data) - 1 - sizeof(mic),
- &prov_data[1],
- &mic, sizeof(mic));
- if (test_mode)
- print_packet("DataEncrypted + mic", prov_data + 1,
- sizeof(prov_data) - 1);
-
- int_prov_state = INT_PROV_DATA_SENT;
- mesh_prov_send(prov, prov_data, sizeof(prov_data),
- int_prov_send_cmplt, prov);
- mesh_prov_set_addr(prov, uni_addr);
-}
-
-static void send_prov_conf(struct mesh_prov *prov,
- mesh_prov_send_func_t send_callback)
-{
- struct mesh_net *net = prov->net;
- uint8_t *test_rand = mesh_net_prov_rand(net);
- uint8_t prov_conf[1 + sizeof(prov->conf)] = { PROV_CONFIRM };
- bool test_mode = mesh_net_test_mode(net);
-
- if (test_mode && test_rand[0])
- memcpy(prov->rand_auth, test_rand, 16);
- else
- l_getrandom(prov->rand_auth, 16);
-
- /* Calculate Confirmation */
- mesh_crypto_aes_cmac(prov->conf_key, prov->rand_auth,
- sizeof(prov->rand_auth), prov->conf);
-
- /* Marshal Confirmation */
- memcpy(prov_conf + 1, prov->conf, sizeof(prov->conf));
-
- if (test_mode) {
- print_packet("ConfirmationKey", prov->conf_key,
- sizeof(prov->conf_key));
- print_packet("RandomAuthValue", prov->rand_auth,
- sizeof(prov->rand_auth));
- print_packet("Sending Confirmation", prov->conf,
- sizeof(prov->conf));
- }
-
- mesh_prov_send(prov, prov_conf, sizeof(prov_conf),
- send_callback, prov);
-}
-
-static void send_prov_rand(struct mesh_prov *prov,
- mesh_prov_send_func_t send_callback)
-{
- struct mesh_net *net = prov->net;
- uint8_t prov_rand[17] = { PROV_RANDOM };
- bool test_mode = mesh_net_test_mode(net);
-
- /* Marshal Random */
- memcpy(prov_rand + 1, prov->rand_auth, 16);
-
- if (test_mode)
- print_packet("Sending Random", prov->rand_auth, 16);
-
- mesh_prov_send(prov, prov_rand, sizeof(prov_rand),
- send_callback, prov);
-}
-
-enum inputType {
- INP_key,
- INP_dec,
- INP_text,
-};
-
-struct input_data {
- struct mesh_prov *prov;
- enum inputType type;
- bool initiator;
- void *dest;
- void *user_data;
- union {
- struct {
- uint8_t idx;
- char data[129];
- } key;
- struct {
- uint64_t value;
- } dec;
- struct {
- uint8_t idx;
- char str[16];
- } text;
- } u;
-};
-
-static void collectInput(struct mesh_prov *prov, char *prompt,
- enum inputType type, bool initiator,
- void *dest, void *user_data)
-{
- struct input_data *inp = l_new(struct input_data, 1);
-
- inp->prov = prov;
- inp->type = type;
- inp->dest = dest;
- inp->initiator = initiator;
- inp->user_data = user_data;
-
- if (prompt)
- l_info("%s", prompt);
-
- /* TODO: Request agent get OOB data */
-}
-
-static uint32_t digit_mod(uint8_t power)
-{
- uint32_t ret = 1;
-
- while (power--)
- ret *= 10;
-
- return ret;
-}
-
-static char *key_type(uint8_t type)
-{
- switch (type) {
- case 0x01:
- return "QR-Code";
- case 0x02:
- return "Barcode";
- case 0x03:
- return "NFC Tag";
- case 0x04:
- return "Printed Number";
- default:
- return "unknown Source";
- }
-}
-
-static void int_prov_send_cmplt(bool success, struct mesh_prov *prov)
-{
- struct mesh_net *net = prov->net;
- struct mesh_net_prov_caps *caps = mesh_net_prov_caps_get(net);
-
- l_debug("Provision sending complete");
-
- switch (int_prov_state) {
- case INT_PROV_INVITE_SENT:
- int_prov_state = INT_PROV_INVITE_ACKED;
- if (acp_prov_state == ACP_PROV_CAPS_SENT)
- send_prov_start(prov);
- break;
- case INT_PROV_START_SENT:
- int_prov_state = INT_PROV_START_ACKED;
- if (pub_key_type == PUB_KEY_TYPE_ephemeral) {
- int_prov_state = INT_PROV_KEY_SENT;
- send_prov_key(prov, int_prov_send_cmplt);
- } else {
- collectInput(prov, NULL, INP_key, true,
- prov->r_public, prov);
- l_info("\n\nEnter key from %s:\n",
- key_type(caps->pub_type));
- }
- break;
- case INT_PROV_KEY_SENT:
- int_prov_state = INT_PROV_KEY_ACKED;
- if (pub_key_type == PUB_KEY_TYPE_ephemeral) {
- prov_expected = PROV_PUB_KEY;
- break;
- }
-
- /* Start Step 3 */
- memset(prov->rand_auth + 16, 0, 16);
- if (prov_auth_type == AUTH_TYPE_3a)
- collectInput(prov,
- "\n\nEnter prompted number from device:",
- INP_dec, true,
- prov->rand_auth + 32 - sizeof(uint32_t),
- prov);
-
- else if (prov_auth_type == AUTH_TYPE_3b) {
- uint32_t oob_key;
-
- l_getrandom(&oob_key, sizeof(uint32_t));
- oob_key %= digit_mod(caps->input_size);
- l_put_be32(oob_key,
- prov->rand_auth + 32 -
- sizeof(uint32_t));
- l_info("\n\nEnter %d on Device\n", oob_key);
- prov_expected = PROV_INP_CMPLT;
-
- } else if (caps->static_type) {
- collectInput(prov, NULL, INP_text, true,
- prov->rand_auth + 16, prov);
- l_info("\n\nstatic OOB str from %s:\n",
- key_type(caps->static_type));
-
- } else {
- int_prov_state = INT_PROV_CONF_SENT;
- send_prov_conf(prov, int_prov_send_cmplt);
- }
-
- break;
- case INT_PROV_CONF_SENT:
- int_prov_state = INT_PROV_CONF_ACKED;
- if (acp_prov_state == ACP_PROV_CONF_SENT) {
- int_prov_state = INT_PROV_RAND_SENT;
- prov_expected = PROV_RANDOM;
- send_prov_rand(prov, int_prov_send_cmplt);
- }
- break;
- case INT_PROV_RAND_SENT:
- int_prov_state = INT_PROV_RAND_ACKED;
- if (acp_prov_state == ACP_PROV_RAND_SENT)
- send_prov_data(prov);
- break;
- case INT_PROV_DATA_SENT:
- int_prov_state = INT_PROV_DATA_ACKED;
- break;
- default:
- case INT_PROV_INVITE_ACKED:
- case INT_PROV_START_ACKED:
- case INT_PROV_KEY_ACKED:
- case INT_PROV_CONF_ACKED:
- case INT_PROV_RAND_ACKED:
- case INT_PROV_DATA_ACKED:
- case INT_PROV_IDLE:
- break;
- }
-}
-
-void initiator_prov_open(struct mesh_prov *prov)
-{
- uint8_t invite[] = { PROV_INVITE, 30 };
- uint8_t *priv_key;
-
- l_info("Provisioning link opened");
-
- priv_key = mesh_net_priv_key_get(prov->net);
- ecc_make_key(prov->l_public, priv_key);
-
- int_prov_state = INT_PROV_INVITE_SENT;
- prov_expected = PROV_CAPS;
- prov_last = -1;
- prov->conf_inputs.invite.attention = invite[1];
- mesh_prov_send(prov, invite, sizeof(invite),
- int_prov_send_cmplt, prov);
-}
-
-void initiator_prov_close(struct mesh_prov *prov, uint8_t reason)
-{
- struct mesh_net *net = prov->net;
- uint32_t iv_index;
- uint8_t snb_flags;
-
- l_info("Provisioning link closed");
-
- /* Get the provisioned node's composition data*/
- if (reason == 0) {
- mesh_net_get_snb_state(net, &snb_flags, &iv_index);
-
- l_info("Save provisioner's DB");
- }
-}
-
-void initiator_prov_receive(const void *pkt, uint16_t size,
- struct mesh_prov *prov)
-{
- struct mesh_net *net = prov->net;
- struct mesh_net_prov_caps *caps = mesh_net_prov_caps_get(net);
- bool test_mode = mesh_net_test_mode(net);
- const uint8_t *data = pkt;
- uint8_t tmp[16];
- uint8_t type = *data++;
- uint8_t err = 0;
-
-
- l_debug("Provisioning packet received type: %2.2x (%u octets)",
- type, size);
-
- if (type == prov_last) {
- l_error("Ignore repeated %2.2x packet", type);
- return;
- } else if ((type > prov_expected || type < prov_last) &&
- type != PROV_FAILED) {
- l_error("Expected %2.2x, Got:%2.2x", prov_expected, type);
- err = PROV_ERR_UNEXPECTED_PDU;
- goto failure;
- }
-
- if (type >= L_ARRAY_SIZE(expected_pdu_size) ||
- size != expected_pdu_size[type]) {
- l_error("Expected PDU size %d, Got %d (type: %2.2x)",
- expected_pdu_size[type], size, type);
- err = PROV_ERR_INVALID_FORMAT;
- goto failure;
- }
-
- prov_last = type;
-
- switch (type) {
- case PROV_CAPS: /* Capabilities */
- int_prov_state = INT_PROV_INVITE_ACKED;
- acp_prov_state = ACP_PROV_CAPS_SENT;
- caps->num_ele = data[0];
- if (test_mode)
- l_info("Got Num Ele %d", data[0]);
-
- caps->algorithms = l_get_be16(data + 1);
- if (test_mode)
- l_info("Got alg %d", caps->algorithms);
-
- caps->pub_type = data[3];
- if (test_mode)
- l_info("Got pub_type %d", data[3]);
-
- caps->static_type = data[4];
- if (test_mode)
- l_info("Got static_type %d", data[4]);
-
- caps->output_size = data[5];
- if (test_mode)
- l_info("Got output_size %d", data[5]);
-
- caps->output_action = l_get_be16(data + 6);
- if (test_mode)
- l_info("Got output_action %d", l_get_be16(data + 6));
-
- caps->input_size = data[8];
- if (test_mode)
- l_info("Got input_size %d", data[8]);
-
- caps->input_action = l_get_be16(data + 9);
- if (test_mode)
- l_info("Got input_action %d", l_get_be16(data + 9));
-
- if (caps->algorithms != 0x0001) {
- l_error("Unsupported Algorithm");
- err = PROV_ERR_INVALID_FORMAT;
- goto failure;
- }
-
- memcpy(&prov->conf_inputs.caps, data, 11);
-
- if (int_prov_state == INT_PROV_INVITE_ACKED)
- send_prov_start(prov);
- break;
-
- case PROV_PUB_KEY: /* Public Key */
- int_prov_state = INT_PROV_KEY_ACKED;
- acp_prov_state = ACP_PROV_KEY_SENT;
- memcpy(prov->r_public, data, 64);
- calculate_secrets(prov, true);
- prov_expected = PROV_CONFIRM;
-
- memset(prov->rand_auth + 16, 0, 16);
- if (prov_auth_type == AUTH_TYPE_3a) {
- collectInput(prov,
- "\n\nEnter number from device:",
- INP_dec, true,
- prov->rand_auth + 32 - sizeof(uint32_t),
- prov);
-
- } else if (prov_auth_type == AUTH_TYPE_3b) {
-
- uint32_t oob_key;
-
- l_getrandom(&oob_key, sizeof(uint32_t));
- oob_key %= digit_mod(caps->input_size);
- l_put_be32(oob_key,
- prov->rand_auth + 32 -
- sizeof(uint32_t));
- l_info("\n\nEnter %d on Device\n", oob_key);
- prov_expected = PROV_INP_CMPLT;
-
- } else if (caps->static_type) {
- collectInput(prov, NULL, INP_dec, true,
- prov->rand_auth + 16, prov);
- l_info("\n\nstatic OOB str from %s:\n",
- key_type(caps->static_type));
-
- } else
- send_prov_conf(prov, int_prov_send_cmplt);
- break;
-
- case PROV_INP_CMPLT: /* Provisioning Input Complete */
- acp_prov_state = ACP_PROV_INP_CMPLT_SENT;
- prov_expected = PROV_CONFIRM;
- send_prov_conf(prov, int_prov_send_cmplt);
- break;
-
- case PROV_CONFIRM: /* Confirmation */
- int_prov_state = INT_PROV_CONF_ACKED;
- acp_prov_state = ACP_PROV_CONF_SENT;
- /* RXed Device Confirmation */
- memcpy(prov->conf, data, sizeof(prov->conf));
- if (test_mode)
- print_packet("ConfirmationDevice", prov->conf,
- sizeof(prov->conf));
-
- if (int_prov_state == INT_PROV_CONF_ACKED) {
- prov_expected = PROV_RANDOM;
- send_prov_rand(prov, int_prov_send_cmplt);
- }
- break;
-
- case PROV_RANDOM: /* Random */
- int_prov_state = INT_PROV_RAND_ACKED;
- acp_prov_state = ACP_PROV_RAND_SENT;
-
- /* Calculate SessionKey while the data is fresh */
- mesh_crypto_prov_prov_salt(prov->conf_salt,
- prov->rand_auth, data,
- prov->prov_salt);
- mesh_crypto_session_key(prov->secret, prov->prov_salt,
- prov->s_key);
- mesh_crypto_nonce(prov->secret, prov->prov_salt, prov->s_nonce);
- if (test_mode) {
- print_packet("SessionKey", prov->s_key,
- sizeof(prov->s_key));
- print_packet("Nonce", prov->s_nonce,
- sizeof(prov->s_nonce));
- }
-
- /* RXed Device Confirmation */
- memcpy(prov->rand_auth, data, sizeof(prov->conf));
- if (test_mode)
- print_packet("RandomDevice", prov->rand_auth, 16);
-
- mesh_crypto_aes_cmac(prov->conf_key, prov->rand_auth,
- sizeof(prov->rand_auth), tmp);
-
- if (memcmp(tmp, prov->conf, sizeof(prov->conf))) {
- l_error("Provisioning Failed-Confirm compare)");
- err = PROV_ERR_CONFIRM_FAILED;
- goto failure;
- }
-
- if (int_prov_state == INT_PROV_RAND_ACKED) {
- prov_expected = PROV_COMPLETE;
- send_prov_data(prov);
- }
- break;
-
- case PROV_COMPLETE: /* Complete */
- l_info("Provisioning Complete");
- int_prov_state = INT_PROV_IDLE;
- mesh_prov_close(prov, 0);
- break;
-
- case PROV_FAILED: /* Failed */
- l_error("Provisioning Failed (reason: %d)", data[0]);
- err = data[0];
- goto failure;
-
- default:
- l_error("Unknown Pkt %2.2x", type);
- err = PROV_ERR_UNEXPECTED_PDU;
- goto failure;
- }
-
- return;
-
-failure:
- int_prov_state = INT_PROV_IDLE;
- mesh_prov_close(prov, err);
-}
-
-static void acp_prov_send_cmplt(bool success, struct mesh_prov *prov)
-{
- l_debug("Provision sending complete");
-
- switch (acp_prov_state) {
- case ACP_PROV_CAPS_SENT:
- acp_prov_state = ACP_PROV_CAPS_ACKED;
- if (int_prov_state == INT_PROV_KEY_SENT) {
- acp_prov_state = ACP_PROV_KEY_SENT;
- prov_expected = PROV_CONFIRM;
- send_prov_key(prov, acp_prov_send_cmplt);
- }
- break;
- case ACP_PROV_KEY_SENT:
- acp_prov_state = ACP_PROV_KEY_ACKED;
- if (int_prov_state == INT_PROV_CONF_SENT) {
- acp_prov_state = ACP_PROV_CONF_SENT;
- prov_expected = PROV_RANDOM;
- send_prov_conf(prov, acp_prov_send_cmplt);
- }
- break;
- case ACP_PROV_INP_CMPLT_SENT:
- acp_prov_state = ACP_PROV_INP_CMPLT_ACKED;
- break;
- case ACP_PROV_CONF_SENT:
- acp_prov_state = ACP_PROV_CONF_ACKED;
- if (int_prov_state == INT_PROV_RAND_SENT) {
- acp_prov_state = ACP_PROV_RAND_SENT;
- prov_expected = PROV_DATA;
- send_prov_rand(prov, acp_prov_send_cmplt);
- }
- break;
- case ACP_PROV_RAND_SENT:
- acp_prov_state = ACP_PROV_RAND_ACKED;
- break;
- case ACP_PROV_CMPLT_SENT:
- acp_prov_state = ACP_PROV_IDLE;
- mesh_net_provisioned_set(prov->net, true);
- default:
- case ACP_PROV_IDLE:
- case ACP_PROV_CAPS_ACKED:
- case ACP_PROV_KEY_ACKED:
- case ACP_PROV_INP_CMPLT_ACKED:
- case ACP_PROV_CONF_ACKED:
- case ACP_PROV_RAND_ACKED:
- case ACP_PROV_FAIL_SENT:
- break;
- }
-}
-
-void acceptor_prov_open(struct mesh_prov *prov)
-{
- uint8_t *priv_key;
-
- l_info("Provisioning link opened");
-
- priv_key = mesh_net_priv_key_get(prov->net);
- ecc_make_key(prov->l_public, priv_key);
-
- prov_expected = PROV_INVITE;
- prov_last = -1;
-}
-
-void acceptor_prov_close(struct mesh_prov *prov, uint8_t reason)
-{
- l_info("Provisioning link closed");
- mesh_prov_unref(prov);
-}
-
-static void prov_store_cfm(void *user_data, bool result)
-{
- struct mesh_prov *prov = user_data;
- uint8_t out[2];
-
- if (result) {
- acp_prov_state = ACP_PROV_CMPLT_SENT;
- out[0] = PROV_COMPLETE;
- mesh_prov_send(prov, out, 1,
- acp_prov_send_cmplt,
- prov);
- } else {
- acp_prov_state = ACP_PROV_FAIL_SENT;
- out[0] = PROV_FAILED;
- out[1] = PROV_ERR_INSUF_RESOURCE;
- mesh_prov_send(prov, out, 2, NULL, NULL);
- }
-}
-
-void acceptor_prov_receive(const void *pkt, uint16_t size,
- struct mesh_prov *prov)
-{
- struct mesh_net *net = prov->net;
- struct mesh_net_prov_caps *caps = mesh_net_prov_caps_get(net);
- uint8_t *priv_key = mesh_net_priv_key_get(net);
- bool test_mode = mesh_net_test_mode(net);
- bool ret;
- const uint8_t *data = pkt;
- uint8_t type = *data++;
- uint8_t out[129];
- uint8_t tmp[16];
- uint8_t rand_dev[16];
- uint64_t rx_mic, decode_mic;
-
- l_debug("Provisioning packet received type: %2.2x (%u octets)",
- type, size);
-
- if (type == prov_last) {
- l_error("Ignore repeated %2.2x packet", type);
- return;
- } else if (type > prov_expected || type < prov_last) {
- l_error("Expected %2.2x, Got:%2.2x", prov_expected, type);
- out[1] = PROV_ERR_UNEXPECTED_PDU;
- goto failure;
- }
-
- if (type >= L_ARRAY_SIZE(expected_pdu_size) ||
- size != expected_pdu_size[type]) {
- l_error("Expected PDU size %d, Got %d (type: %2.2x)",
- size, expected_pdu_size[type], type);
- out[1] = PROV_ERR_INVALID_FORMAT;
- goto failure;
- }
-
- prov_last = type;
-
- switch (type) {
- case PROV_INVITE: /* Prov Invite */
- int_prov_state = INT_PROV_INVITE_SENT;
- /* Prov Capabilities */
- out[0] = PROV_CAPS;
- out[1] = caps->num_ele;
- l_put_be16(caps->algorithms, out + 2);
- out[4] = caps->pub_type;
- out[5] = caps->static_type;
- out[6] = caps->output_size;
- l_put_be16(caps->output_action, out + 7);
- out[9] = caps->input_size;
- l_put_be16(caps->input_action, out + 10);
-
- prov->conf_inputs.invite.attention = data[0];
- memcpy(&prov->conf_inputs.caps, out + 1,
- sizeof(prov->conf_inputs.caps));
-
- acp_prov_state = ACP_PROV_CAPS_SENT;
- prov_expected = PROV_START;
- mesh_prov_send(prov, out, sizeof(*caps) + 1,
- acp_prov_send_cmplt, prov);
- break;
-
- case PROV_START: /* Prov Start */
- if (data[0]) {
- /* Only Algorithm 0x00 supported */
- l_error("Invalid Algorithm: %2.2x", data[0]);
- out[1] = PROV_ERR_INVALID_FORMAT;
- goto failure;
- }
-
- acp_prov_state = ACP_PROV_CAPS_ACKED;
- int_prov_state = INT_PROV_START_SENT;
- prov_expected = PROV_PUB_KEY;
- memcpy(&prov->conf_inputs.start, data,
- sizeof(prov->conf_inputs.start));
- if (data[1] == 1 && caps->pub_type) {
- pub_key_type = PUB_KEY_TYPE_available;
- ecc_make_key(prov->l_public, priv_key);
- } else if (data[1] == 0) {
- pub_key_type = PUB_KEY_TYPE_ephemeral;
- /* Use Ephemeral Key */
- l_getrandom(priv_key, 32);
- ecc_make_key(prov->l_public, priv_key);
- } else {
- out[1] = PROV_ERR_INVALID_FORMAT;
- goto failure;
- }
-
- swap_u256_bytes(prov->l_public);
- swap_u256_bytes(prov->l_public + 32);
-
- switch (data[2]) {
- default:
- out[1] = PROV_ERR_INVALID_FORMAT;
- goto failure;
-
- case 0x00:
- case 0x01:
- prov_auth_type = AUTH_TYPE_3c;
- break;
-
- case 0x02:
- prov_auth_type = AUTH_TYPE_3a;
- caps->output_action = 1 << data[3];
- caps->output_size = data[4];
- break;
-
- case 0x03:
- prov_auth_type = AUTH_TYPE_3b;
- caps->input_action = 1 << data[3];
- caps->input_size = data[4];
- break;
- }
- break;
-
- case PROV_PUB_KEY: /* Public Key */
- int_prov_state = INT_PROV_KEY_SENT;
- prov_expected = PROV_CONFIRM;
- /* Save Key */
- memcpy(prov->r_public, data, 64);
- calculate_secrets(prov, false);
-
- if (pub_key_type == PUB_KEY_TYPE_ephemeral) {
- acp_prov_state = ACP_PROV_KEY_SENT;
- send_prov_key(prov, acp_prov_send_cmplt);
- }
-
- /* Start Step 3 */
- memset(prov->rand_auth + 16, 0, 16);
- if (prov_auth_type == AUTH_TYPE_3a) {
- uint32_t oob_key;
-
- l_getrandom(&oob_key, sizeof(uint32_t));
- oob_key %= digit_mod(caps->output_size);
- l_put_be32(oob_key,
- prov->rand_auth + 32 - sizeof(uint32_t));
- l_info("\n\nEnter %d on Provisioner\n",
- oob_key);
-
- } else if (prov_auth_type == AUTH_TYPE_3b) {
- if (caps->input_action == (1 << 3)) {
- /* TODO: Collect Text Input data */
- ;
- } else {
- /* TODO: Collect Decimal Input data */
- ;
- }
-
- } else {
- if (caps->static_type) {
- /* TODO: Collect Static Input data */
- /* (If needed) */
- ;
- }
- }
-
- break;
-
- case PROV_CONFIRM: /* Confirmation */
- int_prov_state = INT_PROV_CONF_SENT;
- acp_prov_state = ACP_PROV_KEY_ACKED;
- /* RXed Provision Confirmation */
- memcpy(prov->r_conf, data, sizeof(prov->r_conf));
- if (test_mode)
- print_packet("ConfirmationProvisioner",
- prov->r_conf,
- sizeof(prov->r_conf));
-
- if (acp_prov_state == ACP_PROV_KEY_ACKED) {
- prov_expected = PROV_RANDOM;
- send_prov_conf(prov, acp_prov_send_cmplt);
- }
- break;
-
- case PROV_RANDOM: /* Random */
- int_prov_state = INT_PROV_RAND_SENT;
- acp_prov_state = ACP_PROV_CONF_ACKED;
-
- /* Calculate Session key while the data is fresh */
- mesh_crypto_prov_prov_salt(prov->conf_salt, data,
- prov->rand_auth,
- prov->prov_salt);
- mesh_crypto_session_key(prov->secret, prov->prov_salt,
- prov->s_key);
- mesh_crypto_nonce(prov->secret, prov->prov_salt, prov->s_nonce);
-
- if (test_mode) {
- print_packet("SessionKey", prov->s_key,
- sizeof(prov->s_key));
- print_packet("Nonce", prov->s_nonce,
- sizeof(prov->s_nonce));
- }
-
-
- /* Save Local Random data to send after verification */
- memcpy(rand_dev, prov->rand_auth, 16);
- /* RXed Provisioner Confirmation */
- memcpy(prov->rand_auth, data, 16);
- if (test_mode)
- print_packet("RandomProvisioner", prov->rand_auth, 16);
-
- mesh_crypto_aes_cmac(prov->conf_key, prov->rand_auth,
- sizeof(prov->rand_auth), tmp);
-
- if (memcmp(tmp, prov->r_conf,
- sizeof(prov->r_conf))) {
- l_error("Provisioning Failed-Confirm compare");
- out[1] = PROV_ERR_CONFIRM_FAILED;
- goto failure;
- }
-
-
- memcpy(prov->rand_auth, rand_dev, 16);
- if (acp_prov_state == ACP_PROV_CONF_ACKED) {
- prov_expected = PROV_DATA;
- send_prov_rand(prov, acp_prov_send_cmplt);
- }
- break;
-
- case PROV_DATA: /* Provisioning Data */
- int_prov_state = INT_PROV_DATA_SENT;
- acp_prov_state = ACP_PROV_RAND_ACKED;
- if (test_mode) {
- print_packet("DataEncrypted + mic", data, size - 1);
- print_packet("Rxed-mic", data + 16 + 2 + 1 + 4 + 2, 8);
- }
-
- rx_mic = l_get_be64(data + 16 + 2 + 1 + 4 + 2);
- mesh_crypto_aes_ccm_decrypt(prov->s_nonce, prov->s_key,
- NULL, 0,
- data, size - 1, out + 1,
- &decode_mic, sizeof(decode_mic));
-
- if (test_mode) {
- print_packet("Data", out + 1, 16 + 2 + 1 + 4 + 2);
- l_info("Calc-mic: %16.16lx", decode_mic);
- }
-
- if (rx_mic == decode_mic) {
- mesh_crypto_device_key(prov->secret,
- prov->prov_salt,
- prov->dev_key);
- if (test_mode) {
- print_packet("DevKey", prov->dev_key, 16);
- print_packet("NetworkKey", out + 1, 16);
- print_packet("NetworkKey Index",
- out + 1 + 16, 2);
- print_packet("SNB Flags",
- out + 1 + 16 + 2, 1);
- print_packet("IVindex",
- out + 1 + 16 + 2 + 1, 4);
- print_packet("Unicast Addr",
- out + 1 + 16 + 2 + 1 + 4, 2);
- }
-
- /* Set Provisioned Data */
- ret = mesh_net_provisioned_new(prov->net,
- prov->dev_key,
- l_get_be16(out + 17),
- out + 1,
- l_get_be16(out + 24),
- out[19],
- l_get_be32(out + 20),
- prov_store_cfm, prov);
-
- if (!ret) {
- out[1] = PROV_ERR_INSUF_RESOURCE;
- goto failure;
- }
- } else {
- l_error("Provisioning Failed-MIC compare");
- out[1] = PROV_ERR_DECRYPT_FAILED;
- goto failure;
- }
- break;
-
- default:
- l_error("Unknown Pkt %2.2x", type);
- out[1] = PROV_ERR_UNEXPECTED_PDU;
- goto failure;
- }
-
- return;
-
-failure:
- acp_prov_state = ACP_PROV_FAIL_SENT;
- out[0] = PROV_FAILED;
- mesh_prov_send(prov, out, 2, acp_prov_send_cmplt, prov);
-}