Re: snmp agent inform w/AES privacy not working

Raimo Niskanen <[email protected]>
Newsgroups gmane.comp.lang.erlang.bugs,gmane.comp.lang.erlang.patches
Message-ID <[email protected]>
Sorry about the looong delay but I have just created a ticket for
this, now awaiting to be prioritized...

/ Raimo


On Tue, Feb 25, 2014 at 11:56:32AM -0600, Daniel Goertzen wrote:
> The SNMP agent AES initialization vector calculation is definitely wrong.
>  The IV is composed from the authoritative engine boots, engine time, and a
> random locally generated number.  The agent is currently always using the
> *local* engine to get engine boots and engine time, which happens to be
> correct for GET, SET, and TRAP, but is wrong for INFORM.
> 
> The attached patch fixes it.  When composing a packet for transmission, the
> existing code collects the correct engine parameters, so this patch just
> uses those for the AES IV instead of going off and getting the wrong local
> engine params.  The patch looks bigger than it really is because the order
> of packet composition had to be changed slightly.
> 
> With this patch applied, I am able to send AES encrypted informs.  AES
> encrypted traps also continued to work.
> 
> Cheers,
> Dan.
> 
> 
> On Mon, Feb 24, 2014 at 4:57 PM, Daniel Goertzen
> <[email protected]>wrote:
> 
> > I am struggling to get SNMP informs with AES privacy working.  I have no
> > problems with DES privacy on informs.
> >
> > In snmpa_usm.erl I see that the *local engine* boots and time is passed to
> > snmp_usm:aes_encrypt() which forms part of the IV....
> >
> >
> >
> > However RFC 3826 states that the *authoritative* engine boots and time
> > should be used, and in the case of informs the authoritative engine is the
> > inform target engine, not the local engine....
> >
> > [from RFC 3826]
> >
> > 3.1.2.1.  AES Encryption Key and IV
> >
> >    The first 128 bits of the localized key Kul are used as the AES
> >    encryption key.  The 128-bit IV is obtained as the concatenation of
> >    the authoritative SNMP engine's 32-bit snmpEngineBoots, the SNMP
> >    engine's 32-bit snmpEngineTime, and a local 64-bit integer.  The 64-
> >    bit integer is initialized to a pseudo-random value at boot time.
> >
> >
> >
> > Could this be why AES privacy is not working for informs?
> >
> > Dan.
> >

