commit ad57be45af926241bc49a8c729e4cd088a6074fa
parent 16da247f5fe20e3f1fae591b8ba99a77b43be969
Author: Daniel Barlow <dan@telent.net>
Date: Fri, 20 Feb 2026 00:34:42 +0000
simplify ble
send credentials as ssid + encrypted(secret) instead of resetting
current_network to indicate which one to use
it was kind of misleading as where there are two or more APs with the
same name and the user may suppose we are choosing a specific AP -
but we're not, we just set the name and assume the device will connect
to whiever is stronger
Diffstat:
2 files changed, 22 insertions(+), 34 deletions(-)
diff --git a/client/ble.py b/client/ble.py
@@ -54,23 +54,13 @@ def encrypt_password(plaintext):
r.insert(0, len(mybytes))
return r
-# encrypt_password("hello world")
-
-
async def choose_network(client, name):
- for i in range(1, max_index + 1):
- if networks[i].find(name) >= 0:
- print(f"found {name} in {networks[i]}")
- chosen = i
- break
- if chosen:
- await client.write_gatt_char(UUIDS['current_index'], bytes([chosen]))
- new_index = await client.read_gatt_char(UUIDS['current_index'])
- print(f"set to {new_index[0]}")
- secret = encrypt_password(os.getenv('PASSWORD'))
- print(f"about to write secret {len(secret)}")
- await client.write_gatt_char(UUIDS['secret'], secret)
- await client.write_gatt_char(UUIDS['connecting'], bytes([1]))
+ buf = bytearray(name)
+ buf.insert(0, len(name))
+ secret = encrypt_password(os.getenv('PASSWORD'))
+ print(f"writing {len(buf)}, {len(secret)}")
+ await client.write_gatt_char(UUIDS['secret'], buf + secret)
+ await client.write_gatt_char(UUIDS['connecting'], bytes([1]))
async def main(address):
diff --git a/ecu-esp32/src/wibble.rs b/ecu-esp32/src/wibble.rs
@@ -49,9 +49,9 @@ struct WifiProvisioningService {
current_network: [u8; 40],
#[characteristic(uuid = "76be25c2-0805-44fc-a97c-bcb56c69c926",
- value = [0; (24 + 16 + 64 + 1)],
+ value = [0; (1 + 32 + 1 + 24 + 16 + 64)],
write)]
- secret: [u8; 24 + 16 + 64 + 1]
+ secret: [u8; 1+ 32 + 1 + 24 + 16 + 64]
}
@@ -129,7 +129,7 @@ impl From<alloc::str::Utf8Error> for DecryptError {
fn from(e: alloc::str::Utf8Error) -> Self { Self::Encoding(e) }
}
-fn decrypt_secret(ciphertext : &[u8]) -> Result<String,DecryptError> {
+fn decrypt_secret(ciphertext : &[u8]) -> Result<Vec<u8>, DecryptError> {
let client_public_key = PublicKey::from(*CLIENT_PUBLIC_KEY_BYTES);
let secret_key= SecretKey::from(*SECRET_KEY_BYTES);
@@ -142,7 +142,7 @@ fn decrypt_secret(ciphertext : &[u8]) -> Result<String,DecryptError> {
let sbox = SalsaBox::new(&client_public_key, &secret_key);
let plain_bytes = sbox.decrypt(nonce, encrypted)?;
- Ok(String::from(core::str::from_utf8(&plain_bytes[..])?))
+ Ok(Vec::from(plain_bytes))
}
@@ -179,17 +179,16 @@ async fn gatt_events_task<P: PacketPool>(server: &Server<'_>,
warn!("index {:?} out of range", i);
}
} else if event.handle() == wps.connecting.handle {
- let network = server.get(&wps.current_network).unwrap();
- let password = decrypt_secret(&server.get(&wps.secret).unwrap());
-
- match password {
- Ok(plaintext) => {
- write_wifi_config(
- flasher, &network[8..], &plaintext[..]
- ).await;
+ let val = server.get(&wps.secret).unwrap();
+ let name_len : usize = val[0].into();
+ let name = &val[1..name_len+1];
+
+ match decrypt_secret(&val[name_len+1..]) {
+ Ok(pw) => {
+ write_wifi_config(flasher, name, &pw[..]).await;
},
Err(e) => {
- warn!("decdrpt error: {:?}", e);
+ warn!("decrypt error: {:?}", e);
}
}
}
@@ -211,11 +210,10 @@ async fn gatt_events_task<P: PacketPool>(server: &Server<'_>,
Ok(())
}
-async fn write_wifi_config(flasher: &mut Flasher<'_>, ssid: &[u8], password: &str) -> Result<(),esp_nvs::error::Error> {
- let n_s = core::str::from_utf8(&ssid).unwrap();
- let n0 =
- if let Some(i) = n_s.find("\0") { i } else { n_s.len() };
- flasher.set_var("ssid", Some(&n_s[..n0]))?;
+async fn write_wifi_config(flasher: &mut Flasher<'_>, ssid: &[u8], password: &[u8]) -> Result<(),esp_nvs::error::Error> {
+ let ssid = core::str::from_utf8(ssid).unwrap();
+ let password = core::str::from_utf8(password).unwrap();
+ flasher.set_var("ssid", Some(ssid))?;
flasher.set_var("secret", Some(password))?;
info!("[gatt] deep breath then reboot");
Timer::after(Duration::from_millis(2000)).await;