Improve handling of encrypted telegrams when there is no key available.

pull/505/head
Fredrik Öhrström 2022-03-27 21:48:42 +02:00
rodzic 073e4b5151
commit fb729d5f35
7 zmienionych plików z 64 dodań i 21 usunięć

Wyświetl plik

@ -118,7 +118,7 @@ MeterAventiesWM::MeterAventiesWM(MeterInfo &mi, DriverInfo &di) :
// |Votten;61070071;466.472000;;1111-11-11 11:11.11
// Test: Votten aventieswm 61070071 NOKEY
// telegram=76442104710007612507727100076121042507B50060052F2F0413281E0700431404B60083011440B300C30114A5AF00830214CBAC00C3021463A8008303149EA500C3031433A200830414C79F00C304148F9C00830514989900C30514CF9700830614269400C30614069100830714C88B0002FD171111
// {"media":"water","meter":"aventieswm","name":"Votten","id":"61070071","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"error_flags":"MEASUREMENT HF UNKNOWN_ERROR_FLAGS(0x1100)","timestamp":"1111-11-11T11:11:11Z"}
// |Votten;61070071;466.472000;MEASUREMENT HF UNKNOWN_ERROR_FLAGS(0x1100);1111-11-11 11:11.11
// Test: Vatten aventieswm 61070072 NOKEY
// telegram=76442104720007612507727200076121042507B50060052F2F0413281E0700431404B60083011440B300C30114A5AF00830214CBAC00C3021463A8008303149EA500C3031433A200830414C79F00C304148F9C00830514989900C30514CF9700830614269400C30614069100830714C88B0002FD171111
// {"media":"water","meter":"aventieswm","name":"Vatten","id":"61070072","total_m3":466.472,"consumption_at_set_date_1_m3":465.96,"consumption_at_set_date_2_m3":458.88,"consumption_at_set_date_3_m3":449.65,"consumption_at_set_date_4_m3":442.35,"consumption_at_set_date_5_m3":431.07,"consumption_at_set_date_6_m3":423.98,"consumption_at_set_date_7_m3":415.23,"consumption_at_set_date_8_m3":409.03,"consumption_at_set_date_9_m3":400.79,"consumption_at_set_date_10_m3":393.2,"consumption_at_set_date_11_m3":388.63,"consumption_at_set_date_12_m3":379.26,"consumption_at_set_date_13_m3":371.26,"consumption_at_set_date_14_m3":357.84,"error_flags":"MEASUREMENT HF UNKNOWN_ERROR_FLAGS(0x1100)","timestamp":"1111-11-11T11:11:11Z"}
// |Vatten;61070072;466.472000;MEASUREMENT HF UNKNOWN_ERROR_FLAGS(0x1100);1111-11-11 11:11.11

Wyświetl plik

@ -100,6 +100,9 @@ void MeterCompact5::processContent(Telegram *t)
vector<uchar> content;
t->extractPayload(&content);
if (content.size() < 9) return;
uchar prev_lo = content[3];
uchar prev_hi = content[4];
double prev = (256.0*prev_hi+prev_lo);

Wyświetl plik

@ -100,6 +100,8 @@ void MeterVario451::processContent(Telegram *t)
vector<uchar> content;
t->extractPayload(&content);
if (content.size() < 9) return;
uchar prev_lo = content[3];
uchar prev_hi = content[4];
double prev = (256.0*prev_hi+prev_lo)/1000;

Wyświetl plik

