mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-10 09:16:53 +00:00
WMBus: correction for mode 7 encryption with long ELL
git-svn-id: https://svn.fhem.de/fhem/trunk@20053 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
0bfcba3778
commit
9c379488b0
@ -47,7 +47,7 @@ use constant {
|
|||||||
CI_TL_4 => 0x8a, # Transport layer from device, 4 Bytes
|
CI_TL_4 => 0x8a, # Transport layer from device, 4 Bytes
|
||||||
CI_TL_12 => 0x8b, # Transport layer from device, 12 Bytes
|
CI_TL_12 => 0x8b, # Transport layer from device, 12 Bytes
|
||||||
CI_ELL_2 => 0x8c, # Extended Link Layer, 2 Bytes
|
CI_ELL_2 => 0x8c, # Extended Link Layer, 2 Bytes
|
||||||
CI_ELL_6 => 0x8e, # Extended Link Layer, 6 Bytes
|
CI_ELL_10 => 0x8e, # Extended Link Layer, 10 Bytes
|
||||||
CI_ELL_8 => 0x8d, # Extended Link Layer, 8 Bytes (see https://www.telit.com/wp-content/uploads/2017/09/Telit_Wireless_M-bus_2013_Part4_User_Guide_r14.pdf, 2.3.4)
|
CI_ELL_8 => 0x8d, # Extended Link Layer, 8 Bytes (see https://www.telit.com/wp-content/uploads/2017/09/Telit_Wireless_M-bus_2013_Part4_User_Guide_r14.pdf, 2.3.4)
|
||||||
CI_ELL_16 => 0x8f, # Extended Link Layer, 16 Bytes (see https://www.telit.com/wp-content/uploads/2017/09/Telit_Wireless_M-bus_2013_Part4_User_Guide_r14.pdf, 2.3.4)
|
CI_ELL_16 => 0x8f, # Extended Link Layer, 16 Bytes (see https://www.telit.com/wp-content/uploads/2017/09/Telit_Wireless_M-bus_2013_Part4_User_Guide_r14.pdf, 2.3.4)
|
||||||
CI_AFL => 0x90, # Authentification and Fragmentation Layer, variable size
|
CI_AFL => 0x90, # Authentification and Fragmentation Layer, variable size
|
||||||
@ -1654,6 +1654,7 @@ sub decrypt_mode7($) {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $encrypted = shift;
|
my $encrypted = shift;
|
||||||
my $padding = 2;
|
my $padding = 2;
|
||||||
|
my $identno;
|
||||||
|
|
||||||
# generate dynamic key
|
# generate dynamic key
|
||||||
my $cmac = Digest::CMAC->new($self->{aeskey});
|
my $cmac = Digest::CMAC->new($self->{aeskey});
|
||||||
@ -1668,8 +1669,13 @@ sub decrypt_mode7($) {
|
|||||||
#$self->{afl}{mcr} = pack("H*", "b30a0000");
|
#$self->{afl}{mcr} = pack("H*", "b30a0000");
|
||||||
$cmac->add($self->{afl}{mcr});
|
$cmac->add($self->{afl}{mcr});
|
||||||
#print "MCR " . unpack("H*", $self->{afl}{mcr}) . "\n";
|
#print "MCR " . unpack("H*", $self->{afl}{mcr}) . "\n";
|
||||||
#print "identno " . unpack("H*", $self->{afield_identno}) . "\n";
|
if (exists($self->{meter_id_raw})) {
|
||||||
$cmac->add($self->{afield_identno});
|
$identno = $self->{meter_id_raw};
|
||||||
|
} else {
|
||||||
|
$identno = $self->{afield_identno};
|
||||||
|
}
|
||||||
|
#print "identno " . unpack("H*", $identno) . "\n";
|
||||||
|
$cmac->add($identno);
|
||||||
$cmac->add(pack("H*", "07070707070707"));
|
$cmac->add(pack("H*", "07070707070707"));
|
||||||
#$cmac->add(pack("H*",'7856341207070707070707'));
|
#$cmac->add(pack("H*",'7856341207070707070707'));
|
||||||
|
|
||||||
@ -1679,7 +1685,7 @@ sub decrypt_mode7($) {
|
|||||||
|
|
||||||
#printf("Dynamic key %s\n", $cmac->hexdigest);
|
#printf("Dynamic key %s\n", $cmac->hexdigest);
|
||||||
|
|
||||||
# see 9.2.3, page 52
|
# see 9.2.4, page 59
|
||||||
my $initVector = '';
|
my $initVector = '';
|
||||||
for (1..16) {
|
for (1..16) {
|
||||||
$initVector .= pack('C',0x00);
|
$initVector .= pack('C',0x00);
|
||||||
@ -1778,10 +1784,16 @@ sub decodeApplicationLayer($) {
|
|||||||
# Extended Link Layer
|
# Extended Link Layer
|
||||||
($self->{ell}{cc}, $self->{ell}{access_no}) = unpack('CC', substr($applicationlayer,$offset));
|
($self->{ell}{cc}, $self->{ell}{access_no}) = unpack('CC', substr($applicationlayer,$offset));
|
||||||
$offset += 2;
|
$offset += 2;
|
||||||
} elsif ($self->{cifield} == CI_ELL_6) {
|
} elsif ($self->{cifield} == CI_ELL_10) {
|
||||||
# Extended Link Layer
|
# Extended Link Layer (long)
|
||||||
($self->{ell}{cc}, $self->{ell}{access_no}) = unpack('CC', substr($applicationlayer,$offset));
|
($self->{ell}{cc}, $self->{ell}{access_no}) = unpack('CC', substr($applicationlayer,$offset));
|
||||||
$offset += 6;
|
$offset += 2;
|
||||||
|
$self->{ell}{manufacturer} = substr($applicationlayer,$offset, 2);
|
||||||
|
$offset += 2;
|
||||||
|
$self->{ell}{identno} = substr($applicationlayer,$offset, 4);
|
||||||
|
$offset += 4;
|
||||||
|
($self->{ell}{version},$self->{ell}{device}) = unpack('CC', substr($applicationlayer,$offset));
|
||||||
|
$offset += 2;
|
||||||
} elsif ($self->{cifield} == CI_ELL_8) {
|
} elsif ($self->{cifield} == CI_ELL_8) {
|
||||||
# Extended Link Layer, payload CRC is part of (encrypted) payload
|
# Extended Link Layer, payload CRC is part of (encrypted) payload
|
||||||
($self->{ell}{cc}, $self->{ell}{access_no}, $self->{ell}{session_number}) = unpack('CCV', substr($applicationlayer, $offset));
|
($self->{ell}{cc}, $self->{ell}{access_no}, $self->{ell}{session_number}) = unpack('CCV', substr($applicationlayer, $offset));
|
||||||
@ -1887,9 +1899,10 @@ sub decodeApplicationLayer($) {
|
|||||||
$offset += 4;
|
$offset += 4;
|
||||||
} elsif ($self->{cifield} == CI_RESP_12 || $self->{cifield} == CI_RESP_SML_12) {
|
} elsif ($self->{cifield} == CI_RESP_12 || $self->{cifield} == CI_RESP_SML_12) {
|
||||||
# Long header
|
# Long header
|
||||||
($self->{meter_id}, $self->{meter_man}, $self->{meter_vers}, $self->{meter_dev}, $self->{access_no}, $self->{status}, $self->{cw_1}, $self->{cw_2}, $self->{cw_3})
|
$self->{meter_id_raw} = substr($applicationlayer,$offset,4);
|
||||||
= unpack('VvCCCCCCC', substr($applicationlayer,$offset));
|
($self->{meter_man}, $self->{meter_vers}, $self->{meter_dev}, $self->{access_no}, $self->{status}, $self->{cw_1}, $self->{cw_2}, $self->{cw_3})
|
||||||
$self->{meter_id} = sprintf("%08d", $self->{meter_id});
|
= unpack('vCCCCCCC', substr($applicationlayer,$offset+4));
|
||||||
|
$self->{meter_id} = sprintf("%08d", unpack('V', $self->{meter_id}));
|
||||||
$self->{meter_devtypestring} = $validDeviceTypes{$self->{meter_dev}} || 'unknown';
|
$self->{meter_devtypestring} = $validDeviceTypes{$self->{meter_dev}} || 'unknown';
|
||||||
$self->{meter_manufacturer} = uc($self->manId2ascii($self->{meter_man}));
|
$self->{meter_manufacturer} = uc($self->manId2ascii($self->{meter_man}));
|
||||||
#printf("Long header access_no %x\n", $self->{access_no});
|
#printf("Long header access_no %x\n", $self->{access_no});
|
||||||
@ -1975,8 +1988,8 @@ sub decodeApplicationLayer($) {
|
|||||||
# payload can be only partially encrypted.
|
# payload can be only partially encrypted.
|
||||||
# decrypt only the encrypted part
|
# decrypt only the encrypted part
|
||||||
my $encrypted_length = $self->{cw_parts}{encrypted_blocks} * 16;
|
my $encrypted_length = $self->{cw_parts}{encrypted_blocks} * 16;
|
||||||
#printf("encrypted payload %s\n", unpack("H*", substr($applicationlayer,$offset, $encrypted_length)));
|
|
||||||
if ($self->{cw_parts}{mode} == 5) {
|
if ($self->{cw_parts}{mode} == 5) {
|
||||||
|
#printf("encrypted payload %s\n", unpack("H*", substr($applicationlayer,$offset, $encrypted_length)));
|
||||||
eval {
|
eval {
|
||||||
$payload = $self->decrypt_mode5(substr($applicationlayer, $offset, $encrypted_length));
|
$payload = $self->decrypt_mode5(substr($applicationlayer, $offset, $encrypted_length));
|
||||||
};
|
};
|
||||||
@ -1984,6 +1997,7 @@ sub decodeApplicationLayer($) {
|
|||||||
# mode 7
|
# mode 7
|
||||||
if ($hasCMAC) {
|
if ($hasCMAC) {
|
||||||
$offset++; # account for codeword byte 3
|
$offset++; # account for codeword byte 3
|
||||||
|
#printf("encrypted payload %s\n", unpack("H*", substr($applicationlayer,$offset, $encrypted_length)));
|
||||||
eval {
|
eval {
|
||||||
$payload = $self->decrypt_mode7(substr($applicationlayer, $offset, $encrypted_length));
|
$payload = $self->decrypt_mode7(substr($applicationlayer, $offset, $encrypted_length));
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user