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