diff -uNr a/vtools/ksum.gpr b/vtools/ksum.gpr --- a/vtools/ksum.gpr 134fd11107c54b29987b07535a29ace30b0ab066c929988a973c15acfb7340a02dd812f21e5ce104482c432590029f58efd78c58e50e9fa561c4e788d973ea0b +++ b/vtools/ksum.gpr 6c2b5269b86205c1e1c5bc13ac432631747a551b2a4110249e2541aca4745f6e10c361771987a0ab936bfd9be35fa70240b4e006f0ef1e9549933c66f508fac8 @@ -4,4 +4,26 @@ for Object_Dir use "obj"; for Exec_Dir use "."; for Main use ("ksum.adb"); + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "release"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-O2", "-ggdb3"); + when "release" => + for Switches ("Ada") + use ("-O2"); + end case; + end Compiler; + + package Binder is + for Switches ("Ada") use ("-static"); + end Binder; + + package Linker is + for Switches ("Ada") use ("-static"); + end Linker; end Ksum; diff -uNr a/vtools/manifest b/vtools/manifest --- a/vtools/manifest e3f059374c1d6e57a7897b0e834261ee3db264d486cbb8efecb18d3acb22b0bf9cf40014d742454e54a6ac398378106e2ae6b5605db053637427843ed9baa94e +++ b/vtools/manifest ae142381984d8c6c3b1834e0b9ddc18662ee8c7b5e159ff531f375646d942891e8dbd0911258d1d85804d2aa187e7b510a3a3a938f6c664418d69261e7fd16e5 @@ -19,3 +19,4 @@ 620790 bvt vtools_ascii_visualization Add "vtree" command, work towards pipeable output. 621251 bvt vtools_vsh_ascii_fix2 vflow: remove early exit, DFS-based toposorting; v.sh: correct error checking and reporting in v.sh, fix vtree indentation, better error reporting in case of conflicts; makefile: remove. 621530 bvt vtools_vsh_orphans Handle vpatches without antecedents without crashing. +622175 bvt vtools_update_keccak Use latest SMG_Keccak version (2x speed improvement). diff -uNr a/vtools/src/bits.adb b/vtools/src/bits.adb --- a/vtools/src/bits.adb b400c9418d40715d1063d700657c8cee23e4b6de0d237a23bcbb5293944543de71c1dd0fb0e9984f6dda83b57930906c4c7479a35e88f9d32bd284b5c796dec3 +++ b/vtools/src/bits.adb 217be6a3c9081212fcb3e41e50392b991cb39d1dba4aa5fd20a470b3859e145f48ff40e805d0781372b5c3f63af287f780569490418b2fcd97ce1a76ab1890f6 @@ -1,55 +1,37 @@ with Interfaces; use Interfaces; package body Bits is -- helper functions - procedure ToBitstream(S: in String; B: out Bitstream ) is + procedure ToBytestream(S: in String; B: out Bytestream ) is V : Unsigned_8; Pos : Natural; begin Pos := B'First; for C of S loop V := Character'Pos( C ); - B( Pos ) := Bit( V and 1 ); - B( Pos + 1 ) := Bit( Shift_Right( V, 1 ) and 1 ); - B( Pos + 2 ) := Bit( Shift_Right( V, 2 ) and 1 ); - B( Pos + 3 ) := Bit( Shift_Right( V, 3 ) and 1 ); - B( Pos + 4 ) := Bit( Shift_Right( V, 4 ) and 1 ); - B( Pos + 5 ) := Bit( Shift_Right( V, 5 ) and 1 ); - B( Pos + 6 ) := Bit( Shift_Right( V, 6 ) and 1 ); - B( Pos + 7 ) := Bit( Shift_Right( V, 7 ) and 1 ); - Pos := Pos + 8; + B( Pos ) := V; + Pos := Pos + 1; end loop; - end ToBitstream; + end ToBytestream; - procedure ToString(B: in Bitstream; S: out String ) is + procedure ToString(B: in Bytestream; S: out String ) is N : Natural; Pos : Natural; begin Pos := B'First; for I in S'Range loop - N := Natural( B( Pos ) ) + - Natural( B( Pos + 1 ) ) * 2 + - Natural( B( Pos + 2 ) ) * 4 + - Natural( B( Pos + 3 ) ) * 8 + - Natural( B( Pos + 4 ) ) * 16 + - Natural( B( Pos + 5 ) ) * 32 + - Natural( B( Pos + 6 ) ) * 64 + - Natural( B( Pos + 7 ) ) * 128; - Pos := Pos + 8; + N := Natural( B( Pos ) ); + Pos := Pos + 1; S( I ) := Character'Val( N ); end loop; end ToString; -- direction translation of C function from vdiff - procedure ToHex(B: in Bitstream; S: out String) is - Bytes: String(1..B'Length/8); + procedure ToHex(B: in Bytestream; S: out String) is Hex_Digits: constant String := "0123456789abcdef"; I: Positive := 1; - V: Unsigned_8; X: Positive := 1; begin - ToString(B, Bytes); - for C of Bytes loop - V := Character'Pos(C); + for V of B loop S(I) := Hex_Digits(Integer(Shift_Right(V, 4) + 1)); I := I + 1; S(I) := Hex_Digits(Integer((V and 16#F#) + 1)); @@ -57,8 +39,8 @@ end loop; end; - function ToHex(B: in Bitstream) return String is - S: String(1..B'Length/4); + function ToHex(B: in Bytestream) return String is + S: String(1..B'Length*2); begin ToHex(B, S); return S; diff -uNr a/vtools/src/bits.ads b/vtools/src/bits.ads --- a/vtools/src/bits.ads 8ad58fb0739dc94201e75308b93d1741700e42527532fe5efd38acd819d5047d38462e9fe7fb10263817317420c285ddb6a411be6ebb29c94111a2c5782abe24 +++ b/vtools/src/bits.ads fae766caf1a37276efa5e29815cccf2bc6cc6e1681a190dd92dd613614b0a35c9bb72ae3920a36132f39e0636ed1827d05ffa0e59d582c2e30e6b182e4d3575e @@ -1,11 +1,10 @@ +with SMG_Keccak; use SMG_Keccak; + package Bits is pragma Pure(Bits); - type Bit is mod 2; - type Bitstream is array( Natural range <> ) of Bit; -- any length; message - - procedure ToBitstream(S: in String; B: out Bitstream); - procedure ToString(B: in Bitstream; S: out String); - procedure ToHex(B: in Bitstream; S: out String); - function ToHex(B: in Bitstream) return String; + procedure ToBytestream(S: in String; B: out Bytestream); + procedure ToString(B: in Bytestream; S: out String); + procedure ToHex(B: in Bytestream; S: out String); + function ToHex(B: in Bytestream) return String; end Bits; diff -uNr a/vtools/src/keccak_c.adb b/vtools/src/keccak_c.adb --- a/vtools/src/keccak_c.adb 130484edcb794a78db04eeb6293a21ef5ea70ac04c55a7641e67fac4879935fb1a51624081d583ae47bc30948610eaa6a3d6639ce53d0be53d7f315406d22e9a +++ b/vtools/src/keccak_c.adb d2cf3b039cc59a6151fc93a40e9fd9183caeb3deb0137c8406823f5783dc4665a327fe3661f6446b887a72f7cc2df9715746e18935956931be7ee99f533717f1 @@ -19,12 +19,11 @@ Input: Char_Star; Len: Interfaces.C.size_t) is Buffer_Size: constant Natural := 2048; - Byte_Size: constant Natural := 8; N: Natural := 0; I: Natural := 0; L: Natural := Natural(Len); Buf: String(1..Buffer_Size); - B: Bitstream(1..Buf'Length*Byte_Size); + B: Bytestream(1..Buf'Length); Ptr: Char_Star := Input; begin if Input = null then @@ -39,8 +38,8 @@ N := N + 1; I := I + 1; end loop; - ToBitstream(Buf(1..N), B(1..N*Byte_Size)); - KeccakHash(Ctx.all, B(1..N*Byte_Size)); + ToBytestream(Buf(1..N), B(1..N)); + KeccakHash(Ctx.all, B(1..N)); end loop; end C_Hash; @@ -49,7 +48,7 @@ Len: Interfaces.C.Size_T) is L: Natural := Natural(Len); S: String(1..L); - B: Bitstream(1..S'Length*8); + B: Bytestream(1..S'Length); Ptr: Char_Star := Output; begin if Output = null then diff -uNr a/vtools/src/keccak_c.ads b/vtools/src/keccak_c.ads --- a/vtools/src/keccak_c.ads 90e5e7dd39779fb38469b32ef8d6206a5a2eb190d7cb7ef90fe61922f7572f640ecd062e85688a3a99f22b0842cb690fd705adc15a3b67df31ba397a3f017a9e +++ b/vtools/src/keccak_c.ads 7ead881dd3744e3e83086b6e56f9e665ad9eb16ee9205fefffde9d327c63446b3dd25b168c95c1579cac34188a092067fe639a226555dcde03814418151d12d5 @@ -11,7 +11,7 @@ Default_Terminator => nul); use type Char_Ptrs.Pointer; subtype Char_Star is Char_Ptrs.Pointer; - subtype C_Context is Keccak_Context(Block_Len=>Default_Bitrate); + subtype C_Context is Keccak_Context(Block_Len=>Default_Byterate); type C_Context_Access is access C_Context; procedure C_Get_Size(Size: out Interfaces.C.size_t); pragma Export (C, C_Get_Size, "keccak_get_ctx_byte_size"); diff -uNr a/vtools/src/ksum.adb b/vtools/src/ksum.adb --- a/vtools/src/ksum.adb 8e8a8226998e5b74501e6ff7fb05c7ebb289a737b72d6fe90cc27d61adf25fcf52333cee743dac032353f5bec17d68b7e87891a74e4bfd5d482879a191e5489a +++ b/vtools/src/ksum.adb aaef35f7feb278f016ba4c8d327d4ef11dc493a67766e2bccfc07bad49208cfeb1f0c6a7c756c988536c4d299576705e59b7a04fad3e1b4cac80c5383916a9bc @@ -11,13 +11,12 @@ procedure Ksum is Buffer_Size: constant Natural := 2048; Hash_Size: constant Natural := 64; - Byte_Size: constant Natural := 8; package CIO renames Character_IO.Character_IO; File: CIO.File_Type; - Ctx: Keccak_Context(Block_Len=>Default_Bitrate); + Ctx: Keccak_Context(Block_Len=>Default_Byterate); Buf: String(1..Buffer_Size); - B: Bitstream(1..Buf'Length*Byte_Size); + B: Bytestream(1..Buf'Length) := (others => 0); function Read_Buffer return Integer is C: Character; @@ -31,7 +30,7 @@ end loop; return Buf'Length; end Read_Buffer; - + begin for Arg in 1..Argument_Count loop declare @@ -39,7 +38,7 @@ begin Character_IO.Open(File, CIO.In_File, Filename); declare - O: Bitstream(1..Hash_Size*Byte_Size); + O: Bytestream(1..Hash_Size); N: Integer; begin KeccakBegin(Ctx); @@ -47,8 +46,8 @@ loop exit Read_Loop when End_Of_File(File); N := Read_Buffer; - ToBitstream(Buf(1..N), B(1..N*Byte_Size)); - KeccakHash(Ctx, B(1..N*Byte_Size)); + ToBytestream(Buf(1..N), B(1..N)); + KeccakHash(Ctx, B(1..N)); end loop Read_Loop; KeccakEnd(Ctx, O); declare diff -uNr a/vtools/src/smg_keccak.adb b/vtools/src/smg_keccak.adb --- a/vtools/src/smg_keccak.adb b45b24d4e1024ed3c006f3b1754cea63cb7dd34ba653e3ad017bb54800d4b43c5283e7fba95c434d8f7fe470118c2137da999d55a6335bd80be7491ad7fdca92 +++ b/vtools/src/smg_keccak.adb f58cd15cda85003c734b80fbbdfbb22768abf75cc2bc859660d6cd0da1922180634629cfb32d91a365aedd86ffb71cd38e5647519e8f29b283137155dc299bdc @@ -1,30 +1,32 @@ -- S.MG, 2018 with System; use System; -- for Bit_Order +with Interfaces; use Interfaces; package body SMG_Keccak is -- public function, sponge - procedure Sponge( Input : in Bitstream; - Output : out Bitstream; - Block_Len : in Keccak_Rate := Default_Bitrate ) is + procedure Sponge( Input : in Bytestream; + Output : out Bytestream; + Block_Len : in Keccak_Rate := Default_Byterate ) is Internal : State := (others => (others => 0)); begin --absorb input into sponge in a loop on available blocks, including padding declare - -- number of input blocks after padding (between 2 and block_len bits pad) - Padded_Blocks : constant Positive := 1 + (Input'Length + 1) / Block_Len; - Padded : Bitstream ( 1 .. Padded_Blocks * Block_Len ); - Block : Bitstream ( 1 .. Block_Len ); + -- number of input blocks after padding (pad between 1 and block_len) + Padded_Blocks : constant Positive := 1 + Input'Length / Block_Len; + Padded : Bytestream ( 1 .. Padded_Blocks * Block_Len ); + Block : Bytestream ( 1 .. Block_Len ); begin -- initialise Padded with 0 everywhere Padded := ( others => 0 ); -- copy and pad input with rule 10*1 Padded( Padded'First .. Padded'First + Input'Length - 1 ) := Input; + -- padding is 10*1 so start and end with an 1 but LSB order hence 16#80# Padded( Padded'First + Input'Length ) := 1; - Padded( Padded'Last ) := 1; + Padded( Padded'Last ) := Padded( Padded'Last ) + 16#80#; -- loop through padded input and absorb block by block into sponge - -- padded input IS a multiple of blocks, so no stray bits left + -- padded input IS a multiple of blocks, so no stray octets left for B in 0 .. Padded_Blocks - 1 loop -- first get the current block to absorb Block := Padded( Padded'First + B * Block_Len .. @@ -36,13 +38,13 @@ end loop; -- end absorb loop for blocks end; -- end absorb stage - --squeeze required bits from sponge in a loop as needed + --squeeze required octets from sponge in a loop as needed declare -- full blocks per output BPO : constant Natural := Output'Length / Block_Len; - -- stray bits per output + -- stray octets per output SPO : constant Natural := Output'Length mod Block_Len; - Block : Bitstream( 1 .. Block_Len ); + Block : Bytestream( 1 .. Block_Len ); begin -- squeeze block by block (if at least one full block is needed) for I in 0 .. BPO - 1 loop @@ -54,12 +56,12 @@ Internal := Keccak_Function( Internal ); end loop; -- end squeezing full blocks - -- squeeze any partial block needed (stray bits) + -- squeeze any partial block needed (stray octets) if SPO > 0 then SqueezeBlock( Block, Internal ); Output( Output'Last - SPO + 1 .. Output'Last ) := Block( Block'First .. Block'First + SPO - 1 ); - end if; -- end squeezing partial last block (stray bits) + end if; -- end squeezing partial last block (stray octets) end; -- end squeeze stage end Sponge; @@ -73,7 +75,7 @@ end; procedure KeccakHash(Ctx : in out Keccak_Context; - Input : Bitstream) is + Input : Bytestream) is I0 : Natural; I1 : Natural; B0 : Natural; @@ -105,18 +107,18 @@ end; procedure KeccakEnd(Ctx : in out Keccak_Context; - Output : out Bitstream) is - BlocksPerOutput : constant Natural := Output'Length / Ctx.Block_Len; - StrayPerOutput : constant Natural := Output'Length mod Ctx.Block_Len; - Block : Bitstream(1 .. Ctx.Block_Len); - Need : Natural; + Output : out Bytestream) is + BlocksPerOutput : constant Natural := Output'Length / Ctx.Block_Len; + StrayPerOutput : constant Natural := Output'Length mod Ctx.Block_Len; + Block : Bytestream(1 .. Ctx.Block_Len) := (others => 0); begin if Ctx.Pos /= 0 then -- needs padding - Block := (others => 0); - Need := Ctx.Block'Last - Ctx.Pos; - Block(Block'First) := 1; - Block(Block'First+Need) := 1; - KeccakHash(Ctx, Block(1..Need+1)); + Ctx.Block(Ctx.Pos..Ctx.Block'Last) := (others => 0); + Ctx.Block(Ctx.Pos) := 1; + Ctx.Block(Ctx.Block'Last) := Ctx.Block(Ctx.Block'Last) or 16#80#; + AbsorbBlock(Ctx.Block, Ctx.Internal); + Ctx.Internal := Keccak_Function(Ctx.Internal); + Ctx.Pos := 0; end if; -- squeez bits @@ -133,78 +135,81 @@ end if; end; - -- convert from a bitstream of ZWord size to an actual ZWord number - function BitsToWord( BWord: in Bitword ) return ZWord is + -- convert from a bytestream of ZWord/8 size to an actual ZWord number + -- NB: this will FLIP bits on big endian because keccak expects input LSB + -- NOT exact opposite of WordToBytes + function BytesToWordLE( BWord: in Byteword ) return ZWord is W : ZWord; - Bits: Bitword; + B : Byteword; begin -- just copy octets if machine is little endian - -- flip octets if machine is big endian + -- flip octets AND bits if machine is big endian if Default_Bit_Order = Low_Order_First then - Bits := BWord; + B := BWord; else - Bits := FlipOctets( BWord ); + B := FlipOctets( BWord ); + for I in B'First..B'Last loop + B(I) := Reverse_Table(Natural(B(I))); + end loop; end if; - -- actual bits to word conversion - W := 0; - -- LSB bit order (inside octet) as per Keccak spec - for I in reverse Bitword'Range loop - W := Shift_Left( W, 1 ) + ZWord( Bits( I ) ); - end loop; + -- actual bytes to word conversion + W := Cast(B); return W; - end BitsToWord; + end BytesToWordLE; - -- convert from a ZWord (lane of state) to a bitstream of ZWord size - function WordToBits( Word: in ZWord ) return Bitword is - Bits: Bitword := (others => 0); - W: ZWord; - begin - W := Word; - for I in Bitword'Range loop - Bits( I ) := Bit( W mod 2 ); - W := Shift_Right( W, 1 ); - end loop; + -- convert from a ZWord (lane of state) to a bytestream of ZWord size + -- NOT exact oppositve of BytesToWordLE + -- Keccak sponge spits out MSB so bits are flipped on LITTLE Endian iron. + function WordToBytesBE( Word: in ZWord ) return Byteword is + B: Byteword; + begin + B := Cast( Word ); -- flip octets if machine is big endian if Default_Bit_Order = High_Order_First then - Bits := FlipOctets( Bits ); + B := FlipOctets( B ); + else + -- onth flip bits if machine is little endian.... + -- for I in B'First..B'Last loop + -- B(I) := Reverse_Table(Natural(B(I))); + -- end loop; + null; end if; - return Bits; - end WordToBits; + return B; + end WordToBytesBE; -- flip given octets (i.e. groups of 8 bits) - function FlipOctets( BWord : in Bitword ) return Bitword is - Bits : Bitword; + function FlipOctets( BWord : in Byteword ) return Byteword is + B : Byteword; begin - -- copy groups of 8 octets changing their order in the array - -- i.e. 1st octet in BWord becomes last octet in Bits and so on - for I in 0 .. ( Bitword'Length / 8 - 1 ) loop - Bits ( Bits'First + I * 8 .. Bits'First + I * 8 + 7 ) := - BWord( BWord'Last - I * 8 - 7 .. BWord'Last - I * 8); + -- copy octets changing their order in the array + -- i.e. 1st octet in BWord becomes last octet in B and so on + for I in 0 .. BWord'Length-1 loop + B(B'First + I) := BWord(BWord'Last-I); end loop; - return Bits; + return B; end FlipOctets; -- helper procedures for sponge absorb/squeeze -- NO scramble here, this will absorb ALL given block, make sure it fits! - procedure AbsorbBlock( Block: in Bitstream; S: in out State ) is - WPB: constant Natural := Block'Length / Z_Length; -- words per block - SBB: constant Natural := Block'Length mod Z_Length; -- stray bits + procedure AbsorbBlock( Block: in Bytestream; S: in out State ) is + WPB: constant Natural := Block'Length / Byteword'Length; -- words per block + SBB: constant Natural := Block'Length mod Byteword'Length; -- stray octets FromPos, ToPos : Natural; X, Y : XYCoord; Word : ZWord; - BWord : Bitword; + BWord : Byteword; begin - -- xor current block into first Block'Length bits of state + -- xor current block into first Block'Length octets of state -- a block can consist in more than one word X := 0; Y := 0; for I in 0..WPB-1 loop - FromPos := Block'First + I * Z_Length; - ToPos := FromPos + Z_Length - 1; - Word := BitsToWord( Block( FromPos .. ToPos ) ); + FromPos := Block'First + I * Byteword'Length; + ToPos := FromPos + Byteword'Length - 1; + Word := BytesToWordLE( Block( FromPos .. ToPos ) ); S( X, Y ) := S( X, Y ) xor Word; -- move on to next word in state X := X + 1; @@ -212,21 +217,21 @@ Y := Y + 1; end if; end loop; - -- absorb also any remaining bits from block + -- absorb also any remaining bytes from block if SBB > 0 then ToPos := Block'Last; FromPos := ToPos - SBB + 1; BWord := (others => 0); - BWord(Bitword'First .. Bitword'First + SBB - 1) := Block(FromPos..ToPos); - Word := BitsToWord( BWord ); + BWord(Byteword'First .. Byteword'First + SBB - 1) := Block(FromPos..ToPos); + Word := BytesToWordLE( BWord ); S( X, Y ) := S( X, Y ) xor Word; end if; end AbsorbBlock; -- NO scramble here, this will squeeze Block'Length bits out of *same* state S - procedure SqueezeBlock( Block: out Bitstream; S: in State) is + procedure SqueezeBlock( Block: out Bytestream; S: in State) is X, Y : XYCoord; - BWord : Bitword; + BWord : Byteword; FromPos : Natural; Len : Natural; begin @@ -235,7 +240,7 @@ FromPos := Block'First; while FromPos <= Block'Last loop - BWord := WordToBits( S(X, Y) ); + BWord := WordToBytesBE( S(X, Y) ); X := X + 1; if X = 0 then @@ -243,10 +248,10 @@ end if; -- copy full word if it fits or - -- only as many bits as are still needed to fill the block + -- only as many bytes as are still needed to fill the block Len := Block'Last - FromPos + 1; - if Len > Z_Length then - Len := Z_Length; + if Len > BWord'Length then + Len := BWord'Length; end if; Block(FromPos..FromPos+Len-1) := BWord(BWord'First..BWord'First+Len-1); diff -uNr a/vtools/src/smg_keccak.ads b/vtools/src/smg_keccak.ads --- a/vtools/src/smg_keccak.ads 116e16b2714ef88045a3cbea42e604a1fdf8b0f55fc1017af960105c046c97ef84edc4d74c919652029d0ea61bd1049f4ff445873ca9f0a73549ddd3146a3faa +++ b/vtools/src/smg_keccak.ads ee688a71a3cb22658b65de936dd33230ca185fb2d7c0311333b09433a94591180609f25642d54bae79b354665d3b3e47d1db2d502864213bcc523d8305e9d2e4 @@ -3,18 +3,23 @@ -- (Based on The Keccak Reference, Version 3.0, January 14, 2011, by -- Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche) + -- NB: this is a byte-level (octet) implementation! + -- Input/output are always multiple of octets, NOT bits. + -- S.MG, 2018 +with Ada.Unchecked_Conversion; --for byteword to zword +with Interfaces.C; +with Interfaces; -with Bits; use Bits; package SMG_Keccak is - pragma Pure(SMG_Keccak); --stateless, no side effects -> can cache calls + pragma Pure(SMG_Keccak); --stateless, no side effects -> can cache calls --knobs (can change as per keccak design but fixed here for S.MG purposes)-- Keccak_L: constant := 6; --gives keccak z (word) dimension of 2^6=64 and --therefore keccak function 1600 with current --constants (5*5*2^6) - Default_Bitrate: constant := 1344; --max bits the sponge can eat/spit without + Default_Byterate: constant := 168;--max octets the sponge can eat/spit without --needing to scramble the state --constants: dimensions of keccak state and number of rounds @@ -34,59 +39,99 @@ type Round_Constants is array(Round_Index) of ZWord; --magic keccak constants - -- rate can be chosen by caller at each call, between 1 and width of state - -- higher rate means sponge "eats" more bits at a time but has fewer bits in - -- the "secret" part of the state (i.e. lower capacity) - subtype Keccak_Rate is Positive range 1..Width; -- capacity = width - rate - - subtype Bitword is Bitstream( 0..Z_Length - 1 ); -- bits of one state "word" + -- rate can be chosen by caller at each call, between 1 and width of state /8 + -- higher rate means sponge "eats" more octets at a time but has fewer octets + -- in the "secret" part of the state (i.e. lower capacity) + subtype Keccak_Rate is Positive range 1..Width/8; -- capacity = width - rate + + type Bytestream is array( Natural range <> ) of Interfaces.Unsigned_8; + subtype Byteword is Bytestream( 0..Z_Length/8-1); --octets of one state "word" + function Cast is new Ada.Unchecked_Conversion (Byteword, ZWord); + function Cast is new Ada.Unchecked_Conversion (ZWord, Byteword); -- type conversions - function BitsToWord( BWord : in Bitword ) return ZWord; - function WordToBits( Word : in ZWord ) return Bitword; + -- NB: those are NOT perfect opposites! + -- BytesToWord assumes input is raw and in LSB order, will flip on MSB iron + -- WordToBytes assumes input is MSB and will flip on LSB + -- This is because the Sponge squeezes MSB but absorbs LSB... + function BytesToWordLE( BWord : in Byteword ) return ZWord; + function WordToBytesBE( Word : in ZWord ) return Byteword; -- flip input octets (i.e. groups of 8 bits) - function FlipOctets( BWord : in Bitword ) return Bitword; + function FlipOctets( BWord : in Byteword ) return Byteword; -- public function, the sponge itself - -- Keccak sponge structure using Keccak_Function, Pad and a given bitrate; + -- Keccak sponge structure using Keccak_Function, Pad and a given octetrate; -- Input - the stream of bits to hash (the message) - -- Output - a bitstream of desired size for holding output - -- Block_Len - the bitrate to use; this is effectively the block length + -- Output - a bytestream of desired size for holding output + -- Block_Len - the octetrate to use; this is effectively the block length -- for splitting Input AND squeezing output between scrambles - procedure Sponge(Input : in Bitstream; - Output : out Bitstream; - Block_Len : in Keccak_Rate := Default_Bitrate ); + procedure Sponge(Input : in Bytestream; + Output : out Bytestream; + Block_Len : in Keccak_Rate := Default_Byterate ); + + Reverse_Table : constant array(0..255) of Interfaces.Unsigned_8 := ( + 16#00#, 16#80#, 16#40#, 16#C0#, 16#20#, 16#A0#, 16#60#, 16#E0#, + 16#10#, 16#90#, 16#50#, 16#D0#, 16#30#, 16#B0#, 16#70#, 16#F0#, + 16#08#, 16#88#, 16#48#, 16#C8#, 16#28#, 16#A8#, 16#68#, 16#E8#, + 16#18#, 16#98#, 16#58#, 16#D8#, 16#38#, 16#B8#, 16#78#, 16#F8#, + 16#04#, 16#84#, 16#44#, 16#C4#, 16#24#, 16#A4#, 16#64#, 16#E4#, + 16#14#, 16#94#, 16#54#, 16#D4#, 16#34#, 16#B4#, 16#74#, 16#F4#, + 16#0C#, 16#8C#, 16#4C#, 16#CC#, 16#2C#, 16#AC#, 16#6C#, 16#EC#, + 16#1C#, 16#9C#, 16#5C#, 16#DC#, 16#3C#, 16#BC#, 16#7C#, 16#FC#, + 16#02#, 16#82#, 16#42#, 16#C2#, 16#22#, 16#A2#, 16#62#, 16#E2#, + 16#12#, 16#92#, 16#52#, 16#D2#, 16#32#, 16#B2#, 16#72#, 16#F2#, + 16#0A#, 16#8A#, 16#4A#, 16#CA#, 16#2A#, 16#AA#, 16#6A#, 16#EA#, + 16#1A#, 16#9A#, 16#5A#, 16#DA#, 16#3A#, 16#BA#, 16#7A#, 16#FA#, + 16#06#, 16#86#, 16#46#, 16#C6#, 16#26#, 16#A6#, 16#66#, 16#E6#, + 16#16#, 16#96#, 16#56#, 16#D6#, 16#36#, 16#B6#, 16#76#, 16#F6#, + 16#0E#, 16#8E#, 16#4E#, 16#CE#, 16#2E#, 16#AE#, 16#6E#, 16#EE#, + 16#1E#, 16#9E#, 16#5E#, 16#DE#, 16#3E#, 16#BE#, 16#7E#, 16#FE#, + 16#01#, 16#81#, 16#41#, 16#C1#, 16#21#, 16#A1#, 16#61#, 16#E1#, + 16#11#, 16#91#, 16#51#, 16#D1#, 16#31#, 16#B1#, 16#71#, 16#F1#, + 16#09#, 16#89#, 16#49#, 16#C9#, 16#29#, 16#A9#, 16#69#, 16#E9#, + 16#19#, 16#99#, 16#59#, 16#D9#, 16#39#, 16#B9#, 16#79#, 16#F9#, + 16#05#, 16#85#, 16#45#, 16#C5#, 16#25#, 16#A5#, 16#65#, 16#E5#, + 16#15#, 16#95#, 16#55#, 16#D5#, 16#35#, 16#B5#, 16#75#, 16#F5#, + 16#0D#, 16#8D#, 16#4D#, 16#CD#, 16#2D#, 16#AD#, 16#6D#, 16#ED#, + 16#1D#, 16#9D#, 16#5D#, 16#DD#, 16#3D#, 16#BD#, 16#7D#, 16#FD#, + 16#03#, 16#83#, 16#43#, 16#C3#, 16#23#, 16#A3#, 16#63#, 16#E3#, + 16#13#, 16#93#, 16#53#, 16#D3#, 16#33#, 16#B3#, 16#73#, 16#F3#, + 16#0B#, 16#8B#, 16#4B#, 16#CB#, 16#2B#, 16#AB#, 16#6B#, 16#EB#, + 16#1B#, 16#9B#, 16#5B#, 16#DB#, 16#3B#, 16#BB#, 16#7B#, 16#FB#, + 16#07#, 16#87#, 16#47#, 16#C7#, 16#27#, 16#A7#, 16#67#, 16#E7#, + 16#17#, 16#97#, 16#57#, 16#D7#, 16#37#, 16#B7#, 16#77#, 16#F7#, + 16#0F#, 16#8F#, 16#4F#, 16#CF#, 16#2F#, 16#AF#, 16#6F#, 16#EF#, + 16#1F#, 16#9F#, 16#5F#, 16#DF#, 16#3F#, 16#BF#, 16#7F#, 16#FF#); -- state based Sponge - type Keccak_Context (Block_Len: Keccak_Rate := Default_Bitrate) is + type Keccak_Context (Block_Len: Keccak_Rate := Default_Byterate) is record Internal: State := (others => (others => 0)); - Block: Bitstream(1..Block_Len) := (others => 0); + Block: Bytestream(1..Block_Len) := (others => 0); Pos: Natural; end record; procedure KeccakBegin(Ctx: in out Keccak_Context); procedure KeccakHash(Ctx: in out Keccak_Context; - Input: Bitstream); + Input: Bytestream); procedure KeccakEnd(Ctx: in out Keccak_Context; - Output: out Bitstream); - + Output: out Bytestream); private -- these are internals of the keccak implementation, not meant to be directly -- accessed/used - -- this will squeeze Block'Length bits out of state S + -- this will squeeze Block'Length octets out of state S -- NO scramble of state in here! - -- NB: make SURE that Block'Length is the correct bitrate for this sponge - -- in particular, Block'Length should be a correct bitrate aka LESS than Width - procedure SqueezeBlock( Block: out Bitstream; S: in State); + -- NB: make SURE that Block'Length is the correct octetrate for this sponge + -- esp: Block'Length should be a correct octetrate aka LESS than Width/8 + procedure SqueezeBlock( Block: out Bytestream; S: in State); -- This absorbs into sponge the given block, modifying the state accordingly -- NO scramble of state in here so make sure the whole Block fits in state! - -- NB: make SURE that Block'Length is *the correct bitrate* for this sponge - -- in particular, Block'Length should be a correct bitrate aka LESS than Width - procedure AbsorbBlock( Block: in Bitstream; S: in out State ); + -- NB: make SURE that Block'Length is *the correct byterate* for this sponge + -- esp: Block'Length should be a correct byterate aka LESS than Width + procedure AbsorbBlock( Block: in Bytestream; S: in out State ); --Keccak magic numbers RC : constant Round_Constants := diff -uNr a/vtools/src/temporary_file.adb b/vtools/src/temporary_file.adb --- a/vtools/src/temporary_file.adb 4747969b6df8aa268419f3259a757d1fee33b8b4a7d440b8adfe07c7f6335060b533791908ff1f5022ecfb51708277a59b0876812c4343e17df1f3f0de0ea767 +++ b/vtools/src/temporary_file.adb aa1b5b276c8d7e2025edaebd375bd3a1d67c762fe3132630855e28ba24b0d8dae44d8bae5969eda386e2647ab53311a9abf989038bfde5ec2a1501b8205c2eec @@ -36,18 +36,18 @@ -- if the file with random component F exists, retry with -- H(F) as a new random component. Function Temporary_File(Path_Prefix: String; - Seed: Bitstream) return String is - Hash: Bitstream(1..64*8); + Seed: Bytestream) return String is + Hash: Bytestream(1..64); Name_Ctx: Keccak_Context; - procedure Hash_Bitstream(Input: Bitstream) is + procedure Hash_Bytestream(Input: Bytestream) is begin KeccakBegin(Name_Ctx); KeccakHash(Name_Ctx, Input); KeccakEnd(Name_Ctx, Hash); - end Hash_Bitstream; + end Hash_Bytestream; begin - Hash_Bitstream(Seed); + Hash_Bytestream(Seed); loop declare File_Name: String := Path_Prefix & ToHex(Hash); @@ -56,15 +56,15 @@ return File_Name; end if; end; - Hash_Bitstream(Hash); + Hash_Bytestream(Hash); end loop; end Temporary_File; function Temporary_File(Path_Prefix: String; Seed: String) return String is - B: Bitstream(1..Seed'Length*8); + B: Bytestream(1..Seed'Length); begin - ToBitstream(Seed, B); + ToBytestream(Seed, B); return Temporary_File(Path_Prefix, B); end Temporary_File; diff -uNr a/vtools/src/vpatch_utils.adb b/vtools/src/vpatch_utils.adb --- a/vtools/src/vpatch_utils.adb 95e0f4bd9b0399b9d2ff524a0400edab21e366c05e248dfdceaef65030a93df01b2ea510aad2d29c7811de00cd002df0f6566e1dccb4c8e720a0aebbec2acc1f +++ b/vtools/src/vpatch_utils.adb 88b4aca5c46b27a789f613dca1025f01eed23e56c10c1f440e902d4c30cc2758f2042ef13f5a2feaf8dad26bc479e23929e24d4d114db852c2303dd709bb0b64 @@ -296,8 +296,8 @@ Line: Positive := 1; In_Ctx: Keccak_Context; To_Ctx: Keccak_Context; - In_Hash: Bitstream(1..64*8); - To_Hash: Bitstream(1..64*8); + In_Hash: Bytestream(1..64); + To_Hash: Bytestream(1..64); To_F_Name: constant String := Press_Name(A_Header); Op: Patch_Op; Newline_Directive: constant String := "\ No newline at end of file"; @@ -305,10 +305,10 @@ procedure Hash_Line(Ctx: in out Keccak_Context; S: String; New_Line: Boolean := True) is - B: Bitstream(1..S'Length*8); - LF_B: constant Bitstream(1..8) := (0, 1, 0, 1, 0, 0, 0, 0); + B: Bytestream(1..S'Length); + LF_B: constant Bytestream(1..1) := (1 => 10); begin - ToBitstream(S, B); + ToBytestream(S, B); KeccakHash(Ctx, B); if New_Line then KeccakHash(Ctx, LF_B); diff -uNr a/vtools/vdiff.gpr b/vtools/vdiff.gpr --- a/vtools/vdiff.gpr 9213651f0823c96399660f3b7f2e3ba5026a74176e7e83f8ac6e0cbbf13f141a72e4b91c581d8cdda3015c69486469b114d830c12530768286aed84a63ad971c +++ b/vtools/vdiff.gpr 83bc161ba8667a9d84bf5eca1f4f22178ffa6ca025531b912bcbddf1d4bad8617ce438cd455260298f5f91ab1df6e40f254a631f4c7757e3a5606913f197398f @@ -10,4 +10,32 @@ package Builder is for Executable ("diff.c") use "vdiff"; end Builder; + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "release"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-O2", "-ggdb3"); + for Switches ("C") + use ("-O2", "-ggdb3"); + when "release" => + for Switches ("Ada") + use ("-O2"); + for Switches ("C") + use ("-O2"); + end case; + end Compiler; + + package Binder is + for Switches ("Ada") use ("-static"); + for Switches ("C") use ("-static"); + end Binder; + + package Linker is + for Switches ("Ada") use ("-static"); + for Switches ("C") use ("-static"); + end Linker; end Vdiff; diff -uNr a/vtools/vfilter.gpr b/vtools/vfilter.gpr --- a/vtools/vfilter.gpr efaf66fea0cf128535f35fac412a915d042b2481576185b73d1ccdc05f9af8d1658fcb5694d25a9abf6fe26df49db9dc8b60bf05c2025964bdb8dc2b2fd17ca6 +++ b/vtools/vfilter.gpr 52c3e37c3cf63c7882a1b0df631f93e0a4a21867b3fac2ceab758ed610330b16e878acf7a1a11d7e750750343870f343f18a9e7141c29107c1c579f3d8651a49 @@ -4,4 +4,26 @@ for Object_Dir use "obj"; for Exec_Dir use "."; for Main use ("vfilter.adb"); + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "release"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-O2", "-ggdb3"); + when "release" => + for Switches ("Ada") + use ("-O2"); + end case; + end Compiler; + + package Binder is + for Switches ("Ada") use ("-static"); + end Binder; + + package Linker is + for Switches ("Ada") use ("-static"); + end Linker; end Vfilter; diff -uNr a/vtools/vflow.gpr b/vtools/vflow.gpr --- a/vtools/vflow.gpr f9f7ce7f9def005d0a8872621043b8ed64ebd41344b966e370cbdf8ec4a1feaa881ae89b81db5b4322b650f9aef115ff111338701dabc91c8bfa8cb832ff0b44 +++ b/vtools/vflow.gpr 8f133b73beb7d8bb7e9fad17effd31a3631fb1ccbbe49045e6e7fe09efe844a378fa4c65ec0eb74520a9a937d405cdb2656d689380378301286588e3d8581e10 @@ -6,16 +6,24 @@ for Main use ("vflow.adb"); type Mode_Type is ("debug", "release"); - Mode : Mode_Type := external ("mode", "debug"); + Mode : Mode_Type := external ("mode", "release"); package Compiler is case Mode is when "debug" => for Switches ("Ada") - use ("-O0", "-ggdb3"); + use ("-O2", "-ggdb3"); when "release" => for Switches ("Ada") use ("-O2"); end case; end Compiler; + + package Binder is + for Switches ("Ada") use ("-static"); + end Binder; + + package Linker is + for Switches ("Ada") use ("-static"); + end Linker; end Vflow; diff -uNr a/vtools/vpatch.gpr b/vtools/vpatch.gpr --- a/vtools/vpatch.gpr f882850d136201ac5874c309fba57ba908028b86de996919766631e22ab62fe9e1c22405ec8145aed9f6fed762f9a97185b2bd8c1ecd96f7499f3575dc4973c0 +++ b/vtools/vpatch.gpr adb4dfa4f23ad1d33d5f3b3eece417628f8d69f240308fcdb7e887d3c6294d6f77fc466ba5bc1875ca1cfa4e0f6f508f81f05e723001321037bcc736ab3bc1ef @@ -4,4 +4,26 @@ for Object_Dir use "obj"; for Exec_Dir use "."; for Main use ("vpatch.adb"); + + type Mode_Type is ("debug", "release"); + Mode : Mode_Type := external ("mode", "release"); + + package Compiler is + case Mode is + when "debug" => + for Switches ("Ada") + use ("-O2", "-ggdb3"); + when "release" => + for Switches ("Ada") + use ("-O2"); + end case; + end Compiler; + + package Binder is + for Switches ("Ada") use ("-static"); + end Binder; + + package Linker is + for Switches ("Ada") use ("-static"); + end Linker; end Vpatch;