Skip to content

Commit 72284f3

Browse files
committed
Fix FIDO2 CBOR response, BLE exchange filter, temperature display
- Revert getInfo to 9 map entries (remove 0x0A algorithms) - fixes FIDO2 - Filter BLE scan results to only show CDC Badge devices with vCard UUID - Add proper APP_STATE_VCARD_EXCHANGE with info screen - Disable exchange mode on exit with N key - Display temperature as integer on lock screen - Update FIDO2 slot limits documentation (0-28, slot 29 reserved for GPG)
1 parent 2b2da28 commit 72284f3

10 files changed

Lines changed: 57 additions & 44 deletions

File tree

README.md

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@ Hardware security key firmware for the CDC Badge v1.0 featuring TROPIC01 secure
2525
| **WiFi + NTP** | Time synchronization over WiFi |
2626
| **E-Paper Display** | 2.9" low-power display with backlight |
2727
| **12-Button Keypad** | Phone-style T9 input |
28-
| **Multi-Language** | English and German UI |
29-
| **Error Log** | Captures WARNING/ERROR messages (max 50 entries) |
28+
| **Multi-Language** | English and German UI (expandable, translaters welcome) |
3029

3130
> **Note:** WiFi and Bluetooth are currently **mutually exclusive** (enable one at a time).
3231
33-
> **Warning:** WiFi is currently unstable and crashes easily. Need hardware to debug (help wanted).
32+
> **Warning:** WiFi is currently unstable and crashes easily. Need different hardware to debug (help wanted).
3433
3534
### Bluetooth Serial (BLE UART)
3635

@@ -45,7 +44,7 @@ https://play.google.com/store/apps/details?id=de.kai_morich.serial_bluetooth_ter
4544
### BLE vCard (Badge2Badge)
4645

4746
What it does:
48-
- Broadcasts a short mini-card (name + slogan) via BLE advertising
47+
- Broadcasts a short mini-card (name + short info) via BLE advertising
4948
- Exchanges full vCard 4.0 **badge-to-badge only** (custom GATT)
5049
- Shows a QR code for interoperability with phones/computers (no app required)
5150
- Stores up to 100 received vCards in NVS (max 768 bytes each), sorted by last name
@@ -55,16 +54,14 @@ See [BLE vCard Protocol](docs/ble_vcard_protocol.md) for technical details.
5554
Notes:
5655
- BLE UART is disabled while the vCard feature is active
5756
- BLE and WiFi are mutually exclusive
58-
- **Exchange is currently untested**: Only one badge available for testing
57+
- **Exchange is currently untested** (Only one badge available for testing)
5958

6059
### Secure Serial
6160

6261
Serial commands require PIN authentication when `FEATURE_SECURE_SERIAL` is enabled.
6362

6463
- Use `AUTH <pin>` to authenticate
6564
- Use `LOGOUT` to end session
66-
- Anti-bruteforce: 3 attempts, then 5 minute lockout
67-
- Works on both USB and BLE serial
6865

6966
### GPG Key Management (v0.5 - Untested)
7067

components/ble_badge/ble_badge.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ static bool g_gatts_connected = false;
7878
static uint16_t g_gatts_conn_id = 0;
7979
static uint16_t g_gatts_mtu_payload = BLE_BADGE_TX_PAYLOAD_DEFAULT;
8080
static esp_bd_addr_t g_gatts_bda = {0};
81+
static esp_bd_addr_t g_own_bda = {0}; // Own BLE address to filter self from scan
8182

