// generateRoundMaterial creates the TMC (TBox + MixColumns) tables. func generateRoundMaterial(rs *random.Source, out *Construction, hidden func(int, int) table.DoubleToWord) { for round := 0; round < 10; round++ { for pos := 0; pos < 16; pos += 2 { out.TBoxMixCol[round][pos/2] = encoding.DoubleToWordTable{ encoding.NewDoubleLinear(common.MixingBijection(rs, 16, round, pos/2)), encoding.InverseWord{ encoding.NewWordLinear(common.MixingBijection(rs, 32, round, pos/4)), }, hidden(round, pos), } } } }
// generateRoundMaterial creates the TMC (TBox + MixColumns) tables. func generateRoundMaterial(rs *common.RandomSource, out *Construction, hidden func(int, int) table.DoubleToWord) { for round := 0; round < 10; round++ { for pos := 0; pos < 16; pos += 2 { inEnc := common.MixingBijection(rs, 16, round, pos/2) outEnc := common.MixingBijection(rs, 32, round, pos/4) inInv, _ := inEnc.Invert() outInv, _ := outEnc.Invert() out.TBoxMixCol[round][pos/2] = encoding.DoubleToWordTable{ encoding.DoubleLinear{inEnc, inInv}, encoding.WordLinear{outInv, outEnc}, hidden(round, pos), } } } }
func maskSwap(rs *random.Source, size, round int) (out matrix.Matrix) { out = matrix.GenerateEmpty(128, 128) for row := 0; row < 128; row += size { col := row / 8 m := common.MixingBijection(rs, size, round, row/size) for subRow := 0; subRow < size; subRow++ { copy(out[row+subRow][col:], m[subRow]) } } return }
// blockMaskEncoding concatenates all the mask encodings for InputMask or TBoxOutputMask into a block encoding, so that // it can easily be put on the output of one of the Block tables. // // position is the index of the Block table and shift is the permutation that will be applied between this round and the // next or noshift if this is an input encoding; the other parameters are explained in MaskEncoding documentation. func blockMaskEncoding(rs *random.Source, position int, surface common.Surface, shift func(int) int) encoding.Block { out := encoding.ConcatenatedBlock{} for i := 0; i < 16; i++ { out[i] = encoding.ConcatenatedByte{ maskEncoding(rs, surface)(position, 2*i+0), maskEncoding(rs, surface)(position, 2*i+1), } if surface == common.Inside { out[i] = encoding.ComposedBytes{ encoding.NewByteLinear(common.MixingBijection(rs, 8, -1, shift(i))), out[i], } } } return out }
func generateKeys(rs *random.Source, opts common.KeyGenerationOpts, out *Construction, inputMask, outputMask *matrix.Matrix, shift func(int) int, skinny func(int) table.Byte, wide func(int, int) table.Word) { // Generate input and output encodings. common.GenerateMasks(rs, opts, inputMask, outputMask) // Generate the Input Mask slices and XOR tables. for pos := 0; pos < 16; pos++ { out.InputMask[pos] = encoding.BlockTable{ encoding.IdentityByte{}, blockMaskEncoding(rs, pos, common.Inside, shift), common.BlockMatrix{Linear: *inputMask, Position: pos}, } } out.InputXORTables = common.BlockNibbleXORTables( maskEncoding(rs, common.Inside), xorEncoding(rs, 10, common.Inside), roundEncoding(rs, -1, common.Outside, shift), ) // Generate round material. for round := 0; round < 9; round++ { for pos := 0; pos < 16; pos++ { // Generate a word-sized mixing bijection and stick it on the end of the T-Box/Tyi Table. mb := common.MixingBijection(rs, 32, round, pos/4) // Build the T-Box and Tyi Table for this round and position in the state matrix. out.TBoxTyiTable[round][pos] = encoding.WordTable{ encoding.ComposedBytes{ encoding.NewByteLinear(common.MixingBijection(rs, 8, round-1, pos)), byteRoundEncoding(rs, round-1, pos, common.Outside, common.NoShift), }, encoding.ComposedWords{ encoding.ConcatenatedWord{ encoding.NewByteLinear(common.MixingBijection(rs, 8, round, shift(pos/4*4+0))), encoding.NewByteLinear(common.MixingBijection(rs, 8, round, shift(pos/4*4+1))), encoding.NewByteLinear(common.MixingBijection(rs, 8, round, shift(pos/4*4+2))), encoding.NewByteLinear(common.MixingBijection(rs, 8, round, shift(pos/4*4+3))), }, encoding.NewWordLinear(mb), wordStepEncoding(rs, round, pos, common.Inside), }, wide(round, pos), } // Encode the inverse of the mixing bijection from above in the MB^(-1) table for this round and position. mbInv, _ := mb.Invert() out.MBInverseTable[round][pos] = encoding.WordTable{ byteRoundEncoding(rs, round, pos, common.Inside, common.NoShift), wordStepEncoding(rs, round, pos, common.Outside), mbInverseTable{mbInv, uint(pos) % 4}, } } } // Generate the High and Low XOR Tables for reach round. out.HighXORTable = xorTables(rs, common.Inside, common.NoShift) out.LowXORTable = xorTables(rs, common.Outside, shift) // Generate the 10th T-Box/Output Mask slices and XOR tables. for pos := 0; pos < 16; pos++ { out.TBoxOutputMask[pos] = encoding.BlockTable{ encoding.ComposedBytes{ encoding.NewByteLinear(common.MixingBijection(rs, 8, 8, pos)), byteRoundEncoding(rs, 8, pos, common.Outside, common.NoShift), }, blockMaskEncoding(rs, pos, common.Outside, shift), table.ComposedToBlock{ Heads: skinny(pos), Tails: common.BlockMatrix{Linear: *outputMask, Position: pos}, }, } } out.OutputXORTables = common.BlockNibbleXORTables( maskEncoding(rs, common.Outside), xorEncoding(rs, 10, common.Outside), func(position int) encoding.Nibble { return encoding.IdentityByte{} }, ) }