File 0960-Fix-PrivParams-for-SNMPv3-USM-with-AES-privacy.patch of Package erlang

From a33b8c2e52e766f3ee90dae9d122d3d8e00528a9 Mon Sep 17 00:00:00 2001
From: "Jonathan D. Storm" <jds@idio.link>
Date: Sun, 15 Jul 2018 13:56:17 -0500
Subject: [PATCH 1/4] Fix PrivParams for SNMPv3 USM with AES privacy

* In `snmp_usm:do_decrypt/3`, pass full UsmSecParams to
  `snmp_usm:try_decrypt/5` as expected by AES clause.

* Change `snmpm_usm:aes_encrypt/3` to use EngineBoots and
  EngineTime as cached by `snmpm_config:get_usm_eboots/1`
  and `snmpm_config:get_usm_etime/1` instead of
  `snmpm_config:get_engine_boots/0` and
  `snmpm_config:get_engine_time/0`. This ensures correct
  msgPrivacyParameters are sent when AES is used.

* Add test `snmp.snmp_manager_SUITE.usm_priv_aes/1` to
  avoid regression.

* Fix counting bug in `snmp_usm` macro `?BLOCK_CIPHER_AES`,
  introduced by commit 8d942cd.
---
 lib/snmp/src/manager/snmpm_usm.erl   |  36 +++----
 lib/snmp/src/misc/snmp_usm.erl       |  11 +-
 lib/snmp/test/snmp_manager_SUITE.erl | 155 ++++++++++++++++++++++++++-
 3 files changed, 179 insertions(+), 23 deletions(-)

diff --git a/lib/snmp/src/manager/snmpm_usm.erl b/lib/snmp/src/manager/snmpm_usm.erl
index 7dd79e703a..9e625d0315 100644
--- a/lib/snmp/src/manager/snmpm_usm.erl
+++ b/lib/snmp/src/manager/snmpm_usm.erl
@@ -268,15 +268,16 @@ decrypt(Data, UsmUser, UsmSecParams, SecLevel) ->
 do_decrypt(Data, #usm_user{sec_name = SecName,
 			   priv     = PrivP,
 			   priv_key = PrivKey}, 
-	   #usmSecurityParameters{msgPrivacyParameters = PrivParms}) ->
+	   UsmSecParams) ->
     EncryptedPDU = snmp_pdus:dec_scoped_pdu_data(Data),
-    try_decrypt(PrivP, PrivKey, PrivParms, EncryptedPDU, SecName).
+    try_decrypt(PrivP, PrivKey, UsmSecParams, EncryptedPDU, SecName).
 
 try_decrypt(usmNoPrivProtocol, _, _, _, SecName) -> % 3.2.5
     error(usmStatsUnsupportedSecLevels, 
 	  ?usmStatsUnsupportedSecLevels_instance, SecName);
 try_decrypt(usmDESPrivProtocol, 
-	    PrivKey, MsgPrivParams, EncryptedPDU, SecName) ->
+	    PrivKey, UsmSecParams, EncryptedPDU, SecName) ->
+    #usmSecurityParameters{msgPrivacyParameters = MsgPrivParams} = UsmSecParams,
     case (catch des_decrypt(PrivKey, MsgPrivParams, EncryptedPDU)) of
 	{ok, DecryptedData} ->
 	    DecryptedData;
@@ -328,11 +329,6 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) ->
 	    _ -> % 3.1.1a
 		SecData
 	end,
-    %% 3.1.4
-    ?vtrace("generate_outgoing_msg -> (3.1.4)",[]),
-    ScopedPduBytes = Message#message.data,
-    {ScopedPduData, MsgPrivParams} =
-	encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel),
     SnmpEngineID = get_engine_id(),
     ?vtrace("SnmpEngineID: ~p (3.1.6)",[SnmpEngineID]),
     %% 3.1.6
@@ -345,6 +341,11 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) ->
 	    _ ->
 		{get_engine_boots(), get_engine_time()}
 	end,
+    %% 3.1.4
+    ?vtrace("generate_outgoing_msg -> (3.1.4)",[]),
+    ScopedPduBytes = Message#message.data,
+    {ScopedPduData, MsgPrivParams} = encrypt(ScopedPduBytes, PrivProtocol, PrivKey, SecLevel, MsgAuthEngineBoots,
+        MsgAuthEngineTime),
     %% 3.1.5 - 3.1.7
     ?vtrace("generate_outgoing_msg -> (3.1.5 - 3.1.7)",[]),
     UsmSecParams =
@@ -361,12 +362,12 @@ generate_outgoing_msg(Message, SecEngineID, SecName, SecData, SecLevel) ->
 
 
 %% Ret: {ScopedPDU, MsgPrivParams} - both are already encoded as OCTET STRINGs
