%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% 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

Generated on Fri Sep 24 10:39:12 CEST 2010
Home