> diff --git a/lib/snmp/src/agent/snmpa_usm.erl b/lib/snmp/src/agent/snmpa_usm.erl
> index 719ea4e..0c3528a 100644
> --- a/lib/snmp/src/agent/snmpa_usm.erl
> +++ b/lib/snmp/src/agent/snmpa_usm.erl
> @@ -474,6 +474,23 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel,
>  	    _ -> % 3.1.1a
>  		SecData
>  	end,
> +    %% 3.1.6
> +    SnmpEngineID = LocalEngineID,
> +    ?vtrace("generate_outgoing_msg -> SnmpEngineID: ~p [3.1.6]",
> +            [SnmpEngineID]),
> +    {MsgAuthEngineBoots, MsgAuthEngineTime} =
> +    case snmp_misc:is_auth(SecLevel) of
> +        false when SecData =:= [] -> % not a response
> +            {0, 0};
> +        false when UserName =:= "" -> % reply (report) to discovery step 1
> +            {0, 0};
> +        true when SecEngineID =/= SnmpEngineID ->
> +            {get_engine_boots(SecEngineID),
> +             get_engine_time(SecEngineID)};
> +        _ ->
> +            {get_local_engine_boots(SnmpEngineID),
> +             get_local_engine_time(SnmpEngineID)}
> +    end,
>      %% 3.1.4
>      ?vtrace("generate_outgoing_msg -> [3.1.4]"
>  	    "~n   UserName:     ~p"
> @@ -482,24 +499,7 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel,
>  	    [UserName, AuthProtocol, PrivProtocol]),
>      ScopedPduBytes = Message#message.data,
>      {ScopedPduData, MsgPrivParams} =
> -	encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel),
> -    SnmpEngineID = LocalEngineID, 
> -    ?vtrace("generate_outgoing_msg -> SnmpEngineID: ~p [3.1.6]",
> -	    [SnmpEngineID]),
> -    %% 3.1.6
> -    {MsgAuthEngineBoots, MsgAuthEngineTime} =
> -	case snmp_misc:is_auth(SecLevel) of
> -	    false when SecData =:= [] -> % not a response
> -		{0, 0}; 
> -	    false when UserName =:= "" -> % reply (report) to discovery step 1
> -		{0, 0}; 
> -	    true when SecEngineID =/= SnmpEngineID ->
> -		{get_engine_boots(SecEngineID),
> -		 get_engine_time(SecEngineID)};
> -	    _ ->
> -		{get_local_engine_boots(SnmpEngineID),
> -		 get_local_engine_time(SnmpEngineID)}
> -	end,
> +	encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel, MsgAuthEngineBoots, MsgAuthEngineTime),
>      %% 3.1.5 - 3.1.7
>      ?vtrace("generate_outgoing_msg -> [3.1.5 - 3.1.7]",[]),
>      UsmSecParams =
> @@ -560,12 +560,14 @@ generate_discovery_msg(Message,
>  		end
>  	end,
>      ScopedPduBytes = Message#message.data,
> +    Boots = 0,
> +    Time = 0,
>      {ScopedPduData, MsgPrivParams} =
> -	encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel),
> +	encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel, Boots, Time),
>      UsmSecParams =
>  	#usmSecurityParameters{msgAuthoritativeEngineID    = SecEngineID, 
> -			       msgAuthoritativeEngineBoots = 0, % Boots, 
> -			       msgAuthoritativeEngineTime  = 0, % Time, 
> +			       msgAuthoritativeEngineBoots = Boots,
> +			       msgAuthoritativeEngineTime  = Time,
>  			       msgUserName                 = UserName,
>  			       msgPrivacyParameters        = MsgPrivParams},
>      Message2 = Message#message{data = ScopedPduData},
> @@ -574,14 +576,14 @@ generate_discovery_msg(Message,
>  
>      
>  %% Ret: {ScopedPDU, MsgPrivParams} - both are already encoded as OCTET STRINGs
> -encrypt(Data, PrivProtocol, PrivKey, SecLevel) ->
> +encrypt(Data, PrivProtocol, PrivKey, SecLevel, AuthEngineBoots, AuthEngineTime) ->
>      case snmp_misc:is_priv(SecLevel) of
>  	false -> % 3.1.4b
>  	    ?vtrace("encrypt -> 3.1.4b",[]),
>  	    {Data, []};
>  	true -> % 3.1.4a
>  	    ?vtrace("encrypt -> 3.1.4a",[]),
> -	    case (catch try_encrypt(PrivProtocol, PrivKey, Data)) of
> +	    case (catch try_encrypt(PrivProtocol, PrivKey, Data, AuthEngineBoots, AuthEngineTime)) of
>  		{ok, ScopedPduData, MsgPrivParams} ->
>  		    ?vtrace("encrypt -> encrypted - now encode tag",[]),
>  		    {snmp_pdus:enc_oct_str_tag(ScopedPduData), MsgPrivParams};
> @@ -596,12 +598,12 @@ encrypt(Data, PrivProtocol, PrivKey, SecLevel) ->
>  	    end
>      end.
>  
> -try_encrypt(?usmNoPrivProtocol, _PrivKey, _Data) -> % 3.1.2
> +try_encrypt(?usmNoPrivProtocol, _PrivKey, _Data, _AuthEngineBoots, _AuthEngineTime) -> % 3.1.2
>      error(unsupportedSecurityLevel);
> -try_encrypt(?usmDESPrivProtocol, PrivKey, Data) ->
> +try_encrypt(?usmDESPrivProtocol, PrivKey, Data, _AuthEngineBoots, _AuthEngineTime) ->
>      des_encrypt(PrivKey, Data);
> -try_encrypt(?usmAesCfb128Protocol, PrivKey, Data) ->
> -    aes_encrypt(PrivKey, Data).
> +try_encrypt(?usmAesCfb128Protocol, PrivKey, Data, AuthEngineBoots, AuthEngineTime) ->
> +    aes_encrypt(PrivKey, Data, AuthEngineBoots, AuthEngineTime).
>  
>  
>  authenticate_outgoing(Message, UsmSecParams, 
> @@ -654,10 +656,8 @@ get_des_salt() ->
>      EngineBoots = snmp_framework_mib:get_engine_boots(),
>      [?i32(EngineBoots), ?i32(SaltInt)].
>  
> -aes_encrypt(PrivKey, Data) ->
> -    EngineBoots = snmp_framework_mib:get_engine_boots(),
> -    EngineTime  = snmp_framework_mib:get_engine_time(),
> -    snmp_usm:aes_encrypt(PrivKey, Data, fun get_aes_salt/0, 
> +aes_encrypt(PrivKey, Data, EngineBoots, EngineTime) ->
> +    snmp_usm:aes_encrypt(PrivKey, Data, fun get_aes_salt/0,
>  			 EngineBoots, EngineTime).
>  
>  aes_decrypt(PrivKey, UsmSecParams, EncData) ->

> _______________________________________________
> erlang-bugs mailing list
> [email protected]
> http://erlang.org/mailman/listinfo/erlang-bugs


-- 

/ Raimo Niskanen, Erlang/OTP, Ericsson AB
_______________________________________________
erlang-bugs mailing list
[email protected]
http://erlang.org/mailman/listinfo/erlang-bugs
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.