diff --git a/CHANGELOG.md b/CHANGELOG.md index 394726fb1..52287404c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `client/resources/pm3_generic_private_key.pem` in order to self-sign a modded device (@iceman1001) - Fix `hf mfdes value --op clear` commands for clearing more than 0x80000000 values and getfilesettings mac mode (@merlokk) - Added ATR fingerprinting to `hf 14a/14b info` (@doegox) +- Added `Verkada 40-bit` format (@aaronmaxlevy) ## [Phrack.4.20728][2025-09-11] - Changed `lf t55xx restore` - now skips writing block0 if its all zeros (@iceman1001) diff --git a/client/src/wiegand_formats.c b/client/src/wiegand_formats.c index d43ab3f40..7cecb4825 100644 --- a/client/src/wiegand_formats.c +++ b/client/src/wiegand_formats.c @@ -1125,6 +1125,46 @@ static bool Unpack_CasiRusco40(wiegand_message_t *packed, wiegand_card_t *card) return true; } +static bool Pack_Verkada40(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bool preamble) { + memset(packed, 0, sizeof(wiegand_message_t)); + + if (!validate_card_limit(format_idx, card)) return false; + + packed->Length = 40; // Set number of bits + + set_linear_field(packed, card->FacilityCode, 1, 10); + + set_linear_field(packed, card->CardNumber, 11, 28); + + set_bit_by_position(packed, + evenparity32(get_linear_field(packed, 1, 10)) + , 0); + + set_bit_by_position(packed, + evenparity32(get_linear_field(packed, 11, 28)) + , 39); + + if (preamble) + return add_HID_header(packed); + return true; +} + +static bool Unpack_Verkada40(wiegand_message_t *packed, wiegand_card_t *card) { + if (packed->Length != 40) return false; // Wrong length? Stop here. + + memset(card, 0, sizeof(wiegand_card_t)); + + card->FacilityCode = get_linear_field(packed, 1, 10); + + card->CardNumber = get_linear_field(packed, 11, 28); + + card->ParityValid = + (get_bit_by_position(packed, 0) == evenparity32(get_linear_field(packed, 1, 10))) && + (get_bit_by_position(packed, 39) == evenparity32(get_linear_field(packed, 11, 28))); + + return true; +} + static bool Pack_Optus(int format_idx, wiegand_card_t *card, wiegand_message_t *packed, bool preamble) { if (!validate_card_limit(format_idx, card)) return false; @@ -1542,6 +1582,7 @@ static const cardformat_t FormatTable[] = { {"PW39", Pack_pw39, Unpack_pw39, "Pyramid 39-bit wiegand format", 39, {1, 1, 0, 0, 1, 0x0000FFFFu, 0x00000000000FFFFFu, 0x00000000u, 0x00000000u}}, // from cardinfo.barkweb.com.au {"P10001", Pack_P10001, Unpack_P10001, "HID P10001 Honeywell 40-bit", 40, {1, 1, 0, 0, 0, 0x00000FFFu, 0x000000000000FFFFu, 0x00000000u, 0x00000000u}}, // from cardinfo.barkweb.com.au {"Casi40", Pack_CasiRusco40, Unpack_CasiRusco40, "Casi-Rusco 40-bit", 40, {1, 0, 0, 0, 0, 0x00000000u, 0x000000FFFFFFFFFFu, 0x00000000u, 0x00000000u}}, // from cardinfo.barkweb.com.au + {"Verkada40", Pack_Verkada40, Unpack_Verkada40, "Verkada 40-bit", 40, {1, 1, 0, 0, 1, 0x000003FFu, 0x000000000FFFFFFFu, 0x00000000u, 0x00000000u}}, // Verkada 40-bit format {"BC40", Pack_bc40, Unpack_bc40, "Bundy TimeClock 40-bit", 40, {1, 1, 0, 1, 1, 0x00000FFFu, 0x00000000000FFFFFu, 0x00000000u, 0x0000007Fu}}, // from {"Defcon32", Pack_Defcon32, Unpack_Defcon32, "Custom Defcon RFCTF 42-bit", 42, {1, 1, 1, 0, 1, 0x0000FFFFu, 0x00000000000FFFFFu, 0x0000000Fu, 0x00000000u}}, // Created by (@micsen) for the CTF {"H800002", Pack_H800002, Unpack_H800002, "HID H800002 46-bit", 46, {1, 1, 0, 0, 1, 0x00003FFFu, 0x000000003FFFFFFFu, 0x00000000u, 0x00000000u}}, diff --git a/tools/pm3_tests.sh b/tools/pm3_tests.sh index f8e2dba2b..4d3f35040 100755 --- a/tools/pm3_tests.sh +++ b/tools/pm3_tests.sh @@ -450,6 +450,12 @@ while true; do if ! CheckExecute "nfc decode test - signature" "$CLIENTBIN -c 'nfc decode -d 03FF010194113870696C65742E65653A656B616172743A3266195F26063132303832325904202020205F28033233335F2701316E1B5A13333038363439303039303030323636343030355304EBF2CE704103000000AC536967010200803A2448FCA7D354A654A81BD021150D1A152D1DF4D7A55D2B771F12F094EAB6E5E10F2617A2F8DAD4FD38AFF8EA39B71C19BD42618CDA86EE7E144636C8E0E7CFC4096E19C3680E09C78A0CDBC05DA2D698E551D5D709717655E56FE3676880B897D2C70DF5F06ECE07C71435255144F8EE41AF110E7B180DA0E6C22FB8FDEF61800025687474703A2F2F70696C65742E65652F6372742F33303836343930302D303030312E637274FE'" "30864900-0001.crt"; then break; fi if ! CheckExecute "wiegand decode test - raw" "$CLIENTBIN -c 'wiegand decode --raw 2006F623AE'" "FC: 123 CN: 4567 parity \( ok \)"; then break; fi if ! CheckExecute "wiegand decode test - new" "$CLIENTBIN -c 'wiegand decode --new 06BD88EB80'" "FC: 123 CN: 4567 parity \( ok \)"; then break; fi + if ! CheckExecute "wiegand Verkada40 encode test 1" "$CLIENTBIN -c 'wiegand encode -w Verkada40 --fc 50 --cn 1001'" "86400007D3"; then break; fi + if ! CheckExecute "wiegand Verkada40 decode test 1" "$CLIENTBIN -c 'wiegand decode --raw 86400007D3'" "Verkada40.*FC: 50 CN: 1001 parity \( ok \)"; then break; fi + if ! CheckExecute "wiegand Verkada40 encode test 2" "$CLIENTBIN -c 'wiegand encode -w Verkada40 --fc 50 --cn 1004'" "86400007D9"; then break; fi + if ! CheckExecute "wiegand Verkada40 decode test 2" "$CLIENTBIN -c 'wiegand decode --raw 86400007D9'" "Verkada40.*FC: 50 CN: 1004 parity \( ok \)"; then break; fi + if ! CheckExecute "wiegand Verkada40 encode test 3" "$CLIENTBIN -c 'wiegand encode -w Verkada40 --fc 81 --cn 5008'" "8A20002721"; then break; fi + if ! CheckExecute "wiegand Verkada40 decode test 3" "$CLIENTBIN -c 'wiegand decode --raw 8A20002721'" "Verkada40.*FC: 81 CN: 5008 parity \( ok \)"; then break; fi echo -e "\n${C_BLUE}Testing LF:${C_NC}" if ! CheckExecute "lf hitag2 test" "$CLIENTBIN -c 'lf hitag test'" "Tests \( ok"; then break; fi