--- USM.pm.default 2025-01-24 17:51:21.777264690 +0300 +++ USM.pm 2025-01-24 18:03:43.338158040 +0300 @@ -25,8 +25,8 @@ use Crypt::DES(); use Digest::MD5(); -use Digest::SHA(); -use Digest::HMAC(); +use Digest::SHA qw( hmac_sha1 hmac_sha224 hmac_sha256 hmac_sha384 hmac_sha512 ); +use Digest::HMAC_MD5 qw ( hmac_md5 ); ## Version of the Net::SNMP::Security::USM module @@ -40,7 +40,9 @@ our %EXPORT_TAGS = ( authprotos => [ - qw( AUTH_PROTOCOL_NONE AUTH_PROTOCOL_HMACMD5 AUTH_PROTOCOL_HMACSHA ) + qw( AUTH_PROTOCOL_NONE AUTH_PROTOCOL_HMACMD5 AUTH_PROTOCOL_HMACSHA + AUTH_PROTOCOL_HMACSHA224 AUTH_PROTOCOL_HMACSHA256. + AUTH_PROTOCOL_HMACSHA384 AUTH_PROTOCOL_HMACSHA512 ) ], levels => [ qw( SECURITY_LEVEL_NOAUTHNOPRIV SECURITY_LEVEL_AUTHNOPRIV @@ -63,9 +65,13 @@ ## RCC 3414 - Authentication protocols -sub AUTH_PROTOCOL_NONE { '1.3.6.1.6.3.10.1.1.1' } # usmNoAuthProtocol -sub AUTH_PROTOCOL_HMACMD5 { '1.3.6.1.6.3.10.1.1.2' } # usmHMACMD5AuthProtocol -sub AUTH_PROTOCOL_HMACSHA { '1.3.6.1.6.3.10.1.1.3' } # usmHMACSHAAuthProtocol +sub AUTH_PROTOCOL_NONE { '1.3.6.1.6.3.10.1.1.1' } # usmNoAuthProtocol +sub AUTH_PROTOCOL_HMACMD5 { '1.3.6.1.6.3.10.1.1.2' } # usmHMACMD5AuthProtocol +sub AUTH_PROTOCOL_HMACSHA { '1.3.6.1.6.3.10.1.1.3' } # usmHMACSHAAuthProtocol +sub AUTH_PROTOCOL_HMACSHA224 { '1.3.6.1.6.3.10.1.1.4' } # usmHMAC128SHA224AuthProtocol +sub AUTH_PROTOCOL_HMACSHA256 { '1.3.6.1.6.3.10.1.1.5' } # usmHMAC192SHA256AuthProtocol +sub AUTH_PROTOCOL_HMACSHA384 { '1.3.6.1.6.3.10.1.1.6' } # usmHMAC256SHA384AuthProtocol +sub AUTH_PROTOCOL_HMACSHA512 { '1.3.6.1.6.3.10.1.1.7' } # usmHMAC384SHA512AuthProtocol ## RFC 3414 - Privacy protocols @@ -124,6 +130,7 @@ '_time_epoc' => time(), # snmpEngineBoots epoc '_user_name' => q{}, # securityName '_auth_data' => undef, # Authentication data + '_auth_maclen' => undef, # MAC length '_auth_key' => undef, # authKey '_auth_password' => undef, # Authentication password '_auth_protocol' => AUTH_PROTOCOL_HMACMD5, # authProtocol @@ -280,10 +287,10 @@ if ($pdu->security_level() > SECURITY_LEVEL_NOAUTHNOPRIV) { # Save the location to fill in msgAuthenticationParameters later - $auth_location = $msg->length() + 12 + length $pdu_buffer; + $auth_location = $msg->length() + $this->{_auth_maclen} + length $pdu_buffer; # Set the msgAuthenticationParameters to all zeros - $auth_params = pack 'x12'; + $auth_params = pack "x$this->{_auth_maclen}"; } if (!defined $msg->prepare(OCTET_STRING, $auth_params)) { @@ -418,12 +425,12 @@ # to compute the HMAC properly. if (my $len = length $auth_params) { - if ($len != 12) { + if ($len != $this->{_auth_maclen}) { return $this->_error( 'The msgAuthenticationParameters length of %d is invalid', $len ); } - substr ${$msg->reference}, ($msg->index() - 12), 12, pack 'x12'; + substr ${$msg->reference}, ($msg->index() - $this->{_auth_maclen}), $this->{_auth_maclen}, pack "x$this->{_auth_maclen}"; } # msgPrivacyParameters::=OCTET STRING @@ -747,6 +754,18 @@ quotemeta AUTH_PROTOCOL_HMACMD5, AUTH_PROTOCOL_HMACMD5, '(?:hmac-)?sha(?:-?1|-96)?', AUTH_PROTOCOL_HMACSHA, quotemeta AUTH_PROTOCOL_HMACSHA, AUTH_PROTOCOL_HMACSHA, + '(?:hmac-)?sha(?:-?224)', AUTH_PROTOCOL_HMACSHA224, + 'usmHMAC128SHA224AuthProtocol', AUTH_PROTOCOL_HMACSHA224, + quotemeta AUTH_PROTOCOL_HMACSHA224,AUTH_PROTOCOL_HMACSHA224, + '(?:hmac-)?sha(?:-?256)', AUTH_PROTOCOL_HMACSHA256, + 'usmHMAC192SHA256AuthProtocol', AUTH_PROTOCOL_HMACSHA256, + quotemeta AUTH_PROTOCOL_HMACSHA256,AUTH_PROTOCOL_HMACSHA256, + '(?:hmac-)?sha(?:-?384)', AUTH_PROTOCOL_HMACSHA384, + 'usmHMAC256SHA384AuthProtocol', AUTH_PROTOCOL_HMACSHA384, + quotemeta AUTH_PROTOCOL_HMACSHA384,AUTH_PROTOCOL_HMACSHA384, + '(?:hmac-)?sha(?:-?512)', AUTH_PROTOCOL_HMACSHA512, + 'usmHMAC384SHA512AuthProtocol', AUTH_PROTOCOL_HMACSHA512, + quotemeta AUTH_PROTOCOL_HMACSHA512,AUTH_PROTOCOL_HMACSHA512, }; sub _auth_protocol @@ -1099,8 +1118,7 @@ } # Set the msgAuthenticationParameters - substr ${$msg->reference}, -$auth_location, 12, $this->_auth_hmac($msg); - + substr ${$msg->reference}, -$auth_location, $this->{_auth_maclen}, $this->_auth_hmac($msg); return TRUE; } @@ -1125,7 +1143,7 @@ return q{} if (!defined($this->{_auth_data}) || !defined $msg); return substr - $this->{_auth_data}->reset()->add(${$msg->reference()})->digest(), 0, 12; + $this->{_auth_data}(${$msg->reference()}, $this->{_auth_key}), 0, $this->{_auth_maclen}; } sub _auth_data_init @@ -1140,13 +1158,33 @@ if ($this->{_auth_protocol} eq AUTH_PROTOCOL_HMACMD5) { - $this->{_auth_data} = - Digest::HMAC->new($this->{_auth_key}, 'Digest::MD5'); + $this->{_auth_data} = \&hmac_md5; + $this->{_auth_maclen} = 12; } elsif ($this->{_auth_protocol} eq AUTH_PROTOCOL_HMACSHA) { - $this->{_auth_data} = - Digest::HMAC->new($this->{_auth_key}, 'Digest::SHA'); + $this->{_auth_data} = \&hmac_sha1; + $this->{_auth_maclen} = 12; + + } elsif ($this->{_auth_protocol} eq AUTH_PROTOCOL_HMACSHA224) { + + $this->{_auth_data} = \&hmac_sha224; + $this->{_auth_maclen} = 16; + + } elsif ($this->{_auth_protocol} eq AUTH_PROTOCOL_HMACSHA256) { + + $this->{_auth_data} = \&hmac_sha256; + $this->{_auth_maclen} = 24; + + } elsif ($this->{_auth_protocol} eq AUTH_PROTOCOL_HMACSHA384) { + + $this->{_auth_data} = \&hmac_sha384; + $this->{_auth_maclen} = 32; + + } elsif ($this->{_auth_protocol} eq AUTH_PROTOCOL_HMACSHA512) { + + $this->{_auth_data} = \&hmac_sha512; + $this->{_auth_maclen} = 48; } else { @@ -1627,6 +1665,10 @@ { AUTH_PROTOCOL_HMACMD5, [ 16, 'HMAC-MD5' ], AUTH_PROTOCOL_HMACSHA, [ 20, 'HMAC-SHA' ], + AUTH_PROTOCOL_HMACSHA224, [ 28, 'HMAC-SHA224' ], + AUTH_PROTOCOL_HMACSHA256, [ 32, 'HMAC-SHA256' ], + AUTH_PROTOCOL_HMACSHA384, [ 48, 'HMAC-SHA384' ], + AUTH_PROTOCOL_HMACSHA512, [ 64, 'HMAC-SHA512' ], }; if (!exists $key_len->{$this->{_auth_protocol}}) { @@ -1782,9 +1824,13 @@ my $digests = { - AUTH_PROTOCOL_HMACMD5, 'Digest::MD5', - AUTH_PROTOCOL_HMACSHA, 'Digest::SHA', - }; + AUTH_PROTOCOL_HMACMD5, ['Digest::MD5', ], + AUTH_PROTOCOL_HMACSHA, ['Digest::SHA', 1], + AUTH_PROTOCOL_HMACSHA224, ['Digest::SHA', 224], + AUTH_PROTOCOL_HMACSHA256, ['Digest::SHA', 256], + AUTH_PROTOCOL_HMACSHA384, ['Digest::SHA', 384], + AUTH_PROTOCOL_HMACSHA512, ['Digest::SHA', 512], + }; if (!exists $digests->{$this->{_auth_protocol}}) { return $this->_error( @@ -1792,7 +1838,12 @@ ); } - my $digest = $digests->{$this->{_auth_protocol}}->new; + my $digest; + if (!defined($digests->{$this->{_auth_protocol}}[1])) { + $digest = $digests->{$this->{_auth_protocol}}[0]->new; + } else { + $digest = $digests->{$this->{_auth_protocol}}[0]->new($digests->{$this->{_auth_protocol}}[1]); + } # Create the initial digest using the password