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