diff -uNr a/smg_comms/manifest b/smg_comms/manifest --- a/smg_comms/manifest 268276f725ebbbf0eb0e11adcd2516571acb8958068b17040e1fb841a2edd44878d73c932982d70c4192b70c43f2cc9edf699380aa98fe15a968d81bfc911b14 +++ b/smg_comms/manifest a11ec7a815179c71a1c1b0239ee392930b811cffc2d83328bc4d6d9d7182eb9d5d55f3c010ed9fb8a1a98b14e578407331fb6229b479386abe16f6dff21b98f1 @@ -9,3 +9,4 @@ 549785 smg_comms_io_rsa_tests_only diana_coman Small refactoring of tests extracting the reading of RSA key into package of its own so it can be used throughout tests and thus get rid of the too long lines in test_packing.adb. 550310 smg_comms_keymgm diana_coman Adds read/write for Keys Management messages (both Serpent and RSA). Refactors the read/write of Serpent Keys messages so that the same core is called by RSA/Serpent specific-methods, adding also read/write of keys from/to RSA messages. 551086 smg_comms_files diana_coman Adds read/write for File Transfer (4.3) and File Request (4.4). Refactors the rest to have read/write of 16 bits values in one single place (i.e. separate method called from everywhere else) because of how common it is + sensitive to endianness. +551832 smg_comms_actions_rsa diana_coman Adds read/write for RSA keys (5.1) and Client Action (4.5). Refactors to allow choice of padding and enable direct testing of private procedure in Messages. diff -uNr a/smg_comms/src/data_structs.ads b/smg_comms/src/data_structs.ads --- a/smg_comms/src/data_structs.ads d472416a6fdbb7fd240664149e4a120f449ac15839d611e8a6987c145d3fe13c0a2227fe8c6ba3bc8f4ed2350973e7dfe6a074ab87cb02fbaf786396169fe5cf +++ b/smg_comms/src/data_structs.ads 973fcd28aff8d88504de9a8507277d84c0514edde25437433f00e3662da0070bee6fc80d428fccebd7b0f996c5b0eda8e2bbfce9fcdd99a542c5ad647b4b5a09 @@ -44,14 +44,13 @@ RZ at 12 range 0 .. 7; end record; - -- length of a text field (i.e. 16 bits, strictly > 0) - subtype Text_Len is Positive range 1..2**16-1; - -- A set of file names glued into a single string -- NB: there IS at least ONE filename and one character -- Upper limit for Text_Len is due to protocol's spec of text basic type - type U16_Array is array (Text_Len range <> ) of Interfaces.Unsigned_16; - type Filenames( F_No: Text_Len := 1; Sz: Text_Len := 1 ) is + type U16_Array is array (Raw_Types.Text_Len range <> ) + of Interfaces.Unsigned_16; + type Filenames( F_No: Raw_Types.Text_Len := 1; + Sz: Raw_Types.Text_Len := 1 ) is record -- filenames glued together into 1 single string S : String( 1 .. Sz ) := (others => '0'); @@ -60,9 +59,9 @@ end record; -- A chunk of a file (for file transfer) - type File_Chunk( Len : Text_Len := 1; + type File_Chunk( Len : Raw_Types.Text_Len := 1; Count : Interfaces.Unsigned_16 := 1; - Name_Len: Text_len := 1) is + Name_Len: Raw_Types.Text_len := 1) is record Filename: String(1..Name_Len); Content : Raw_Types.Octets(1..Len); @@ -112,4 +111,27 @@ end case; end record; + type Player_RSA is + record + -- communication protocol Version number + Proto_V : Interfaces.Unsigned_8; + + -- communication protocol Subversion number + Proto_Subv : Interfaces.Unsigned_16; + + -- Keccak hash of client binary + Client_Hash: Raw_Types.Octets_8; + + -- public exponent (e) of RSA key (64 bits precisely) + -- nb: this is protocol-specific e, aka shorter than TMSR e... + e : Raw_Types.Octets_8; + + -- public modulus (n) of RSA key (490 bits precisely) + n : Raw_Types.RSA_len; + + -- preferred padding; magic value 0x13370000 means random padding + Padding : Raw_Types.Octets_8; + + end record; + end Data_Structs; diff -uNr a/smg_comms/src/messages.adb b/smg_comms/src/messages.adb --- a/smg_comms/src/messages.adb fd5121b49fcbcb70293b002298fc82272ef291e959fe63d17b5b22ba02b1abb2b1d12a6d0d9541caebe43a300fe08cc329fbcace81b8341a00296f66eb182a84 +++ b/smg_comms/src/messages.adb 04b433f10c5557d2f696febe95ca6e9497354129ddfcc95c1e366af2744b214db5f7a9e63b401754f1e345adb0ef658a95a60fb54bc761ba628962aa2e40ccac @@ -1,6 +1,7 @@ -- Message reader & writers for SMG Communication Protocol -- S.MG, 2018 +with Raw_Types; use Raw_Types; with Interfaces; use Interfaces; with Serpent; with System; use System; @@ -14,10 +15,11 @@ procedure Write_SKeys_SMsg( Keyset : in Serpent_Keyset; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg) is begin -- call internal write on Octets with correct type id - Write_SKeys( Keyset, Counter, SKeys_S_Type, Msg ); + Write_SKeys( Keyset, Counter, SKeys_S_Type, Pad, Msg ); end Write_SKeys_SMsg; @@ -37,10 +39,11 @@ -- writes given key mgm structure into a Serpent message procedure Write_KMgm_SMsg( KMgm : in Keys_Mgm; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg) is begin -- call internal write of key mgm with correct type ID - Write_KMgm( KMgm, Counter, Key_Mgm_S_Type, Msg ); + Write_KMgm( KMgm, Counter, Key_Mgm_S_Type, Pad, Msg ); end Write_KMgm_SMsg; -- reads a key mgm structure from the given Serpent message @@ -58,6 +61,7 @@ ------ File Transfer ------ procedure Write_File_Transfer( Chunk : in File_Chunk; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg) is Pos: Integer := Msg'First; U16: Interfaces.Unsigned_16; @@ -68,7 +72,7 @@ -- write filename as text field (size+2, text) -- check against overflows - if Chunk.Name_Len > Text_Len'Last - 2 or + if Chunk.Name_Len > Raw_Types.Text_Len'Last - 2 or Pos + Integer(Chunk.Name_Len) + 2 > Msg'Last then raise Invalid_Msg; end if; @@ -84,7 +88,7 @@ --write content -- check against overflow, including the 2 octets for counter at the end - if Chunk.Len > Text_Len'Last - 2 or + if Chunk.Len > Raw_Types.Text_Len'Last - 2 or Pos + Integer(Chunk.Len) + 4 > Msg'Last then raise Invalid_Msg; end if; @@ -97,13 +101,8 @@ Msg(Pos..Pos+Chunk.Content'Length-1) := Chunk.Content; Pos := Pos + Chunk.Content'Length; - -- write counter - Write_U16( Msg, Pos, Chunk.Count ); - - -- write padding if needed - if Pos <= Msg'Last then - RNG.Get_Octets( Msg(Pos..Msg'Last) ); - end if; + -- write counter + padding + Write_End( Msg, Pos, Chunk.Count, Pad ); end Write_File_Transfer; @@ -115,9 +114,9 @@ Pos: Integer := Msg'First; U16: Interfaces.Unsigned_16; S_Name, E_Name: Integer; --start/end for filename in Msg - S_Len: Text_Len; -- length of filename (needed as Text_Len anyway) + S_Len: Raw_Types.Text_Len; -- length of filename S_Content, E_Content: Integer; --start/end for content in Msg - Content_Len: text_Len; -- length of content (needed as Text_Len anyway) + Content_Len: Raw_Types.Text_Len; -- length of content begin -- read and check type ID if Msg(Pos) /= File_Transfer_S_Type then @@ -134,7 +133,7 @@ raise Invalid_Msg; end if; U16 := U16 - 2; - S_Len := Text_Len(U16); + S_Len := Raw_Types.Text_Len(U16); -- set start + end for reading filename later, when ready S_Name := Pos; @@ -149,7 +148,7 @@ raise Invalid_msg; end if; U16 := U16 - 2; - Content_Len := Text_Len(U16); + Content_Len := Raw_Types.Text_Len(U16); -- set start and end for reading content later, when ready S_Content := Pos; E_Content := Pos + Integer(U16) - 1; @@ -180,6 +179,7 @@ ---- File Requests ---- procedure Write_File_Request( FR : in Filenames; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg; Written : out Natural) is Pos : Integer := Msg'First; @@ -262,13 +262,9 @@ end; end loop; - -- write the message counter in little endian at all times - Write_U16( Msg, Pos, Counter ); + -- write counter + padding + Write_End( Msg, Pos, Counter, Pad ); - -- write padding if needed - if Pos <= Msg'Last then - Rng.Get_Octets( Msg(Pos..Msg'Last) ); - end if; end Write_File_Request; -- Reads a request for files; the opposite of Write_File_Request above @@ -314,7 +310,8 @@ -- if it's not that => Invalid_Msg -- F_No and Text_Sz are not overflow (earlier check + calc) declare - F : Filenames(Text_Len(F_No), Text_Len(Text_Sz-F_No+1)); + F : Filenames(Raw_Types.Text_Len(F_No), + Raw_Types.Text_Len(Text_Sz-F_No+1)); S_Pos : Positive; Index : Positive; begin @@ -350,16 +347,158 @@ end Read_File_Request; + -- writes the action (octets+length) into the specified Serpent message + procedure Write_Action( A : in Raw_Types.Text_Octets; + Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; + Msg : out Raw_Types.Serpent_Msg) is + Pos : Natural := Msg'First + 1; + MaxPos : Natural := Msg'Last - 1; --2 octets reserved for counter at end + U16 : Interfaces.Unsigned_16; + begin + -- check whether given action FITS into a Serpent message + if Pos + 2 + A.Len > MaxPos then + raise Invalid_Msg; + end if; + + -- write correct type ID + Msg( Msg'First ) := Client_Action_S_Type; + + -- write action's TOTAL length + U16 := Interfaces.Unsigned_16(A.Len + 2); + Write_U16( Msg, Pos, U16 ); + + -- write the action itself + Msg( Pos..Pos+A.Len-1 ) := A.Content; + Pos := Pos + A.Len; + + -- write counter + padding + Write_End( Msg, Pos, Counter, Pad ); + + end Write_Action; + + -- reads a client action as octets+length from the given Serpent message + procedure Read_Action( Msg : in Raw_Types.Serpent_Msg; + Counter : out Interfaces.Unsigned_16; + A : out Raw_Types.Text_Octets) is + Pos : Natural := Msg'First + 1; + U16 : Interfaces.Unsigned_16; + begin + -- read and check message type ID + if Msg( Msg'First ) /= Client_Action_S_Type then + raise Invalid_Msg; + end if; + + -- read size of action (content+ 2 octets the size itself) + Read_U16( Msg, Pos, U16 ); + + -- check size + if U16 < 3 or Pos + Natural(U16) - 2 > Msg'Last - 1 then + raise Invalid_Msg; + else + U16 := U16 - 2; --size of content only + end if; + + -- create action, read it from message + assign to output variable + declare + Act : Raw_Types.Text_Octets( Raw_Types.Text_Len( U16 ) ); + begin + Act.Content := Msg( Pos..Pos+Act.Len-1 ); + Pos := Pos + Act.Len; + A := Act; + end; + + -- read counter + Read_U16( Msg, Pos, Counter ); + + end Read_Action; + ------------------ -- RSA Messages -- ------------------ + procedure Write_RKeys_RMsg( K : in Player_RSA; + Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; + Msg : out Raw_Types.RSA_Msg) is + Pos : Natural := Msg'First + 1; + begin + -- write correct message type + Msg( Msg'First ) := RKeys_R_Type; + + -- write protocol version and subversion + Msg( Pos ) := K.Proto_V; + Pos := Pos + 1; + Write_U16( Msg, Pos, K.Proto_Subv ); + + -- write keccak hash of client binary + Msg( Pos..Pos + K.Client_Hash'Length-1 ) := K.Client_Hash; + Pos := Pos + K.Client_Hash'Length; + + -- write e of RSA key + Msg( Pos..Pos + K.e'Length - 1 ) := K.e; + Pos := Pos + K.e'Length; + + -- write n of RSA key + Msg( Pos..Pos + K.n'Length - 1 ) := K.n; + Pos := Pos + K.n'Length; + + -- write preferred padding + Msg( Pos..Pos + K.Padding'Length - 1 ) := K.Padding; + Pos := Pos + K.Padding'Length; + + -- write counter + padding + Write_End( Msg, Pos, Counter, Pad ); + + end Write_RKeys_RMsg; + + -- Reads a RSA Keyset (Player_RSA structures) from the given RSA Message. + -- Opposite of Write_RKeys_RMsg above + procedure Read_RKeys_RMsg( Msg : in Raw_Types.RSA_Msg; + Counter : out Interfaces.Unsigned_16; + K : out Player_RSA) is + Pos : Natural := Msg'First + 1; + begin + -- check type id and raise exception if incorrect + if Msg(Msg'First) /= RKeys_R_Type then + raise Invalid_Msg; + end if; + + -- read protocol version and subversion + K.Proto_V := Msg( Pos ); + Pos := Pos + 1; + Read_U16( Msg, Pos, K.Proto_Subv ); + + -- read Keccak hash of client binary + K.Client_Hash := Msg( Pos..Pos+K.Client_Hash'Length - 1 ); + Pos := Pos + K.Client_Hash'Length; + + -- read e + K.e := Msg( Pos .. Pos + K.e'Length - 1 ); + Pos := Pos + K.e'Length; + + -- read n + K.n := Msg( Pos .. Pos + K.n'Length - 1 ); + Pos := Pos + K.n'Length; + + -- read choice of padding + K.Padding := Msg( Pos .. Pos+K.Padding'Length - 1 ); + Pos := Pos + K.Padding'Length; + + -- read message counter + Read_U16( Msg, Pos, Counter ); + + -- the rest is message padding, so ignore it + + end Read_RKeys_RMsg; + procedure Write_SKeys_RMsg( Keyset : in Serpent_Keyset; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.RSA_Msg) is begin -- call internal write of Serpent keys with correct type ID - Write_SKeys( Keyset, Counter, SKeys_R_Type, Msg ); + Write_SKeys( Keyset, Counter, SKeys_R_Type, Pad, Msg ); end Write_SKeys_RMsg; procedure Read_SKeys_RMsg( Msg : in Raw_Types.RSA_Msg; @@ -376,10 +515,11 @@ procedure Write_KMgm_RMsg( KMgm : in Keys_Mgm; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.RSA_Msg) is begin -- call internal write of key mgm with correct type ID - Write_KMgm( KMgm, Counter, Key_Mgm_R_Type, Msg ); + Write_KMgm( KMgm, Counter, Key_Mgm_R_Type, Pad, Msg ); end Write_KMgm_RMsg; procedure Read_KMgm_RMsg( Msg : in Raw_Types.RSA_Msg; @@ -436,6 +576,7 @@ procedure Write_SKeys( Keyset : in Serpent_Keyset; Counter : in Interfaces.Unsigned_16; Type_ID : in Interfaces.Unsigned_8; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Octets) is Pos : Integer := Msg'First; Check : CRC32.CRC32; @@ -471,13 +612,8 @@ Msg(Pos) := Keyset.Flag; Pos := Pos + 1; - -- write message counter - Write_U16( Msg, Pos, Counter ); - - -- write padding as needed; endianness is irrelevant here - if Pos <= Msg'Last then - RNG.Get_Octets( Msg(Pos..Msg'Last) ); - end if; + -- write counter + padding + Write_End( Msg, Pos, Counter, Pad ); end Write_SKeys; @@ -539,6 +675,7 @@ procedure Write_KMgm( KMgm : in Keys_Mgm; Counter : in Interfaces.Unsigned_16; Type_ID : in Interfaces.Unsigned_8; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Octets) is Pos : Integer := Msg'First; begin @@ -568,13 +705,8 @@ Pos := Pos + KMgm.Burnt'Length; end if; - -- write the message count - Write_U16( Msg, Pos, Counter ); - - -- pad with random octets until the end of Msg - if Pos <= Msg'Last then - RNG.Get_Octets( Msg(Pos..Msg'Last) ); - end if; + -- write counter + padding + Write_End( Msg, Pos, Counter, Pad ); end Write_KMgm; @@ -647,4 +779,33 @@ Pos := Pos + 2; end Read_U16; + -- Writes Counter and padding (rng or otherwise) into Msg starting from Pos. + procedure Write_End( Msg : in out Raw_Types.Octets; + Pos : in out Natural; + Counter : in Interfaces.Unsigned_16; + Padding : in Raw_Types.Octets_8) is + begin + -- check that there is space for Counter at the very least + if Pos > Msg'Last - 1 then + raise Invalid_Msg; + end if; + + -- write counter + Write_U16( Msg, Pos, Counter ); + + -- pad to the end of the message + if Pos <= Msg'Last then + if Padding = RNG_PAD then + RNG.Get_Octets( Msg( Pos..Msg'Last ) ); + else + -- repeat the Padding value itself + for I in Pos..Msg'Last loop + Msg(I) := Padding( Padding'First + (I - Pos) mod Padding'Length ); + end loop; + end if; + -- either rng or fixed, update Pos though + Pos := Msg'Last + 1; + end if; + end Write_End; + end Messages; diff -uNr a/smg_comms/src/messages.ads b/smg_comms/src/messages.ads --- a/smg_comms/src/messages.ads d6c3980da332629a8c09cfbfb32e1962ad689c7ecbc4a8ee83b02f85c1aa1a3374c5371eeee7f0cc49fe4c4d8e758f86fa5ba204c5900bd6f4f95cabb3a06ef6 +++ b/smg_comms/src/messages.ads 00b24d7c457c5e0a82dfff5e1e184597d7699ade009353120910bc18a5577b63291758f88461aafb79efcb80065cc8b85f45870f55c29050dd6bfb2f86bca53c @@ -32,6 +32,7 @@ -- Counter - the message count procedure Write_SKeys_SMsg( Keyset : in Serpent_Keyset; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg); -- Reads a Serpent Keyset from the given Serpent Message @@ -48,6 +49,7 @@ -- Counter - the message count procedure Write_KMgm_SMsg( KMgm : in Keys_Mgm; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg); -- Reads a Key management structure from the given Serpent Message @@ -61,7 +63,9 @@ -- Writes the given File Chunk to a File Transfer type of message -- Chunk - chunk of file to write; contains counter, filename, content + -- Pad - whether random padding (RNG_PAD value) or given value procedure Write_File_Transfer( Chunk : in File_Chunk; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg); -- The opposite of Write_File_Transfer method above. @@ -77,6 +81,7 @@ -- did not fit into the message and it's up to caller to decide what to do. procedure Write_File_Request( FR : in Filenames; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Serpent_Msg; Written : out Natural); @@ -86,17 +91,45 @@ Counter : out Interfaces.Unsigned_16; FR : out Filenames); + -------------------------Client Actions------------------------------ + -- writes the action (octets+length) into the specified Serpent message + procedure Write_Action( A : in Raw_Types.Text_Octets; + Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; + Msg : out Raw_Types.Serpent_Msg); + + -- reads a client action as octets+length from the given Serpent message + procedure Read_Action( Msg : in Raw_Types.Serpent_Msg; + Counter : out Interfaces.Unsigned_16; + A : out Raw_Types.Text_Octets); + ------------------ -- RSA Messages -- ------------------ -------------------------Keys---------------------------------------- + + -- Writes a RSA Keyset (with 8 octets e) to the given RSA Message. + -- K - the Player_RSA structures with all needed information to write + -- Counter - the message count + procedure Write_RKeys_RMsg( K : in Player_RSA; + Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; + Msg : out Raw_Types.RSA_Msg); + + -- Reads a RSA Keyset (Player_RSA structures) from the given RSA Message. + -- Opposite of Write_RKeys_RMsg above + procedure Read_RKeys_RMsg( Msg : in Raw_Types.RSA_Msg; + Counter : out Interfaces.Unsigned_16; + K : out Player_RSA); + -- Writes a Serpent Keyset to the given RSA Message -- -- Keyset - the set of keys to write to message -- Counter - the message count procedure Write_SKeys_RMsg( Keyset : in Serpent_Keyset; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.RSA_Msg); -- Reads a Serpent Keyset from the given RSA Message @@ -111,8 +144,10 @@ -- -- KMgm - the keys management structure to write to message -- Counter - the message count + -- Pad - whether random padding (RNG_PAD) or not. procedure Write_KMgm_RMsg( KMgm : in Keys_Mgm; Counter : in Interfaces.Unsigned_16; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.RSA_Msg); -- Reads a Key management structure from the given RSA Message @@ -131,6 +166,10 @@ -- NB: Str'Length has to be EQUAL to Octets'Length! procedure Octets_To_String(O: in Raw_Types.Octets; Str: out String); + -- magic value used to request random padding + RNG_PAD: constant Raw_Types.Octets_8 := ( 16#00#, 16#00#, 16#00#, 16#00#, + 16#13#, 16#37#, 16#00#, 16#00#); + private -- if native is little endian, does nothing; @@ -180,6 +219,7 @@ procedure Write_SKeys( Keyset : in Serpent_Keyset; Counter : in Interfaces.Unsigned_16; Type_ID : in Interfaces.Unsigned_8; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Octets); -- NB: caller has to ensure that Msg is a valid RSA or Serpent message @@ -196,6 +236,7 @@ procedure Write_KMgm( KMgm : in Keys_Mgm; Counter : in Interfaces.Unsigned_16; Type_ID : in Interfaces.Unsigned_8; + Pad : in Raw_Types.Octets_8; Msg : out Raw_Types.Octets); -- NB: caller has to ensure that Msg is a valid RSA or Serpent message @@ -223,4 +264,17 @@ procedure Read_U16( Msg: in Raw_Types.Octets; Pos: in out Natural; U16: out Interfaces.Unsigned_16); + + -- Writes the Counter + padding at the end of messages. + -- The padding is either random or repeated value, depending on "Padding". + -- NB: This raises Invalid_Msg exception if Pos > Msg'Last - 1 + -- Msg - the array of octets into which the counter+padding are to be written + -- Pos - the position in Msg from which to start writing counter+padding + -- Counter - the message counter to write at Pos in Msg. + -- Padding - magic value 0x13370000 means random padding; + -- - any other value for Padding gets used as it is (repeated) + procedure Write_End( Msg : in out Raw_Types.Octets; + Pos : in out Natural; + Counter : in Interfaces.Unsigned_16; + Padding : in Raw_Types.Octets_8); end Messages; diff -uNr a/smg_comms/src/raw_types.ads b/smg_comms/src/raw_types.ads --- a/smg_comms/src/raw_types.ads af8d8aef6af31a1e9b664ed49aa62785576de0526849596269ec46ede622c474756fb58ac151a26c93484913881afdedd3a069d4327cbc741d6f0c62fed9238d +++ b/smg_comms/src/raw_types.ads 6e8e85bfafe5928021ee613a17d9f7d1befe761771e1508141128be52b52424d380199d14ec42a5b1256373030bc474f3568038dbb2b3da034715a9d7b61c5d6 @@ -16,6 +16,17 @@ -- all messages and packets are simply arrays of octets at low level/raw type Octets is array( Natural range <> ) of Interfaces.Unsigned_8; + -- length of a text field (i.e. 16 bits, strictly > 0) + subtype Text_Len is Positive range 1..2**16-1; + + -- "text" type has a 2-byte header with total length + -- Len here is length of actual content ONLY (i.e. it needs + 2 for total) + type Text_Octets( Len: Text_Len := 1 ) is + record + -- actual octets making up the "text" + Content: Octets( 1..Len ) := (others => 0); + end record; + -- constants from SMG.COMMS standard specification -- RSA key size in octets diff -uNr a/smg_comms/tests/messages-test_serializing.adb b/smg_comms/tests/messages-test_serializing.adb --- a/smg_comms/tests/messages-test_serializing.adb false +++ b/smg_comms/tests/messages-test_serializing.adb 9f725d85955f8c39aa166d4f5e1b63d54f9f153084a351667d78c9bb709a41f86927936730feb6615127f6111821624e7f67b5d7ae6a95299716f78b5c9a3b87 @@ -0,0 +1,478 @@ + -- Tests for the serialization of data structures in SMG Protocol + -- S.MG, 2018 + +with RNG; +with Data_Structs; +with Messages; use Messages; +with Interfaces; use Interfaces; +with System; +with System.Storage_Elements; use System.Storage_Elements; +with Ada.Text_IO; use Ada.Text_IO; + +package body Messages.Test_Serializing is + + procedure Serialize_Keyset_RSA is + Msg : RSA_Msg; + ReadK : Player_RSA; + ReadC : Interfaces.Unsigned_16; + WMsg : RSA_Msg; + TypeID : constant Interfaces.Unsigned_8 := 251; + begin + Put_Line("Generating data for 5.1 RSA key set in RSA message."); + -- fill message with random data + RNG.Get_Octets(Msg); + + -- attempt read - it should fail + begin + Read_RKeys_RMsg( Msg, ReadC, ReadK ); + exception + when Invalid_Msg => + if Msg(Msg'First) /= TypeID then + Put_Line("PASS: exception correctly raised for invalid message"); + else + Put_Line("FAIL: exception raised on VALID message!"); + end if; + end; + + -- set correct type id + Msg(Msg'First) := TypeID; + + -- attempt read + write and compare + Read_RKeys_RMsg( Msg, ReadC, ReadK ); + Write_RKeys_RMsg( ReadK, ReadC, RNG_PAD, WMsg ); + + -- check result (without trailing padding since that CAN be different!) + if WMsg(1..520) /= Msg(1..520) then + Put_Line("FAIL: read+write of RSA keys to RSA message."); + for I in 1..520 loop + if WMsg(I) /= Msg(I) then + Put_Line("At " & Integer'Image(I) & " WMsg is " & + Unsigned_8'Image(WMsg(I)) & " while Msg is " & + Unsigned_8'Image(Msg(I))); + end if; + end loop; + else + Put_Line("PASS: read+write of RSA keys to RSA message."); + end if; + end Serialize_Keyset_RSA; + + procedure Serialize_Keyset_SS is + Msg : Serpent_Msg; + RMsg : RSA_Msg; + KSet : Serpent_Keyset(5); + LSB : Interfaces.Unsigned_8 := 16#01#; + MSB : Interfaces.Unsigned_8 := 16#80#; + LMSB : Interfaces.Unsigned_8 := 16#81#; + Counter : Interfaces.Unsigned_16 := 101; + NewSetS : Serpent_Keyset; + NewSetR : Serpent_Keyset; + NewCounterR: Interfaces.Unsigned_16:=0; + NewCounterS: Interfaces.Unsigned_16:=0; + begin + Put_Line("Generating the Serpent Keys..."); + -- fill a set of Serpent Keys + for I in 1..KSet.N loop + RNG.Get_Octets(KSet.Keys(Interfaces.Unsigned_8(I))); + end loop; + KSet.Flag := LSB; + + Put_Line("Writing the keys to messages..."); + -- write keyset to serpent & rsa messages + Write_SKeys_SMsg( KSet, Counter, RNG_PAD, Msg ); + Write_SKeys_RMsg( KSet, Counter, RNG_PAD, RMsg ); + + Put_Line("Reading keys back from messages..."); + -- read keyset from serpent and rsa messages + Read_SKeys_SMsg( Msg, NewCounterS, NewSetS ); + Read_SKeys_RMsg( RMsg, NewCounterR, NewSetR ); + + Put_Line("Comparing the keysets..."); + -- compare the two keysets + if NewCounterS /= Counter or NewCounterS /= Counter or + NewSetS /= KSet or NewSetR /= KSet then + Put_Line("FAIL: keysets are different!"); + else + Put_Line("PASS: keysets are the same!"); + end if; + + Put_Line("Attempting to read from mangled message"); + begin + Msg(Msg'First) := Msg(Msg'First)+25; + Read_SKeys_SMsg( Msg, Counter, NewSetS); + Put_Line("FAIL: read failed to raise invalid message exception!"); + exception + when Invalid_Msg => + Put_Line("PASS: exception correctly raised for invalid message"); + end; + end Serialize_Keyset_SS; + + procedure Serialize_Keys_Mgm is + N_Burnt : Counter_8bits; + Counter : Interfaces.Unsigned_16 := 16#EDA9#; + Mgm_S : Keys_Mgm; + Mgm_R : Keys_Mgm; + Cnt_S : Interfaces.Unsigned_16:=0; + Cnt_R : Interfaces.Unsigned_16:=0; + O1 : Octets_1; + SMsg : Serpent_Msg; + RMsg : RSA_Msg; + begin + -- fill the struct with random stuff + RNG.Get_Octets( O1 ); + N_Burnt := Cast(O1); + declare + Mgm: Keys_Mgm(N_Burnt); + begin + RNG.Get_Octets( O1 ); + Mgm.N_Server := O1(O1'First); + RNG.Get_Octets( O1 ); + Mgm.N_Client := O1(O1'First); + RNG.Get_Octets( O1 ); + Mgm.Key_ID := O1(O1'First); + if N_Burnt > 0 then + RNG.Get_Octets( Mgm.Burnt ); + end if; + -- write it to Serpent and RSA messages + Write_KMgm_SMsg(Mgm, Counter, RNG_PAD, SMsg); + Write_KMgm_RMsg(Mgm, Counter, RNG_PAD, RMsg); + + -- read it back from Serpent and RSA messages + Read_KMgm_SMsg( SMsg, Cnt_S, Mgm_S ); + Read_KMgm_RMsg( RMsg, Cnt_R, Mgm_R ); + + -- check results + if Cnt_S /= Counter or + Mgm_S.N_Burnt /= Mgm.N_Burnt or + Mgm_S /= Mgm then + Put_Line("FAIL: read/write key management struct to S msg."); + else + Put_Line("PASS: read/write key management struct to S msg."); + end if; + + if Cnt_R /= Counter or + Mgm_R.N_Burnt /= Mgm.N_Burnt or + Mgm_R /= Mgm then + Put_Line("FAIL: read/write key management struct to R msg."); + Put_Line("Cnt_R is " & Unsigned_16'Image(Cnt_R)); + Put_Line("Counter is " & Unsigned_16'Image(Counter)); + Put_Line("Mgm_R.N_Burnt is " & Counter_8bits'Image(Mgm_R.N_Burnt)); + Put_Line("Mgm.N_Burnt is " & Counter_8bits'Image(Mgm.N_Burnt)); + else + Put_Line("PASS: read/write key management struct to R msg."); + end if; + + -- attempt mangled call - should raise exception + begin + SMsg(SMsg'First) := SMsg(SMsg'First) + 1; + Read_KMgm_SMsg( SMsg, Cnt_S, Mgm_S); + Put_Line("FAIL: Read_KMgm_SMsg failed to raise exception!"); + exception + when Invalid_Msg => + Put_Line("PASS: Read_KMgm_SMsg correctly raised exception."); + end; + + end; + + end Serialize_Keys_Mgm; + + procedure Serialize_File_Request( Reps: in Positive) is + MaxSz: Positive := 340; + O2 : Raw_Types.Octets_2; + U16 : Interfaces.Unsigned_16; + Counter : Interfaces.Unsigned_16; + ReadCounter: Interfaces.Unsigned_16; + Written: Natural; + Msg : Raw_Types.Serpent_Msg; + F_No, Sz: Text_Len; + begin + for I in 1 .. Reps loop + -- generate a random size + RNG.Get_Octets( O2 ); + U16 := Raw_Types.Cast( O2 ); + Sz := Text_Len( Positive(U16) mod MaxSz + 1); + + -- generate a random number of files + RNG.Get_Octets( O2 ); + U16 := Raw_Types.Cast( O2 ); + -- make sure it's within Positive range i.e. not 0 + if U16 = 0 then + U16 := 1; + end if; + F_No := Text_Len( Positive(U16) mod Sz + 1 ); + + declare + FR: Filenames(F_No, Sz); + ReadFR: Filenames; + O : Octets(1..Sz); + Len : Positive := Sz / F_No; + begin + Put_Line("Generating test for File Request with " & + Integer'Image(FR.F_No) & " filenames."); + -- generate a random counter + RNG.Get_Octets(O2); + Counter := Raw_Types.Cast(O2); + + -- fill FR + RNG.Get_Octets( O ); + -- replace separators if any + for I in O'Range loop + if O(I) = 59 then + O(I) := 69; + end if; + end loop; + + Octets_To_String( O, FR.S ); + for I in FR.Starts'Range loop + FR.Starts(I) := Interfaces.Unsigned_16( FR.Starts'First + + Len*(I-FR.Starts'First)); + end loop; + + -- write FR to message + Write_File_Request(FR, Counter, RNG_PAD, Msg, Written); + + -- check how many filenames were written + if Written /= FR.F_No then + Put_Line("FAIL: only " & Natural'Image(Written) & + " filenames written out of " & Natural'Image(FR.F_No)); + else + Put_Line("PASS: wrote " & Natural'Image(Written) & " filenames."); + end if; + + -- read it from message and check result + Read_File_Request(Msg, ReadCounter, ReadFR); + if ReadCounter /= Counter then + Put_Line("FAIL: ReadCounter is " & Unsigned_16'Image(ReadCounter) & + " instead of expected " & Unsigned_16'Image(Counter) ); + else + Put_Line("PASS: ReadCounter was read correctly as " & + Unsigned_16'Image(ReadCounter)); + end if; + if ReadFr.Sz /= FR.Sz then + Put_Line("FAIL: Read FR.Sz = " & Text_Len'Image(ReadFr.Sz) & + " while expected sz is " & Text_Len'Image(FR.Sz)); + else + Put_Line("PASS: Read FR.Sz as expected = " & + Text_Len'Image(ReadFr.Sz)); + end if; + if ReadFr /= FR then + Put_Line("FAIL: ReadFr different from FR."); + else + Put_Line("PASS: ReadFr as expected, same as FR."); + end if; + end; + end loop; + + -- test with more files than can fit + Put_Line("Test case for File Request with more files than fit."); + declare + F: Filenames(4, 16384); + ReadF: Filenames; + begin + F.Starts(1) := Interfaces.Unsigned_16(F.S'First); + F.Starts(2) := Interfaces.Unsigned_16(F.S'First + 342); + F.Starts(3) := 16370; + F.Starts(4) := 16380; + Write_File_Request(F, Counter, RNG_PAD, Msg, Written); + if Written /= 1 then + Put_Line("FAIL: Written is " & Natural'Image(Written) & + " instead of expected 1."); + else + Put_Line("PASS: Written is 1 out of 4, as expected."); + end if; + Read_File_Request(Msg, ReadCounter, ReadF); + if ReadF.F_No /= 1 or ReadF.Starts(1) /= 1 or ReadF.Sz /= 342 then + Put_Line("FAIL: F_No is " & Text_Len'Image(ReadF.F_No) & + " Sz is " & Text_Len'Image(ReadF.Sz)); + else + Put_line("PASS: written 1 out of 4 correctly."); + end if; + end; + end Serialize_File_Request; + + procedure Serialize_File_Chunk is + Filename : String := "afile.png"; + FC : File_Chunk( Len => 945, + Count => 0, + Name_Len => Filename'Length); + ReadFC : File_Chunk; + Msg : Raw_Types.Serpent_Msg; + Pad : Raw_Types.Octets_8 := RNG_PAD; + begin + -- fill FC with random content + FC.Filename := Filename; + RNG.Get_Octets(FC.Content); + + -- write FC to message with random padding + Write_File_Transfer( FC, Pad, Msg ); + + -- read FC and check + Read_File_Transfer( Msg, ReadFC ); + + if FC /= ReadFC then + Put_Line("FAIL: read/write file chunk."); + else + Put_Line("PASS: read/write file chunk."); + end if; + end Serialize_File_Chunk; + + procedure Serialize_Action is + O2 : Raw_Types.Octets_2; + U16: Interfaces.Unsigned_16; + Len: Raw_Types.Text_Len; + Counter: Interfaces.Unsigned_16; + begin + Put_Line("Generating a random action for testing."); + -- generate random counter + RNG.Get_Octets( O2 ); + Counter := Raw_Types.Cast( O2 ); + + -- generate action length + RNG.Get_Octets( O2 ); + U16 := Raw_Types.Cast( O2 ); + if U16 < 1 then + U16 := 1; + else + if U16 + 5 > Raw_Types.Serpent_Msg'Length then + U16 := Raw_Types.Serpent_Msg'Length - 5; + end if; + end if; + Len := Raw_Types.Text_Len( U16 ); + + declare + A: Raw_Types.Text_Octets( Len ); + B: Raw_Types.Text_Octets; + Msg: Raw_Types.Serpent_Msg; + ReadC : Interfaces.Unsigned_16; + begin + RNG.Get_Octets( A.Content ); + begin + Write_Action( A, Counter, RNG_PAD, Msg ); + Read_Action( Msg, ReadC, B ); + if B /= A then + Put_Line("FAIL: read/write of Action."); + else + Put_Line("PASS: read/write of Action."); + end if; + exception + when Invalid_Msg => + if Len + 5 > Raw_Types.Serpent_Msg'Length then + Put_Line("PASS: exception correctly raised for Action too long"); + else + Put_Line("FAIL: exception INCORRECTLY raised at action r/w!"); + end if; + end; + end; + end Serialize_Action; + + procedure Converter_String_Octets is + Len: constant Natural := 234; + -- original values + S: String(1..Len); + O: Octets(1..Len); + -- converted values + CS: String(1..Len); + CO: Octets(1..Len); + begin + -- original octets + RNG.Get_Octets(O); + Octets_To_String(O, CS); + String_To_Octets(CS, CO); + if CO /= O then + Put_Line("FAIL: octets different after string/octets conversion."); + else + Put_Line("PASS: octets same after string/octets conversion."); + end if; + + -- original string + for I in S'Range loop + S(I) := Character'Val(I mod 12); + end loop; + String_To_Octets(S, CO); + Octets_To_String(CO, CS); + if CS /= S then + Put_Line("FAIL: string different after string/octets conversion."); + else + Put_Line("PASS: string same after string/octets conversion."); + end if; + end Converter_String_Octets; + + procedure Test_Padding is + Msg : Raw_Types.Serpent_Msg := (others => 12); + Old : Raw_Types.Serpent_Msg := Msg; + Pos : Natural := 16; + NewPos : Natural := Pos; + Counter : Interfaces.Unsigned_16; + U16 : Interfaces.Unsigned_16; + O2 : Raw_Types.Octets_2; + Pad : Raw_Types.Octets_8; + Pass : Boolean; + begin + -- get random counter + RNG.Get_Octets( O2 ); + Counter := Raw_Types.Cast( O2 ); + + -- test with random padding + Pad := RNG_PAD; + Write_End( Msg, NewPos, Counter, Pad ); + -- check NewPos and counter + Pass := True; + if NewPos /= Msg'Last + 1 then + Put_Line("FAIL: incorrect Pos value after Write_End with rng."); + Pass := False; + end if; + Read_U16(Msg, Pos, U16); + if U16 /= Counter then + Put_Line("FAIL: incorrect Counter by Write_End with rng."); + Pass := False; + end if; + -- check that the padding is at least different... + if Msg(Pos..Msg'Last) = Old(Pos..Old'Last) or + Msg(Pos..Pos+Pad'Length-1) = Pad then + Put_Line("FAIL: no padding written by Write_End with rng."); + Pass := False; + end if; + if Pass then + Put_Line("PASS: Write_End with rng."); + end if; + + -- prepare for the next test + Pass := True; + Pos := Pos - 2; + NewPos := Pos; + Msg := Old; + + -- get random padding + RNG.Get_Octets( Pad ); + + -- write with fixed padding and check + Write_End( Msg, NewPos, Counter, Pad ); + Pass := True; + + if NewPos = Msg'Last + 1 then + -- check counter + padding + Read_U16( Msg, Pos, U16 ); + if U16 /= Counter then + Put_Line("FAIL: Counter was not written by Write_End."); + Pass := False; + end if; + for I in Pos..Msg'Last loop + if Msg( I ) /= Pad( Pad'First + (I - Pos) mod Pad'Length ) then + Put_Line("FAIL: Msg(" & Natural'Image(I) & ")=" & + Unsigned_8'Image(Msg(I)) & " /= Pad(" & + Natural'Image(Pad'First+(I-Pos) mod Pad'Length) & + ") which is " & + Unsigned_8'Image(Pad(Pad'First+(I-Pos) mod Pad'Length))); + Pass := False; + end if; + end loop; + else + Put_Line("FAIL: Pos is wrong after call to Write_End."); + Pass := False; + end if; + if Pass then + Put_Line("PASS: test for Write_End with fixed padding."); + end if; + end Test_Padding; + +end Messages.Test_Serializing; + diff -uNr a/smg_comms/tests/messages-test_serializing.ads b/smg_comms/tests/messages-test_serializing.ads --- a/smg_comms/tests/messages-test_serializing.ads false +++ b/smg_comms/tests/messages-test_serializing.ads 2f33b454a28b303e34077b17360bdeceaa095dd336f286c26046da82ab4395c2f783a3ab3dee64c87ffd088728b4721196e20154f15b71ba704da0f7d6f9cab7 @@ -0,0 +1,20 @@ + -- Tests for the serialization of data structures in SMG Protocol + -- S.MG, 2018 + +with Raw_Types; use Raw_Types; + +package Messages.Test_Serializing is + + procedure Serialize_Keyset_RSA; + procedure Serialize_Keyset_SS; + procedure Serialize_Keys_Mgm; + procedure Serialize_File_Request( Reps: in Positive ); + procedure Serialize_File_Chunk; + procedure Serialize_Action; + + procedure Converter_String_Octets; + procedure Test_Padding; + +private + +end Messages.Test_Serializing; diff -uNr a/smg_comms/tests/test_serializing.adb b/smg_comms/tests/test_serializing.adb --- a/smg_comms/tests/test_serializing.adb 60ba5dffa63414f5b2d28611da978ef0cdaaccaeeba3383699e8ebff223f608bed0f6752411067cf8a40bbb209040fcc621557bcf771f2459268abe0edcdc6a9 +++ b/smg_comms/tests/test_serializing.adb false @@ -1,304 +0,0 @@ - -- Tests for the serialization of data structures in SMG Protocol - -- S.MG, 2018 - -with RNG; -with Data_Structs; use Data_Structs; -with Messages; use Messages; -with Interfaces; use Interfaces; -with System; -with System.Storage_Elements; use System.Storage_Elements; -with Ada.Text_IO; use Ada.Text_IO; - -package body Test_Serializing is - - procedure Serialize_Keyset_SS is - Msg : Serpent_Msg; - RMsg : RSA_Msg; - KSet : Serpent_Keyset(5); - LSB : Interfaces.Unsigned_8 := 16#01#; - MSB : Interfaces.Unsigned_8 := 16#80#; - LMSB : Interfaces.Unsigned_8 := 16#81#; - Counter : Interfaces.Unsigned_16 := 101; - NewSetS : Serpent_Keyset; - NewSetR : Serpent_Keyset; - NewCounterR: Interfaces.Unsigned_16:=0; - NewCounterS: Interfaces.Unsigned_16:=0; - begin - Put_Line("Generating the Serpent Keys..."); - -- fill a set of Serpent Keys - for I in 1..KSet.N loop - RNG.Get_Octets(KSet.Keys(Interfaces.Unsigned_8(I))); - end loop; - KSet.Flag := LSB; - - Put_Line("Writing the keys to messages..."); - -- write keyset to serpent & rsa messages - Write_SKeys_SMsg( KSet, Counter, Msg ); - Write_SKeys_RMsg( KSet, Counter, RMsg ); - - Put_Line("Reading keys back from messages..."); - -- read keyset from serpent and rsa messages - Read_SKeys_SMsg( Msg, NewCounterS, NewSetS ); - Read_SKeys_RMsg( RMsg, NewCounterR, NewSetR ); - - Put_Line("Comparing the keysets..."); - -- compare the two keysets - if NewCounterS /= Counter or NewCounterS /= Counter or - NewSetS /= KSet or NewSetR /= KSet then - Put_Line("FAIL: keysets are different!"); - else - Put_Line("PASS: keysets are the same!"); - end if; - - Put_Line("Attempting to read from mangled message"); - begin - Msg(Msg'First) := Msg(Msg'First)+25; - Read_SKeys_SMsg( Msg, Counter, NewSetS); - Put_Line("FAIL: read failed to raise invalid message exception!"); - exception - when Invalid_Msg => - Put_Line("PASS: exception correctly raised for invalid message"); - end; - end Serialize_Keyset_SS; - - procedure Serialize_Keys_Mgm is - N_Burnt : Counter_8bits; - Counter : Interfaces.Unsigned_16 := 16#EDA9#; - Mgm_S : Keys_Mgm; - Mgm_R : Keys_Mgm; - Cnt_S : Interfaces.Unsigned_16:=0; - Cnt_R : Interfaces.Unsigned_16:=0; - O1 : Octets_1; - SMsg : Serpent_Msg; - RMsg : RSA_Msg; - begin - -- fill the struct with random stuff - RNG.Get_Octets( O1 ); - N_Burnt := Cast(O1); - declare - Mgm: Keys_Mgm(N_Burnt); - begin - RNG.Get_Octets( O1 ); - Mgm.N_Server := O1(O1'First); - RNG.Get_Octets( O1 ); - Mgm.N_Client := O1(O1'First); - RNG.Get_Octets( O1 ); - Mgm.Key_ID := O1(O1'First); - if N_Burnt > 0 then - RNG.Get_Octets( Mgm.Burnt ); - end if; - -- write it to Serpent and RSA messages - Write_KMgm_SMsg(Mgm, Counter, SMsg); - Write_KMgm_RMsg(Mgm, Counter, RMsg); - - -- read it back from Serpent and RSA messages - Read_KMgm_SMsg( SMsg, Cnt_S, Mgm_S ); - Read_KMgm_RMsg( RMsg, Cnt_R, Mgm_R ); - - -- check results - if Cnt_S /= Counter or - Mgm_S.N_Burnt /= Mgm.N_Burnt or - Mgm_S /= Mgm then - Put_Line("FAIL: read/write key management struct to S msg."); - else - Put_Line("PASS: read/write key management struct to S msg."); - end if; - - if Cnt_R /= Counter or - Mgm_R.N_Burnt /= Mgm.N_Burnt or - Mgm_R /= Mgm then - Put_Line("FAIL: read/write key management struct to R msg."); - Put_Line("Cnt_R is " & Unsigned_16'Image(Cnt_R)); - Put_Line("Counter is " & Unsigned_16'Image(Counter)); - Put_Line("Mgm_R.N_Burnt is " & Counter_8bits'Image(Mgm_R.N_Burnt)); - Put_Line("Mgm.N_Burnt is " & Counter_8bits'Image(Mgm.N_Burnt)); - else - Put_Line("PASS: read/write key management struct to R msg."); - end if; - - -- attempt mangled call - should raise exception - begin - SMsg(SMsg'First) := SMsg(SMsg'First) + 1; - Read_KMgm_SMsg( SMsg, Cnt_S, Mgm_S); - Put_Line("FAIL: Read_KMgm_SMsg failed to raise exception!"); - exception - when Invalid_Msg => - Put_Line("PASS: Read_KMgm_SMsg correctly raised exception."); - end; - - end; - - end Serialize_Keys_Mgm; - - procedure Serialize_File_Request( Reps: in Positive) is - MaxSz: Positive := 340; - O2 : Raw_Types.Octets_2; - U16 : Interfaces.Unsigned_16; - Counter : Interfaces.Unsigned_16; - ReadCounter: Interfaces.Unsigned_16; - Written: Natural; - Msg : Raw_Types.Serpent_Msg; - F_No, Sz: Text_Len; - begin - for I in 1 .. Reps loop - -- generate a random size - RNG.Get_Octets( O2 ); - U16 := Raw_Types.Cast( O2 ); - Sz := Text_Len( Positive(U16) mod MaxSz + 1); - - -- generate a random number of files - RNG.Get_Octets( O2 ); - U16 := Raw_Types.Cast( O2 ); - F_No := Text_Len( Positive(U16) mod Sz ); - if F_No = 0 then - F_No := 1; - end if; - - declare - FR: Filenames(F_No, Sz); - ReadFR: Filenames; - O : Octets(1..Sz); - Len : Positive := Sz / F_No; - begin - Put_Line("Generating test for File Request with " & - Integer'Image(FR.F_No) & " filenames."); - -- generate a random counter - RNG.Get_Octets(O2); - Counter := Raw_Types.Cast(O2); - - -- fill FR - RNG.Get_Octets( O ); - -- replace separators if any - for I in O'Range loop - if O(I) = 59 then - O(I) := 69; - end if; - end loop; - - Octets_To_String( O, FR.S ); - for I in FR.Starts'Range loop - FR.Starts(I) := Interfaces.Unsigned_16( FR.Starts'First + - Len*(I-FR.Starts'First)); - end loop; - - -- write FR to message - Write_File_Request(FR, Counter, Msg, Written); - - -- check how many filenames were written - if Written /= FR.F_No then - Put_Line("FAIL: only " & Natural'Image(Written) & - " filenames written out of " & Natural'Image(FR.F_No)); - else - Put_Line("PASS: wrote " & Natural'Image(Written) & " filenames."); - end if; - - -- read it from message and check result - Read_File_Request(Msg, ReadCounter, ReadFR); - if ReadCounter /= Counter then - Put_Line("FAIL: ReadCounter is " & Unsigned_16'Image(ReadCounter) & - " instead of expected " & Unsigned_16'Image(Counter) ); - else - Put_Line("PASS: ReadCounter was read correctly as " & - Unsigned_16'Image(ReadCounter)); - end if; - if ReadFr.Sz /= FR.Sz then - Put_Line("FAIL: Read FR.Sz = " & Text_Len'Image(ReadFr.Sz) & - " while expected sz is " & Text_Len'Image(FR.Sz)); - else - Put_Line("PASS: Read FR.Sz as expected = " & - Text_Len'Image(ReadFr.Sz)); - end if; - if ReadFr /= FR then - Put_Line("FAIL: ReadFr different from FR."); - else - Put_Line("PASS: ReadFr as expected, same as FR."); - end if; - end; - end loop; - - -- test with more files than can fit - Put_Line("Test case for File Request with more files than fit."); - declare - F: Filenames(4, 16384); - ReadF: Filenames; - begin - F.Starts(1) := Interfaces.Unsigned_16(F.S'First); - F.Starts(2) := Interfaces.Unsigned_16(F.S'First + 342); - F.Starts(3) := 16370; - F.Starts(4) := 16380; - Write_File_Request(F, Counter, Msg, Written); - if Written /= 1 then - Put_Line("FAIL: Written is " & Natural'Image(Written) & - " instead of expected 1."); - else - Put_Line("PASS: Written is 1 out of 4, as expected."); - end if; - Read_File_Request(Msg, ReadCounter, ReadF); - if ReadF.F_No /= 1 or ReadF.Starts(1) /= 1 or ReadF.Sz /= 342 then - Put_Line("FAIL: F_No is " & Text_Len'Image(ReadF.F_No) & - " Sz is " & Text_Len'Image(ReadF.Sz)); - else - Put_line("PASS: written 1 out of 4 correctly."); - end if; - end; - end Serialize_File_Request; - - procedure Serialize_File_Chunk is - Filename : String := "afile.png"; - FC : File_Chunk( Len => 945, - Count => 0, - Name_Len => Filename'Length); - ReadFC : File_Chunk; - Msg : Raw_Types.Serpent_Msg; - begin - -- fill FC with random content - FC.Filename := Filename; - RNG.Get_Octets(FC.Content); - - -- write FC to message - Write_File_Transfer( FC, Msg ); - - -- read FC and check - Read_File_Transfer( Msg, ReadFC ); - - if FC /= ReadFC then - Put_Line("FAIL: read/write file chunk."); - else - Put_Line("PASS: read/write file chunk."); - end if; - end Serialize_File_Chunk; - - procedure Converter_String_Octets is - Len: constant Natural := 234; - -- original values - S: String(1..Len); - O: Octets(1..Len); - -- converted values - CS: String(1..Len); - CO: Octets(1..Len); - begin - -- original octets - RNG.Get_Octets(O); - Octets_To_String(O, CS); - String_To_Octets(CS, CO); - if CO /= O then - Put_Line("FAIL: octets different after string/octets conversion."); - else - Put_Line("PASS: octets same after string/octets conversion."); - end if; - - -- original string - for I in S'Range loop - S(I) := Character'Val(I mod 12); - end loop; - String_To_Octets(S, CO); - Octets_To_String(CO, CS); - if CS /= S then - Put_Line("FAIL: string different after string/octets conversion."); - else - Put_Line("PASS: string same after string/octets conversion."); - end if; - end Converter_String_Octets; - -end Test_Serializing; - diff -uNr a/smg_comms/tests/test_serializing.ads b/smg_comms/tests/test_serializing.ads --- a/smg_comms/tests/test_serializing.ads 77dfbf402e60b9cd4d8838421571bc7d018078b66c4b7d54c40bcae20cd5554072704d6476659f19f8dd4ba82a3a006f1e0b5b2c2228aaa0abaaa87c338c025a +++ b/smg_comms/tests/test_serializing.ads false @@ -1,17 +0,0 @@ - -- Tests for the serialization of data structures in SMG Protocol - -- S.MG, 2018 - -with Raw_Types; use Raw_Types; - -package Test_Serializing is - - procedure Serialize_Keyset_SS; - procedure Serialize_Keys_Mgm; - procedure Serialize_File_Request( Reps: in Positive ); - procedure Serialize_File_Chunk; - - procedure Converter_String_Octets; - -private - -end Test_Serializing; diff -uNr a/smg_comms/tests/testall.adb b/smg_comms/tests/testall.adb --- a/smg_comms/tests/testall.adb 8ccd7a252824f3a0ba71e0b69fb36b7347146ea1b64aa0b297799717384c3ff1e954792ec2c4e1c762252a0c96ae46e438fe4cd541fa5a477c29b11c991b5775 +++ b/smg_comms/tests/testall.adb 4fcbe6d5f83c385c895668661f49ec5994d54b274866f52ed032815938ce3b3cdf94d8dfc18523aaa45ad17f9d691263aa6ef4080fb8cc55f2184217af041f4a @@ -3,7 +3,7 @@ with Test_Serpent; with Test_Packing; with Test_RSA_OAEP; -with Test_Serializing; +with Messages.Test_Serializing; procedure testall is begin @@ -14,9 +14,12 @@ Test_RSA_OAEP.test_rsa_oaep; Test_Packing.Test_Pack_Unpack_Serpent; Test_Packing.Test_Pack_Unpack_RSA; - Test_Serializing.Serialize_Keyset_SS; - Test_Serializing.Serialize_Keys_Mgm; - Test_Serializing.Serialize_File_Chunk; - Test_Serializing.Serialize_File_Request(5); - Test_Serializing.Converter_String_Octets; + Messages.Test_Serializing.Serialize_Keyset_SS; + Messages.Test_Serializing.Serialize_Keyset_RSA; + Messages.Test_Serializing.Serialize_Keys_Mgm; + Messages.Test_Serializing.Serialize_File_Chunk; + Messages.Test_Serializing.Serialize_File_Request(5); + Messages.Test_Serializing.Serialize_Action; + Messages.Test_Serializing.Converter_String_Octets; + Messages.Test_Serializing.Test_Padding; end testall;