├── .gitattributes ├── OpenHS.ino └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /OpenHS.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "esp_bt.h" 14 | #include "esp_bt_defs.h" 15 | #include "esp_bt_main.h" 16 | #include "esp_gap_ble_api.h" 17 | #include "esp_gatt_defs.h" 18 | #include "esp_gattc_api.h" 19 | #include "esp_log.h" 20 | #include "freertos/FreeRTOS.h" 21 | 22 | #define LED_BUILTIN 10 23 | 24 | /** Random device address */ 25 | esp_bd_addr_t rnd_addr = {0xFF, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}; 26 | 27 | /** REPLACE WITH YOUR KEY, this is fake one, consider this padding 28 | uint8_t public_key[28] = { 29 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 30 | 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 31 | 0x05, 0x05, 0x05, 0x05}; 32 | 33 | /** Advertisement payload */ 34 | uint8_t adv_data[31] = { 35 | 0x1e, /* Length (30) */ 36 | 0xff, /* Manufacturer Specific Data (type 0xff) */ 37 | 0x4c, 0x00, /* Company ID (Apple) */ 38 | 0x12, 0x19, /* Offline Finding type and length */ 39 | 0x00, /* State */ 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 43 | 0x00, /* First two bits */ 44 | 0x00, /* Hint (0x00) */ 45 | }; 46 | 47 | /* https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/esp_gap_ble.html#_CPPv420esp_ble_adv_params_t */ 48 | static esp_ble_adv_params_t ble_adv_params = { 49 | // Advertising min interval: 50 | // Minimum advertising interval for undirected and low duty cycle 51 | // directed advertising. Range: 0x0020 to 0x4000 Default: N = 0x0800 52 | // (1.28 second) Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec 53 | .adv_int_min = 0x0640, // 1s 54 | // Advertising max interval: 55 | // Maximum advertising interval for undirected and low duty cycle 56 | // directed advertising. Range: 0x0020 to 0x4000 Default: N = 0x0800 57 | // (1.28 second) Time = N * 0.625 msec Time Range: 20 ms to 10.24 sec 58 | .adv_int_max = 0x0C80, // 2s 59 | // Advertisement type 60 | .adv_type = ADV_TYPE_NONCONN_IND, 61 | // Use the random address 62 | .own_addr_type = BLE_ADDR_TYPE_RANDOM, 63 | .peer_addr = { 64 | 0x00, 65 | }, 66 | .peer_addr_type = BLE_ADDR_TYPE_PUBLIC, 67 | 68 | // All channels 69 | .channel_map = ADV_CHNL_ALL, 70 | // Allow both scan and connection requests from anyone. 71 | .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY, 72 | }; 73 | 74 | void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param) { 75 | esp_err_t err; 76 | 77 | switch (event) { 78 | case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT: 79 | esp_ble_gap_start_advertising(&ble_adv_params); 80 | break; 81 | 82 | case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: 83 | //adv start complete event to indicate adv start successfully or failed 84 | if ((err = param->adv_start_cmpl.status) != ESP_BT_STATUS_SUCCESS) { 85 | Serial.printf("advertising start failed: %s", esp_err_to_name(err)); 86 | } else { 87 | Serial.printf("advertising has started."); 88 | } 89 | break; 90 | 91 | case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT: 92 | if ((err = param->adv_stop_cmpl.status) != ESP_BT_STATUS_SUCCESS) { 93 | Serial.printf("adv stop failed: %s", esp_err_to_name(err)); 94 | } else { 95 | Serial.printf("stop adv successfully"); 96 | } 97 | break; 98 | default: 99 | break; 100 | } 101 | } 102 | 103 | void set_addr_from_key(esp_bd_addr_t addr, uint8_t *public_key) { 104 | addr[0] = public_key[0] | 0b11000000; 105 | addr[1] = public_key[1]; 106 | addr[2] = public_key[2]; 107 | addr[3] = public_key[3]; 108 | addr[4] = public_key[4]; 109 | addr[5] = public_key[5]; 110 | } 111 | 112 | void set_payload_from_key(uint8_t *payload, uint8_t *public_key) { 113 | /* copy last 22 bytes */ 114 | memcpy(&payload[7], &public_key[6], 22); 115 | /* append two bits of public key */ 116 | payload[29] = public_key[0] >> 6; 117 | } 118 | 119 | void setup() { 120 | Serial.begin(115200); 121 | M5.begin(); 122 | // M5.Axp.ScreenBreath(7); 123 | 124 | // Write text on LCD 125 | M5.Lcd.setRotation(3); 126 | M5.Lcd.setCursor(0, 30, 4); 127 | M5.Lcd.println("OHS Ready!"); 128 | 129 | // RED LED 130 | pinMode(LED_BUILTIN, OUTPUT); 131 | 132 | set_addr_from_key(rnd_addr, public_key); 133 | set_payload_from_key(adv_data, public_key); 134 | 135 | BLEDevice::init(""); 136 | BLEDevice::setCustomGapHandler(esp_gap_cb); 137 | 138 | esp_err_t status; 139 | if ((status = esp_ble_gap_set_rand_addr(rnd_addr)) != ESP_OK) { 140 | Serial.printf("couldn't set random address: %s", esp_err_to_name(status)); 141 | } 142 | 143 | BLEAdvertisementData advertisementData = BLEAdvertisementData(); 144 | advertisementData.setManufacturerData(std::string((char *)adv_data + 2, sizeof(adv_data) - 2)); 145 | 146 | BLEAdvertising *pAdvertising = BLEDevice::getAdvertising(); 147 | pAdvertising->setScanResponse(true); 148 | pAdvertising->setMaxInterval(0x0C80); 149 | pAdvertising->setMinInterval(0x0640); 150 | pAdvertising->setAdvertisementData(advertisementData); 151 | 152 | BLEDevice::startAdvertising(); 153 | } 154 | 155 | void loop() { 156 | // LED loop 157 | digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) 158 | delay(10000); // wait for a second 159 | digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW 160 | delay(1000); // wait for a second 161 | } 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OHS Arduino 2 | OpenHayStack Arduino sketch 3 | 4 | This sketch is based upon OpenHayStack main.c Firmware code for ESP32. 5 | https://github.com/seemoo-lab/openhaystack 6 | 7 | 8 | # Setup 9 | - Open .ino in Arduino IDE 10 | - EDIT actual adv key on line 27 with your key. Follow padding as shown on example (0x05) 11 | 12 | Is it possibile to get a key creating a new accessory in OHS app e copy its advertising key. 13 | To generate a .key file with correct padding it'd useful what's on flash_esp.sh script on OHS main project. 14 | 15 | echo "$PUBKEY" | python3 -m base64 -d - > "$KEYFILE" where PUBKEY is your adv_key and KEYFILE is your tmp.key blank file. 16 | 17 | # What is working 18 | - Blinking RED LED (1sec on, 10 sec off) 19 | - LCD initialization with some text printed. 20 | 21 | # What's next 22 | - Battery icon 23 | - M5 button for lcd on/off 24 | - Right button for some infos 25 | - BT Paring 26 | 27 | ![M5StickC](https://user-images.githubusercontent.com/14237462/122478870-76e51480-cfca-11eb-9ce0-593bfe8623aa.gif) 28 | 29 | 30 | --------------------------------------------------------------------------------