subroutine sha3_update( state, buffer, d )
! this routine
type(sha3_state), intent(inout) :: state
integer(kind=int8), dimension(:), intent(in) :: buffer
integer, optional, intent(in) :: d
integer, save :: r8
integer :: j
if ( state%bufsize == -1 ) then
! means we never, ever called sha3_update before, and thus the buffer pointer
! in state is in limbo
nullify( state%buffer )
endif
if ( state%bufsize < 0 ) then
! means that we start working on a new input
if ( present(d) ) then
state%d = d
else
state%d = 224
endif
if ( state%d == 224 ) then
state%c = 448
elseif ( state%d == 256 ) then
state%c = 512
elseif ( state%d == 384 ) then
state%c = 768
elseif ( state%d == 512 ) then
state%c = 1024
else
! todo
endif
state%r = 25*W - state%c
! initialize state
state%S = 0_int64
allocate( state%buffer(state%r / 4 ) )
state%bufsize = 0 ! buffer allocated, but empty
r8 = state%r / 8
endif
! in case there was data left in the *state* buffer from a previous call
! to sha3_update, we append the received data to it
if ( state%bufsize > 0 ) then
! complete the state buffer
j = min( size(buffer), r8 - state%bufsize ) ! how many bytes from buffer to use
state%buffer( state%bufsize+1 : state%bufsize+j ) = buffer(1:j)
state%bufsize = state%bufsize + j
if ( state%bufsize >= r8 ) then
call sha3_block( state%S, state%buffer(1:r8), r8 )
state%bufsize = 0
! hash the remainder of the data (if any)
do
if ( j+r8 >= size(buffer) ) exit
! hash this block, w
call sha3_block( state%S, buffer(j+1:j+r8), r8 )
! go to next input block
j = j + r8
enddo
else
return
endif
else
! hash what we can from buffer
j = 0
do
if ( j+r8 >= size(buffer) ) exit
! hash this block, w
call sha3_block( state%S, buffer(j+1:j+r8), r8 )
! go to next input block
j = j + r8
enddo
endif
! add the remainder to state%buffer:
! just accumulate data, because this cannot be hashed without taking
! padding into account
if ( state%bufsize + (size(buffer) - j) > size(state%buffer) ) then
print *, 'error, buffer is too small ???'
else
state%buffer( state%bufsize+1 : state%bufsize+size(buffer)-j ) = buffer( j+1:size(buffer) )
state%bufsize = state%bufsize + size(buffer) - j
if ( state%bufsize < 0 ) print *, 'error, buffer size < 0'
endif
! is buffer large enough to process a block ?
if ( state%bufsize >= r8 ) then
call sha3_block( state%S, state%buffer(1:r8), r8 )
! "resize" buffer
state%buffer(1:state%bufsize-r8) = state%buffer(r8+1:state%bufsize)
state%bufsize = state%bufsize - r8
endif
end subroutine sha3_update