@ -1472,7 +1472,7 @@ bool loadFormatBytesFromSignature(uint16_t format_signature, vector<uchar> *form
bool Telegram::alreadyDecryptedCBC(vector<uchar>::iterator &pos)
{
if (*(pos+0) != 0x2f || *(pos+1) != 0x2f) return false;
addExplanationAndIncrementPos(pos, 2, KindOfData::PROTOCOL, Understanding::FULL, "%02x%02x decrypt check bytes", *(pos+0), *(pos+1));
addExplanationAndIncrementPos(pos, 2, KindOfData::PROTOCOL, Understanding::FULL, "%02x%02x already decrypted check bytes", *(pos+0), *(pos+1));
return true;
}
@ -1486,8 +1486,8 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
{
// Oups! This telegram is already decrypted (but the header still says it should be encrypted)
// this is probably a replay telegram from --logtelegrams.
// Since we have specified a key! Do not accept this telegram!
warning("(wmbus) WARNING! telegram should have been fully encrypted, but was not! "
// But since we have specified a key! Do not accept this telegram!
warning("(wmbus) WARNING!! telegram should have been fully encrypted, but was not! "
"id: %02x%02x%02x%02x mfct: (%s) %s (0x%02x) type: %s (0x%02x) ver: 0x%02x\n",
dll_id_b[3], dll_id_b[2], dll_id_b[1], dll_id_b[0],
manufacturerFlag(dll_mfct).c_str(),
@ -1506,6 +1506,7 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
}
int num_encrypted_bytes = 0;
int num_not_encrypted_at_end = 0;
bool ok = decrypt_TPL_AES_CBC_IV(this, frame, pos, meter_keys->confidentiality_key,
&num_encrypted_bytes, &num_not_encrypted_at_end);
if (!ok)
@ -1513,11 +1514,23 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
string info = bin2hex(pos, frame.end(), num_encrypted_bytes);
info += " encrypted";
addExplanationAndIncrementPos(pos, num_encrypted_bytes, KindOfData::CONTENT, Understanding::ENCRYPTED, info.c_str());
if (meter_keys->confidentiality_key.size() > 0)
if (parser_warns_)
{
// Only fail if we gave an explicit key.
return false;
if (!beingAnalyzed() && (isVerboseEnabled() || isDebugEnabled() || !warned_for_telegram_before(this, dll_a)))
{
// Print this warning only once! Unless you are using verbose or debug.
warning("(wmbus) WARNING! no key to decrypt payload! "
"Permanently ignoring telegrams from id: %02x%02x%02x%02x mfct: (%s) %s (0x%02x) type: %s (0x%02x) ver: 0x%02x\n",
dll_id_b[3], dll_id_b[2], dll_id_b[1], dll_id_b[0],
manufacturerFlag(dll_mfct).c_str(),
manufacturer(dll_mfct).c_str(),
dll_mfct,
mediaType(dll_type, dll_mfct).c_str(), dll_type,
dll_version);
}
}
return false;
}
// Now the frame from pos and onwards has been decrypted.
@ -1546,14 +1559,26 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
}
else if (tpl_sec_mode == TPLSecurityMode::AES_CBC_NO_IV)
{
if (alreadyDecryptedCBC(pos)) return true;
if (meter_keys == NULL || (!meter_keys->hasConfidentialityKey() && isSimulated()))
if (alreadyDecryptedCBC(pos))
{
CHECK(2);
addExplanationAndIncrementPos(pos, 2, KindOfData::PROTOCOL, Understanding::FULL,
"%02x%02x (already) decrypted check bytes", *(pos+0), *(pos+1));
if (meter_keys && meter_keys->hasConfidentialityKey())
{
// Oups! This telegram is already decrypted (but the header still says it should be encrypted)
// this is probably a replay telegram from --logtelegrams.
// But since we have specified a key! Do not accept this telegram!
warning("(wmbus) WARNING! telegram should have been fully encrypted, but was not! "
"id: %02x%02x%02x%02x mfct: (%s) %s (0x%02x) type: %s (0x%02x) ver: 0x%02x\n",
dll_id_b[3], dll_id_b[2], dll_id_b[1], dll_id_b[0],
manufacturerFlag(dll_mfct).c_str(),
manufacturer(dll_mfct).c_str(),
dll_mfct,
mediaType(dll_type, dll_mfct).c_str(), dll_type,
dll_version);
return false;
}
return true;
}
bool mac_ok = checkMAC(frame, tpl_start, frame.end(), afl_mac_b, tpl_generated_mac_key);
// Do not attempt to decrypt if the mac has failed!
@ -1572,7 +1597,18 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
dll_mfct,
mediaType(dll_type, dll_mfct).c_str(), dll_type,
dll_version);
return false;
}
string info = bin2hex(pos, frame.end(), frame.end()-pos);
info += " mac fails";
addExplanationAndIncrementPos(pos, frame.end()-pos, KindOfData::CONTENT, Understanding::ENCRYPTED, info.c_str());
if (meter_keys->confidentiality_key.size() > 0)
{
// Only fail if we gave an explicit key.
return false;
}
return true;
}
return false;
}
@ -1598,7 +1634,7 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
if (!beingAnalyzed() && (isVerboseEnabled() || isDebugEnabled() || !warned_for_telegram_before(this, dll_a)))
{
// Print this warning only once! Unless you are using verbose or debug.
warning("(wmbus) WARNING! decrypted content failed check, did you use the correct decryption key? "
warning("(wmbus) WARNING!! decrypted content failed check, did you use the correct decryption key? "
"Permanently ignoring telegrams from id: %02x%02x%02x%02x mfct: (%s) %s (0x%02x) type: %s (0x%02x) ver: 0x%02x\n",
dll_id_b[3], dll_id_b[2], dll_id_b[1], dll_id_b[0],
manufacturerFlag(dll_mfct).c_str(),
@ -1634,7 +1670,7 @@ bool Telegram::potentiallyDecrypt(vector<uchar>::iterator &pos)
{
// Oups! This telegram is NOT encrypted, but we have specified a key!
// Do not accept this telegram!
warning("(wmbus) WARNING! telegram should have been encrypted, but was not! "
warning("(wmbus) WARNING!!! telegram should have been encrypted, but was not! "
"id: %02x%02x%02x%02x mfct: (%s) %s (0x%02x) type: %s (0x%02x) ver: 0x%02x\n",
dll_id_b[3], dll_id_b[2], dll_id_b[1], dll_id_b[0],
manufacturerFlag(dll_mfct).c_str(),

Wyświetl plik

@ -213,6 +213,8 @@ bool decrypt_TPL_AES_CBC_NO_IV(Telegram *t, vector<uchar> &frame, vector<uchar>:
debug("(TPL) num encrypted blocks %d (%d bytes and remaining unencrypted %d bytes)\n",
t->tpl_num_encr_blocks, num_bytes_to_decrypt, buffer.size()-num_bytes_to_decrypt);
if (aeskey.size() == 0) return false;
if (buffer.size() < num_bytes_to_decrypt)
{
warning("(TPL) warning: decryption received less bytes than expected for decryption! "

Wyświetl plik

@ -31,13 +31,13 @@ TESTNAME="Test that telegram really is encrypted"
TESTRESULT="ERROR"
cat > $TEST/test_expected.txt <<EOF
(wmbus) WARNING! telegram should have been fully encrypted, but was not! id: 88888888 mfct: (APA) Apator, Poland (0x601) type: Water meter (0x07) ver: 0x05
(wmbus) WARNING!! telegram should have been fully encrypted, but was not! id: 88888888 mfct: (APA) Apator, Poland (0x601) type: Water meter (0x07) ver: 0x05
(meter) newly created meter (ApWater 88888888 apator162) did not handle telegram!
(wmbus) WARNING! decrypted payload crc failed check, did you use the correct decryption key? e1d6 payload crc (calculated a528) Permanently ignoring telegrams from id: 76348799 mfct: (KAM) Kamstrup Energi (0x2c2d) type: Cold water meter (0x16) ver: 0x1b
(meter) newly created meter (Vatten 76348799 multical21) did not handle telegram!
(wmbus) WARNING! telegram should have been fully encrypted, but was not! id: 77777777 mfct: (SON) Sontex, Switzerland (0x4dee) type: Water meter (0x07) ver: 0x3c
(wmbus) WARNING!! telegram should have been fully encrypted, but was not! id: 77777777 mfct: (SON) Sontex, Switzerland (0x4dee) type: Water meter (0x07) ver: 0x3c
(meter) newly created meter (Wasser 77777777 supercom587) did not handle telegram!
(wmbus) WARNING! telegram should have been encrypted, but was not! id: 77777777 mfct: (SON) Sontex, Switzerland (0x4dee) type: Water meter (0x07) ver: 0x3c
(wmbus) WARNING!!! telegram should have been encrypted, but was not! id: 77777777 mfct: (SON) Sontex, Switzerland (0x4dee) type: Water meter (0x07) ver: 0x3c
EOF
$PROG --format=json simulations/simulation_aes_removed.msg \

Wyświetl plik

@ -13,7 +13,7 @@ $PROG --format=json simulations/simulation_bad_keys.txt room fhkvdataiii 0306571
cat > $TEST/expected_err.txt <<EOF
(meter) room: meter detection did not match the selected driver fhkvdataiii! correct driver is: fhkvdataiv
(meter) Not printing this warning again for id: 03065716 mfct: (TCH) Techem Service (0x5068) type: Heat Cost Allocator (0x08) ver: 0x94
(wmbus) WARNING! decrypted content failed check, did you use the correct decryption key? Permanently ignoring telegrams from id: 03065716 mfct: (TCH) Techem Service (0x5068) type: Heat Cost Allocator (0x08) ver: 0x94
(wmbus) WARNING! no key to decrypt payload! Permanently ignoring telegrams from id: 03065716 mfct: (TCH) Techem Service (0x5068) type: Heat Cost Allocator (0x08) ver: 0x94
EOF
diff $TEST/test_stderr.txt $TEST/expected_err.txt