#!/usr/bin/ruby # jh_tablegen.rb =begin This file is part of the AVR-Crypto-Lib. Copyright (C) 2006-2015 Daniel Otte (bg@nerilex.org) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . =end $sbox0 = [ 9, 0, 4, 11, 13, 12, 3, 15, 1, 10, 2, 6, 7, 5, 8, 14] $sbox1 = [ 3, 12, 6, 13, 5, 7, 1, 9, 15, 2, 0, 4, 11, 10, 14, 8] # (b) ^= ( ( (a) << 1) ^ ( (a) >> 3) ^ (( (a) >> 2) & 2) ) & 0xf; # (a) ^= ( ( (b) << 1) ^ ( (b) >> 3) ^ (( (b) >> 2) & 2) ) & 0xf; def L_transform(v,w) v = v&0x0f; w = w&0x0f # a = ((v<<1)|(v>>3))&0xf # d = a^w^((v>>2)&2) # d_ = ((d<<1)|(d>>3))&0xf # c = v^d_^((d>>2)&2) # return c, d w ^= ((v<<1)^(v>>3)^((v>>2)&2))&0x0f v ^= ((w<<1)^(w>>3)^((w>>2)&2))&0x0f return v,w end def L_transform_inv(v,w) a,b = L_transform(w,v) return b,a end def pi_permute(a, d=8) b=Array.new (2**(d-2)).times{ |i| b[4*i+0] = a[4*i+0]} (2**(d-2)).times{ |i| b[4*i+1] = a[4*i+1]} (2**(d-2)).times{ |i| b[4*i+2] = a[4*i+3]} (2**(d-2)).times{ |i| b[4*i+3] = a[4*i+2]} return b end def p_permute(a, d=8) b=Array.new (2**(d-1)).times{ |i| b[i] = a[2*i]} (2**(d-1)).times{ |i| b[i+2**(d-1)] = a[2*i+1]} return b end def phi_permute(a, d=8) b=Array.new (2**(d-1)).times{ |i| b[i] = a[i]} (2**(d-2)).times{ |i| b[2**(d-1)+2*i+0] = a[2**(d-1)+2*i+1]} (2**(d-2)).times{ |i| b[2**(d-1)+2*i+1] = a[2**(d-1)+2*i+0]} return b end def test_permutations a = Array.new 16.times{|i| a[i]=i} puts a.inspect b = pi_permute(a,4) puts b.inspect b = p_permute(a,4) puts b.inspect b = phi_permute(a,4) puts b.inspect end def permutation(a, d=8) return phi_permute(p_permute(pi_permute(a,d),d),d) end $permutation_table=Array.new def gen_permutation_table a = Array.new 256.times {|i| a<>4)&0xf b = v&0xf return b,a if $nibble_invert return a,b end def join_nibbles(a,b) if($nibble_invert) v = ((b<<4)|(a&0xf))&0xff else v = ((a<<4)|(b&0xf))&0xff end return v end $lutbox=Array.new def gen_lutboxes 4.times do |box| $lutbox[box]=Array.new 256.times do |i| a,b = split_byte(i) a = ((box&2)==2)?$sbox1[a]:$sbox0[a] b = ((box&1)==1)?$sbox1[b]:$sbox0[b] c,d = L_transform(a,b) $lutbox[box]<>4)&0x8 | ((a[i/8+32])>>5)&0x4 | ((a[i/8+64])>>6)&0x2 | ((a[i/8+96])>>7)&0x1 a[i/8] <<= 1; a[i/8+32]<<=1; a[i/8+64]<<=1; a[i/8+96]<<=1; q[2*i+1] = ((a[i/8+16])>>4)&0x8 | ((a[i/8+48])>>5)&0x4 | ((a[i/8+80])>>6)&0x2 | ((a[i/8+112])>>7)&0x1 a[i/8+16] <<= 1; a[i/8+48]<<=1; a[i/8+80]<<=1; a[i/8+112]<<=1; end b = Array.new 128.times {|i| b<>7)&1; a[i]<<=1 b[i/8+ 32]<<=1; b[i/8+ 32] |= (a[i]>>7)&1; a[i]<<=1 b[i/8+ 64]<<=1; b[i/8+ 64] |= (a[i]>>7)&1; a[i]<<=1 b[i/8+ 96]<<=1; b[i/8+ 96] |= (a[i]>>7)&1; a[i]<<=1 b[i/8+ 16]<<=1; b[i/8+ 16] |= (a[i]>>7)&1; a[i]<<=1 b[i/8+ 48]<<=1; b[i/8+ 48] |= (a[i]>>7)&1; a[i]<<=1 b[i/8+ 80]<<=1; b[i/8+ 80] |= (a[i]>>7)&1; a[i]<<=1 b[i/8+112]<<=1; b[i/8+112] |= (a[i]>>7)&1; a[i]<<=1 end return b end # data is an array of bytes # def single_round(data, round) a = Array.new rc = $round_const[round] =begin printf("\n== round %2d==\n\t", round) 16.times do |y| 8.times do |x| printf("%02X ", data[8*y+x]) end print("\n\t") end =end 128.times do |idx| x,y=split_byte($lutbox[((rc)>>(254))&0x3][data[idx]]) rc <<= 2 a << x << y end a = permutation(a) b = Array.new 128.times {|idx| b << join_nibbles(a[2*idx],a[2*idx+1])} return b end def next_rc(data) a = Array.new =begin printf("\n== rc round ==\n\t") 4.times do |y| 8.times do |x| printf("%02X ", data[8*y+x]) end print("\n\t") end =end 32.times do |idx| x,y=split_byte($lutbox[0][data[idx]]) a << x << y # if(x==nil)or(y==nil) # printf("DBG: idx=%2d, x=%2x, y=%2x", idx, x, y) # end end a = permutation(a, 6) b = Array.new 32.times {|idx| b << join_nibbles(a[2*idx],a[2*idx+1])} return b end def encrypt(data) =begin print("\n== ENCRYPT ==\n") print("=== pre group: ===\n\t") 16.times do |y| 8.times do |x| printf("%02X ", data[8*y+x]) end print("\n\t") end puts("") =end data = group(data) =begin print("=== post group: ===\n\t") 16.times do |y| 8.times do |x| printf("%02X ", data[8*y+x]) end print("\n\t") end puts("") =end 35.times do |round| data = single_round(data, round) end a = Array.new rc = $round_const[35] data.length.times do |idx| x, y = split_byte($lutbox[(rc>>254)&3][data[idx]]) rc <<= 2 v, w = L_transform_inv(x, y) a << join_nibbles(v,w) end a = degroup(a) =begin print("\n=== post enc: ===\n\t") 16.times do |y| 8.times do |x| printf("%02X ", a[8*y+x]) end print("\n\t") end puts("") =end return a end def hash_block(state_a, block) 64.times { |i| state_a[i] ^= block[i]} state_a = encrypt(state_a) 64.times { |i| state_a[64+i] ^= block[i]} return state_a end def test_L_inverse print("\nL_inv_test:\n\t") 256.times do |i| a,b = split_byte(i) c,d = L_transform(a, b) a,b = L_transform_inv(c, d) if join_nibbles(a,b)==i print('*') else print('!') end print("\n\t") if(i%16==15) end end #test_permutations gen_lutboxes gen_permutation_table print_permute_table 4.times{ |i| print_lutbox(i) } test_L_inverse print("\nsingle round:\n\t") h = single_round([0,0,0,0,0,0,0,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],0) 16.times do |y| 8.times do |x| printf("%02X, ",h[y*8+x]) end print("\n\t") end #=begin print("\nH(0):\n\t") h = hash_block([0x01,0,0,0,0,0,0,0x0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) h = hash_block(h, [0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]) 16.times do |y| 8.times do |x| printf("%02X, ",h[y*8+x]) end print("\n\t") end #=end puts("") c0 = [ 0x6a, 0x09, 0xe6, 0x67, 0xf3, 0xbc, 0xc9, 0x08, 0xb2, 0xfb, 0x13, 0x66, 0xea, 0x95, 0x7d, 0x3e, 0x3a, 0xde, 0xc1, 0x75, 0x12, 0x77, 0x50, 0x99, 0xda, 0x2f, 0x59, 0x0b, 0x06, 0x67, 0x32, 0x2a ] rc = c0 42.times do |i| printf("/* C_%02d: */\n", i) 4.times do |y| printf("\t") 8.times do |x| printf("0x%02x, ", rc[y*8+x]) end printf("\n") end rc = next_rc(rc) end