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