xref: /btstack/test/mesh/provisioning_device_test.cpp (revision 7dd36736a374f819de3bf17c37f6cbfc0de037e2)
1 /*
2  * Copyright (C) 2017 BlueKitchen GmbH
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holders nor the names of
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  * 4. Any redistribution, use, or modification is done solely for
17  *    personal benefit and not for any commercial purpose or for
18  *    monetary gain.
19  *
20  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * Please inquire about commercial licensing options at
34  * [email protected]
35  *
36  */
37 
38 #include <stdint.h>
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include "ble/mesh/pb_adv.h"
43 #include "ble/gatt-service/mesh_provisioning_service_server.h"
44 #include "provisioning_device.h"
45 #include "btstack.h"
46 
47 #include "CppUTest/TestHarness.h"
48 #include "CppUTest/CommandLineTestRunner.h"
49 
50 static void CHECK_EQUAL_ARRAY(uint8_t * expected, uint8_t * actual, int size){
51     int i;
52     for (i=0; i<size; i++){
53         if (expected[i] != actual[i]) {
54             printf("offset %u wrong\n", i);
55             printf("expected: "); printf_hexdump(expected, size);
56             printf("actual:   "); printf_hexdump(actual, size);
57         }
58         BYTES_EQUAL(expected[i], actual[i]);
59     }
60 }
61 
62 void dump_data(uint8_t * buffer, uint16_t size){
63     static int data_counter = 1;
64     char var_name[80];
65     sprintf(var_name, "test_data_%02u", data_counter);
66     printf("uint8_t %s[] = { ", var_name);
67     for (int i = 0; i < size ; i++){
68         if ((i % 16) == 0) printf("\n    ");
69         printf ("0x%02x, ", buffer[i]);
70     }
71     printf("};\n");
72     data_counter++;
73 }
74 
75 int parse_hex(uint8_t * buffer, const char * hex_string){
76     int len = 0;
77     while (*hex_string){
78         if (*hex_string == ' '){
79             hex_string++;
80             continue;
81         }
82         int high_nibble = nibble_for_char(*hex_string++);
83         int low_nibble = nibble_for_char(*hex_string++);
84         *buffer++ = (high_nibble << 4) | low_nibble;
85         len++;
86     }
87     return len;
88 }
89 
90 // returns if anything was done
91 extern "C" int mock_process_hci_cmd(void);
92 
93 const static uint8_t device_uuid[] = { 0x00, 0x1B, 0xDC, 0x08, 0x10, 0x21, 0x0B, 0x0E, 0x0A, 0x0C, 0x00, 0x0B, 0x0E, 0x0A, 0x0C, 0x00 };
94 
95 // pb-adv mock for testing
96 
97 static btstack_packet_handler_t pb_adv_packet_handler;
98 
99 static uint8_t * pdu_data;
100 static uint16_t  pdu_size;
101 
102 /**
103  * Initialize Provisioning Bearer using Advertisement Bearer
104  * @param DeviceUUID
105  */
106 void pb_adv_init(const uint8_t * device_uuid){}
107 void pb_gatt_init(const uint8_t * device_uuid){}
108 
109 /**
110  * Close Link
111  * @param con_handle
112  * @param reason 0 = success, 1 = timeout, 2 = fail
113  */
114 void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){}
115 void pb_adv_close_link(hci_con_handle_t con_handle, uint8_t reason){}
116 
117 
118 /**
119  * Register listener for Provisioning PDUs and MESH_PBV_ADV_SEND_COMPLETE
120  */
121 void pb_adv_register_packet_handler(btstack_packet_handler_t packet_handler){
122     pb_adv_packet_handler = packet_handler;
123 }
124 
125 void pb_gatt_register_packet_handler(btstack_packet_handler_t packet_handler){
126     UNUSED(packet_handler);
127 }
128 /**
129  * Send Provisioning PDU
130  */
131 void pb_adv_send_pdu(uint16_t pb_transport_cid, const uint8_t * pdu, uint16_t size){
132     UNUSED(pb_transport_cid);
133     pdu_data = (uint8_t*) pdu;
134     pdu_size = size;
135     // dump_data((uint8_t*)pdu,size);
136     // printf_hexdump(pdu, size);
137 }
138 void pb_gatt_send_pdu(uint16_t con_handle, const uint8_t * pdu, uint16_t pdu_size){}
139 
140 static void perform_crypto_operations(void){
141     int more = 1;
142     while (more){
143         more = mock_process_hci_cmd();
144     }
145 }
146 
147 static void send_prov_pdu(const uint8_t * packet, uint16_t size){
148     pb_adv_packet_handler(PROVISIONING_DATA_PACKET, 0, (uint8_t*) packet, size);
149     perform_crypto_operations();
150 }
151 
152 static void pb_adv_emit_pdu_sent(uint8_t status){
153     uint8_t event[] = { HCI_EVENT_MESH_META, 2, MESH_PB_TRANSPORT_PDU_SENT, status};
154     pb_adv_packet_handler(HCI_EVENT_PACKET, 0, event, sizeof(event));
155 }
156 
157 static int scan_hex_byte(const char * byte_string){
158     int upper_nibble = nibble_for_char(*byte_string++);
159     if (upper_nibble < 0) return -1;
160     int lower_nibble = nibble_for_char(*byte_string);
161     if (lower_nibble < 0) return -1;
162     return (upper_nibble << 4) | lower_nibble;
163 }
164 
165 static int btstack_parse_hex(const char * string, uint16_t len, uint8_t * buffer){
166     int i;
167     for (i = 0; i < len; i++) {
168         int single_byte = scan_hex_byte(string);
169         if (single_byte < 0) return 0;
170         string += 2;
171         buffer[i] = (uint8_t)single_byte;
172         // don't check seperator after last byte
173         if (i == len - 1) {
174             return 1;
175         }
176         // optional seperator
177         char separator = *string;
178         if (separator == ':' && separator == '-' && separator == ' ') {
179             string++;
180         }
181     }
182     return 1;
183 }
184 
185 // void pb_gatt_close_link(hci_con_handle_t con_handle, uint8_t reason){
186 // }
187 
188 static uint8_t      prov_static_oob_data[16];
189 static const char * prov_static_oob_string = "00000000000000000102030405060708";
190 
191 TEST_GROUP(Provisioning){
192     void setup(void){
193         btstack_crypto_init();
194         provisioning_device_init(device_uuid);
195         btstack_parse_hex(prov_static_oob_string, 16, prov_static_oob_data);
196         provisioning_device_set_static_oob(16, prov_static_oob_data);
197         provisioning_device_set_output_oob_actions(0x08, 0x08);
198         provisioning_device_set_input_oob_actions(0x08, 0x08);
199         perform_crypto_operations();
200     }
201 };
202 
203 uint8_t prov_invite[] = { 0x00, 0x00 };
204 uint8_t prov_capabilities[] = { 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x08, 0x00, 0x08, 0x08, 0x00, 0x08, };
205 uint8_t prov_start[] = { 0x02, 0x00, 0x00, 0x02, 0x00, 0x01 };
206 uint8_t prov_public_key[] = { 0x03,
207     0xf0, 0xc8, 0x63, 0xf8, 0xe5, 0x55, 0x11, 0x4b, 0xf4, 0x88, 0x2c, 0xc7, 0x87, 0xb9, 0x5c, 0x27,
208     0x2a, 0x7f, 0xe4, 0xdc, 0xdd, 0xf1, 0x92, 0x2f, 0x4f, 0x18, 0xa4, 0x94, 0xe1, 0xc3, 0x57, 0xa1,
209     0xa6, 0xc3, 0x2d, 0x07, 0xbe, 0xb5, 0x76, 0xab, 0x60, 0x10, 0x68, 0x06, 0x8f, 0x0a, 0x9e, 0x01,
210     0x60, 0xc3, 0xa1, 0x41, 0x19, 0xf5, 0xd4, 0x26, 0xa7, 0x95, 0x5d, 0xa3, 0xe6, 0xed, 0x3e, 0x81, };
211 uint8_t prov_confirm[] = { 0x05, 0x80, 0x4d, 0xdc, 0x3b, 0xba, 0x60, 0xd5, 0x93, 0x5b, 0x56, 0xef, 0xb5, 0xcb, 0x59, 0x31, 0xfa, };
212 uint8_t prov_random[]  = { 0x06, 0x9b, 0x4d, 0x39, 0xf6, 0xf7, 0xe8, 0xa1, 0x05, 0xd3, 0xfe, 0xed, 0xa5, 0xd5, 0xf3, 0xd9, 0xe4, };
213 uint8_t prov_data[] = {
214     0x07,
215     0x85, 0x66, 0xac, 0x46, 0x37, 0x34, 0x86, 0xe1, 0x3e, 0x4c, 0x13, 0x52, 0xd0, 0x6d, 0x34, 0x7d,
216     0xce, 0xf1, 0xd1, 0x7d, 0xbd, 0xbe, 0xcc, 0x99, 0xc3,
217     0x93, 0x87, 0xfc, 0xb0, 0x72, 0x0f, 0xd8, 0x8d };
218 uint8_t prov_complete[] = { 0x08, };
219 
220 TEST(Provisioning, Prov1){
221     // send prov inviate
222     send_prov_pdu(prov_invite, sizeof(prov_invite));
223     // check for prov cap
224     CHECK_EQUAL_ARRAY(prov_capabilities, pdu_data, sizeof(prov_capabilities));
225     pb_adv_emit_pdu_sent(0);
226     // send prov start
227     send_prov_pdu(prov_start, sizeof(prov_start));
228     // send public key
229     send_prov_pdu(prov_public_key, sizeof(prov_public_key));
230     // check for public key
231     CHECK_EQUAL_ARRAY(prov_public_key, pdu_data, sizeof(prov_public_key));
232     pb_adv_emit_pdu_sent(0);
233     // send prov confirm
234     send_prov_pdu(prov_confirm, sizeof(prov_confirm));
235     // check for prov confirm
236     CHECK_EQUAL_ARRAY(prov_confirm, pdu_data, sizeof(prov_confirm));
237     pb_adv_emit_pdu_sent(0);
238     // send prov random
239     send_prov_pdu(prov_random, sizeof(prov_random));
240     // check for prov random
241     CHECK_EQUAL_ARRAY(prov_random, pdu_data, sizeof(prov_random));
242     pb_adv_emit_pdu_sent(0);
243     // send prov data
244     send_prov_pdu(prov_data, sizeof(prov_data));
245     // check prov complete
246     CHECK_EQUAL_ARRAY(prov_complete, pdu_data, sizeof(prov_complete));
247     pb_adv_emit_pdu_sent(0);
248 }
249 
250 int main (int argc, const char * argv[]){
251     hci_dump_open("hci_dump.pklg", HCI_DUMP_PACKETLOGGER);
252     return CommandLineTestRunner::RunAllTests(argc, argv);
253 }
254