mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-22 20:24:36 +00:00
WMBus: add missing changes to mode 7 encyrption
git-svn-id: https://svn.fhem.de/fhem/trunk@20051 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
c3b9d59283
commit
98b5ef3e48
@ -11,6 +11,8 @@ eval "use Crypt::Mode::CBC"; # cpan -i Crypt::Mode::CBC
|
|||||||
my $hasCBC = ($@)?0:1;
|
my $hasCBC = ($@)?0:1;
|
||||||
eval "use Crypt::Mode::CTR"; # cpan -i Crypt::Mode::CTR
|
eval "use Crypt::Mode::CTR"; # cpan -i Crypt::Mode::CTR
|
||||||
my $hasCTR = ($@)?0:1;
|
my $hasCTR = ($@)?0:1;
|
||||||
|
eval "use Digest::CMAC"; # cpan -i Digest::CMAC
|
||||||
|
my $hasCMAC = ($@)?0:1;
|
||||||
|
|
||||||
require Exporter;
|
require Exporter;
|
||||||
my @ISA = qw(Exporter);
|
my @ISA = qw(Exporter);
|
||||||
@ -1198,6 +1200,7 @@ sub getCRCsize {
|
|||||||
sub decodeConfigword($) {
|
sub decodeConfigword($) {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
|
|
||||||
#printf("cw: %01x %01x\n", $self->{cw_1}, $self->{cw_2});
|
#printf("cw: %01x %01x\n", $self->{cw_1}, $self->{cw_2});
|
||||||
$self->{cw_parts}{mode} = ($self->{cw_2} & 0b00011111);
|
$self->{cw_parts}{mode} = ($self->{cw_2} & 0b00011111);
|
||||||
#printf("mode: %02x\n", $self->{cw_parts}{mode});
|
#printf("mode: %02x\n", $self->{cw_parts}{mode});
|
||||||
@ -1209,10 +1212,13 @@ sub decodeConfigword($) {
|
|||||||
$self->{cw_parts}{content} = ($self->{cw_1} & 0b00001100) >> 2;
|
$self->{cw_parts}{content} = ($self->{cw_1} & 0b00001100) >> 2;
|
||||||
$self->{cw_parts}{repeated_access} = ($self->{cw_1} & 0b00000010) >> 1;
|
$self->{cw_parts}{repeated_access} = ($self->{cw_1} & 0b00000010) >> 1;
|
||||||
$self->{cw_parts}{hops} = ($self->{cw_1} & 0b00000001);
|
$self->{cw_parts}{hops} = ($self->{cw_1} & 0b00000001);
|
||||||
} #elsif ($self->{cw_parts}{mode} == 7) {
|
} elsif ($self->{cw_parts}{mode} == 7) {
|
||||||
# ToDo: wo kommt das dritte Byte her?
|
# configword ist 3 Bytes lang
|
||||||
# $self->{cw_parts}{mode} = $self->{cw} & 0b0000111100000000 >> 8;
|
$self->{cw_parts}{key_id} = ($self->{cw_3} & 0b00001111);
|
||||||
#}
|
$self->{cw_parts}{dynamic_key} = ($self->{cw_3} & 0b01110000) >> 4;
|
||||||
|
$self->{cw_parts}{content} = ($self->{cw_2} & 0b11000000) >> 6;
|
||||||
|
$self->{cw_parts}{encrypted_blocks} = ($self->{cw_1} & 0b11110000) >> 4;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub decodeBCD($$$) {
|
sub decodeBCD($$$) {
|
||||||
@ -1622,7 +1628,7 @@ sub decodePayload($$) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub decrypt($) {
|
sub decrypt_mode5($) {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $encrypted = shift;
|
my $encrypted = shift;
|
||||||
my $padding = 2;
|
my $padding = 2;
|
||||||
@ -1647,106 +1653,50 @@ sub decrypt($) {
|
|||||||
sub decrypt_mode7($) {
|
sub decrypt_mode7($) {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $encrypted = shift;
|
my $encrypted = shift;
|
||||||
|
my $padding = 2;
|
||||||
|
|
||||||
# see 9.2.4, page 59
|
# generate dynamic key
|
||||||
|
my $cmac = Digest::CMAC->new($self->{aeskey});
|
||||||
|
#my $cmac = Digest::CMAC->new(pack("H*",'000102030405060708090A0B0C0D0E0F'));
|
||||||
|
|
||||||
|
# The calculation of Kenc and Kmac for the meter:
|
||||||
|
# Kenc = CMAC(MK, 0x00 ||C[7..0] ||C[15..8] ||C[23..16] ||C[31..24] ||ID_0||ID_1||ID_2||ID_3||0x07||0x07||0x07||0x07||0x07||0x07||0x07)
|
||||||
|
# Where C[7..0] is the LSB and C[31..24] is the MSB (Big Endian) of the counter AFL.MCR.C from meter to other (gateway).
|
||||||
|
|
||||||
|
$cmac->add(pack("H*", "00"));
|
||||||
|
|
||||||
|
#$self->{afl}{mcr} = pack("H*", "b30a0000");
|
||||||
|
$cmac->add($self->{afl}{mcr});
|
||||||
|
#print "MCR " . unpack("H*", $self->{afl}{mcr}) . "\n";
|
||||||
|
#print "identno " . unpack("H*", $self->{afield_identno}) . "\n";
|
||||||
|
$cmac->add($self->{afield_identno});
|
||||||
|
$cmac->add(pack("H*", "07070707070707"));
|
||||||
|
#$cmac->add(pack("H*",'7856341207070707070707'));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
my $key = $cmac->digest;
|
||||||
|
|
||||||
|
#printf("Dynamic key %s\n", $cmac->hexdigest);
|
||||||
|
|
||||||
|
# see 9.2.3, page 52
|
||||||
my $initVector = '';
|
my $initVector = '';
|
||||||
for (1..16) {
|
for (1..16) {
|
||||||
$initVector .= pack('C',0x00);
|
$initVector .= pack('C',0x00);
|
||||||
}
|
}
|
||||||
my $cipher = Crypt::Mode::CBC->new('AES', 2);
|
if (length($encrypted)%16 == 0) {
|
||||||
return $cipher->decrypt($encrypted, $self->{aeskey}, $initVector);
|
# no padding if data length is multiple of blocksize
|
||||||
}
|
$padding = 0;
|
||||||
|
|
||||||
# Generate MAC of data
|
|
||||||
#
|
|
||||||
# Parameter 1: private key as byte string, 16bytes
|
|
||||||
# Parameter 2: data fro which mac should be calculated in hexadecimal format, len variable
|
|
||||||
# Parameter 3: length of MAC to be generated in bytes
|
|
||||||
#
|
|
||||||
# Returns: MAC in hexadecimal format
|
|
||||||
#
|
|
||||||
# This function currently supports data with lentgh of less then 16bytes,
|
|
||||||
# MAC for longer data is untested but specified
|
|
||||||
#
|
|
||||||
# copied from 10_EnOcean.pm
|
|
||||||
sub generateMAC($$$$) {
|
|
||||||
my $self = shift;
|
|
||||||
my $private_key = $_[0];
|
|
||||||
my $data = $_[1];
|
|
||||||
my $cmac_len = $_[2];
|
|
||||||
|
|
||||||
#print "Calculating MAC for data $data\n";
|
|
||||||
|
|
||||||
# Pack data to 16byte byte string, padd with 10..0 binary
|
|
||||||
my $data_expanded = pack('H32', $data.'80');
|
|
||||||
|
|
||||||
#print "Exp. data ".unpack('H32', $data_expanded)."\n";
|
|
||||||
|
|
||||||
# Constants according to specification
|
|
||||||
my $const_zero = pack('H32','00');
|
|
||||||
my $const_rb = pack('H32', '00000000000000000000000000000087');
|
|
||||||
|
|
||||||
# Encrypt zero data with private key to get L
|
|
||||||
my $cipher = Crypt::Rijndael->new($private_key);
|
|
||||||
my $l = $cipher->encrypt($const_zero);
|
|
||||||
#print "L ".unpack('H32', $l)."\n";
|
|
||||||
#print "L ".unpack('B128', $l)."\n";
|
|
||||||
|
|
||||||
# Expand L to 128bit string
|
|
||||||
my $l_bit = unpack('B128', $l);
|
|
||||||
|
|
||||||
# K1 and K2 stored as 128bit string
|
|
||||||
my $k1_bit;
|
|
||||||
my $k2_bit;
|
|
||||||
|
|
||||||
# K1 and K2 as binary
|
|
||||||
my $k1;
|
|
||||||
my $k2;
|
|
||||||
|
|
||||||
# Store L << 1 in K1
|
|
||||||
$l_bit =~ /^.(.{127})/;
|
|
||||||
$k1_bit = $1.'0';
|
|
||||||
$k1 = pack('B128', $k1_bit);
|
|
||||||
|
|
||||||
# If MSB of L == 1, K1 = K1 XOR const_Rb
|
|
||||||
if($l_bit =~ m/^1/) {
|
|
||||||
#print "MSB of L is set\n";
|
|
||||||
$k1 = $k1 ^ $const_rb;
|
|
||||||
$k1_bit = unpack('B128', $k1);
|
|
||||||
} else {
|
} else {
|
||||||
#print "MSB of L is unset\n";
|
$padding = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
# Store K1 << 1 in K2
|
#$encrypted = pack("H*","9058475F4BC91DF878B80A1B0F98B629024AAC727942BFC549233C0140829B93");
|
||||||
$k1_bit =~ /^.(.{127})/;
|
#print unpack("H*", $encrypted) . "\n";
|
||||||
$k2_bit = $1.'0';
|
my $cipher = Crypt::Mode::CBC->new('AES', $padding);
|
||||||
$k2 = pack('B128', $k2_bit);
|
return $cipher->decrypt($encrypted, $key, $initVector);
|
||||||
|
|
||||||
# If MSB of K1 == 1, K2 = K2 XOR const_Rb
|
|
||||||
if($k1_bit =~ m/^1/) {
|
|
||||||
#print "MSB of K1 is set\n";
|
|
||||||
$k2 = $k2 ^ $const_rb;
|
|
||||||
} else {
|
|
||||||
#print "MSB of K1 is unset\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# XOR data with K2
|
|
||||||
$data_expanded ^= $k2;
|
|
||||||
|
|
||||||
# Encrypt data
|
|
||||||
my $cmac = $cipher->encrypt($data_expanded);
|
|
||||||
|
|
||||||
#print "CMAC ".unpack('H32', $cmac)."\n";
|
|
||||||
|
|
||||||
# Extract specified len of MAC
|
|
||||||
my $cmac_pattern = '^(.{'.($cmac_len * 2).'})';
|
|
||||||
unpack('H32', $cmac) =~ /$cmac_pattern/;
|
|
||||||
|
|
||||||
# Return MAC in hexadecimal format
|
|
||||||
return uc($1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sub decodeAFL($$) {
|
sub decodeAFL($$) {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $afl = shift;
|
my $afl = shift;
|
||||||
@ -1766,16 +1716,18 @@ sub decodeAFL($$) {
|
|||||||
if ($self->{afl}{fcl_mclp}) {
|
if ($self->{afl}{fcl_mclp}) {
|
||||||
# AFL Message Control Field (AFL.MCL)
|
# AFL Message Control Field (AFL.MCL)
|
||||||
$self->{afl}{mcl} = unpack('C', substr($afl, $offset, 1));
|
$self->{afl}{mcl} = unpack('C', substr($afl, $offset, 1));
|
||||||
|
#printf "AFL MCL %01x\n", $self->{afl}{mcl};
|
||||||
$offset += 1;
|
$offset += 1;
|
||||||
$self->{afl}{mcl_mlmp} = ($self->{afl}{mcl} & 0b01000000) != 0;
|
$self->{afl}{mcl_mlmp} = ($self->{afl}{mcl} & 0b01000000) != 0;
|
||||||
$self->{afl}{mcl_mcmp} = ($self->{afl}{mcl} & 0b00100000) != 0;
|
$self->{afl}{mcl_mcmp} = ($self->{afl}{mcl} & 0b00100000) != 0;
|
||||||
$self->{afl}{mcl_kimp} = ($self->{afl}{mcl} & 0b00010000) != 0;
|
$self->{afl}{mcl_kimp} = ($self->{afl}{mcl} & 0b00010000) != 0;
|
||||||
$self->{afl}{mcl_at} = ($self->{afl}{mcl} & 0b00001111);
|
$self->{afl}{mcl_at} = ($self->{afl}{mcl} & 0b00001100) >> 2;
|
||||||
|
$self->{afl}{mcl_ato} = ($self->{afl}{mcl} & 0b00000011);
|
||||||
}
|
}
|
||||||
if ($self->{afl}{fcl_mcrp}) {
|
if ($self->{afl}{fcl_mcrp}) {
|
||||||
# AFL Message Counter Field (AFL.MCR)
|
# AFL Message Counter Field (AFL.MCR)
|
||||||
$self->{afl}{mcr} = unpack('V', substr($afl, $offset));
|
#$self->{afl}{mcr} = unpack('N', substr($afl, $offset));
|
||||||
#printf "AFL MC %08x\n", $self->{afl}{mcr};
|
$self->{afl}{mcr} = substr($afl, $offset, 4);
|
||||||
$offset += 4;
|
$offset += 4;
|
||||||
}
|
}
|
||||||
if ($self->{afl}{fcl_mlp}) {
|
if ($self->{afl}{fcl_mlp}) {
|
||||||
@ -1783,23 +1735,16 @@ sub decodeAFL($$) {
|
|||||||
$self->{afl}{ml} = unpack('v', substr($afl, $offset));
|
$self->{afl}{ml} = unpack('v', substr($afl, $offset));
|
||||||
$offset += 2;
|
$offset += 2;
|
||||||
}
|
}
|
||||||
if ($self->{afl}{fcl_macp}) {
|
if ($self->{afl}{mcl_at} == 1) {
|
||||||
# AFL MAC Field (AFL.MCL)
|
# CMAC-AES128 (see 9.3.1)
|
||||||
# The length of the MAC field depends on the selected option AFL.MCL.AT indicated by the
|
|
||||||
# AFL.MCL field.
|
|
||||||
my $mac_len = 0;
|
my $mac_len = 0;
|
||||||
if ($self->{afl}{mcl_at} == 4) {
|
if ($self->{afl}{mcl_ato} == 1) {
|
||||||
$mac_len = 4;
|
|
||||||
$self->{afl}{mac} = unpack('N', substr($afl, $offset, $mac_len));
|
|
||||||
} elsif ($self->{afl}{mcl_at} == 5) {
|
|
||||||
$mac_len = 8;
|
$mac_len = 8;
|
||||||
$self->{afl}{mac} = (unpack('N', substr($afl, $offset, 4))) << 32 | ((unpack('N', substr($afl, $offset+4, 4))));
|
$self->{afl}{mac} = (unpack('N', substr($afl, $offset, 4))) << 32 | ((unpack('N', substr($afl, $offset+4, 4))));
|
||||||
} elsif ($self->{afl}{mcl_at} == 6) {
|
#printf "AFL MAC %8x\n", $self->{afl}{mac};
|
||||||
$mac_len = 12;
|
} else {
|
||||||
} elsif ($self->{afl}{mcl_at} == 7) {
|
# reserved
|
||||||
$mac_len = 16;
|
|
||||||
}
|
}
|
||||||
#printf "AFL MAC %16x\n", $self->{afl}{mac};
|
|
||||||
$offset += $mac_len;
|
$offset += $mac_len;
|
||||||
}
|
}
|
||||||
if ($self->{afl}{fcl_kip}) {
|
if ($self->{afl}{fcl_kip}) {
|
||||||
@ -1827,6 +1772,7 @@ sub decodeApplicationLayer($) {
|
|||||||
$self->{cifield} = unpack('C', $applicationlayer);
|
$self->{cifield} = unpack('C', $applicationlayer);
|
||||||
|
|
||||||
my $offset = 1;
|
my $offset = 1;
|
||||||
|
my $has_ell = 1;
|
||||||
|
|
||||||
if ($self->{cifield} == CI_ELL_2) {
|
if ($self->{cifield} == CI_ELL_2) {
|
||||||
# Extended Link Layer
|
# Extended Link Layer
|
||||||
@ -1844,6 +1790,8 @@ sub decodeApplicationLayer($) {
|
|||||||
# Extended Link Layer
|
# Extended Link Layer
|
||||||
($self->{ell}{cc}, $self->{ell}{access_no}, $self->{ell}{m2}, $self->{ell}{a2}, $self->{ell}{session_number}) = unpack('CCvC6V', substr($applicationlayer,$offset));
|
($self->{ell}{cc}, $self->{ell}{access_no}, $self->{ell}{m2}, $self->{ell}{a2}, $self->{ell}{session_number}) = unpack('CCvC6V', substr($applicationlayer,$offset));
|
||||||
$offset += 14;
|
$offset += 14;
|
||||||
|
} else {
|
||||||
|
$has_ell = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exists($self->{ell}{session_number})) {
|
if (exists($self->{ell}{session_number})) {
|
||||||
@ -1920,6 +1868,7 @@ sub decodeApplicationLayer($) {
|
|||||||
# initialize some fields
|
# initialize some fields
|
||||||
$self->{cw_1} = 0;
|
$self->{cw_1} = 0;
|
||||||
$self->{cw_2} = 0;
|
$self->{cw_2} = 0;
|
||||||
|
$self->{cw_3} = 0;
|
||||||
$self->{status} = 0;
|
$self->{status} = 0;
|
||||||
$self->{statusstring} = "";
|
$self->{statusstring} = "";
|
||||||
$self->{access_no} = 0;
|
$self->{access_no} = 0;
|
||||||
@ -1928,15 +1877,18 @@ sub decodeApplicationLayer($) {
|
|||||||
|
|
||||||
#printf("CI Field %02x\n", $self->{cifield});
|
#printf("CI Field %02x\n", $self->{cifield});
|
||||||
|
|
||||||
|
# Config Word ist normalerweise 2 Bytes lang, nur bei encryption mode 7 drei Bytes
|
||||||
|
# erstmal drei Bytes auslesen, aber den Offset nur um 2 Bytes erhöhen
|
||||||
|
|
||||||
if ($self->{cifield} == CI_RESP_4 || $self->{cifield} == CI_RESP_SML_4) {
|
if ($self->{cifield} == CI_RESP_4 || $self->{cifield} == CI_RESP_SML_4) {
|
||||||
# Short header
|
# Short header
|
||||||
($self->{access_no}, $self->{status}, $self->{cw_1}, $self->{cw_2}) = unpack('CCCC', substr($applicationlayer,$offset));
|
($self->{access_no}, $self->{status}, $self->{cw_1}, $self->{cw_2}, $self->{cw_3}) = unpack('CCCCC', substr($applicationlayer,$offset));
|
||||||
#printf("Short header access_no %x\n", $self->{access_no});
|
#printf("Short header access_no %x\n", $self->{access_no});
|
||||||
$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->{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})
|
||||||
= unpack('VvCCCCCC', substr($applicationlayer,$offset));
|
= unpack('VvCCCCCCC', substr($applicationlayer,$offset));
|
||||||
$self->{meter_id} = sprintf("%08d", $self->{meter_id});
|
$self->{meter_id} = sprintf("%08d", $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}));
|
||||||
@ -2012,7 +1964,7 @@ sub decodeApplicationLayer($) {
|
|||||||
$self->{decrypted} = 1;
|
$self->{decrypted} = 1;
|
||||||
}
|
}
|
||||||
$payload = substr($applicationlayer, $offset);
|
$payload = substr($applicationlayer, $offset);
|
||||||
} elsif ($self->{cw_parts}{mode} == 5) {
|
} elsif ($self->{cw_parts}{mode} == 5 || $self->{cw_parts}{mode} == 7) {
|
||||||
# data is encrypted with AES 128, dynamic init vector
|
# data is encrypted with AES 128, dynamic init vector
|
||||||
# decrypt data before further processing
|
# decrypt data before further processing
|
||||||
$self->{isEncrypted} = 1;
|
$self->{isEncrypted} = 1;
|
||||||
@ -2020,24 +1972,41 @@ sub decodeApplicationLayer($) {
|
|||||||
|
|
||||||
if ($self->{aeskey}) {
|
if ($self->{aeskey}) {
|
||||||
if ($hasCBC) {
|
if ($hasCBC) {
|
||||||
|
# payload can be only partially encrypted.
|
||||||
|
# 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)));
|
#printf("encrypted payload %s\n", unpack("H*", substr($applicationlayer,$offset, $encrypted_length)));
|
||||||
|
if ($self->{cw_parts}{mode} == 5) {
|
||||||
eval {
|
eval {
|
||||||
$payload = $self->decrypt(substr($applicationlayer, $offset, $encrypted_length))
|
$payload = $self->decrypt_mode5(substr($applicationlayer, $offset, $encrypted_length));
|
||||||
. substr($applicationlayer, $offset+$encrypted_length);
|
|
||||||
};
|
};
|
||||||
|
} else {
|
||||||
|
# mode 7
|
||||||
|
if ($hasCMAC) {
|
||||||
|
$offset++; # account for codeword byte 3
|
||||||
|
eval {
|
||||||
|
$payload = $self->decrypt_mode7(substr($applicationlayer, $offset, $encrypted_length));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$self->{errormsg} = 'Digest::CMAC is not installed, please install it (sudo cpan -i Digest::CMAC)';
|
||||||
|
$self->{errorcode} = ERR_CIPHER_NOT_INSTALLED;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
if ($@) {
|
if ($@) {
|
||||||
#fatal decryption error occurred
|
#fatal decryption error occurred
|
||||||
$self->{errormsg} = "fatal decryption error: $@";
|
$self->{errormsg} = "fatal decryption error for mode " . $self->{cw_parts}{mode} . ": $@";
|
||||||
$self->{errorcode} = ERR_DECRYPTION_FAILED;
|
$self->{errorcode} = ERR_DECRYPTION_FAILED;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
# add unencrypted payload
|
||||||
|
$payload .= substr($applicationlayer, $offset+$encrypted_length);
|
||||||
#printf("decrypted payload %s\n", unpack("H*", $payload));
|
#printf("decrypted payload %s\n", unpack("H*", $payload));
|
||||||
if (unpack('n', $payload) == 0x2f2f) {
|
if (unpack('n', $payload) == 0x2f2f) {
|
||||||
$self->{decrypted} = 1;
|
$self->{decrypted} = 1;
|
||||||
} else {
|
} else {
|
||||||
# Decryption verification failed
|
# Decryption verification failed
|
||||||
$self->{errormsg} = 'Decryption failed, wrong key?';
|
$self->{errormsg} = sprintf('Decryption mode %d failed, wrong key?', $self->{cw_parts}{mode});
|
||||||
$self->{errorcode} = ERR_DECRYPTION_FAILED;
|
$self->{errorcode} = ERR_DECRYPTION_FAILED;
|
||||||
#printf("%x\n", unpack('n', $payload));
|
#printf("%x\n", unpack('n', $payload));
|
||||||
return 0;
|
return 0;
|
||||||
@ -2052,7 +2021,6 @@ sub decodeApplicationLayer($) {
|
|||||||
$self->{errorcode} = ERR_NO_AESKEY;
|
$self->{errorcode} = ERR_NO_AESKEY;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
# error, encryption mode not implemented
|
# error, encryption mode not implemented
|
||||||
$self->{errormsg} = sprintf('Encryption mode %x not implemented', $self->{cw_parts}{mode});
|
$self->{errormsg} = sprintf('Encryption mode %x not implemented', $self->{cw_parts}{mode});
|
||||||
@ -2085,6 +2053,7 @@ sub decodeLinkLayer($$)
|
|||||||
}
|
}
|
||||||
($self->{lfield}, $self->{cfield}, $self->{mfield}) = unpack('CCv', $linklayer);
|
($self->{lfield}, $self->{cfield}, $self->{mfield}) = unpack('CCv', $linklayer);
|
||||||
$self->{afield} = substr($linklayer,4,6);
|
$self->{afield} = substr($linklayer,4,6);
|
||||||
|
$self->{afield_identno} = substr($self->{afield}, 0, 4);
|
||||||
$self->{afield_id} = sprintf("%08d", $self->decodeBCD(8,substr($linklayer,4,4)));
|
$self->{afield_id} = sprintf("%08d", $self->decodeBCD(8,substr($linklayer,4,4)));
|
||||||
($self->{afield_ver}, $self->{afield_type}) = unpack('CC', substr($linklayer,8,2));
|
($self->{afield_ver}, $self->{afield_type}) = unpack('CC', substr($linklayer,8,2));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user