10_ZWave.pm: Update NONCE Handling (Forum #60976)
git-svn-id: https://svn.fhem.de/fhem/trunk@12909 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -3592,16 +3592,97 @@ ZWave_secCreateNonce($)
|
|||||||
{
|
{
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
if (ZWave_secIsEnabled($hash)) {
|
if (ZWave_secIsEnabled($hash)) {
|
||||||
my $nonce = ZWave_secGetNonce();
|
my $nonce;
|
||||||
setReadingsVal($hash, "send_nonce", $nonce, TimeNow());
|
my $nonce_id;
|
||||||
#return ("",'80'.$nonce);
|
my $n=0;
|
||||||
|
|
||||||
|
$hash->{secNonce} = {} if (!$hash->{secNonce});
|
||||||
|
foreach my $id (sort keys %{$hash->{secNonce}}) {
|
||||||
|
$n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $time = gettimeofday();
|
||||||
|
if ($n>50) { #clean up only if more than 50 nonce are active
|
||||||
|
foreach my $id (sort keys %{$hash->{secNonce}}) {
|
||||||
|
my $dt = $time - $hash->{secNonce}{$id}{timeStamp};
|
||||||
|
if ($dt > 10) {
|
||||||
|
Log3 $hash->{NAME}, 3, "$hash->{NAME}: SECURITY: nonce "
|
||||||
|
.$hash->{secNonce}{$id}{nonce} ."is too old ("
|
||||||
|
.sprintf("%d seconds", $dt)
|
||||||
|
.") and is removed from list";
|
||||||
|
delete($hash->{secNonce}{$id});
|
||||||
|
$n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($n >10) {
|
||||||
|
Log3 $hash->{NAME}, 2, "$hash->{NAME}: SECURITY: multiple nonce warning, "
|
||||||
|
."there are $n nonce active";
|
||||||
|
}
|
||||||
|
|
||||||
|
$n=0;
|
||||||
|
do {
|
||||||
|
$nonce = ZWave_secGetNonce();
|
||||||
|
$nonce_id = substr($nonce, 0, 2);
|
||||||
|
$n++;
|
||||||
|
} until ((!$hash->{secNonce}{$nonce_id}) || $n>512);
|
||||||
|
|
||||||
|
if ($n >512) {
|
||||||
|
Log3 $hash->{NAME}, 1, "$hash->{NAME}: SECURITY: could not generate "
|
||||||
|
."unique nonce, ignoring request!";
|
||||||
|
return ('00');
|
||||||
|
}
|
||||||
|
|
||||||
|
my $id = substr($nonce, 0 ,2);
|
||||||
|
|
||||||
|
$hash->{secNonce} = {} if (!$hash->{secNonce});
|
||||||
|
|
||||||
|
$hash->{secNonce}{$id}{nonce} = $nonce;
|
||||||
|
$hash->{secNonce}{$id}{timeStamp} = gettimeofday();
|
||||||
|
|
||||||
return ('80'.$nonce);
|
return ('80'.$nonce);
|
||||||
} else {
|
} else {
|
||||||
#return ("", '00');
|
|
||||||
return ('00');
|
return ('00');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
ZWave_secRetrieveNonce($$)
|
||||||
|
{
|
||||||
|
my ($hash, $s_nonce_id_hex) = @_;
|
||||||
|
my $s_nonce_hex;
|
||||||
|
my $n=0;
|
||||||
|
|
||||||
|
return undef if (!$hash->{secNonce});
|
||||||
|
|
||||||
|
# remove old (>10 seconds) entries BEFORE trying to retrieve nonce
|
||||||
|
my $time = gettimeofday();
|
||||||
|
foreach my $id (sort keys %{$hash->{secNonce}}) {
|
||||||
|
$n++;
|
||||||
|
my $dt = $time - $hash->{secNonce}{$id}{timeStamp};
|
||||||
|
if ($dt > 10) {
|
||||||
|
Log3 $hash->{NAME}, 5, "$hash->{NAME}: SECURITY: nonce "
|
||||||
|
.$hash->{secNonce}{$id}{nonce} ."is too old ("
|
||||||
|
.sprintf("%d seconds", $dt)
|
||||||
|
.") and is removed from list";
|
||||||
|
delete($hash->{secNonce}{$id});
|
||||||
|
$n--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($n >1) {
|
||||||
|
Log3 $hash->{NAME}, 5, "$hash->{NAME}: SECURITY: multiple nonce warning, "
|
||||||
|
."there are $n nonce active";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($hash->{secNonce}{$s_nonce_id_hex}) {
|
||||||
|
$s_nonce_hex = $hash->{secNonce}{$s_nonce_id_hex}{nonce};
|
||||||
|
delete($hash->{secNonce}{$s_nonce_id_hex});
|
||||||
|
return $s_nonce_hex;
|
||||||
|
} else {
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
ZWave_secGetNonce()
|
ZWave_secGetNonce()
|
||||||
{
|
{
|
||||||
@@ -3664,15 +3745,6 @@ ZWave_secDecrypt($$$)
|
|||||||
my $enc_key = ZWave_secEncryptECB($key, $init_enc_key);
|
my $enc_key = ZWave_secEncryptECB($key, $init_enc_key);
|
||||||
my $auth_key = ZWave_secEncryptECB($key, $init_auth_key);
|
my $auth_key = ZWave_secEncryptECB($key, $init_auth_key);
|
||||||
|
|
||||||
my $s_nonce_hex = ReadingsVal($name, "send_nonce", undef);
|
|
||||||
if (!$s_nonce_hex) {
|
|
||||||
Log3 $name, 1, "$name: Error, no send_nonce to decrypt message available";
|
|
||||||
ZWave_secEnd($hash);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
delete $hash->{READINGS}{send_nonce};
|
|
||||||
|
|
||||||
# encrypted message format:
|
# encrypted message format:
|
||||||
# data= bcb328fe5d924a402b2901fc2699cc3bcacd30e0
|
# data= bcb328fe5d924a402b2901fc2699cc3bcacd30e0
|
||||||
# bcb328fe5d924a40 = 8 byte r_nonce
|
# bcb328fe5d924a40 = 8 byte r_nonce
|
||||||
@@ -3685,6 +3757,14 @@ ZWave_secDecrypt($$$)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
my ($r_nonce_hex, $msg_hex, $s_nonce_id_hex, $auth_code_hex) = ($1, $2, $3, $4);
|
my ($r_nonce_hex, $msg_hex, $s_nonce_id_hex, $auth_code_hex) = ($1, $2, $3, $4);
|
||||||
|
my $s_nonce_hex = ZWave_secRetrieveNonce($hash, $s_nonce_id_hex);
|
||||||
|
if (!$s_nonce_hex) {
|
||||||
|
Log3 $name, 1, "$name: Error, no send_nonce to decrypt message available";
|
||||||
|
ZWave_secEnd($hash);
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
Log3 $name, 5, "$name: secDecrypt: send_nonce $s_nonce_hex with "
|
||||||
|
."nonce_id $s_nonce_id_hex retrieved";
|
||||||
|
|
||||||
my $iv = pack 'H*', $r_nonce_hex . $s_nonce_hex;
|
my $iv = pack 'H*', $r_nonce_hex . $s_nonce_hex;
|
||||||
my $out_hex = ZWave_secEncryptOFB ($enc_key, $iv, $msg_hex);
|
my $out_hex = ZWave_secEncryptOFB ($enc_key, $iv, $msg_hex);
|
||||||
|
|||||||
Reference in New Issue
Block a user