%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Copyright: 2010 Integrated Sytems Laboratory, ETH Zurich %% http://www.iis.ee.ethz.ch/~sha3 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Matlab Golden Model of Shabal function [state_final, hashval] = Hash(hashbitlen, data, databitlen) global sM nR % constants sM = 16; % block size nR = 12; % parameter r state_init = Init(hashbitlen); state_update = Update(state_init, data, databitlen); [state_final, hashval] = Final(state_update, data, databitlen, hashbitlen); end function state = Init(hashbitlen) global sM nR % Initialize the state (all zero, except the counter which is % set to -1). state.A = fi(zeros(1,nR),0,32,0); state.B = fi(zeros(1,sM),0,32,0); state.C = fi(zeros(1,sM),0,32,0); state.Wlow = fi(hex2dec('FFFFFFFF'),0,32,0); state.Whigh = fi(hex2dec('FFFFFFFF'),0,32,0); % We compute the first two blocks, corresponding to the prefix, % and process them immediately. m = fi(zeros(1, sM),0,32,0); for j = 1:sM:(2 * sM) % j={1,17} for i = 1:sM m(i) = hashbitlen + j + i - 2; % m(1)=hashbitlen (for 1st block) end % process block state = input_block_add(state, m); state = xor_counter(state); state = apply_perm(state, m); state = input_block_sub(state, m); state = swap_bc(state); state = incr_counter(state); end end function state = Update(state, data, databitlen) % Process all message blocks except the last one, which will be processed in % Final(). messageblocks = databitlen/512; for i=1:(messageblocks - 1) m = data(((i-1)*16+1):(i*16)); % process block state = input_block_add(state, m); state = xor_counter(state); state = apply_perm(state, m); state = input_block_sub(state, m); state = swap_bc(state); state = incr_counter(state); end end function [state, hashval] = Final(state, data, databitlen, hashbitlen) global sM nE = 3; % parameter e % Now, we process the last (padded) block. We add three extra % permutations, and we optimize away the unnecessary message % additions and subtractions. There is no increment of the % counter either in those last rounds (we keep the counter % value used for the last data block). We transfer the swap to % the next round, because there needs to be no final swap. % % Note that we reuse the final block in several calls % to apply_perm(). messageblocks = databitlen/512; m = data(((messageblocks-1)*16+1):(messageblocks*16)); state = input_block_add(state, m); state = xor_counter(state); state = apply_perm(state, m); for i = 1:nE state = swap_bc(state); state = xor_counter(state); state = apply_perm(state, m); end % The output consists of the B words, truncated to the requested % length (in the formal description, the C words are used, but % we omitted the last swap, so we have the words in B). hashval = state.B(sM - hashbitlen/32 +1:sM); end % Swap the B and C state words. function state = swap_bc(state) t = state.B; state.B = state.C; state.C = t; end % Add the message block m to the B state words. function state = input_block_add(state, m) global sM for i = 1:sM state.B(i) = bitsliceget(state.B(i) + m(i),32); end end % Subtract the message block m from the C state words. function state = input_block_sub(state, m) global sM for i = 1:sM state.C(i) = bitsliceget(fi(4294967296,0,33,0) + state.C(i) - m(i),32); end end % Combine the block counter with the A state words. function state = xor_counter(state) state.A(1) = bitxor(state.A(1),state.Wlow); state.A(2) = bitxor(state.A(2),state.Whigh); end % Increment the block counter, for the next block. function state = incr_counter(state) % The counter extends over two 32-bit words. We manually propagate % the carry when needed. state.Wlow = bitsliceget(state.Wlow+fi(1,0,32,0),32); if state.Wlow == 0 state.Whigh = bitsliceget(state.Whigh+fi(1,0,32,0),32); end end % Apply the core Shabal permutation. The message block is provided % in the m parameter. function state = apply_perm(state, m) global sM nR % offset values in keyed permutation o1 = 13; o2 = 9; o3 = 6; nP = 3; % parameter p for i = 1:sM state.B(i) = bitrol(state.B(i),17); end for j = 0:(nP - 1) % j=0:2 for i = 0:(sM - 1) state.A(mod((i + sM * j), nR)+1) = bitxor(bitxor(bitxor(U(bitxor(bitxor(state.A(mod((i + sM * j), nR)+1),... V(bitsliceget(... bitrol(state.A(mod((i + sM * j + (nR - 1)), nR)+1),15),32))), state.C(mod((8 + sM - i), sM)+1))),... state.B(mod((i + o1), sM)+1)),... bitand(state.B(mod((i + o2), sM)+1), bitcmp(state.B(mod((i + o3), sM)+1)))),m(i+1)); state.B(i+1) = bitxor(bitrol(state.B(i+1), 1), bitcmp(state.A(mod((i + sM * j), nR)+1))); end end for j = 0:((3*nR)-1) % j=0:35 state.A(mod((3*nR - 1 - j), nR)+1) = bitsliceget(state.A(mod((3*nR - 1 - j), nR)+1) + state.C(mod((3*nR*sM + 6 - j), sM)+1),32); end end function y = U(x) y = bitsliceget(fi(3,0,32,0) * x,32); end function y = V(x) y = bitsliceget(fi(5,0,32,0) * x, 32); end