minor updates

This commit is contained in:
KaraZajac
2026-02-15 19:52:21 -05:00
parent daed5321d9
commit e5005c9083
9 changed files with 164 additions and 93 deletions
+83 -85
View File
@@ -6,7 +6,8 @@
//! - **Star Line format**: 64 bits, 250/500µs PWM, 433 MHz
//!
//! All decryption is done via [keeloq_common]; this module only orchestrates bit collection
//! (delegated to the format-specific collectors) and tries each key.
//! (delegated to the format-specific collectors) and tries each key in both byte orders
//! (as stored, and byte-swapped) in case the source used big- or little-endian.
use super::common::DecodedSignal;
use super::keeloq_common::{keeloq_decrypt, keeloq_normal_learning, reverse_key, reverse8};
@@ -19,39 +20,32 @@ const KIA_V3_V4_BITS: usize = 68;
const STAR_LINE_BITS: usize = 64;
/// Try to decode an unknown signal as KeeLoq using every keystore manufacturer key.
/// Tries Kia V3/V4 format first (315/433 MHz), then Star Line format (433 MHz).
/// Tries both Kia V3/V4 format (68-bit, 400/800µs) and Star Line format (64-bit, 250/500µs)
/// regardless of frequency; each key is tried in both byte orders (LE and BE) until one validates.
/// Returns `("Keeloq (keystore name)", decoded)` on first successful decrypt.
pub fn try_decode(
pairs: &[LevelDuration],
frequency: u32,
_frequency: u32,
) -> Option<(String, DecodedSignal)> {
let keys = keystore::keeloq_mf_keys_with_names();
if keys.is_empty() {
return None;
}
// Kia V3/V4 format: 400/800µs, 315/433 MHz
let kia_freq_ok = [315_000_000u32, 433_920_000].iter().any(|&f| {
let diff = if f > frequency { f - frequency } else { frequency - f };
diff < (f / 50)
});
if kia_freq_ok {
for invert in [false, true] {
if let Some((buf, is_v3)) = kia_v3_v4::collect_kia_v3_v4_bits(pairs, invert) {
if let Some((name, decoded)) = try_kia_v3_v4_format(&buf, is_v3, &keys) {
return Some((format!("Keeloq ({})", name), decoded));
}
// Kia V3/V4 format: 400/800µs, 68 bits (try both polarities, all keys)
for invert in [false, true] {
if let Some((buf, is_v3)) = kia_v3_v4::collect_kia_v3_v4_bits(pairs, invert) {
if let Some((name, decoded)) = try_kia_v3_v4_format(&buf, is_v3, &keys) {
return Some((format!("Keeloq ({})", name), decoded));
}
}
}
// Star Line format: 250/500µs, 433 MHz
if frequency.abs_diff(433_920_000) < (433_920_000 / 50) {
for invert in [false, true] {
if let Some(data) = star_line::collect_star_line_bits(pairs, invert) {
if let Some((name, decoded)) = try_star_line_format(data, &keys) {
return Some((format!("Keeloq ({})", name), decoded));
}
// Star Line format: 250/500µs, 64 bits (try both polarities, all keys)
for invert in [false, true] {
if let Some(data) = star_line::collect_star_line_bits(pairs, invert) {
if let Some((name, decoded)) = try_star_line_format(data, &keys) {
return Some((format!("Keeloq ({})", name), decoded));
}
}
}
@@ -91,27 +85,29 @@ fn try_kia_v3_v4_format(
| (b[7] as u64);
for (name, mf_key) in keys {
if *mf_key == 0 {
continue;
}
let decrypted = keeloq_decrypt(encrypted, *mf_key);
let dec_btn = ((decrypted >> 28) & 0x0F) as u8;
let dec_serial_lsb = ((decrypted >> 16) & 0xFF) as u8;
if dec_btn == button && dec_serial_lsb == our_serial_lsb {
let counter = (decrypted & 0xFFFF) as u16;
return Some((
name.clone(),
DecodedSignal {
serial: Some(serial),
button: Some(button),
counter: Some(counter),
crc_valid: true,
data: key_data,
data_count_bit: KIA_V3_V4_BITS,
encoder_capable: true,
extra: None,
},
));
for key in [*mf_key, mf_key.swap_bytes()] {
if key == 0 {
continue;
}
let decrypted = keeloq_decrypt(encrypted, key);
let dec_btn = ((decrypted >> 28) & 0x0F) as u8;
let dec_serial_lsb = ((decrypted >> 16) & 0xFF) as u8;
if dec_btn == button && dec_serial_lsb == our_serial_lsb {
let counter = (decrypted & 0xFFFF) as u16;
return Some((
name.clone(),
DecodedSignal {
serial: Some(serial),
button: Some(button),
counter: Some(counter),
crc_valid: true,
data: key_data,
data_count_bit: KIA_V3_V4_BITS,
encoder_capable: true,
extra: None,
},
));
}
}
}
None
@@ -131,49 +127,51 @@ fn try_star_line_format(
let serial_lsb = (serial & 0xFF) as u8;
for (name, mf_key) in keys {
if *mf_key == 0 {
continue;
}
// Simple learning
let decrypt = keeloq_decrypt(key_hop, *mf_key);
let dec_btn = (decrypt >> 24) as u8;
let dec_serial_lsb = ((decrypt >> 16) & 0xFF) as u8;
if dec_btn == btn && dec_serial_lsb == serial_lsb {
let counter = (decrypt & 0xFFFF) as u16;
return Some((
name.clone(),
DecodedSignal {
serial: Some(serial),
button: Some(btn),
counter: Some(counter),
crc_valid: true,
data,
data_count_bit: STAR_LINE_BITS,
encoder_capable: true,
extra: None,
},
));
}
// Normal learning
let man_key = keeloq_normal_learning(key_fix, *mf_key);
let decrypt = keeloq_decrypt(key_hop, man_key);
let dec_btn = (decrypt >> 24) as u8;
let dec_serial_lsb = ((decrypt >> 16) & 0xFF) as u8;
if dec_btn == btn && dec_serial_lsb == serial_lsb {
let counter = (decrypt & 0xFFFF) as u16;
return Some((
name.clone(),
DecodedSignal {
serial: Some(serial),
button: Some(btn),
counter: Some(counter),
crc_valid: true,
data,
data_count_bit: STAR_LINE_BITS,
encoder_capable: true,
extra: None,
},
));
for key in [*mf_key, mf_key.swap_bytes()] {
if key == 0 {
continue;
}
// Simple learning
let decrypt = keeloq_decrypt(key_hop, key);
let dec_btn = (decrypt >> 24) as u8;
let dec_serial_lsb = ((decrypt >> 16) & 0xFF) as u8;
if dec_btn == btn && dec_serial_lsb == serial_lsb {
let counter = (decrypt & 0xFFFF) as u16;
return Some((
name.clone(),
DecodedSignal {
serial: Some(serial),
button: Some(btn),
counter: Some(counter),
crc_valid: true,
data,
data_count_bit: STAR_LINE_BITS,
encoder_capable: true,
extra: None,
},
));
}
// Normal learning
let man_key = keeloq_normal_learning(key_fix, key);
let decrypt = keeloq_decrypt(key_hop, man_key);
let dec_btn = (decrypt >> 24) as u8;
let dec_serial_lsb = ((decrypt >> 16) & 0xFF) as u8;
if dec_btn == btn && dec_serial_lsb == serial_lsb {
let counter = (decrypt & 0xFFFF) as u16;
return Some((
name.clone(),
DecodedSignal {
serial: Some(serial),
button: Some(btn),
counter: Some(counter),
crc_valid: true,
data,
data_count_bit: STAR_LINE_BITS,
encoder_capable: true,
extra: None,
},
));
}
}
}
None