1 #include <stdint.h> 2 #include <stddef.h> 3 4 #include "ble/gatt_client.h" 5 #include "btstack_run_loop_posix.h" 6 #include "btstack_memory.h" 7 8 static void (*packet_handler)(uint8_t packet_type, uint8_t *packet, uint16_t size); 9 10 static int hci_transport_fuzz_set_baudrate(uint32_t baudrate){ 11 return 0; 12 } 13 14 static int hci_transport_fuzz_can_send_now(uint8_t packet_type){ 15 return 1; 16 } 17 18 static int hci_transport_fuzz_send_packet(uint8_t packet_type, uint8_t * packet, int size){ 19 return 0; 20 } 21 22 static void hci_transport_fuzz_init(const void * transport_config){ 23 } 24 25 static int hci_transport_fuzz_open(void){ 26 return 0; 27 } 28 29 static int hci_transport_fuzz_close(void){ 30 return 0; 31 } 32 33 static void hci_transport_fuzz_register_packet_handler(void (*handler)(uint8_t packet_type, uint8_t *packet, uint16_t size)){ 34 packet_handler = handler; 35 } 36 37 static const hci_transport_t hci_transport_fuzz = { 38 /* const char * name; */ "FUZZ", 39 /* void (*init) (const void *transport_config); */ &hci_transport_fuzz_init, 40 /* int (*open)(void); */ &hci_transport_fuzz_open, 41 /* int (*close)(void); */ &hci_transport_fuzz_close, 42 /* void (*register_packet_handler)(void (*handler)(...); */ &hci_transport_fuzz_register_packet_handler, 43 /* int (*can_send_packet_now)(uint8_t packet_type); */ &hci_transport_fuzz_can_send_now, 44 /* int (*send_packet)(...); */ &hci_transport_fuzz_send_packet, 45 /* int (*set_baudrate)(uint32_t baudrate); */ &hci_transport_fuzz_set_baudrate, 46 /* void (*reset_link)(void); */ NULL, 47 /* void (*set_sco_config)(uint16_t voice_setting, int num_connections); */ NULL, 48 }; 49 50 static void gatt_client_packet_handler(uint8_t packet_type, uint16_t handle, uint8_t *packet, uint16_t size){ 51 } 52 53 void set_gatt_service_uuid16(gatt_client_service_t * service, const uint8_t *data, size_t size){ 54 service->start_group_handle = 0x0001; 55 service->end_group_handle = 0xffff; 56 memset(service->uuid128, 0, 16); 57 service->uuid16 = big_endian_read_16(data, 0); 58 } 59 60 void set_gatt_service_uuid128(gatt_client_service_t * service, const uint8_t *data, size_t size){ 61 service->start_group_handle = 0x0001; 62 service->end_group_handle = 0xffff; 63 service->uuid16 = 0; 64 memcpy(service->uuid128, data, 16); 65 } 66 67 void set_gatt_characteristic_uuid16(gatt_client_characteristic_t * characteristic, const uint8_t *data, size_t size){ 68 characteristic->start_handle = 0x0001; 69 characteristic->value_handle = 0x0002; 70 characteristic->end_handle = 0xffff; 71 characteristic->uuid16 = big_endian_read_16(data, 0); 72 memset(characteristic->uuid128, 0, 16); 73 } 74 75 void set_gatt_characteristic_uuid128(gatt_client_characteristic_t * characteristic, const uint8_t *data, size_t size){ 76 characteristic->start_handle = 0x0001; 77 characteristic->value_handle = 0x0002; 78 characteristic->end_handle = 0xffff; 79 characteristic->uuid16 = 0; 80 memcpy(characteristic->uuid128, data, 16); 81 } 82 83 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 84 const hci_con_handle_t ble_handle = 0x0005; 85 86 static bool gatt_client_initiated = false; 87 if (!gatt_client_initiated){ 88 btstack_memory_init(); 89 btstack_run_loop_init(btstack_run_loop_posix_get_instance()); 90 // init hci, simulate connection 91 hci_init(&hci_transport_fuzz, NULL); 92 hci_setup_test_connections_fuzz(); 93 94 gatt_client_init(); 95 gatt_client_mtu_enable_auto_negotiation(0); 96 gatt_client_initiated = true; 97 } 98 99 // use first byte of random data to pick gatt_client request / set gatt client state 100 // then, only use data from second byte as response 101 // prepare test data 102 if (size < 1) return 0; 103 uint8_t cmd_type = (data[0] & 0x1F); 104 size--; 105 data++; 106 107 uint8_t uuid128[16]; 108 uint16_t uuid16; 109 int offset = 0; 110 gatt_client_service_t service; 111 gatt_client_characteristic_t characteristic; 112 gatt_client_characteristic_descriptor_t descriptor; 113 114 switch (cmd_type){ 115 case 1: 116 gatt_client_discover_primary_services(gatt_client_packet_handler, ble_handle); 117 break; 118 case 2: 119 offset = 2; 120 if (size < offset) return 0; 121 uuid16 = big_endian_read_16(data, 0); 122 gatt_client_discover_primary_services_by_uuid16(gatt_client_packet_handler, ble_handle, uuid16); 123 break; 124 case 3: 125 offset = 16; 126 if (size < offset) return 0; 127 memcpy(uuid128, data, 16); 128 gatt_client_discover_primary_services_by_uuid128(gatt_client_packet_handler, ble_handle, uuid128); 129 break; 130 case 4: 131 offset = 2; 132 if (size < offset) return 0; 133 set_gatt_service_uuid16(&service, data, size); 134 gatt_client_find_included_services_for_service(gatt_client_packet_handler, ble_handle, &service); 135 break; 136 case 5: 137 offset = 2; 138 if (size < offset) return 0; 139 set_gatt_service_uuid16(&service, data, size); 140 gatt_client_discover_characteristics_for_service(gatt_client_packet_handler, ble_handle, &service); 141 break; 142 case 6: 143 offset = 2; 144 if (size < offset) return 0; 145 uuid16 = big_endian_read_16(data, 0); 146 gatt_client_discover_characteristics_for_handle_range_by_uuid16(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid16); 147 break; 148 case 7: 149 offset = 16; 150 if (size < offset) return 0; 151 memcpy(uuid128, data, 16); 152 gatt_client_discover_characteristics_for_handle_range_by_uuid128(gatt_client_packet_handler, ble_handle, 0x0001, 0xffff, uuid128); 153 break; 154 case 8: 155 offset = 4; 156 if (size < offset) return 0; 157 set_gatt_service_uuid16(&service, data, size); 158 uuid16 = big_endian_read_16(data, 2); 159 gatt_client_discover_characteristics_for_service_by_uuid16(gatt_client_packet_handler, ble_handle, &service, uuid16); 160 break; 161 case 9: 162 offset = 18; 163 if (size < offset) return 0; 164 set_gatt_service_uuid16(&service, data, size); 165 memcpy(uuid128, data + 2, 16); 166 gatt_client_discover_characteristics_for_service_by_uuid128(gatt_client_packet_handler, ble_handle, &service, uuid128); 167 break; 168 case 10: 169 offset = 2; 170 if (size < offset) return 0; 171 set_gatt_characteristic_uuid16(&characteristic, data, size); 172 gatt_client_discover_characteristic_descriptors(gatt_client_packet_handler, ble_handle, &characteristic); 173 break; 174 case 11: 175 offset = 2; 176 if (size < offset) return 0; 177 set_gatt_characteristic_uuid16(&characteristic, data, size); 178 gatt_client_read_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic); 179 break; 180 case 12: 181 offset = 2; 182 if (size < offset) return 0; 183 set_gatt_characteristic_uuid16(&characteristic, data, size); 184 gatt_client_read_value_of_characteristics_by_uuid16(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid16); 185 break; 186 case 13: 187 offset = 16; 188 if (size < offset) return 0; 189 set_gatt_characteristic_uuid128(&characteristic, data, size); 190 gatt_client_read_value_of_characteristics_by_uuid128(gatt_client_packet_handler, ble_handle, characteristic.start_handle, characteristic.end_handle, characteristic.uuid128); 191 break; 192 case 14: 193 offset = 2; 194 if (size < offset) return 0; 195 set_gatt_characteristic_uuid16(&characteristic, data, size); 196 gatt_client_read_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, &characteristic); 197 break; 198 case 15: 199 offset = 4; 200 if (size < offset) return 0; 201 set_gatt_characteristic_uuid16(&characteristic, data, size); 202 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 break; 204 case 16: 205 gatt_client_read_multiple_characteristic_values(gatt_client_packet_handler, ble_handle, 0, NULL); 206 break; 207 case 17: 208 gatt_client_write_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL); 209 break; 210 case 18: 211 gatt_client_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL); 212 break; 213 case 19: 214 gatt_client_reliable_write_long_value_of_characteristic(gatt_client_packet_handler, ble_handle, 5, 0, NULL); 215 break; 216 case 20: 217 gatt_client_read_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5); 218 break; 219 case 21: 220 gatt_client_read_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5); 221 break; 222 case 22: 223 gatt_client_write_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL); 224 break; 225 case 23: 226 gatt_client_write_long_characteristic_descriptor_using_descriptor_handle(gatt_client_packet_handler, ble_handle, 5, 0, NULL); 227 break; 228 case 24: 229 offset = 2; 230 if (size < offset) return 0; 231 set_gatt_characteristic_uuid16(&characteristic, data, size); 232 gatt_client_write_client_characteristic_configuration(gatt_client_packet_handler, ble_handle, &characteristic, 1); 233 break; 234 case 25: 235 gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL); 236 break; 237 case 26: 238 gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL); 239 gatt_client_execute_write(gatt_client_packet_handler, ble_handle); 240 break; 241 case 27: 242 gatt_client_prepare_write(gatt_client_packet_handler, ble_handle, 5, 0, 0, NULL); 243 gatt_client_cancel_write(gatt_client_packet_handler, ble_handle); 244 break; 245 default: 246 return 0; 247 } 248 249 data += offset; 250 size -= offset; 251 252 // send test response 253 gatt_client_att_packet_handler_fuzz(ATT_DATA_PACKET, ble_handle, (uint8_t *) data, size); 254 return 0; 255 } 256