xref: /btstack/src/mesh/provisioning_provisioner.c (revision 2fca4dad957cd7b88f4657ed51e89c12615dda72)
1f4854a5eSMatthias Ringwald /*
2f4854a5eSMatthias Ringwald  * Copyright (C) 2017 BlueKitchen GmbH
3f4854a5eSMatthias Ringwald  *
4f4854a5eSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5f4854a5eSMatthias Ringwald  * modification, are permitted provided that the following conditions
6f4854a5eSMatthias Ringwald  * are met:
7f4854a5eSMatthias Ringwald  *
8f4854a5eSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9f4854a5eSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10f4854a5eSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11f4854a5eSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12f4854a5eSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13f4854a5eSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14f4854a5eSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15f4854a5eSMatthias Ringwald  *    from this software without specific prior written permission.
16f4854a5eSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17f4854a5eSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18f4854a5eSMatthias Ringwald  *    monetary gain.
19f4854a5eSMatthias Ringwald  *
20f4854a5eSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21f4854a5eSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22f4854a5eSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*2fca4dadSMilanka Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN
24*2fca4dadSMilanka Ringwald  * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25f4854a5eSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26f4854a5eSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27f4854a5eSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28f4854a5eSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29f4854a5eSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30f4854a5eSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31f4854a5eSMatthias Ringwald  * SUCH DAMAGE.
32f4854a5eSMatthias Ringwald  *
33f4854a5eSMatthias Ringwald  * Please inquire about commercial licensing options at
34f4854a5eSMatthias Ringwald  * [email protected]
35f4854a5eSMatthias Ringwald  *
36f4854a5eSMatthias Ringwald  */
37f4854a5eSMatthias Ringwald 
382d4000d1SMatthias Ringwald #define BTSTACK_FILE__ "provisioning_provisioner.c"
39f4854a5eSMatthias Ringwald 
40f4854a5eSMatthias Ringwald #include "mesh/provisioning_provisioner.h"
41f4854a5eSMatthias Ringwald 
42f4854a5eSMatthias Ringwald #include <stdio.h>
43f4854a5eSMatthias Ringwald #include <stdlib.h>
44f4854a5eSMatthias Ringwald #include <string.h>
45f4854a5eSMatthias Ringwald 
467c76cd61SMatthias Ringwald #include "btstack_debug.h"
477c76cd61SMatthias Ringwald #include "btstack_event.h"
487c76cd61SMatthias Ringwald #include "btstack_run_loop.h"
497c76cd61SMatthias Ringwald #include "btstack_util.h"
50f4854a5eSMatthias Ringwald 
51f4854a5eSMatthias Ringwald #include "mesh/mesh_crypto.h"
52f4854a5eSMatthias Ringwald #include "mesh/pb_adv.h"
53f4854a5eSMatthias Ringwald #include "mesh/provisioning.h"
54f4854a5eSMatthias Ringwald 
55f4854a5eSMatthias Ringwald static void provisioning_public_key_ready(void);
56f4854a5eSMatthias Ringwald 
57f4854a5eSMatthias Ringwald // global
58f4854a5eSMatthias Ringwald static uint8_t         prov_ec_q[64];
59f4854a5eSMatthias Ringwald static const uint8_t * prov_public_key_oob_q;
60f4854a5eSMatthias Ringwald static const uint8_t * prov_public_key_oob_d;
61f4854a5eSMatthias Ringwald static uint8_t  prov_public_key_oob_available;
62f4854a5eSMatthias Ringwald 
63f4854a5eSMatthias Ringwald static btstack_packet_handler_t prov_packet_handler;
64f4854a5eSMatthias Ringwald 
65f4854a5eSMatthias Ringwald // NetKey
66f4854a5eSMatthias Ringwald static uint8_t  net_key[16];
67f4854a5eSMatthias Ringwald // NetKeyIndex
68f4854a5eSMatthias Ringwald static uint16_t net_key_index;
69f4854a5eSMatthias Ringwald // Flags
70f4854a5eSMatthias Ringwald static uint8_t  flags;
71f4854a5eSMatthias Ringwald // IV Index
72f4854a5eSMatthias Ringwald static uint32_t iv_index;
73f4854a5eSMatthias Ringwald 
74f4854a5eSMatthias Ringwald // either used once or per session
75f4854a5eSMatthias Ringwald static btstack_crypto_aes128_cmac_t prov_cmac_request;
76f4854a5eSMatthias Ringwald static btstack_crypto_random_t      prov_random_request;
77f4854a5eSMatthias Ringwald static btstack_crypto_ecc_p256_t    prov_ecc_p256_request;
78f4854a5eSMatthias Ringwald static btstack_crypto_ccm_t         prov_ccm_request;
79f4854a5eSMatthias Ringwald 
80f4854a5eSMatthias Ringwald // data per provisioning session
81f4854a5eSMatthias Ringwald static btstack_timer_source_t       prov_protocol_timer;
82f4854a5eSMatthias Ringwald 
83f4854a5eSMatthias Ringwald static uint16_t pb_adv_cid;
84f4854a5eSMatthias Ringwald static uint8_t  prov_attention_timer;
85f4854a5eSMatthias Ringwald static uint8_t  prov_buffer_out[100];   // TODO: how large are prov messages?
86f4854a5eSMatthias Ringwald static uint8_t  prov_waiting_for_outgoing_complete;
87f4854a5eSMatthias Ringwald static uint8_t  prov_error_code;
88f4854a5eSMatthias Ringwald static uint8_t  prov_start_algorithm;
89f4854a5eSMatthias Ringwald static uint8_t  prov_start_public_key_used;
90f4854a5eSMatthias Ringwald static uint8_t  prov_start_authentication_method;
91f4854a5eSMatthias Ringwald static uint8_t  prov_start_authentication_action;
92f4854a5eSMatthias Ringwald static uint8_t  prov_start_authentication_size;
93f4854a5eSMatthias Ringwald static uint8_t  prov_authentication_string;
949e6ecc42SMatthias Ringwald // ConfirmationInputs = ProvisioningInvitePDUValue || ProvisioningCapabilitiesPDUValue || ProvisioningStartPDUValue || PublicKeyProvisioner || PublicKeyDevice
95f4854a5eSMatthias Ringwald static uint8_t  prov_confirmation_inputs[1 + 11 + 5 + 64 + 64];
96f4854a5eSMatthias Ringwald static uint8_t  confirmation_provisioner[16];
97f4854a5eSMatthias Ringwald static uint8_t  random_provisioner[16];
98f4854a5eSMatthias Ringwald static uint8_t  auth_value[16];
99f4854a5eSMatthias Ringwald static uint8_t  remote_ec_q[64];
100f4854a5eSMatthias Ringwald static uint8_t  dhkey[32];
101f4854a5eSMatthias Ringwald static uint8_t  confirmation_salt[16];
102f4854a5eSMatthias Ringwald static uint8_t  confirmation_key[16];
103f4854a5eSMatthias Ringwald static uint8_t provisioning_salt[16];
104f4854a5eSMatthias Ringwald static uint8_t session_key[16];
105f4854a5eSMatthias Ringwald static uint8_t session_nonce[16];
106f4854a5eSMatthias Ringwald static uint16_t unicast_address;
107f4854a5eSMatthias Ringwald static uint8_t provisioning_data[25];
108f4854a5eSMatthias Ringwald static uint8_t enc_provisioning_data[25];
109f4854a5eSMatthias Ringwald static uint8_t provisioning_data_mic[8];
110f4854a5eSMatthias Ringwald static uint8_t  prov_emit_output_oob_active;
111f4854a5eSMatthias Ringwald 
112f4854a5eSMatthias Ringwald static const uint8_t * prov_static_oob_data;
113f4854a5eSMatthias Ringwald static uint16_t  prov_static_oob_len;
114f4854a5eSMatthias Ringwald 
115f4854a5eSMatthias Ringwald #if 0
116f4854a5eSMatthias Ringwald static uint8_t  prov_public_key_oob_used;
117f4854a5eSMatthias Ringwald static uint8_t  prov_emit_public_key_oob_active;
118f4854a5eSMatthias Ringwald 
119f4854a5eSMatthias Ringwald // capabilites
120f4854a5eSMatthias Ringwald 
121f4854a5eSMatthias Ringwald static uint16_t  prov_output_oob_actions;
122f4854a5eSMatthias Ringwald static uint16_t  prov_input_oob_actions;
123f4854a5eSMatthias Ringwald static uint8_t   prov_output_oob_size;
124f4854a5eSMatthias Ringwald static uint8_t   prov_input_oob_size;
125f4854a5eSMatthias Ringwald 
126f4854a5eSMatthias Ringwald // derived
127f4854a5eSMatthias Ringwald static uint8_t network_id[8];
128f4854a5eSMatthias Ringwald static uint8_t beacon_key[16];
129f4854a5eSMatthias Ringwald 
130f4854a5eSMatthias Ringwald static void provisioning_attention_timer_timeout(btstack_timer_source_t * ts){
131f4854a5eSMatthias Ringwald     UNUSED(ts);
132f4854a5eSMatthias Ringwald     if (prov_attention_timer_timeout == 0) return;
133f4854a5eSMatthias Ringwald     prov_attention_timer_timeout--;
134f4854a5eSMatthias Ringwald     provisioning_attention_timer_set();
135f4854a5eSMatthias Ringwald }
136f4854a5eSMatthias Ringwald 
137f4854a5eSMatthias Ringwald static void provisioning_attention_timer_set(void){
138f4854a5eSMatthias Ringwald     provisioning_emit_attention_timer_event(1, prov_attention_timer_timeout);
139f4854a5eSMatthias Ringwald     if (prov_attention_timer_timeout){
140f4854a5eSMatthias Ringwald         btstack_run_loop_set_timer_handler(&prov_attention_timer, &provisioning_attention_timer_timeout);
141f4854a5eSMatthias Ringwald         btstack_run_loop_set_timer(&prov_attention_timer, 1000);
142f4854a5eSMatthias Ringwald         btstack_run_loop_add_timer(&prov_attention_timer);
143f4854a5eSMatthias Ringwald     }
144f4854a5eSMatthias Ringwald }
145f4854a5eSMatthias Ringwald #endif
146f4854a5eSMatthias Ringwald 
provisioning_emit_output_oob_event(uint16_t the_pb_adv_cid,uint32_t number)1472983fbcbSMatthias Ringwald static void provisioning_emit_output_oob_event(uint16_t the_pb_adv_cid, uint32_t number){
148f4854a5eSMatthias Ringwald     if (!prov_packet_handler) return;
149f4854a5eSMatthias Ringwald     uint8_t event[9] = { HCI_EVENT_MESH_META, 7, MESH_SUBEVENT_PB_PROV_START_EMIT_OUTPUT_OOB};
1502983fbcbSMatthias Ringwald     little_endian_store_16(event, 3, the_pb_adv_cid);
151f4854a5eSMatthias Ringwald     little_endian_store_16(event, 5, number);
152f4854a5eSMatthias Ringwald     prov_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
153f4854a5eSMatthias Ringwald }
154f4854a5eSMatthias Ringwald 
provisioning_emit_event(uint8_t mesh_subevent,uint16_t the_pb_adv_cid)1552983fbcbSMatthias Ringwald static void provisioning_emit_event(uint8_t mesh_subevent, uint16_t the_pb_adv_cid){
156f4854a5eSMatthias Ringwald     if (!prov_packet_handler) return;
157f4854a5eSMatthias Ringwald     uint8_t event[5] = { HCI_EVENT_MESH_META, 3, mesh_subevent};
1582983fbcbSMatthias Ringwald     little_endian_store_16(event, 3, the_pb_adv_cid);
159f4854a5eSMatthias Ringwald     prov_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
160f4854a5eSMatthias Ringwald }
161f4854a5eSMatthias Ringwald 
provisiong_timer_handler(btstack_timer_source_t * ts)162f4854a5eSMatthias Ringwald static void provisiong_timer_handler(btstack_timer_source_t * ts){
163f4854a5eSMatthias Ringwald     UNUSED(ts);
164f4854a5eSMatthias Ringwald     printf("Provisioning Protocol Timeout -> Close Link!\n");
165f4854a5eSMatthias Ringwald     // TODO: use actual pb_adv_cid
166f4854a5eSMatthias Ringwald     pb_adv_close_link(1, 1);
167f4854a5eSMatthias Ringwald }
168f4854a5eSMatthias Ringwald 
169f4854a5eSMatthias Ringwald // The provisioning protocol shall have a minimum timeout of 60 seconds that is reset
170f4854a5eSMatthias Ringwald // each time a provisioning protocol PDU is sent or received
provisioning_timer_start(void)171f4854a5eSMatthias Ringwald static void provisioning_timer_start(void){
172f4854a5eSMatthias Ringwald     btstack_run_loop_remove_timer(&prov_protocol_timer);
173f4854a5eSMatthias Ringwald     btstack_run_loop_set_timer_handler(&prov_protocol_timer, &provisiong_timer_handler);
174f4854a5eSMatthias Ringwald     btstack_run_loop_set_timer(&prov_protocol_timer, PROVISIONING_PROTOCOL_TIMEOUT_MS);
175f4854a5eSMatthias Ringwald     btstack_run_loop_add_timer(&prov_protocol_timer);
176f4854a5eSMatthias Ringwald }
177f4854a5eSMatthias Ringwald 
provisioning_timer_stop(void)178f4854a5eSMatthias Ringwald static void provisioning_timer_stop(void){
179f4854a5eSMatthias Ringwald     btstack_run_loop_remove_timer(&prov_protocol_timer);
180f4854a5eSMatthias Ringwald }
181f4854a5eSMatthias Ringwald 
182f4854a5eSMatthias Ringwald // Outgoing Provisioning PDUs
183f4854a5eSMatthias Ringwald 
provisioning_send_invite(uint16_t the_pb_adv_cid)1842983fbcbSMatthias Ringwald static void provisioning_send_invite(uint16_t the_pb_adv_cid){
185f4854a5eSMatthias Ringwald     prov_buffer_out[0] = MESH_PROV_INVITE;
186f4854a5eSMatthias Ringwald     prov_buffer_out[1] = prov_attention_timer;
1872983fbcbSMatthias Ringwald     pb_adv_send_pdu(the_pb_adv_cid, prov_buffer_out, 2);
188f4854a5eSMatthias Ringwald     // collect confirmation_inputs
1896535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[0], &prov_buffer_out[1], 1);
190f4854a5eSMatthias Ringwald }
191f4854a5eSMatthias Ringwald 
provisioning_send_start(uint16_t the_pb_adv_cid)1922983fbcbSMatthias Ringwald static void provisioning_send_start(uint16_t the_pb_adv_cid){
193f4854a5eSMatthias Ringwald     prov_buffer_out[0] = MESH_PROV_START;
194f4854a5eSMatthias Ringwald     prov_buffer_out[1] = prov_start_algorithm;
195f4854a5eSMatthias Ringwald     prov_buffer_out[2] = prov_start_public_key_used;
196f4854a5eSMatthias Ringwald     prov_buffer_out[3] = prov_start_authentication_method;
197f4854a5eSMatthias Ringwald     prov_buffer_out[4] = prov_start_authentication_action;
198f4854a5eSMatthias Ringwald     prov_buffer_out[5] = prov_start_authentication_size;
1992983fbcbSMatthias Ringwald     pb_adv_send_pdu(the_pb_adv_cid, prov_buffer_out, 6);
200f4854a5eSMatthias Ringwald     // store for confirmation inputs: len 5
2016535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[12], &prov_buffer_out[1], 5);
202f4854a5eSMatthias Ringwald }
203f4854a5eSMatthias Ringwald 
provisioning_send_provisioning_error(uint16_t the_pb_adv_cid)2042983fbcbSMatthias Ringwald static void provisioning_send_provisioning_error(uint16_t the_pb_adv_cid){
205f4854a5eSMatthias Ringwald     prov_buffer_out[0] = MESH_PROV_FAILED;
206f4854a5eSMatthias Ringwald     prov_buffer_out[1] = prov_error_code;
2072983fbcbSMatthias Ringwald     pb_adv_send_pdu(the_pb_adv_cid, prov_buffer_out, 2);
208f4854a5eSMatthias Ringwald }
209f4854a5eSMatthias Ringwald 
provisioning_send_public_key(uint16_t the_pb_adv_cid)2102983fbcbSMatthias Ringwald static void provisioning_send_public_key(uint16_t the_pb_adv_cid){
211f4854a5eSMatthias Ringwald     prov_buffer_out[0] = MESH_PROV_PUB_KEY;
2126535961aSMatthias Ringwald     (void)memcpy(&prov_buffer_out[1], prov_ec_q, 64);
2132983fbcbSMatthias Ringwald     pb_adv_send_pdu(the_pb_adv_cid, prov_buffer_out, 65);
214f4854a5eSMatthias Ringwald     // store for confirmation inputs: len 64
2156535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[17], &prov_buffer_out[1], 64);
216f4854a5eSMatthias Ringwald }
217f4854a5eSMatthias Ringwald 
provisioning_send_confirm(uint16_t the_pb_adv_cid)2182983fbcbSMatthias Ringwald static void provisioning_send_confirm(uint16_t the_pb_adv_cid){
219f4854a5eSMatthias Ringwald     prov_buffer_out[0] = MESH_PROV_CONFIRM;
2206535961aSMatthias Ringwald     (void)memcpy(&prov_buffer_out[1], confirmation_provisioner, 16);
2212983fbcbSMatthias Ringwald     pb_adv_send_pdu(the_pb_adv_cid, prov_buffer_out, 17);
222f4854a5eSMatthias Ringwald }
223f4854a5eSMatthias Ringwald 
provisioning_send_random(uint16_t the_pb_adv_cid)2242983fbcbSMatthias Ringwald static void provisioning_send_random(uint16_t the_pb_adv_cid){
225f4854a5eSMatthias Ringwald     prov_buffer_out[0] = MESH_PROV_RANDOM;
2266535961aSMatthias Ringwald     (void)memcpy(&prov_buffer_out[1], random_provisioner, 16);
2272983fbcbSMatthias Ringwald     pb_adv_send_pdu(the_pb_adv_cid, prov_buffer_out, 17);
228f4854a5eSMatthias Ringwald }
229f4854a5eSMatthias Ringwald 
provisioning_send_data(uint16_t the_pb_adv_cid)2302983fbcbSMatthias Ringwald static void provisioning_send_data(uint16_t the_pb_adv_cid){
231f4854a5eSMatthias Ringwald     prov_buffer_out[0] = MESH_PROV_DATA;
2326535961aSMatthias Ringwald     (void)memcpy(&prov_buffer_out[1], enc_provisioning_data, 25);
2336535961aSMatthias Ringwald     (void)memcpy(&prov_buffer_out[26], provisioning_data_mic, 8);
2342983fbcbSMatthias Ringwald     pb_adv_send_pdu(the_pb_adv_cid, prov_buffer_out, 34);
235f4854a5eSMatthias Ringwald }
236f4854a5eSMatthias Ringwald 
237f4854a5eSMatthias Ringwald typedef enum {
238f4854a5eSMatthias Ringwald     PROVISIONER_IDLE,
23918d0ae06SMatthias Ringwald     PROVISIONER_W4_LINK_OPENED,
240f4854a5eSMatthias Ringwald     PROVISIONER_SEND_INVITE,
241f4854a5eSMatthias Ringwald     PROVISIONER_W4_CAPABILITIES,
242f4854a5eSMatthias Ringwald     PROVISIONER_W4_AUTH_CONFIGURATION,
243f4854a5eSMatthias Ringwald     PROVISIONER_SEND_START,
244f4854a5eSMatthias Ringwald     PROVISIONED_W2_EMIT_READ_PUB_KEY_OOB,
245f4854a5eSMatthias Ringwald     PROVISIONER_SEND_PUB_KEY,
246f4854a5eSMatthias Ringwald     PROVISIONER_W4_PUB_KEY,
247f4854a5eSMatthias Ringwald     PROVISIONER_W4_PUB_KEY_OOB,
248f4854a5eSMatthias Ringwald     PROVISIONER_W4_INPUT_OOK,
249f4854a5eSMatthias Ringwald     PROVISIONER_W4_INPUT_COMPLETE,
250f4854a5eSMatthias Ringwald     PROVISIONER_SEND_CONFIRM,
251f4854a5eSMatthias Ringwald     PROVISIONER_W4_CONFIRM,
252f4854a5eSMatthias Ringwald     PROVISIONER_SEND_RANDOM,
253f4854a5eSMatthias Ringwald     PROVISIONER_W4_RANDOM,
254f4854a5eSMatthias Ringwald     PROVISIONER_SEND_DATA,
255f4854a5eSMatthias Ringwald     PROVISIONER_W4_COMPLETE,
256f4854a5eSMatthias Ringwald     PROVISIONER_SEND_ERROR,
257f4854a5eSMatthias Ringwald } provisioner_state_t;
258f4854a5eSMatthias Ringwald 
259f4854a5eSMatthias Ringwald static provisioner_state_t provisioner_state;
260f4854a5eSMatthias Ringwald 
provisioning_run(void)261f4854a5eSMatthias Ringwald static void provisioning_run(void){
262f4854a5eSMatthias Ringwald     if (prov_waiting_for_outgoing_complete) return;
263f4854a5eSMatthias Ringwald     int start_timer = 1;
264f4854a5eSMatthias Ringwald     switch (provisioner_state){
265f4854a5eSMatthias Ringwald         case PROVISIONER_SEND_ERROR:
266f4854a5eSMatthias Ringwald             start_timer = 0;    // game over
2672983fbcbSMatthias Ringwald             provisioning_send_provisioning_error(pb_adv_cid);
268f4854a5eSMatthias Ringwald             break;
269f4854a5eSMatthias Ringwald         case PROVISIONER_SEND_INVITE:
270f4854a5eSMatthias Ringwald             provisioning_send_invite(pb_adv_cid);
271f4854a5eSMatthias Ringwald             provisioner_state = PROVISIONER_W4_CAPABILITIES;
272f4854a5eSMatthias Ringwald             break;
273f4854a5eSMatthias Ringwald         case PROVISIONER_SEND_START:
274f4854a5eSMatthias Ringwald             provisioning_send_start(pb_adv_cid);
275f4854a5eSMatthias Ringwald             if (prov_start_public_key_used){
276f4854a5eSMatthias Ringwald                 provisioner_state = PROVISIONED_W2_EMIT_READ_PUB_KEY_OOB;
277f4854a5eSMatthias Ringwald             } else {
278f4854a5eSMatthias Ringwald                 provisioner_state = PROVISIONER_SEND_PUB_KEY;
279f4854a5eSMatthias Ringwald             }
280f4854a5eSMatthias Ringwald             break;
281f4854a5eSMatthias Ringwald         case PROVISIONED_W2_EMIT_READ_PUB_KEY_OOB:
282f4854a5eSMatthias Ringwald             printf("Public OOB: please read OOB from remote device\n");
283f4854a5eSMatthias Ringwald             provisioner_state = PROVISIONER_W4_PUB_KEY_OOB;
284f4854a5eSMatthias Ringwald             provisioning_emit_event(MESH_SUBEVENT_PB_PROV_START_RECEIVE_PUBLIC_KEY_OOB, 1);
285f4854a5eSMatthias Ringwald             break;
286f4854a5eSMatthias Ringwald         case PROVISIONER_SEND_PUB_KEY:
2872983fbcbSMatthias Ringwald             provisioning_send_public_key(pb_adv_cid);
288f4854a5eSMatthias Ringwald             if (prov_start_public_key_used){
289f4854a5eSMatthias Ringwald                 provisioning_public_key_ready();
290f4854a5eSMatthias Ringwald             } else {
291f4854a5eSMatthias Ringwald                 provisioner_state = PROVISIONER_W4_PUB_KEY;
292f4854a5eSMatthias Ringwald             }
293f4854a5eSMatthias Ringwald             break;
294f4854a5eSMatthias Ringwald         case PROVISIONER_SEND_CONFIRM:
2952983fbcbSMatthias Ringwald             provisioning_send_confirm(pb_adv_cid);
296f4854a5eSMatthias Ringwald             provisioner_state = PROVISIONER_W4_CONFIRM;
297f4854a5eSMatthias Ringwald             break;
298f4854a5eSMatthias Ringwald         case PROVISIONER_SEND_RANDOM:
2992983fbcbSMatthias Ringwald             provisioning_send_random(pb_adv_cid);
300f4854a5eSMatthias Ringwald             provisioner_state = PROVISIONER_W4_RANDOM;
301f4854a5eSMatthias Ringwald             break;
302f4854a5eSMatthias Ringwald         case PROVISIONER_SEND_DATA:
3032983fbcbSMatthias Ringwald             provisioning_send_data(pb_adv_cid);
304f4854a5eSMatthias Ringwald             provisioner_state = PROVISIONER_W4_COMPLETE;
305f4854a5eSMatthias Ringwald             break;
306f4854a5eSMatthias Ringwald         default:
307f4854a5eSMatthias Ringwald             return;
308f4854a5eSMatthias Ringwald     }
309f4854a5eSMatthias Ringwald     if (start_timer){
310f4854a5eSMatthias Ringwald         provisioning_timer_start();
311f4854a5eSMatthias Ringwald     }
312f4854a5eSMatthias Ringwald     prov_waiting_for_outgoing_complete = 1;
313f4854a5eSMatthias Ringwald }
314f4854a5eSMatthias Ringwald 
315f4854a5eSMatthias Ringwald // End of outgoing PDUs
316f4854a5eSMatthias Ringwald 
provisioning_done(void)317f4854a5eSMatthias Ringwald static void provisioning_done(void){
318f4854a5eSMatthias Ringwald     // if (prov_emit_public_key_oob_active){
319f4854a5eSMatthias Ringwald     //     prov_emit_public_key_oob_active = 0;
320f4854a5eSMatthias Ringwald     //     provisioning_emit_event(MESH_PB_PROV_STOP_EMIT_PUBLIC_KEY_OOB, 1);
321f4854a5eSMatthias Ringwald     // }
322f4854a5eSMatthias Ringwald     if (prov_emit_output_oob_active){
323f4854a5eSMatthias Ringwald         prov_emit_output_oob_active = 0;
324f4854a5eSMatthias Ringwald         provisioning_emit_event(MESH_SUBEVENT_PB_PROV_STOP_EMIT_OUTPUT_OOB, 1);
325f4854a5eSMatthias Ringwald     }
326f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_IDLE;
327f4854a5eSMatthias Ringwald }
328f4854a5eSMatthias Ringwald 
329f4854a5eSMatthias Ringwald 
provisioning_handle_provisioning_error(uint8_t error_code)330f4854a5eSMatthias Ringwald static void provisioning_handle_provisioning_error(uint8_t error_code){
331f4854a5eSMatthias Ringwald     provisioning_timer_stop();
332f4854a5eSMatthias Ringwald     prov_error_code = error_code;
333f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_SEND_ERROR;
334f4854a5eSMatthias Ringwald     provisioning_run();
335f4854a5eSMatthias Ringwald }
336f4854a5eSMatthias Ringwald 
provisioning_handle_link_opened(uint16_t the_pb_adv_cid)3372983fbcbSMatthias Ringwald static void provisioning_handle_link_opened(uint16_t the_pb_adv_cid){
3382983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
339f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_SEND_INVITE;
340f4854a5eSMatthias Ringwald }
341f4854a5eSMatthias Ringwald 
provisioning_handle_capabilities(uint16_t the_pb_adv_cid,const uint8_t * packet_data,uint16_t packet_len)3422983fbcbSMatthias Ringwald static void provisioning_handle_capabilities(uint16_t the_pb_adv_cid, const uint8_t * packet_data, uint16_t packet_len){
343f4854a5eSMatthias Ringwald 
344f4854a5eSMatthias Ringwald     if (packet_len != 11) return;
345f4854a5eSMatthias Ringwald 
346f4854a5eSMatthias Ringwald     // collect confirmation_inputs
3476535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[1], packet_data, packet_len);
348f4854a5eSMatthias Ringwald 
349f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_W4_AUTH_CONFIGURATION;
350f4854a5eSMatthias Ringwald 
351f4854a5eSMatthias Ringwald     // notify client and wait for auth method selection
352f4854a5eSMatthias Ringwald     uint8_t event[16] = { HCI_EVENT_MESH_META, 3, MESH_SUBEVENT_PB_PROV_CAPABILITIES};
3532983fbcbSMatthias Ringwald     little_endian_store_16(event, 3, the_pb_adv_cid);
354f4854a5eSMatthias Ringwald     event[5] = packet_data[0];
355f4854a5eSMatthias Ringwald     little_endian_store_16(event, 6, big_endian_read_16(packet_data, 1));
356f4854a5eSMatthias Ringwald     event[8] = packet_data[3];
357f4854a5eSMatthias Ringwald     event[9] = packet_data[4];
358f4854a5eSMatthias Ringwald     event[10] = packet_data[5];
359f4854a5eSMatthias Ringwald     little_endian_store_16(event, 11, big_endian_read_16(packet_data, 6));
360f4854a5eSMatthias Ringwald     event[13] = packet_data[8];
361f4854a5eSMatthias Ringwald     little_endian_store_16(event, 14, big_endian_read_16(packet_data, 9));
362f4854a5eSMatthias Ringwald     prov_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
363f4854a5eSMatthias Ringwald }
364f4854a5eSMatthias Ringwald 
provisioning_handle_confirmation_provisioner_calculated(void * arg)365f4854a5eSMatthias Ringwald static void provisioning_handle_confirmation_provisioner_calculated(void * arg){
366f4854a5eSMatthias Ringwald     UNUSED(arg);
367f4854a5eSMatthias Ringwald 
368f4854a5eSMatthias Ringwald     printf("ConfirmationProvisioner: ");
369f4854a5eSMatthias Ringwald     printf_hexdump(confirmation_provisioner, sizeof(confirmation_provisioner));
370f4854a5eSMatthias Ringwald 
371f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_SEND_CONFIRM;
372f4854a5eSMatthias Ringwald     provisioning_run();
373f4854a5eSMatthias Ringwald }
374f4854a5eSMatthias Ringwald 
provisioning_handle_random_provisioner(void * arg)375f4854a5eSMatthias Ringwald static void provisioning_handle_random_provisioner(void * arg){
3762983fbcbSMatthias Ringwald     UNUSED(arg);
3772983fbcbSMatthias Ringwald 
378f4854a5eSMatthias Ringwald     printf("RandomProvisioner:   ");
379f4854a5eSMatthias Ringwald     printf_hexdump(random_provisioner, sizeof(random_provisioner));
380f4854a5eSMatthias Ringwald 
381f4854a5eSMatthias Ringwald     // re-use prov_confirmation_inputs buffer
3826535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[0], random_provisioner, 16);
3836535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[16], auth_value, 16);
384f4854a5eSMatthias Ringwald 
385f4854a5eSMatthias Ringwald     // calc confirmation device
386f4854a5eSMatthias Ringwald     btstack_crypto_aes128_cmac_message(&prov_cmac_request, confirmation_key, 32, prov_confirmation_inputs, confirmation_provisioner, &provisioning_handle_confirmation_provisioner_calculated, NULL);
387f4854a5eSMatthias Ringwald }
388f4854a5eSMatthias Ringwald 
provisioning_handle_confirmation_k1_calculated(void * arg)389f4854a5eSMatthias Ringwald static void provisioning_handle_confirmation_k1_calculated(void * arg){
3902983fbcbSMatthias Ringwald     UNUSED(arg);
3912983fbcbSMatthias Ringwald 
392f4854a5eSMatthias Ringwald     printf("ConfirmationKey:   ");
393f4854a5eSMatthias Ringwald     printf_hexdump(confirmation_key, sizeof(confirmation_key));
394f4854a5eSMatthias Ringwald 
395f4854a5eSMatthias Ringwald     // generate random_device
396f4854a5eSMatthias Ringwald     btstack_crypto_random_generate(&prov_random_request,random_provisioner, 16, &provisioning_handle_random_provisioner, NULL);
397f4854a5eSMatthias Ringwald }
398f4854a5eSMatthias Ringwald 
provisioning_handle_confirmation_salt(void * arg)399f4854a5eSMatthias Ringwald static void provisioning_handle_confirmation_salt(void * arg){
400f4854a5eSMatthias Ringwald     UNUSED(arg);
401f4854a5eSMatthias Ringwald 
402f4854a5eSMatthias Ringwald     // dump
403f4854a5eSMatthias Ringwald     printf("ConfirmationSalt:   ");
404f4854a5eSMatthias Ringwald     printf_hexdump(confirmation_salt, sizeof(confirmation_salt));
405f4854a5eSMatthias Ringwald 
406f4854a5eSMatthias Ringwald     // ConfirmationKey
407f4854a5eSMatthias Ringwald     mesh_k1(&prov_cmac_request, dhkey, sizeof(dhkey), confirmation_salt, (const uint8_t*) "prck", 4, confirmation_key, &provisioning_handle_confirmation_k1_calculated, NULL);
408f4854a5eSMatthias Ringwald }
409f4854a5eSMatthias Ringwald 
provisioning_handle_auth_value_ready(void)410f4854a5eSMatthias Ringwald static void provisioning_handle_auth_value_ready(void){
411f4854a5eSMatthias Ringwald     // CalculationInputs
412f4854a5eSMatthias Ringwald     printf("ConfirmationInputs: ");
413f4854a5eSMatthias Ringwald     printf_hexdump(prov_confirmation_inputs, sizeof(prov_confirmation_inputs));
414f4854a5eSMatthias Ringwald 
415f4854a5eSMatthias Ringwald     // calculate s1
416f4854a5eSMatthias Ringwald     btstack_crypto_aes128_cmac_zero(&prov_cmac_request, sizeof(prov_confirmation_inputs), prov_confirmation_inputs, confirmation_salt, &provisioning_handle_confirmation_salt, NULL);
417f4854a5eSMatthias Ringwald }
418f4854a5eSMatthias Ringwald 
provisioning_handle_auth_value_input_oob(void * arg)419f4854a5eSMatthias Ringwald static void provisioning_handle_auth_value_input_oob(void * arg){
4202983fbcbSMatthias Ringwald     UNUSED(arg);
421f4854a5eSMatthias Ringwald 
422f4854a5eSMatthias Ringwald     // limit auth value to single digit
423f4854a5eSMatthias Ringwald     auth_value[15] = auth_value[15] % 9 + 1;
424f4854a5eSMatthias Ringwald     printf("Input OOB: %u\n", auth_value[15]);
425f4854a5eSMatthias Ringwald 
426f4854a5eSMatthias Ringwald     if (prov_authentication_string){
427f4854a5eSMatthias Ringwald         // strings start at 0 while numbers are stored as 16-byte big endian
428f4854a5eSMatthias Ringwald         auth_value[0] = auth_value[15] + '0';
429f4854a5eSMatthias Ringwald         auth_value[15] = 0;
430f4854a5eSMatthias Ringwald     }
431f4854a5eSMatthias Ringwald 
432f4854a5eSMatthias Ringwald     printf("AuthValue: ");
433f4854a5eSMatthias Ringwald     printf_hexdump(auth_value, sizeof(auth_value));
434f4854a5eSMatthias Ringwald 
435f4854a5eSMatthias Ringwald     // emit output oob value
436f4854a5eSMatthias Ringwald     provisioning_emit_output_oob_event(1, auth_value[15]);
437f4854a5eSMatthias Ringwald     prov_emit_output_oob_active = 1;
438f4854a5eSMatthias Ringwald 
439f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_W4_INPUT_COMPLETE;
440f4854a5eSMatthias Ringwald }
441f4854a5eSMatthias Ringwald 
provisioning_handle_input_complete(uint16_t the_pb_adv_cid)4422983fbcbSMatthias Ringwald static void provisioning_handle_input_complete(uint16_t the_pb_adv_cid){
4432983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
444f4854a5eSMatthias Ringwald     provisioning_handle_auth_value_ready();
445f4854a5eSMatthias Ringwald }
446f4854a5eSMatthias Ringwald 
provisioning_public_key_exchange_complete(void)447f4854a5eSMatthias Ringwald static void provisioning_public_key_exchange_complete(void){
448f4854a5eSMatthias Ringwald     // reset auth_value
449f4854a5eSMatthias Ringwald     memset(auth_value, 0, sizeof(auth_value));
450f4854a5eSMatthias Ringwald 
451f4854a5eSMatthias Ringwald     // handle authentication method
452f4854a5eSMatthias Ringwald     switch (prov_start_authentication_method){
453f4854a5eSMatthias Ringwald         case 0x00:
454f4854a5eSMatthias Ringwald             provisioning_handle_auth_value_ready();
455f4854a5eSMatthias Ringwald             break;
456f4854a5eSMatthias Ringwald         case 0x01:
4576535961aSMatthias Ringwald             (void)memcpy(&auth_value[16 - prov_static_oob_len],
4586535961aSMatthias Ringwald                          prov_static_oob_data, prov_static_oob_len);
459f4854a5eSMatthias Ringwald             provisioning_handle_auth_value_ready();
460f4854a5eSMatthias Ringwald             break;
461f4854a5eSMatthias Ringwald         case 0x02:
462f4854a5eSMatthias Ringwald             // Output OOB
463f4854a5eSMatthias Ringwald             prov_authentication_string = prov_start_authentication_action == 0x04;
464f4854a5eSMatthias Ringwald             printf("Output OOB requested (and we're in Provisioniner role), string %u\n", prov_authentication_string);
465f4854a5eSMatthias Ringwald             provisioner_state = PROVISIONER_W4_INPUT_OOK;
466f4854a5eSMatthias Ringwald             provisioning_emit_event(MESH_SUBEVENT_PB_PROV_OUTPUT_OOB_REQUEST, 1);
467f4854a5eSMatthias Ringwald             break;
468f4854a5eSMatthias Ringwald         case 0x03:
469f4854a5eSMatthias Ringwald             // Input OOB
470f4854a5eSMatthias Ringwald             prov_authentication_string = prov_start_authentication_action == 0x03;
471f4854a5eSMatthias Ringwald             printf("Input OOB requested, string %u\n", prov_authentication_string);
472f4854a5eSMatthias Ringwald             printf("Generate random for auth_value\n");
473f4854a5eSMatthias Ringwald             // generate single byte of random data to use for authentication
474f4854a5eSMatthias Ringwald             btstack_crypto_random_generate(&prov_random_request, &auth_value[15], 1, &provisioning_handle_auth_value_input_oob, NULL);
475f4854a5eSMatthias Ringwald             provisioning_emit_event(MESH_SUBEVENT_PB_PROV_START_EMIT_INPUT_OOB, 1);
476f4854a5eSMatthias Ringwald             break;
477f4854a5eSMatthias Ringwald         default:
478f4854a5eSMatthias Ringwald             break;
479f4854a5eSMatthias Ringwald     }
480f4854a5eSMatthias Ringwald }
481f4854a5eSMatthias Ringwald 
provisioning_handle_public_key_dhkey(void * arg)482f4854a5eSMatthias Ringwald static void provisioning_handle_public_key_dhkey(void * arg){
483f4854a5eSMatthias Ringwald     UNUSED(arg);
484f4854a5eSMatthias Ringwald 
485f4854a5eSMatthias Ringwald     printf("DHKEY: ");
486f4854a5eSMatthias Ringwald     printf_hexdump(dhkey, sizeof(dhkey));
487f4854a5eSMatthias Ringwald 
488f4854a5eSMatthias Ringwald #if 0
489f4854a5eSMatthias Ringwald     // skip sending own public key when public key oob is used
490f4854a5eSMatthias Ringwald     if (prov_public_key_oob_available && prov_public_key_oob_used){
491f4854a5eSMatthias Ringwald         // just copy key for confirmation inputs
492f4854a5eSMatthias Ringwald         memcpy(&prov_confirmation_inputs[81], prov_ec_q, 64);
493f4854a5eSMatthias Ringwald     } else {
494f4854a5eSMatthias Ringwald         // queue public key pdu
495f4854a5eSMatthias Ringwald         provisioning_queue_pdu(MESH_PROV_PUB_KEY);
496f4854a5eSMatthias Ringwald     }
497f4854a5eSMatthias Ringwald #endif
498f4854a5eSMatthias Ringwald 
499f4854a5eSMatthias Ringwald     provisioning_public_key_exchange_complete();
500f4854a5eSMatthias Ringwald }
501f4854a5eSMatthias Ringwald 
provisioning_public_key_ready(void)502f4854a5eSMatthias Ringwald static void provisioning_public_key_ready(void){
503f4854a5eSMatthias Ringwald     // calculate DHKey
504f4854a5eSMatthias Ringwald     btstack_crypto_ecc_p256_calculate_dhkey(&prov_ecc_p256_request, remote_ec_q, dhkey, provisioning_handle_public_key_dhkey, NULL);
505f4854a5eSMatthias Ringwald }
506f4854a5eSMatthias Ringwald 
provisioning_handle_public_key(uint16_t the_pb_adv_cid,const uint8_t * packet_data,uint16_t packet_len)5072983fbcbSMatthias Ringwald static void provisioning_handle_public_key(uint16_t the_pb_adv_cid, const uint8_t *packet_data, uint16_t packet_len){
508f4854a5eSMatthias Ringwald     // validate public key
509f4854a5eSMatthias Ringwald     if (packet_len != sizeof(remote_ec_q) || btstack_crypto_ecc_p256_validate_public_key(packet_data) != 0){
510f4854a5eSMatthias Ringwald         printf("Public Key invalid, abort provisioning\n");
511f4854a5eSMatthias Ringwald 
512f4854a5eSMatthias Ringwald         // disconnect provisioning link
5132983fbcbSMatthias Ringwald         pb_adv_close_link(the_pb_adv_cid, 0x02);    // reason: fail
514f4854a5eSMatthias Ringwald         provisioning_timer_stop();
515f4854a5eSMatthias Ringwald         return;
516f4854a5eSMatthias Ringwald     }
517f4854a5eSMatthias Ringwald 
518f4854a5eSMatthias Ringwald #if 0
519f4854a5eSMatthias Ringwald     // stop emit public OOK if specified and send to crypto module
520f4854a5eSMatthias Ringwald     if (prov_public_key_oob_available && prov_public_key_oob_used){
521f4854a5eSMatthias Ringwald         provisioning_emit_event(MESH_PB_PROV_STOP_EMIT_PUBLIC_KEY_OOB, 1);
522f4854a5eSMatthias Ringwald 
523f4854a5eSMatthias Ringwald         printf("Replace generated ECC with Public Key OOB:");
524f4854a5eSMatthias Ringwald         memcpy(prov_ec_q, prov_public_key_oob_q, 64);
525f4854a5eSMatthias Ringwald         printf_hexdump(prov_ec_q, sizeof(prov_ec_q));
526f4854a5eSMatthias Ringwald         btstack_crypto_ecc_p256_set_key(prov_public_key_oob_q, prov_public_key_oob_d);
527f4854a5eSMatthias Ringwald     }
528f4854a5eSMatthias Ringwald #endif
529f4854a5eSMatthias Ringwald 
530f4854a5eSMatthias Ringwald     // store for confirmation inputs: len 64
5316535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[81], packet_data, 64);
532f4854a5eSMatthias Ringwald 
533f4854a5eSMatthias Ringwald     // store remote q
5346535961aSMatthias Ringwald     (void)memcpy(remote_ec_q, packet_data, sizeof(remote_ec_q));
535f4854a5eSMatthias Ringwald 
536f4854a5eSMatthias Ringwald     provisioning_public_key_ready();
537f4854a5eSMatthias Ringwald }
538f4854a5eSMatthias Ringwald 
provisioning_handle_confirmation(uint16_t the_pb_adv_cid,const uint8_t * packet_data,uint16_t packet_len)5392983fbcbSMatthias Ringwald static void provisioning_handle_confirmation(uint16_t the_pb_adv_cid, const uint8_t *packet_data, uint16_t packet_len){
540f4854a5eSMatthias Ringwald 
5412983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
542f4854a5eSMatthias Ringwald     UNUSED(packet_data);
543f4854a5eSMatthias Ringwald     UNUSED(packet_len);
544f4854a5eSMatthias Ringwald 
545f4854a5eSMatthias Ringwald     //
546f4854a5eSMatthias Ringwald     if (prov_emit_output_oob_active){
547f4854a5eSMatthias Ringwald         prov_emit_output_oob_active = 0;
548f4854a5eSMatthias Ringwald         provisioning_emit_event(MESH_SUBEVENT_PB_PROV_STOP_EMIT_OUTPUT_OOB, 1);
549f4854a5eSMatthias Ringwald     }
550f4854a5eSMatthias Ringwald 
551f4854a5eSMatthias Ringwald #if 0
552f4854a5eSMatthias Ringwald     // CalculationInputs
553f4854a5eSMatthias Ringwald     printf("ConfirmationInputs: ");
554f4854a5eSMatthias Ringwald     printf_hexdump(prov_confirmation_inputs, sizeof(prov_confirmation_inputs));
555f4854a5eSMatthias Ringwald 
556f4854a5eSMatthias Ringwald     // calculate s1
557f4854a5eSMatthias Ringwald     btstack_crypto_aes128_cmac_zero(&prov_cmac_request, sizeof(prov_confirmation_inputs), prov_confirmation_inputs, confirmation_salt, &provisioning_handle_confirmation_s1_calculated, NULL);
558f4854a5eSMatthias Ringwald #endif
559f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_SEND_RANDOM;
560f4854a5eSMatthias Ringwald }
561f4854a5eSMatthias Ringwald 
provisioning_handle_data_encrypted(void * arg)562f4854a5eSMatthias Ringwald static void provisioning_handle_data_encrypted(void * arg){
563f4854a5eSMatthias Ringwald     UNUSED(arg);
564f4854a5eSMatthias Ringwald 
565f4854a5eSMatthias Ringwald     // enc_provisioning_data
566f4854a5eSMatthias Ringwald     printf("EncProvisioningData:   ");
567f4854a5eSMatthias Ringwald     printf_hexdump(enc_provisioning_data, sizeof(enc_provisioning_data));
568f4854a5eSMatthias Ringwald 
569f4854a5eSMatthias Ringwald     btstack_crypto_ccm_get_authentication_value(&prov_ccm_request, provisioning_data_mic);
570f4854a5eSMatthias Ringwald     printf("MIC:   ");
571f4854a5eSMatthias Ringwald     printf_hexdump(provisioning_data_mic, sizeof(provisioning_data_mic));
572f4854a5eSMatthias Ringwald 
573f4854a5eSMatthias Ringwald     // send
574f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_SEND_DATA;
575f4854a5eSMatthias Ringwald     provisioning_run();
576f4854a5eSMatthias Ringwald }
577f4854a5eSMatthias Ringwald 
provisioning_handle_session_nonce_calculated(void * arg)578f4854a5eSMatthias Ringwald static void provisioning_handle_session_nonce_calculated(void * arg){
579f4854a5eSMatthias Ringwald     UNUSED(arg);
580f4854a5eSMatthias Ringwald 
581f4854a5eSMatthias Ringwald     // The nonce shall be the 13 least significant octets == zero most significant octets
582f4854a5eSMatthias Ringwald     uint8_t temp[13];
5836535961aSMatthias Ringwald     (void)memcpy(temp, &session_nonce[3], 13);
5846535961aSMatthias Ringwald     (void)memcpy(session_nonce, temp, 13);
585f4854a5eSMatthias Ringwald 
586f4854a5eSMatthias Ringwald     // SessionNonce
587f4854a5eSMatthias Ringwald     printf("SessionNonce:   ");
588f4854a5eSMatthias Ringwald     printf_hexdump(session_nonce, 13);
589f4854a5eSMatthias Ringwald 
590f4854a5eSMatthias Ringwald     // setup provisioning data
5916535961aSMatthias Ringwald     (void)memcpy(&provisioning_data[0], net_key, 16);
592f4854a5eSMatthias Ringwald     big_endian_store_16(provisioning_data, 16, net_key_index);
593f4854a5eSMatthias Ringwald     provisioning_data[18] = flags;
594f4854a5eSMatthias Ringwald     big_endian_store_32(provisioning_data, 19, iv_index);
595f4854a5eSMatthias Ringwald     big_endian_store_16(provisioning_data, 23, unicast_address);
596f4854a5eSMatthias Ringwald 
597f4854a5eSMatthias Ringwald     btstack_crypto_ccm_init(&prov_ccm_request, session_key, session_nonce, 25, 0, 8);
598f4854a5eSMatthias Ringwald     btstack_crypto_ccm_encrypt_block(&prov_ccm_request, 25, provisioning_data, enc_provisioning_data, &provisioning_handle_data_encrypted, NULL);
599f4854a5eSMatthias Ringwald }
600f4854a5eSMatthias Ringwald 
provisioning_handle_session_key_calculated(void * arg)601f4854a5eSMatthias Ringwald static void provisioning_handle_session_key_calculated(void * arg){
602f4854a5eSMatthias Ringwald     UNUSED(arg);
603f4854a5eSMatthias Ringwald 
604f4854a5eSMatthias Ringwald     // SessionKey
605f4854a5eSMatthias Ringwald     printf("SessionKey:   ");
606f4854a5eSMatthias Ringwald     printf_hexdump(session_key, sizeof(session_key));
607f4854a5eSMatthias Ringwald 
608f4854a5eSMatthias Ringwald     // SessionNonce
609f4854a5eSMatthias Ringwald     mesh_k1(&prov_cmac_request, dhkey, sizeof(dhkey), provisioning_salt, (const uint8_t*) "prsn", 4, session_nonce, &provisioning_handle_session_nonce_calculated, NULL);
610f4854a5eSMatthias Ringwald }
611f4854a5eSMatthias Ringwald 
612f4854a5eSMatthias Ringwald 
provisioning_handle_provisioning_salt_calculated(void * arg)613f4854a5eSMatthias Ringwald static void provisioning_handle_provisioning_salt_calculated(void * arg){
614f4854a5eSMatthias Ringwald     UNUSED(arg);
615f4854a5eSMatthias Ringwald 
616f4854a5eSMatthias Ringwald     // ProvisioningSalt
617f4854a5eSMatthias Ringwald     printf("ProvisioningSalt:   ");
618f4854a5eSMatthias Ringwald     printf_hexdump(provisioning_salt, sizeof(provisioning_salt));
619f4854a5eSMatthias Ringwald 
620f4854a5eSMatthias Ringwald     // SessionKey
621f4854a5eSMatthias Ringwald     mesh_k1(&prov_cmac_request, dhkey, sizeof(dhkey), provisioning_salt, (const uint8_t*) "prsk", 4, session_key, &provisioning_handle_session_key_calculated, NULL);
622f4854a5eSMatthias Ringwald }
623f4854a5eSMatthias Ringwald 
provisioning_handle_random(uint16_t the_pb_adv_cid,const uint8_t * packet_data,uint16_t packet_len)6242983fbcbSMatthias Ringwald static void provisioning_handle_random(uint16_t the_pb_adv_cid, const uint8_t *packet_data, uint16_t packet_len){
625f4854a5eSMatthias Ringwald 
6262983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
627f4854a5eSMatthias Ringwald     UNUSED(packet_len);
628f4854a5eSMatthias Ringwald 
629f4854a5eSMatthias Ringwald     // TODO: validate Confirmation
630f4854a5eSMatthias Ringwald 
631f4854a5eSMatthias Ringwald     // calc ProvisioningSalt = s1(ConfirmationSalt || RandomProvisioner || RandomDevice)
6326535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[0], confirmation_salt, 16);
6336535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[16], random_provisioner, 16);
6346535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[32], packet_data, 16);
635f4854a5eSMatthias Ringwald     btstack_crypto_aes128_cmac_zero(&prov_cmac_request, 48, prov_confirmation_inputs, provisioning_salt, &provisioning_handle_provisioning_salt_calculated, NULL);
636f4854a5eSMatthias Ringwald }
637f4854a5eSMatthias Ringwald 
provisioning_handle_complete(uint16_t the_pb_adv_cid)6382983fbcbSMatthias Ringwald static void provisioning_handle_complete(uint16_t the_pb_adv_cid){
6392983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
640f4854a5eSMatthias Ringwald }
641f4854a5eSMatthias Ringwald 
provisioning_handle_pdu(uint8_t packet_type,uint16_t channel,uint8_t * packet,uint16_t size)642f4854a5eSMatthias Ringwald static void provisioning_handle_pdu(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
6432983fbcbSMatthias Ringwald     UNUSED(channel);
644f4854a5eSMatthias Ringwald 
645f4854a5eSMatthias Ringwald     if (size < 1) return;
646f4854a5eSMatthias Ringwald 
647f4854a5eSMatthias Ringwald     switch (packet_type){
648f4854a5eSMatthias Ringwald         case HCI_EVENT_PACKET:
6497bbeb3adSMilanka Ringwald             if (hci_event_packet_get_type(packet) != HCI_EVENT_MESH_META)  break;
6507bbeb3adSMilanka Ringwald 
6517bbeb3adSMilanka Ringwald             switch (hci_event_mesh_meta_get_subevent_code(packet)){
652f4854a5eSMatthias Ringwald                 case MESH_SUBEVENT_PB_TRANSPORT_LINK_OPEN:
65318d0ae06SMatthias Ringwald                     if (provisioner_state != PROVISIONER_W4_LINK_OPENED) break;
654d16ad46bSMatthias Ringwald                     switch (mesh_subevent_pb_transport_link_open_get_status(packet)) {
655d16ad46bSMatthias Ringwald                         case ERROR_CODE_SUCCESS:
656f4854a5eSMatthias Ringwald                             printf("Link opened, sending Invite\n");
657f4854a5eSMatthias Ringwald                             provisioning_handle_link_opened(pb_adv_cid);
658f4854a5eSMatthias Ringwald                             break;
659d16ad46bSMatthias Ringwald                         default:
660d16ad46bSMatthias Ringwald                             printf("Link open failed, abort\n");
661d16ad46bSMatthias Ringwald                             provisioning_done();
662d16ad46bSMatthias Ringwald                             break;
663d16ad46bSMatthias Ringwald                     }
664d16ad46bSMatthias Ringwald                     break;
665f4854a5eSMatthias Ringwald                 case MESH_SUBEVENT_PB_TRANSPORT_PDU_SENT:
666f4854a5eSMatthias Ringwald                     printf("Outgoing packet acked\n");
667f4854a5eSMatthias Ringwald                     prov_waiting_for_outgoing_complete = 0;
668f4854a5eSMatthias Ringwald                     break;
669f4854a5eSMatthias Ringwald                 case MESH_SUBEVENT_PB_TRANSPORT_LINK_CLOSED:
670f4854a5eSMatthias Ringwald                     printf("Link close, reset state\n");
671f4854a5eSMatthias Ringwald                     provisioning_done();
672f4854a5eSMatthias Ringwald                     break;
6737bbeb3adSMilanka Ringwald                 default:
6747bbeb3adSMilanka Ringwald                     break;
675f4854a5eSMatthias Ringwald             }
676f4854a5eSMatthias Ringwald             break;
677f4854a5eSMatthias Ringwald         case PROVISIONING_DATA_PACKET:
678f4854a5eSMatthias Ringwald             // check state
679f4854a5eSMatthias Ringwald             switch (provisioner_state){
680f4854a5eSMatthias Ringwald                 case PROVISIONER_W4_CAPABILITIES:
681f4854a5eSMatthias Ringwald                     if (packet[0] != MESH_PROV_CAPABILITIES) provisioning_handle_provisioning_error(0x03);
682f4854a5eSMatthias Ringwald                     printf("MESH_PROV_CAPABILITIES: ");
683f4854a5eSMatthias Ringwald                     printf_hexdump(&packet[1], size-1);
684f4854a5eSMatthias Ringwald                     provisioning_handle_capabilities(pb_adv_cid, &packet[1], size-1);
685f4854a5eSMatthias Ringwald                     break;
686f4854a5eSMatthias Ringwald                 case PROVISIONER_W4_PUB_KEY:
687f4854a5eSMatthias Ringwald                     if (packet[0] != MESH_PROV_PUB_KEY) provisioning_handle_provisioning_error(0x03);
688f4854a5eSMatthias Ringwald                     printf("MESH_PROV_PUB_KEY: ");
689f4854a5eSMatthias Ringwald                     printf_hexdump(&packet[1], size-1);
690f4854a5eSMatthias Ringwald                     provisioning_handle_public_key(pb_adv_cid, &packet[1], size-1);
691f4854a5eSMatthias Ringwald                     break;
692f4854a5eSMatthias Ringwald                 case PROVISIONER_W4_INPUT_COMPLETE:
693f4854a5eSMatthias Ringwald                     if (packet[0] != MESH_PROV_INPUT_COMPLETE) provisioning_handle_provisioning_error(0x03);
694f4854a5eSMatthias Ringwald                     printf("MESH_PROV_INPUT_COMPLETE: ");
695f4854a5eSMatthias Ringwald                     printf_hexdump(&packet[1], size-1);
696f4854a5eSMatthias Ringwald                     provisioning_handle_input_complete(pb_adv_cid);
697f4854a5eSMatthias Ringwald                     break;
698f4854a5eSMatthias Ringwald                 case PROVISIONER_W4_CONFIRM:
699f4854a5eSMatthias Ringwald                     if (packet[0] != MESH_PROV_CONFIRM) provisioning_handle_provisioning_error(0x03);
700f4854a5eSMatthias Ringwald                     printf("MESH_PROV_CONFIRM: ");
701f4854a5eSMatthias Ringwald                     printf_hexdump(&packet[1], size-1);
702f4854a5eSMatthias Ringwald                     provisioning_handle_confirmation(pb_adv_cid, &packet[1], size-1);
703f4854a5eSMatthias Ringwald                     break;
704f4854a5eSMatthias Ringwald                 case PROVISIONER_W4_RANDOM:
705f4854a5eSMatthias Ringwald                     if (packet[0] != MESH_PROV_RANDOM) provisioning_handle_provisioning_error(0x03);
706f4854a5eSMatthias Ringwald                     printf("MESH_PROV_RANDOM:  ");
707f4854a5eSMatthias Ringwald                     printf_hexdump(&packet[1], size-1);
708f4854a5eSMatthias Ringwald                     provisioning_handle_random(pb_adv_cid, &packet[1], size-1);
709f4854a5eSMatthias Ringwald                     break;
710f4854a5eSMatthias Ringwald                 case PROVISIONER_W4_COMPLETE:
711f4854a5eSMatthias Ringwald                     if (packet[0] != MESH_PROV_COMPLETE) provisioning_handle_provisioning_error(0x03);
712f4854a5eSMatthias Ringwald                     printf("MESH_PROV_COMPLETE:  ");
713f4854a5eSMatthias Ringwald                     provisioning_handle_complete(pb_adv_cid);
714f4854a5eSMatthias Ringwald                     break;
715f4854a5eSMatthias Ringwald                 default:
716f4854a5eSMatthias Ringwald                     printf("TODO: handle provisioning state %x\n", provisioner_state);
717f4854a5eSMatthias Ringwald                     break;
718f4854a5eSMatthias Ringwald             }
719f4854a5eSMatthias Ringwald             break;
720f4854a5eSMatthias Ringwald         default:
721f4854a5eSMatthias Ringwald             break;
722f4854a5eSMatthias Ringwald     }
723f4854a5eSMatthias Ringwald     provisioning_run();
724f4854a5eSMatthias Ringwald }
725f4854a5eSMatthias Ringwald 
prov_key_generated(void * arg)726f4854a5eSMatthias Ringwald static void prov_key_generated(void * arg){
727f4854a5eSMatthias Ringwald     UNUSED(arg);
728f4854a5eSMatthias Ringwald     printf("ECC-P256: ");
729f4854a5eSMatthias Ringwald     printf_hexdump(prov_ec_q, sizeof(prov_ec_q));
730f4854a5eSMatthias Ringwald     // allow override
731f4854a5eSMatthias Ringwald     if (prov_public_key_oob_available){
732f4854a5eSMatthias Ringwald         printf("Replace generated ECC with Public Key OOB:");
7336535961aSMatthias Ringwald         (void)memcpy(prov_ec_q, prov_public_key_oob_q, 64);
734f4854a5eSMatthias Ringwald         printf_hexdump(prov_ec_q, sizeof(prov_ec_q));
735f4854a5eSMatthias Ringwald         btstack_crypto_ecc_p256_set_key(prov_public_key_oob_q, prov_public_key_oob_d);
736f4854a5eSMatthias Ringwald     }
737f4854a5eSMatthias Ringwald }
738f4854a5eSMatthias Ringwald 
provisioning_provisioner_init(void)739f4854a5eSMatthias Ringwald void provisioning_provisioner_init(void){
740f4854a5eSMatthias Ringwald     pb_adv_cid = MESH_PB_TRANSPORT_INVALID_CID;
741f4854a5eSMatthias Ringwald     pb_adv_init();
74294d617e4SMatthias Ringwald     pb_adv_register_provisioner_packet_handler(&provisioning_handle_pdu);
743f4854a5eSMatthias Ringwald }
744f4854a5eSMatthias Ringwald 
provisioning_provisioner_register_packet_handler(btstack_packet_handler_t packet_handler)745f4854a5eSMatthias Ringwald void provisioning_provisioner_register_packet_handler(btstack_packet_handler_t packet_handler){
746f4854a5eSMatthias Ringwald     prov_packet_handler = packet_handler;
747f4854a5eSMatthias Ringwald }
748f4854a5eSMatthias Ringwald 
provisioning_provisioner_start_provisioning(const uint8_t * device_uuid)749f4854a5eSMatthias Ringwald uint16_t provisioning_provisioner_start_provisioning(const uint8_t * device_uuid){
750f4854a5eSMatthias Ringwald     // generate new public key
751f4854a5eSMatthias Ringwald     btstack_crypto_ecc_p256_generate_key(&prov_ecc_p256_request, prov_ec_q, &prov_key_generated, NULL);
752f4854a5eSMatthias Ringwald 
753f4854a5eSMatthias Ringwald     if (pb_adv_cid == MESH_PB_TRANSPORT_INVALID_CID) {
75418d0ae06SMatthias Ringwald         provisioner_state = PROVISIONER_W4_LINK_OPENED;
755f4854a5eSMatthias Ringwald         pb_adv_cid = pb_adv_create_link(device_uuid);
756f4854a5eSMatthias Ringwald     }
757f4854a5eSMatthias Ringwald     return pb_adv_cid;
758f4854a5eSMatthias Ringwald }
759f4854a5eSMatthias Ringwald 
provisioning_provisioner_set_static_oob(uint16_t the_pb_adv_cid,uint16_t static_oob_len,const uint8_t * static_oob_data)7602983fbcbSMatthias Ringwald void provisioning_provisioner_set_static_oob(uint16_t the_pb_adv_cid, uint16_t static_oob_len, const uint8_t * static_oob_data){
7612983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
762f4854a5eSMatthias Ringwald     prov_static_oob_data = static_oob_data;
763f4854a5eSMatthias Ringwald     prov_static_oob_len  = btstack_min(static_oob_len, 16);
764f4854a5eSMatthias Ringwald }
765f4854a5eSMatthias Ringwald 
provisioning_provisioner_select_authentication_method(uint16_t the_pb_adv_cid,uint8_t algorithm,uint8_t public_key_used,uint8_t authentication_method,uint8_t authentication_action,uint8_t authentication_size)7662983fbcbSMatthias Ringwald uint8_t provisioning_provisioner_select_authentication_method(uint16_t the_pb_adv_cid, uint8_t algorithm, uint8_t public_key_used, uint8_t authentication_method, uint8_t authentication_action, uint8_t authentication_size){
7672983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
768f4854a5eSMatthias Ringwald 
769f4854a5eSMatthias Ringwald     if (provisioner_state != PROVISIONER_W4_AUTH_CONFIGURATION) return ERROR_CODE_COMMAND_DISALLOWED;
770f4854a5eSMatthias Ringwald 
771f4854a5eSMatthias Ringwald     prov_start_algorithm = algorithm;
772f4854a5eSMatthias Ringwald     prov_start_public_key_used = public_key_used;
773f4854a5eSMatthias Ringwald     prov_start_authentication_method = authentication_method;
774f4854a5eSMatthias Ringwald     prov_start_authentication_action = authentication_action;
775f4854a5eSMatthias Ringwald     prov_start_authentication_size   = authentication_size;
776f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_SEND_START;
777f4854a5eSMatthias Ringwald 
778f4854a5eSMatthias Ringwald     return ERROR_CODE_SUCCESS;
779f4854a5eSMatthias Ringwald }
780f4854a5eSMatthias Ringwald 
provisioning_provisioner_public_key_oob_received(uint16_t the_pb_adv_cid,const uint8_t * public_key)7812983fbcbSMatthias Ringwald uint8_t provisioning_provisioner_public_key_oob_received(uint16_t the_pb_adv_cid, const uint8_t * public_key){
7822983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
783f4854a5eSMatthias Ringwald 
784f4854a5eSMatthias Ringwald     if (provisioner_state != PROVISIONER_W4_PUB_KEY_OOB) return ERROR_CODE_COMMAND_DISALLOWED;
785f4854a5eSMatthias Ringwald 
786f4854a5eSMatthias Ringwald     // store for confirmation inputs: len 64
7876535961aSMatthias Ringwald     (void)memcpy(&prov_confirmation_inputs[81], public_key, 64);
788f4854a5eSMatthias Ringwald 
789f4854a5eSMatthias Ringwald     // store remote q
7906535961aSMatthias Ringwald     (void)memcpy(remote_ec_q, public_key, sizeof(remote_ec_q));
791f4854a5eSMatthias Ringwald 
792f4854a5eSMatthias Ringwald     // continue procedure
793f4854a5eSMatthias Ringwald     provisioner_state = PROVISIONER_SEND_PUB_KEY;
794f4854a5eSMatthias Ringwald     provisioning_run();
795f4854a5eSMatthias Ringwald 
796f4854a5eSMatthias Ringwald     return ERROR_CODE_SUCCESS;
797f4854a5eSMatthias Ringwald }
798f4854a5eSMatthias Ringwald 
provisioning_provisioner_input_oob_complete_numeric(uint16_t the_pb_adv_cid,uint32_t input_oob)7992983fbcbSMatthias Ringwald void provisioning_provisioner_input_oob_complete_numeric(uint16_t the_pb_adv_cid, uint32_t input_oob){
8002983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
801f4854a5eSMatthias Ringwald     if (provisioner_state != PROVISIONER_W4_INPUT_OOK) return;
802f4854a5eSMatthias Ringwald 
803f4854a5eSMatthias Ringwald     // store input_oob as auth value
804f4854a5eSMatthias Ringwald     big_endian_store_32(auth_value, 12, input_oob);
805f4854a5eSMatthias Ringwald     provisioning_handle_auth_value_ready();
806f4854a5eSMatthias Ringwald }
807f4854a5eSMatthias Ringwald 
provisioning_provisioner_input_oob_complete_alphanumeric(uint16_t the_pb_adv_cid,const uint8_t * input_oob_data,uint16_t input_oob_len)8082983fbcbSMatthias Ringwald void provisioning_provisioner_input_oob_complete_alphanumeric(uint16_t the_pb_adv_cid, const uint8_t * input_oob_data, uint16_t input_oob_len){
8092983fbcbSMatthias Ringwald     UNUSED(the_pb_adv_cid);
810f4854a5eSMatthias Ringwald     if (provisioner_state != PROVISIONER_W4_INPUT_OOK) return;
811f4854a5eSMatthias Ringwald 
812f4854a5eSMatthias Ringwald     // store input_oob and fillup with zeros
813f4854a5eSMatthias Ringwald     input_oob_len = btstack_min(input_oob_len, 16);
814f4854a5eSMatthias Ringwald     memset(auth_value, 0, 16);
8156535961aSMatthias Ringwald     (void)memcpy(auth_value, input_oob_data, input_oob_len);
816f4854a5eSMatthias Ringwald     provisioning_handle_auth_value_ready();
817f4854a5eSMatthias Ringwald }
818f4854a5eSMatthias Ringwald 
819