sha3_update Subroutine

public subroutine sha3_update(state, buffer, d)

Arguments

Type IntentOptional Attributes Name
type(sha3_state), intent(inout) :: state
integer(kind=int8), intent(in), dimension(:) :: buffer
integer, intent(in), optional :: d

Source Code

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