123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139 |
- MODULE CryptoKeccakSponge; (** OUTHOR "GF"; PURPOSE "Keccak, sponge mode"; *)
- (*
- The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
- Michaël Peeters and Gilles Van Assche. For more information, feedback or
- questions, please refer to our website: http://keccak.noekeon.org/
- *)
- IMPORT Keccak := CryptoKeccakF1600;
- CONST
- LaneSize = Keccak.LaneSize;
- Width* = Keccak.Width;
- DefaultRate* = 1024;
- DefaultCapacity* = 576;
- TYPE
- Instance* = OBJECT
- VAR
- state: Keccak.Instance; (* The state processed by the permutation. *)
- chunk: LONGINT; (* The value of the rate in bytes *)
- index: LONGINT; (* The position in the state of the next byte to be
- input (when absorbing) or output (when squeezing). *)
- squeezing: BOOLEAN ; (* false: in the absorbing phase; otherwise, in the squeezing phase. *)
- cmodl: LONGINT; (* chunk MOD LaneSize *)
- cdivl: LONGINT; (* chunk DIV LaneSize *)
- PROCEDURE &Init*;
- BEGIN
- NEW( state );
- Initialize( DefaultRate, DefaultCapacity )
- END Init;
- PROCEDURE Initialize*( rate, capacity: LONGINT );
- BEGIN
- ASSERT( rate + capacity = Width );
- ASSERT( (rate > 0) & (rate <= Width) & (rate MOD 8 = 0) );
- state.Initialize;
- chunk := rate DIV 8;
- index := 0;
- cmodl := chunk MOD LaneSize;
- cdivl := chunk DIV LaneSize;
- squeezing := FALSE
- END Initialize;
- PROCEDURE Absorb*( CONST data: ARRAY OF CHAR; offset, len: LONGINT );
- VAR
- piece, lanes, laneNo, laneOffset, bytes: LONGINT;
- BEGIN
- ASSERT( squeezing = FALSE );
- WHILE len > 0 DO
- IF (index = 0) & ( len >= chunk) THEN
- (* fast lane: processing whole blocks first *)
- state.XORLanes( data, offset, cdivl );
- IF cmodl # 0 THEN state.XORBytesInLane( cdivl, 0, cmodl, data, offset ) END;
- state.Permute;
- INC( offset, chunk ); DEC( len, chunk );
- ELSE
- (* normal lane: using the message queue*)
- piece := len;
- IF index + piece > chunk THEN piece := chunk - index END;
- IF (index = 0) & (piece >= LaneSize) THEN
- lanes := piece DIV LaneSize; bytes := lanes*LaneSize;
- state.XORLanes( data, offset, lanes );
- INC( offset, bytes ); DEC( len, bytes ); DEC( piece, bytes );
- INC( index, bytes );
- END;
- WHILE piece > 0 DO
- laneNo := index DIV LaneSize;
- laneOffset := index MOD LaneSize;
- bytes := LaneSize - laneOffset;
- IF bytes > piece THEN bytes := piece END;
- state.XORBytesInLane( laneNo, laneOffset, bytes, data, offset );
- INC( offset, bytes ); DEC( len, bytes ); DEC( piece, bytes );
- INC( index, bytes )
- END;
- IF index = chunk THEN state.Permute; index := 0 END
- END
- END
- END Absorb;
- PROCEDURE Squeeze*( VAR data: ARRAY OF CHAR; offset, len: LONGINT );
- VAR piece, lanes, laneNo, laneOffset, bytes: LONGINT;
- BEGIN
- IF ~squeezing THEN AbsorbLastFewBits( 01X ) END;
- WHILE len > 0 DO
- IF (index = chunk) & (len >= chunk) THEN
- (* fast lane: processing whole blocks first*)
- state.Permute;
- state.ExtractLanes( data, offset, cdivl );
- IF cmodl # 0 THEN state.ExtractBytesInLane( cdivl, 0, cmodl, data, offset + cdivl*LaneSize ) END;
- INC( offset, chunk ); DEC( len, chunk )
- ELSE
- (* normal lane: using the message queue *)
- IF index = chunk THEN state.Permute; index := 0 END;
- piece := len;
- IF index + piece > chunk THEN piece := chunk - index END;
- IF (index = 0) & (piece >= LaneSize) THEN
- lanes := piece DIV LaneSize; bytes := lanes*LaneSize;
- state.ExtractLanes( data, offset, lanes );
- DEC( len, bytes ); INC( offset, bytes );
- INC( index, bytes ); DEC( piece, bytes )
- END;
- WHILE piece > 0 DO
- laneNo := index DIV LaneSize;
- laneOffset := index MOD LaneSize;
- bytes := LaneSize - laneOffset;
- IF bytes > piece THEN bytes := piece END;
- state.ExtractBytesInLane( laneNo, laneOffset, bytes, data, offset );
- DEC( len, bytes ); INC( offset, bytes );
- INC( index, bytes ); DEC( piece, bytes )
- END
- END
- END;
- END Squeeze;
- PROCEDURE AbsorbLastFewBits*( data: CHAR );
- VAR tmp: ARRAY 4 OF CHAR;
- BEGIN
- ASSERT( (data # 0X) & (squeezing = FALSE) );
- tmp[0] := data;
- state.XORBytesInLane( index DIV LaneSize, index MOD LaneSize, 1, tmp, 0 );
- IF (data >= 80X) & (index = chunk - 1) THEN state.Permute END;
- state.ComplementBit( chunk*8 - 1 );
- state.Permute;
- index := 0;
- squeezing := TRUE
- END AbsorbLastFewBits;
- END Instance;
- END CryptoKeccakSponge.
|