[erlang-bugs] snmp agent inform w/AES privacy not working
Raimo Niskanen
raimo+erlang-bugs@REDACTED
Wed Aug 6 11:51:33 CEST 2014
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
> <daniel.goertzen@REDACTED>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
> erlang-bugs@REDACTED
> http://erlang.org/mailman/listinfo/erlang-bugs
--
/ Raimo Niskanen, Erlang/OTP, Ericsson AB
More information about the erlang-bugs
mailing list