8283
static bool g_pairing_pending = false;
8384
static bool g_pairing_passkey_req = false;
@@ -571,6 +572,17 @@ static void handle_scan_result(const esp_ble_gap_cb_param_t *param) {
571572
auto *scan = &param->scan_rst;
572573
if (scan->rssi < g_rssi_threshold) return;
573574

575+
// Filter out own device from scan results
576+
// Also filter if own_bda is all zeros (not yet initialized)
577+
bool own_bda_valid = false;
578+
for (int i = 0; i < 6; i++) {
579+
if (g_own_bda[i] != 0) { own_bda_valid = true; break; }
580+
}
581+
if (own_bda_valid && memcmp(scan->bda, g_own_bda, sizeof(esp_bd_addr_t)) == 0) {
582+
LOG_D(BLE_BADGE_TAG, "Filtered self from scan");
583+
return;
584+
}
585+
574586
uint8_t name_len = 0;
575587
uint8_t *name = esp_ble_resolve_adv_data((uint8_t *)scan->ble_adv, ESP_BLE_AD_TYPE_NAME_CMPL, &name_len);
576588
char name_buf[BLE_BADGE_NAME_MAX] = {0};
@@ -603,7 +615,11 @@ static void handle_scan_result(const esp_ble_gap_cb_param_t *param) {
603615
vcard_service_uuid);
604616
g_peers_last_seen[idx] = millis();
605617

606-
if (!g_pending_nearby_set && blacklist_allows(scan->bda)) {
618+
// Only trigger nearby alert for CDC Badge devices (with vCard service UUID)
619+
if (!g_pending_nearby_set && g_peers[idx].exchange_ready && blacklist_allows(scan->bda)) {
620+
LOG_I(BLE_BADGE_TAG, "Nearby CDC Badge: %s BDA=%02X:%02X:%02X:%02X:%02X:%02X RSSI=%d",
621+
name_buf, scan->bda[0], scan->bda[1], scan->bda[2],
622+
scan->bda[3], scan->bda[4], scan->bda[5], scan->rssi);
607623
g_pending_nearby = g_peers[idx];
608624
g_pending_nearby_set = true;
609625
}
@@ -1093,6 +1109,15 @@ bool ble_badge_init(void) {
10931109

10941110
esp_ble_gatt_set_local_mtu(185);
10951111

1112+
// Get own BLE address to filter self from scan results
1113+
const uint8_t *own_addr = esp_bt_dev_get_address();
1114+
if (own_addr) {
1115+
memcpy(g_own_bda, own_addr, sizeof(esp_bd_addr_t));
1116+
LOG_I(BLE_BADGE_TAG, "Own BDA: %02X:%02X:%02X:%02X:%02X:%02X",
1117+
g_own_bda[0], g_own_bda[1], g_own_bda[2],
1118+
g_own_bda[3], g_own_bda[4], g_own_bda[5]);
1119+
}
1120+
10961121
esp_ble_gap_set_scan_params(&scan_params);
10971122
g_initialized = true;
10981123
update_adv_data();

components/cdc_badge/feature_flags.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@
8484
#define FEATURE_CA 1 // Certificate Authority
8585
#endif
8686

87-
// PKCS#11 requires wolfPKCS11 evaluation - disabled until proven viable
87+
// PKCS#11 also on GPG - planned
8888
#ifndef FEATURE_CA_PKCS11
8989
#define FEATURE_CA_PKCS11 0
9090
#endif
@@ -102,7 +102,7 @@
102102
// GPG over USB CCID (SmartCard interface)
103103
// Requires FEATURE_GPG and FEATURE_USB
104104
#ifndef FEATURE_GPG_CCID
105-
#define FEATURE_GPG_CCID 0 // USB CCID SmartCard interface (disabled by default)
105+
#define FEATURE_GPG_CCID 0 // USB CCID SmartCard interface, not yet implemented
106106
#endif
107107

108108
#if FEATURE_GPG_CCID && !FEATURE_GPG

components/cdc_badge/i18n.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ static const char* strings_en[] = {
209209
"TX Power", // STR_TX_POWER
210210
"Receive", // STR_VCARD_RECEIVE
211211
"Exchange", // STR_VCARD_EXCHANGE
212+
"Scanning...\n[N] Back", // STR_VCARD_EXCHANGE_MSG
212213
"Send", // STR_VCARD_SEND
213214
"Show QR", // STR_VCARD_SHOW_QR
214215
"Nearby: %s", // STR_VCARD_NEARBY
@@ -449,6 +450,7 @@ static const char* strings_de[] = {
449450
"Sendeleistung", // STR_TX_POWER
450451
"Empfangen", // STR_VCARD_RECEIVE
451452
"Austausch", // STR_VCARD_EXCHANGE
453+
"Suche...\n[N] Zurueck", // STR_VCARD_EXCHANGE_MSG
452454
"Senden", // STR_VCARD_SEND
453455
"QR anzeigen", // STR_VCARD_SHOW_QR
454456
"In der Naehe: %s", // STR_VCARD_NEARBY

components/cdc_badge/i18n.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ typedef enum {
175175
STR_TX_POWER, // "TX Power"
176176
STR_VCARD_RECEIVE, // "Receive"
177177
STR_VCARD_EXCHANGE, // "Exchange"
178+
STR_VCARD_EXCHANGE_MSG, // "Scanning for badges..."
178179
STR_VCARD_SEND, // "Send"
179180
STR_VCARD_SHOW_QR, // "Show QR"
180181
STR_VCARD_NEARBY, // "Nearby: %s"

components/fido2/ctap2.cpp

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -375,8 +375,8 @@ uint8_t ctap2_get_info(uint8_t *response, uint16_t *response_len) {
375375
cbor_writer_t w;
376376
cbor_writer_init(&w, response + 1, *response_len - 1);
377377

378-
// Response is a map (10 items for FIDO 2.1 compliance with algorithms)
379-
cbor_encode_map(&w, 10);
378+
// Response is a map (9 items for FIDO 2.0 compliance)
379+
cbor_encode_map(&w, 9);
380380

381381
// 0x01: versions (FIDO_2_0, U2F_V2)
382382
cbor_encode_uint(&w, 0x01);
@@ -431,22 +431,6 @@ uint8_t ctap2_get_info(uint8_t *response, uint16_t *response_len) {
431431
cbor_encode_array(&w, 1);
432432
cbor_encode_text(&w, INFO_TRANSPORTS[0]);
433433

434-
// 0x0A: algorithms (FIDO 2.1) - supported public key credential algorithms
435-
cbor_encode_uint(&w, 0x0A);
436-
cbor_encode_array(&w, 2);
437-
// ES256 (P-256/ECDSA)
438-
cbor_encode_map(&w, 2);
439-
cbor_encode_text(&w, "type");
440-
cbor_encode_text(&w, "public-key");
441-
cbor_encode_text(&w, "alg");
442-
cbor_encode_int(&w, COSE_ALG_ES256);
443-
// EdDSA (Ed25519)
444-
cbor_encode_map(&w, 2);
445-
cbor_encode_text(&w, "type");
446-
cbor_encode_text(&w, "public-key");
447-
cbor_encode_text(&w, "alg");
448-
cbor_encode_int(&w, COSE_ALG_EDDSA);
449-
450434
if (cbor_writer_error(&w)) {
451435
response[0] = CTAP2_ERR_OTHER;
452436
*response_len = 1;
@@ -789,11 +773,14 @@ uint8_t ctap2_make_credential(const uint8_t *params, uint16_t params_len,
789773
return CTAP2_ERR_OPERATION_DENIED;
790774
}
791775

776+
LOG_I("CTAP2", "User presence OK, creating credential (curve=%d)...", curve);
777+
792778
// Create credential
793779
uint8_t slot;
794780
uint8_t cred_id[FIDO2_CRED_ID_LEN];
795781
uint8_t pubkey[64]; // P-256: X||Y, Ed25519: 32 bytes (only first half used)
796782

783+
LOG_I("CTAP2", "Calling fido2_storage_create_credential...");
797784
if (!fido2_storage_create_credential(
798785
rp_id, rp_id_hash, user_id, user_id_len, user_name,
799786
rk, cred_protect, curve, &slot, cred_id, pubkey)) {

components/fido2/fido2_storage.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ extern "C" {
1616
// ============================================================================
1717
// Storage Layout
1818
// ============================================================================
19-
// ECC Slots 0-29: Private keys (P-256 or Ed25519 for WebAuthn/SSH)
20-
// R-Memory 0-29: Credential metadata (rp_id, user_id, sign_count, curve, etc.)
19+
// ECC Slots 0-28: Private keys (P-256 or Ed25519 for WebAuthn/SSH)
20+
// R-Memory 0-28: Credential metadata (rp_id, user_id, sign_count, curve, etc.)
2121
// NVS "fido2": Global auth counter, PIN hash
2222

2323
#define FIDO2_ECC_SLOT_BASE 0
24-
#define FIDO2_ECC_SLOT_MAX 29
24+
#define FIDO2_ECC_SLOT_MAX 28
2525
#define FIDO2_RMEM_SLOT_BASE 0
26-
#define FIDO2_RMEM_SLOT_MAX 29
26+
#define FIDO2_RMEM_SLOT_MAX 28
2727

2828
// ============================================================================
2929
// Initialization
@@ -74,7 +74,7 @@ bool fido2_storage_create_credential(
7474
/**
7575
* Get curve type for a credential.
7676
*
77-
* @param slot ECC slot index (0-29)
77+
* @param slot ECC slot index (0-28)
7878
* @return CDC_CURVE_P256 or CDC_CURVE_ED25519, or 0xFF on error
7979
*/
8080
uint8_t fido2_storage_get_curve(uint8_t slot);

main/app_input.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2260,11 +2260,11 @@ void handle_key(char key) {
22602260
}
22612261
#endif
22622262
ble_badge_init();
2263-
ble_badge_set_exchange_enabled(!ble_badge_is_exchange_enabled());
2264-
if (ble_badge_is_exchange_enabled()) {
2265-
view_toast_show(i18n_str(STR_VCARD_EXCHANGE), 1000);
2266-
}
2267-
render_current_state(true);
2263+
ble_badge_set_exchange_enabled(true);
2264+
view_info_screen_init(&g_info_view, i18n_str(STR_VCARD_EXCHANGE),
2265+
i18n_str(STR_VCARD_EXCHANGE_MSG));
2266+
g_app_state = APP_STATE_VCARD_EXCHANGE;
2267+
render_current_state(false);
22682268
break;
22692269
case VCARD_SUB_IDX_LIST:
22702270
vcard_refresh_list();
@@ -2283,9 +2283,10 @@ void handle_key(char key) {
22832283
}
22842284
break;
22852285

2286-
// Exchange mode - currently just a placeholder
2286+
// Exchange mode - scanning for other badges and advertising own vCard
22872287
case APP_STATE_VCARD_EXCHANGE:
22882288
if (key == 'N') {
2289+
ble_badge_set_exchange_enabled(false);
22892290
go_to_vcard_submenu();
22902291
}
22912292
break;

main/app_render.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ void update_lock_screen_data(void) {
7272
} else {
7373
strncpy(g_lock_screen.clock, "--:--", sizeof(g_lock_screen.clock));
7474
if (temp_ok) {
75-
snprintf(g_lock_screen.date, sizeof(g_lock_screen.date), "%.1fC", (double)temp_c);
75+
snprintf(g_lock_screen.date, sizeof(g_lock_screen.date), "%dC", (int)temp_c);
7676
} else {
7777
g_lock_screen.date[0] = '\0';
7878
}

sdkconfig.cdc_badge_usb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,8 +1597,8 @@ CONFIG_ESP_WIFI_TX_BA_WIN=6
15971597
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
15981598
CONFIG_ESP_WIFI_RX_BA_WIN=6
15991599
CONFIG_ESP_WIFI_NVS_ENABLED=y
1600-
CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0=y
1601-
# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1 is not set
1600+
# CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0 is not set
1601+
CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_1=y
16021602
CONFIG_ESP_WIFI_SOFTAP_BEACON_MAX_LEN=752
16031603
CONFIG_ESP_WIFI_MGMT_SBUF_NUM=32
16041604
CONFIG_ESP_WIFI_IRAM_OPT=y
@@ -2633,8 +2633,8 @@ CONFIG_ESP32_WIFI_TX_BA_WIN=6
26332633
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
26342634
CONFIG_ESP32_WIFI_RX_BA_WIN=6
26352635
CONFIG_ESP32_WIFI_NVS_ENABLED=y
2636-
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
2637-
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set
2636+
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 is not set
2637+
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1=y
26382638
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
26392639
CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
26402640
CONFIG_ESP32_WIFI_IRAM_OPT=y

0 commit comments

Comments
 (0)