-encrypt(Data, PrivProtocol, PrivKey, SecLevel) ->
+encrypt(Data, PrivProtocol, PrivKey, SecLevel, EngineBoots, EngineTime) ->
     case snmp_misc:is_priv(SecLevel) of
 	false -> % 3.1.4b
 	    {Data, []};
 	true -> % 3.1.4a
-	    case (catch try_encrypt(PrivProtocol, PrivKey, Data)) of
+	    case (catch try_encrypt(PrivProtocol, PrivKey, Data, EngineBoots, EngineTime)) of
 		{ok, ScopedPduData, MsgPrivParams} ->
 		    {snmp_pdus:enc_oct_str_tag(ScopedPduData), MsgPrivParams};
 		{error, Reason} ->
@@ -376,12 +377,12 @@ encrypt(Data, PrivProtocol, PrivKey, SecLevel) ->
 	    end
     end.
 
-try_encrypt(usmNoPrivProtocol, _PrivKey, _Data) -> % 3.1.2
+try_encrypt(usmNoPrivProtocol, _PrivKey, _Data, _EngineBoots, _EngineTime) -> % 3.1.2
     error(unsupportedSecurityLevel);
-try_encrypt(usmDESPrivProtocol, PrivKey, Data) ->
+try_encrypt(usmDESPrivProtocol, PrivKey, Data, _EngineBoots, _EngineTime) ->
     des_encrypt(PrivKey, Data);
-try_encrypt(usmAesCfb128Protocol, PrivKey, Data) ->
-    aes_encrypt(PrivKey, Data).
+try_encrypt(usmAesCfb128Protocol, PrivKey, Data, EngineBoots, EngineTime) ->
+    aes_encrypt(PrivKey, Data, EngineBoots, EngineTime).
 
 authenticate_outgoing(Message, UsmSecParams, 
 		      AuthKey, AuthProtocol, SecLevel) ->
@@ -419,11 +420,8 @@ get_des_salt() ->
     EngineBoots = get_engine_boots(),
     [?i32(EngineBoots), ?i32(SaltInt)].
 
-aes_encrypt(PrivKey, Data) ->
-    EngineBoots = get_engine_boots(), 
-    EngineTime  = get_engine_time(), 
-    snmp_usm:aes_encrypt(PrivKey, Data, fun get_aes_salt/0, 
-			 EngineBoots, EngineTime).
+aes_encrypt(PrivKey, Data, EngineBoots, EngineTime) ->
+    snmp_usm:aes_encrypt(PrivKey, Data, fun get_aes_salt/0, EngineBoots, EngineTime).
 
 aes_decrypt(PrivKey, UsmSecParams, EncData) ->
     #usmSecurityParameters{msgPrivacyParameters        = MsgPrivParams,
diff --git a/lib/snmp/src/misc/snmp_usm.erl b/lib/snmp/src/misc/snmp_usm.erl
index bae6bdec72..149d9f0dfb 100644
--- a/lib/snmp/src/misc/snmp_usm.erl
+++ b/lib/snmp/src/misc/snmp_usm.erl
@@ -45,7 +45,12 @@
 
 -define(i32(Int), (Int bsr 24) band 255, (Int bsr 16) band 255, (Int bsr 8) band 255, Int band 255).
 
--define(BLOCK_CIPHER_AES, aes_cfb128).
+-define(BLOCK_CIPHER_AES(Key), case bit_size(iolist_to_binary(Key)) of
+                                   128 -> aes_128_cfb128;
+                                   192 -> aes_192_cfb128;
+                                   256 -> aes_256_cfb128
+                               end).
+
 -define(BLOCK_CIPHER_DES, des_cbc).
 
 
@@ -248,7 +253,7 @@ aes_encrypt(PrivKey, Data, SaltFun, EngineBoots, EngineTime) ->
     AesKey = PrivKey,
     Salt = SaltFun(),
     IV = list_to_binary([?i32(EngineBoots), ?i32(EngineTime) | Salt]),
-    EncData = crypto:block_encrypt(?BLOCK_CIPHER_AES, 
+    EncData = crypto:block_encrypt(?BLOCK_CIPHER_AES(AesKey), 
 				   AesKey, IV, Data),
     {ok, binary_to_list(EncData), Salt}.
 
@@ -258,7 +263,7 @@ aes_decrypt(PrivKey, MsgPrivParams, EncData, EngineBoots, EngineTime)
     Salt = MsgPrivParams,
     IV = list_to_binary([?i32(EngineBoots), ?i32(EngineTime) | Salt]),
     %% Whatabout errors here???  E.g. not a mulitple of 8!
-    Data = binary_to_list(crypto:block_decrypt(?BLOCK_CIPHER_AES, 
+    Data = binary_to_list(crypto:block_decrypt(?BLOCK_CIPHER_AES(AesKey), 
 					       AesKey, IV, EncData)),
     Data2 = snmp_pdus:strip_encrypted_scoped_pdu_data(Data),
     {ok, Data2}.
-- 
2.26.2

openSUSE Build Service is sponsored by