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