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