From: Thomas Quinot Date: Thu, 7 May 2020 14:08:03 +0000 (+0200) Subject: [Ada] Use Stream_Element_Arrays internally for secure hash computations X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=58d94a32b4cfe6065b736cac38f73d9a8deaa5d4;p=gcc.git [Ada] Use Stream_Element_Arrays internally for secure hash computations gcc/ada/ * libgnat/g-sechas.ads, libgnat/g-sechas.adb: Refactor to use Stream_Element_Array as the internal buffer type. * libgnat/g-shshco.adb: Adjust to use Stream_Element_Offset instead of Integer as the index in the internal state buffer. --- diff --git a/gcc/ada/libgnat/g-sechas.adb b/gcc/ada/libgnat/g-sechas.adb index 8918647e62e..bd9757174d7 100644 --- a/gcc/ada/libgnat/g-sechas.adb +++ b/gcc/ada/libgnat/g-sechas.adb @@ -40,25 +40,25 @@ package body GNAT.Secure_Hashes is type Fill_Buffer_Access is access procedure (M : in out Message_State; - S : String; - First : Natural; - Last : out Natural); - -- A procedure to transfer data from S, starting at First, into M's block + SEA : Stream_Element_Array; + First : Stream_Element_Offset; + Last : out Stream_Element_Offset); + -- A procedure to transfer data from SEA, starting at First, into M's block -- buffer until either the block buffer is full or all data from S has been -- consumed. procedure Fill_Buffer_Copy (M : in out Message_State; - S : String; - First : Natural; - Last : out Natural); + SEA : Stream_Element_Array; + First : Stream_Element_Offset; + Last : out Stream_Element_Offset); -- Transfer procedure which just copies data from S to M procedure Fill_Buffer_Swap (M : in out Message_State; - S : String; - First : Natural; - Last : out Natural); + SEA : Stream_Element_Array; + First : Stream_Element_Offset; + Last : out Stream_Element_Offset); -- Transfer procedure which swaps bytes from S when copying into M. S must -- have even length. Note that the swapping is performed considering pairs -- starting at S'First, even if S'First /= First (that is, if @@ -75,22 +75,23 @@ package body GNAT.Secure_Hashes is procedure Fill_Buffer_Copy (M : in out Message_State; - S : String; - First : Natural; - Last : out Natural) + SEA : Stream_Element_Array; + First : Stream_Element_Offset; + Last : out Stream_Element_Offset) is - Buf_String : String (M.Buffer'Range); - for Buf_String'Address use M.Buffer'Address; - pragma Import (Ada, Buf_String); + Buf_SEA : Stream_Element_Array (M.Buffer'Range); + for Buf_SEA'Address use M.Buffer'Address; + pragma Import (Ada, Buf_SEA); - Length : constant Natural := - Natural'Min (M.Block_Length - M.Last, S'Last - First + 1); + Length : constant Stream_Element_Offset := + Stream_Element_Offset'Min + (M.Block_Length - M.Last, SEA'Last - First + 1); begin pragma Assert (Length > 0); - Buf_String (M.Last + 1 .. M.Last + Length) := - S (First .. First + Length - 1); + Buf_SEA (M.Last + 1 .. M.Last + Length) := + SEA (First .. First + Length - 1); M.Last := M.Last + Length; Last := First + Length - 1; end Fill_Buffer_Copy; @@ -101,20 +102,21 @@ package body GNAT.Secure_Hashes is procedure Fill_Buffer_Swap (M : in out Message_State; - S : String; - First : Natural; - Last : out Natural) + SEA : Stream_Element_Array; + First : Stream_Element_Offset; + Last : out Stream_Element_Offset) is - pragma Assert (S'Length mod 2 = 0); - Length : constant Natural := - Natural'Min (M.Block_Length - M.Last, S'Last - First + 1); + pragma Assert (SEA'Length mod 2 = 0); + Length : constant Stream_Element_Offset := + Stream_Element_Offset'Min + (M.Block_Length - M.Last, SEA'Last - First + 1); begin Last := First; while Last - First < Length loop M.Buffer (M.Last + 1 + Last - First) := - (if (Last - S'First) mod 2 = 0 - then S (Last + 1) - else S (Last - 1)); + (if (Last - SEA'First) mod 2 = 0 + then SEA (Last + 1) + else SEA (Last - 1)); Last := Last + 1; end loop; M.Last := M.Last + Length; @@ -146,7 +148,7 @@ package body GNAT.Secure_Hashes is procedure Update (C : in out Context; - S : String; + SEA : Stream_Element_Array; Fill_Buffer : Fill_Buffer_Access); -- Internal common routine for all Update procedures @@ -161,8 +163,7 @@ package body GNAT.Secure_Hashes is ------------ function Digest (C : Context) return Message_Digest is - Hash_Bits : Stream_Element_Array - (1 .. Stream_Element_Offset (Hash_Length)); + Hash_Bits : Stream_Element_Array (1 .. Hash_Length); begin Final (C, Hash_Bits); return MD : Message_Digest do @@ -185,8 +186,7 @@ package body GNAT.Secure_Hashes is end Digest; function Digest (C : Context) return Binary_Message_Digest is - Hash_Bits : Stream_Element_Array - (1 .. Stream_Element_Offset (Hash_Length)); + Hash_Bits : Stream_Element_Array (1 .. Hash_Length); begin Final (C, Hash_Bits); return Hash_Bits; @@ -223,13 +223,13 @@ package body GNAT.Secure_Hashes is is FC : Context := C; - Zeroes : Natural; + Zeroes : Stream_Element_Count; -- Number of 0 bytes in padding Message_Length : Unsigned_64 := FC.M_State.Length; -- Message length in bytes - Size_Length : constant Natural := + Size_Length : constant Stream_Element_Count := 2 * Hash_State.Word'Size / 8; -- Length in bytes of the size representation @@ -237,11 +237,11 @@ package body GNAT.Secure_Hashes is Zeroes := (Block_Length - 1 - Size_Length - FC.M_State.Last) mod FC.M_State.Block_Length; declare - Pad : String (1 .. 1 + Zeroes + Size_Length) := - (1 => Character'Val (128), others => ASCII.NUL); + Pad : Stream_Element_Array (1 .. 1 + Zeroes + Size_Length) := + (1 => 128, others => 0); - Index : Natural; - First_Index : Natural; + Index : Stream_Element_Offset; + First_Index : Stream_Element_Offset; begin First_Index := (if Hash_Bit_Order = Low_Order_First @@ -255,12 +255,12 @@ package body GNAT.Secure_Hashes is -- Message_Length is in bytes, but we need to store it as -- a bit count. - Pad (Index) := Character'Val + Pad (Index) := Stream_Element (Shift_Left (Message_Length and 16#1f#, 3)); Message_Length := Shift_Right (Message_Length, 5); else - Pad (Index) := Character'Val (Message_Length and 16#ff#); + Pad (Index) := Stream_Element (Message_Length and 16#ff#); Message_Length := Shift_Right (Message_Length, 8); end if; @@ -308,7 +308,7 @@ package body GNAT.Secure_Hashes is return C : Context (KL => (if Key'Length <= Key_Length'Last then Key'Length - else Stream_Element_Offset (Hash_Length))) + else Hash_Length)) do -- Set Key (if longer than block length, first hash it) @@ -361,22 +361,29 @@ package body GNAT.Secure_Hashes is procedure Update (C : in out Context; - S : String; + SEA : Stream_Element_Array; Fill_Buffer : Fill_Buffer_Access) is - Last : Natural; + First, Last : Stream_Element_Offset; begin - C.M_State.Length := C.M_State.Length + S'Length; + if SEA'Length = 0 then + return; + end if; + + C.M_State.Length := C.M_State.Length + SEA'Length; - Last := S'First - 1; - while Last < S'Last loop - Fill_Buffer (C.M_State, S, Last + 1, Last); + First := SEA'First; + loop + Fill_Buffer (C.M_State, SEA, First, Last); if C.M_State.Last = Block_Length then Transform (C.H_State, C.M_State); C.M_State.Last := 0; end if; + + exit when Last = SEA'Last; + First := Last + 1; end loop; end Update; @@ -384,7 +391,7 @@ package body GNAT.Secure_Hashes is -- Update -- ------------ - procedure Update (C : in out Context; Input : String) is + procedure Update (C : in out Context; Input : Stream_Element_Array) is begin Update (C, Input, Fill_Buffer_Copy'Access); end Update; @@ -393,12 +400,13 @@ package body GNAT.Secure_Hashes is -- Update -- ------------ - procedure Update (C : in out Context; Input : Stream_Element_Array) is - S : String (1 .. Input'Length); - for S'Address use Input'Address; - pragma Import (Ada, S); + procedure Update (C : in out Context; Input : String) is + pragma Assert (Input'Length <= Stream_Element_Offset'Last); + SEA : Stream_Element_Array (1 .. Input'Length); + for SEA'Address use Input'Address; + pragma Import (Ada, SEA); begin - Update (C, S, Fill_Buffer_Copy'Access); + Update (C, SEA, Fill_Buffer_Copy'Access); end Update; ----------------- @@ -406,12 +414,12 @@ package body GNAT.Secure_Hashes is ----------------- procedure Wide_Update (C : in out Context; Input : Wide_String) is - S : String (1 .. 2 * Input'Length); - for S'Address use Input'Address; - pragma Import (Ada, S); + SEA : Stream_Element_Array (1 .. 2 * Input'Length); + for SEA'Address use Input'Address; + pragma Import (Ada, SEA); begin Update - (C, S, + (C, SEA, (if System.Default_Bit_Order /= Low_Order_First then Fill_Buffer_Swap'Access else Fill_Buffer_Copy'Access)); @@ -460,7 +468,7 @@ package body GNAT.Secure_Hashes is ------------- procedure To_Hash (H : State; H_Bits : out Stream_Element_Array) is - Hash_Words : constant Natural := H'Size / Word'Size; + Hash_Words : constant Stream_Element_Offset := H'Size / Word'Size; Result : State (1 .. Hash_Words) := H (H'Last - Hash_Words + 1 .. H'Last); diff --git a/gcc/ada/libgnat/g-sechas.ads b/gcc/ada/libgnat/g-sechas.ads index fb34bf93239..2edc2e358ac 100644 --- a/gcc/ada/libgnat/g-sechas.ads +++ b/gcc/ada/libgnat/g-sechas.ads @@ -44,7 +44,7 @@ with System; package GNAT.Secure_Hashes is - type Buffer_Type is new String; + type Buffer_Type is new Stream_Element_Array; for Buffer_Type'Alignment use 8; -- Secure hash functions use a string buffer that is also accessed as an -- array of words, which may require up to 64 bit alignment. @@ -52,8 +52,8 @@ package GNAT.Secure_Hashes is -- The function-independent part of processing state: A buffer of data -- being accumulated until a complete block is ready for hashing. - type Message_State (Block_Length : Natural) is record - Last : Natural := 0; + type Message_State (Block_Length : Stream_Element_Count) is record + Last : Stream_Element_Offset := 0; -- Index of last used element in Buffer Length : Interfaces.Unsigned_64 := 0; @@ -81,7 +81,7 @@ package GNAT.Secure_Hashes is package Hash_Function_State is - type State is array (Natural range <>) of Word; + type State is array (Stream_Element_Offset range <>) of Word; -- Used to store a hash function's internal state procedure To_Hash @@ -97,13 +97,13 @@ package GNAT.Secure_Hashes is -- secure hash function is an instance of this generic package. generic - Block_Words : Natural; + Block_Words : Stream_Element_Count; -- Number of words in each block - State_Words : Natural; + State_Words : Stream_Element_Count; -- Number of words in internal state - Hash_Words : Natural; + Hash_Words : Stream_Element_Count; -- Number of words in the final hash (must be no greater than -- State_Words). @@ -157,11 +157,10 @@ package GNAT.Secure_Hashes is -- the Wide_String version, each Wide_Character is processed low order -- byte first. - Word_Length : constant Natural := Hash_State.Word'Size / 8; - Hash_Length : constant Natural := Hash_Words * Word_Length; + Word_Length : constant Stream_Element_Offset := Hash_State.Word'Size / 8; + Hash_Length : constant Stream_Element_Offset := Hash_Words * Word_Length; - subtype Binary_Message_Digest is - Stream_Element_Array (1 .. Stream_Element_Offset (Hash_Length)); + subtype Binary_Message_Digest is Stream_Element_Array (1 .. Hash_Length); -- The fixed-length byte array returned by Digest, providing -- the hash in binary representation. @@ -176,7 +175,7 @@ package GNAT.Secure_Hashes is -- Wide_Update) on a default initialized Context, followed by Digest -- on the resulting Context. - subtype Message_Digest is String (1 .. 2 * Hash_Length); + subtype Message_Digest is String (1 .. 2 * Integer (Hash_Length)); -- The fixed-length string returned by Digest, providing the hash in -- hexadecimal representation. @@ -199,11 +198,12 @@ package GNAT.Secure_Hashes is private - Block_Length : constant Natural := Block_Words * Word_Length; + Block_Length : constant Stream_Element_Count := + Block_Words * Word_Length; -- Length in bytes of a data block subtype Key_Length is - Stream_Element_Offset range 0 .. Stream_Element_Offset (Block_Length); + Stream_Element_Offset range 0 .. Block_Length; -- KL is 0 for a normal hash context, > 0 for HMAC diff --git a/gcc/ada/libgnat/g-shshco.adb b/gcc/ada/libgnat/g-shshco.adb index f4a90f19178..89e27f087df 100644 --- a/gcc/ada/libgnat/g-shshco.adb +++ b/gcc/ada/libgnat/g-shshco.adb @@ -108,7 +108,8 @@ package body GNAT.Secure_Hashes.SHA2_Common is -- 3. Perform transformation rounds for T in 0 .. Rounds - 1 loop - T1 := H + Sigma1 (E) + Ch (E, F, G) + K (T) + W (T); + T1 := H + Sigma1 (E) + Ch (E, F, G) + + K (Stream_Element_Offset (T)) + W (T); T2 := Sigma0 (A) + Maj (A, B, C); H := G; G := F;