xref: /btstack/test/fuzz/fuzz_gatt_client.c (revision 7d33cb261f4fdca8278df2c164becfe463e20237)
193fdb564SMilanka Ringwald #include <stdint.h>
293fdb564SMilanka Ringwald #include <stddef.h>
393fdb564SMilanka Ringwald 
493fdb564SMilanka Ringwald #include "ble/gatt_client.h"
593fdb564SMilanka Ringwald #include "btstack_run_loop_posix.h"
693fdb564SMilanka Ringwald #include "btstack_memory.h"
793fdb564SMilanka Ringwald 
893fdb564SMilanka Ringwald static  void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size);
993fdb564SMilanka Ringwald 
1093fdb564SMilanka Ringwald static int hci_transport_fuzz_set_baudrate(uint32_t baudrate){
1193fdb564SMilanka Ringwald     return 0;
1293fdb564SMilanka Ringwald }
1393fdb564SMilanka Ringwald 
1493fdb564SMilanka Ringwald static int hci_transport_fuzz_can_send_now(uint8_t packet_type){
1593fdb564SMilanka Ringwald     return 1;
1693fdb564SMilanka Ringwald }
1793fdb564SMilanka Ringwald 
1893fdb564SMilanka Ringwald static int hci_transport_fuzz_send_packet(uint8_t packet_type, uint8_t * packet, int size){
1993fdb564SMilanka Ringwald     return 0;
2093fdb564SMilanka Ringwald }
2193fdb564SMilanka Ringwald 
2293fdb564SMilanka Ringwald static void hci_transport_fuzz_init(const void * transport_config){
2393fdb564SMilanka Ringwald }
2493fdb564SMilanka Ringwald 
2593fdb564SMilanka Ringwald static int hci_transport_fuzz_open(void){
2693fdb564SMilanka Ringwald     return 0;
2793fdb564SMilanka Ringwald }
2893fdb564SMilanka Ringwald 
2993fdb564SMilanka Ringwald static int hci_transport_fuzz_close(void){
3093fdb564SMilanka Ringwald     return 0;
3193fdb564SMilanka Ringwald }
3293fdb564SMilanka Ringwald 
3393fdb564SMilanka Ringwald static void hci_transport_fuzz_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){
3493fdb564SMilanka Ringwald     packet_handler = handler;
3593fdb564SMilanka Ringwald }
3693fdb564SMilanka Ringwald 
3793fdb564SMilanka Ringwald static const hci_transport_t hci_transport_fuzz = {
3893fdb564SMilanka Ringwald         /* const char * name; */                                        "FUZZ",
3993fdb564SMilanka Ringwald         /* void   (*init) (const void *transport_config); */            &hci_transport_fuzz_init,
4093fdb564SMilanka Ringwald         /* int    (*open)(void); */                                     &hci_transport_fuzz_open,
4193fdb564SMilanka Ringwald         /* int    (*close)(void); */                                    &hci_transport_fuzz_close,
4293fdb564SMilanka Ringwald         /* void   (*register_packet_handler)(void (*handler)(...); */   &hci_transport_fuzz_register_packet_handler,
4393fdb564SMilanka Ringwald         /* int    (*can_send_packet_now)(uint8_t packet_type); */       &hci_transport_fuzz_can_send_now,
4493fdb564SMilanka Ringwald         /* int    (*send_packet)(...); */                               &hci_transport_fuzz_send_packet,
4593fdb564SMilanka Ringwald         /* int    (*set_baudrate)(uint32_t baudrate); */                &hci_transport_fuzz_set_baudrate,
4693fdb564SMilanka Ringwald         /* void   (*reset_link)(void); */                               NULL,
4793fdb564SMilanka Ringwald         /* void   (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL,
4893fdb564SMilanka Ringwald };
4993fdb564SMilanka Ringwald 
5093fdb564SMilanka Ringwald static void gatt_client_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){
5193fdb564SMilanka Ringwald }
5293fdb564SMilanka Ringwald 
53*7d33cb26SMilanka Ringwald void set_gatt_service_uuid16(gatt_client_service_t * service, const uint8_t *data, size_t size){
54*7d33cb26SMilanka Ringwald     service->start_group_handle = 0x0001;
55*7d33cb26SMilanka Ringwald     service->end_group_handle = 0xffff;
56*7d33cb26SMilanka Ringwald     memset(service->uuid128, 0, 16);
57*7d33cb26SMilanka Ringwald     service->uuid16 = big_endian_read_16(data, 0);
58*7d33cb26SMilanka Ringwald }
5993fdb564SMilanka Ringwald 
60*7d33cb26SMilanka Ringwald void set_gatt_service_uuid128(gatt_client_service_t * service, const uint8_t *data, size_t size){
61*7d33cb26SMilanka Ringwald     service->start_group_handle = 0x0001;
62*7d33cb26SMilanka Ringwald     service->end_group_handle = 0xffff;
63*7d33cb26SMilanka Ringwald     service->uuid16 = 0;
64*7d33cb26SMilanka Ringwald     memcpy(service->uuid128, data, 16);
65*7d33cb26SMilanka Ringwald }
66*7d33cb26SMilanka Ringwald 
67*7d33cb26SMilanka Ringwald void set_gatt_characteristic_uuid16(gatt_client_characteristic_t * characteristic, const uint8_t *data, size_t size){
68*7d33cb26SMilanka Ringwald     characteristic->start_handle = 0x0001;
69*7d33cb26SMilanka Ringwald     characteristic->value_handle = 0x0002;
70*7d33cb26SMilanka Ringwald     characteristic->end_handle = 0xffff;
71*7d33cb26SMilanka Ringwald     characteristic->uuid16 = big_endian_read_16(data, 0);
72*7d33cb26SMilanka Ringwald     memset(characteristic->uuid128, 0, 16);
73*7d33cb26SMilanka Ringwald }
74*7d33cb26SMilanka Ringwald 
75*7d33cb26SMilanka Ringwald void set_gatt_characteristic_uuid128(gatt_client_characteristic_t * characteristic, const uint8_t *data, size_t size){
76*7d33cb26SMilanka Ringwald     characteristic->start_handle = 0x0001;
77*7d33cb26SMilanka Ringwald     characteristic->value_handle = 0x0002;
78*7d33cb26SMilanka Ringwald     characteristic->end_handle = 0xffff;
79*7d33cb26SMilanka Ringwald     characteristic->uuid16 = 0;
80*7d33cb26SMilanka Ringwald     memcpy(characteristic->uuid128, data, 16);
81*7d33cb26SMilanka Ringwald }
82*7d33cb26SMilanka Ringwald 
83*7d33cb26SMilanka Ringwald int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
8493fdb564SMilanka Ringwald     const hci_con_handle_t ble_handle = 0x0005;
8593fdb564SMilanka Ringwald 
8693fdb564SMilanka Ringwald     static bool gatt_client_initiated = false;
8793fdb564SMilanka Ringwald     if (!gatt_client_initiated){
8893fdb564SMilanka Ringwald         btstack_memory_init();
8993fdb564SMilanka Ringwald         btstack_run_loop_init(btstack_run_loop_posix_get_instance());
9093fdb564SMilanka Ringwald         // init hci, simulate connection
9193fdb564SMilanka Ringwald         hci_init(&hci_transport_fuzz, NULL);
9293fdb564SMilanka Ringwald         hci_setup_test_connections_fuzz();
9393fdb564SMilanka Ringwald 
9493fdb564SMilanka Ringwald         gatt_client_init();
95*7d33cb26SMilanka Ringwald         gatt_client_mtu_enable_auto_negotiation(0);
9693fdb564SMilanka Ringwald         gatt_client_initiated = true;
9793fdb564SMilanka Ringwald     }
9893fdb564SMilanka Ringwald 
99*7d33cb26SMilanka Ringwald     // use first byte of random data to pick gatt_client request / set gatt client state
100*7d33cb26SMilanka Ringwald     // then, only use data from second byte as response
101*7d33cb26SMilanka Ringwald     // prepare test data
102*7d33cb26SMilanka Ringwald     if (size < 1) return 0;
103*7d33cb26SMilanka Ringwald     uint8_t  cmd_type  = (data[0] & 0x1F);
104*7d33cb26SMilanka Ringwald     size--;
105*7d33cb26SMilanka Ringwald     data++;
106*7d33cb26SMilanka Ringwald 
107*7d33cb26SMilanka Ringwald     uint8_t  uuid128[16];
108*7d33cb26SMilanka Ringwald     uint16_t uuid16;
109*7d33cb26SMilanka Ringwald     int offset = 0;
110*7d33cb26SMilanka Ringwald     gatt_client_service_t service;
111*7d33cb26SMilanka Ringwald     gatt_client_characteristic_t characteristic;
112*7d33cb26SMilanka Ringwald     gatt_client_characteristic_descriptor_t descriptor;
113*7d33cb26SMilanka Ringwald 
114*7d33cb26SMilanka Ringwald     switch (cmd_type){
115*7d33cb26SMilanka Ringwald         case 1:
11693fdb564SMilanka Ringwald             gatt_client_discover_primary_services(gatt_client_packet_handler, ble_handle);
117*7d33cb26SMilanka Ringwald             break;
118*7d33cb26SMilanka Ringwald         case 2:
119*7d33cb26SMilanka Ringwald             offset = 2;
120*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
121*7d33cb26SMilanka Ringwald             uuid16 = big_endian_read_16(data, 0);
122*7d33cb26SMilanka Ringwald             gatt_client_discover_primary_services_by_uuid16(gatt_client_packet_handler, ble_handle, uuid16);
123*7d33cb26SMilanka Ringwald             break;
124*7d33cb26SMilanka Ringwald         case 3:
125*7d33cb26SMilanka Ringwald             offset = 16;
126*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
127*7d33cb26SMilanka Ringwald             memcpy(uuid128, data, 16);
128*7d33cb26SMilanka Ringwald             gatt_client_discover_primary_services_by_uuid128(gatt_client_packet_handler, ble_handle, uuid128);
129*7d33cb26SMilanka Ringwald             break;
130*7d33cb26SMilanka Ringwald         case 4:
131*7d33cb26SMilanka Ringwald             offset = 2;
132*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
133*7d33cb26SMilanka Ringwald             set_gatt_service_uuid16(&service, data, size);
134*7d33cb26SMilanka Ringwald             gatt_client_find_included_services_for_service(gatt_client_packet_handler, ble_handle, &service);
135*7d33cb26SMilanka Ringwald             break;
136*7d33cb26SMilanka Ringwald         case 5:
137*7d33cb26SMilanka Ringwald             offset = 2;
138*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
139*7d33cb26SMilanka Ringwald             set_gatt_service_uuid16(&service, data, size);
140*7d33cb26SMilanka Ringwald             gatt_client_discover_characteristics_for_service(gatt_client_packet_handler, ble_handle, &service);
141*7d33cb26SMilanka Ringwald             break;
142*7d33cb26SMilanka Ringwald         case 6:
143*7d33cb26SMilanka Ringwald             offset = 2;
144*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
145*7d33cb26SMilanka Ringwald             uuid16 = big_endian_read_16(data, 0);
146*7d33cb26SMilanka Ringwald             gatt_client_discover_characteristics_for_handle_range_by_uuid16(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid16);
147*7d33cb26SMilanka Ringwald             break;
148*7d33cb26SMilanka Ringwald         case 7:
149*7d33cb26SMilanka Ringwald             offset = 16;
150*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
151*7d33cb26SMilanka Ringwald             memcpy(uuid128, data, 16);
152*7d33cb26SMilanka Ringwald             gatt_client_discover_characteristics_for_handle_range_by_uuid128(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid128);
153*7d33cb26SMilanka Ringwald             break;
154*7d33cb26SMilanka Ringwald         case 8:
155*7d33cb26SMilanka Ringwald             offset = 4;
156*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
157*7d33cb26SMilanka Ringwald             set_gatt_service_uuid16(&service, data, size);
158*7d33cb26SMilanka Ringwald             uuid16 = big_endian_read_16(data, 2);
159*7d33cb26SMilanka Ringwald             gatt_client_discover_characteristics_for_service_by_uuid16(gatt_client_packet_handler, ble_handle, &service, uuid16);
160*7d33cb26SMilanka Ringwald             break;
161*7d33cb26SMilanka Ringwald         case 9:
162*7d33cb26SMilanka Ringwald             offset = 18;
163*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
164*7d33cb26SMilanka Ringwald             set_gatt_service_uuid16(&service, data, size);
165*7d33cb26SMilanka Ringwald             memcpy(uuid128, data + 2, 16);
166*7d33cb26SMilanka Ringwald             gatt_client_discover_characteristics_for_service_by_uuid128(gatt_client_packet_handler, ble_handle, &service, uuid128);
167*7d33cb26SMilanka Ringwald             break;
168*7d33cb26SMilanka Ringwald         case 10:
169*7d33cb26SMilanka Ringwald             offset = 2;
170*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
171*7d33cb26SMilanka Ringwald             set_gatt_characteristic_uuid16(&characteristic, data, size);
172*7d33cb26SMilanka Ringwald             gatt_client_discover_characteristic_descriptors(gatt_client_packet_handler, ble_handle, &characteristic);
173*7d33cb26SMilanka Ringwald             break;
174*7d33cb26SMilanka Ringwald         case 11:
175*7d33cb26SMilanka Ringwald             offset = 2;
176*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
177*7d33cb26SMilanka Ringwald             set_gatt_characteristic_uuid16(&characteristic, data, size);
178*7d33cb26SMilanka Ringwald             gatt_client_read_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic);
179*7d33cb26SMilanka Ringwald             break;
180*7d33cb26SMilanka Ringwald         case 12:
181*7d33cb26SMilanka Ringwald             offset = 2;
182*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
183*7d33cb26SMilanka Ringwald             set_gatt_characteristic_uuid16(&characteristic, data, size);
184*7d33cb26SMilanka Ringwald             gatt_client_read_value_of_characteristics_by_uuid16(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid16);
185*7d33cb26SMilanka Ringwald             break;
186*7d33cb26SMilanka Ringwald         case 13:
187*7d33cb26SMilanka Ringwald             offset = 16;
188*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
189*7d33cb26SMilanka Ringwald             set_gatt_characteristic_uuid128(&characteristic, data, size);
190*7d33cb26SMilanka Ringwald             gatt_client_read_value_of_characteristics_by_uuid128(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid128);
191*7d33cb26SMilanka Ringwald             break;
192*7d33cb26SMilanka Ringwald         case 14:
193*7d33cb26SMilanka Ringwald             offset = 2;
194*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
195*7d33cb26SMilanka Ringwald             set_gatt_characteristic_uuid16(&characteristic, data, size);
196*7d33cb26SMilanka Ringwald             gatt_client_read_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic);
197*7d33cb26SMilanka Ringwald             break;
198*7d33cb26SMilanka Ringwald         case 15:
199*7d33cb26SMilanka Ringwald             offset = 4;
200*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
201*7d33cb26SMilanka Ringwald             set_gatt_characteristic_uuid16(&characteristic, data, size);
202*7d33cb26SMilanka Ringwald             gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(gatt_client_packet_handler, ble_handle, characteristic.value_handle, big_endian_read_16(data, 2));
203*7d33cb26SMilanka Ringwald             break;
204*7d33cb26SMilanka Ringwald         case 16:
205*7d33cb26SMilanka Ringwald             gatt_client_read_multiple_characteristic_values(gatt_client_packet_handler, ble_handle, 0, NULL);
206*7d33cb26SMilanka Ringwald             break;
207*7d33cb26SMilanka Ringwald         case 17:
208*7d33cb26SMilanka Ringwald             gatt_client_write_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
209*7d33cb26SMilanka Ringwald             break;
210*7d33cb26SMilanka Ringwald         case 18:
211*7d33cb26SMilanka Ringwald             gatt_client_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
212*7d33cb26SMilanka Ringwald             break;
213*7d33cb26SMilanka Ringwald         case 19:
214*7d33cb26SMilanka Ringwald             gatt_client_reliable_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
215*7d33cb26SMilanka Ringwald             break;
216*7d33cb26SMilanka Ringwald         case 20:
217*7d33cb26SMilanka Ringwald             gatt_client_read_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5);
218*7d33cb26SMilanka Ringwald             break;
219*7d33cb26SMilanka Ringwald         case 21:
220*7d33cb26SMilanka Ringwald             gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5);
221*7d33cb26SMilanka Ringwald             break;
222*7d33cb26SMilanka Ringwald         case 22:
223*7d33cb26SMilanka Ringwald             gatt_client_write_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
224*7d33cb26SMilanka Ringwald             break;
225*7d33cb26SMilanka Ringwald         case 23:
226*7d33cb26SMilanka Ringwald             gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL);
227*7d33cb26SMilanka Ringwald             break;
228*7d33cb26SMilanka Ringwald         case 24:
229*7d33cb26SMilanka Ringwald             offset = 2;
230*7d33cb26SMilanka Ringwald             if (size < offset) return 0;
231*7d33cb26SMilanka Ringwald             set_gatt_characteristic_uuid16(&characteristic, data, size);
232*7d33cb26SMilanka Ringwald             gatt_client_write_client_characteristic_configuration(gatt_client_packet_handler, ble_handle, &characteristic, 1);
233*7d33cb26SMilanka Ringwald             break;
234*7d33cb26SMilanka Ringwald         case 25:
235*7d33cb26SMilanka Ringwald             gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
236*7d33cb26SMilanka Ringwald             break;
237*7d33cb26SMilanka Ringwald         case 26:
238*7d33cb26SMilanka Ringwald             gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
239*7d33cb26SMilanka Ringwald             gatt_client_execute_write(gatt_client_packet_handler, ble_handle);
240*7d33cb26SMilanka Ringwald             break;
241*7d33cb26SMilanka Ringwald         case 27:
242*7d33cb26SMilanka Ringwald             gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL);
243*7d33cb26SMilanka Ringwald             gatt_client_cancel_write(gatt_client_packet_handler, ble_handle);
244*7d33cb26SMilanka Ringwald             break;
245*7d33cb26SMilanka Ringwald         default:
246*7d33cb26SMilanka Ringwald             return 0;
247*7d33cb26SMilanka Ringwald     }
248*7d33cb26SMilanka Ringwald 
249*7d33cb26SMilanka Ringwald     data += offset;
250*7d33cb26SMilanka Ringwald     size -= offset;
25193fdb564SMilanka Ringwald 
25293fdb564SMilanka Ringwald     // send test response
25393fdb564SMilanka Ringwald     gatt_client_att_packet_handler_fuzz(ATT_DATA_PACKET, ble_handle, (uint8_t *) data, size);
25493fdb564SMilanka Ringwald     return 0;
25593fdb564SMilanka Ringwald }
256