// generateAffineMasks creates the random external masks for the construction. func generateAffineMasks(rs *random.Source) (inputMask, outputMask encoding.BlockAffine) { var inputLinear, outputLinear matrix.Matrix common.GenerateMasks(rs, common.IndependentMasks{common.RandomMask, common.RandomMask}, &inputLinear, &outputLinear) reader := rs.Stream(make([]byte, 16)) var inputConstant, outputConstant [16]byte reader.Read(inputConstant[:]) reader.Read(outputConstant[:]) inputMask = encoding.NewBlockAffine(inputLinear, inputConstant) outputMask = encoding.NewBlockAffine(outputLinear, outputConstant) return }
// generateAffineMasks creates the random external masks for the construction. func generateAffineMasks(rs *random.Source) (inputMask, outputMask *blockAffine) { var inputLinear, outputLinear matrix.Matrix common.GenerateMasks(rs, common.IndependentMasks{common.RandomMask, common.RandomMask}, &inputLinear, &outputLinear) reader := rs.Stream(make([]byte, 16)) inputConstant, outputConstant := matrix.NewRow(128), matrix.NewRow(128) reader.Read(inputConstant[:]) reader.Read(outputConstant[:]) inputMask = &blockAffine{linear: inputLinear, constant: inputConstant} outputMask = &blockAffine{linear: outputLinear, constant: outputConstant} return }
// GenerateDecryptionKeys creates a white-boxed version of the AES key `key` for decryption, with any non-determinism // generated by `seed`. func GenerateDecryptionKeys(key, seed []byte, opts common.KeyGenerationOpts) (out Construction, inputMask, outputMask matrix.Matrix) { rs := random.NewSource("Xiao Decryption", seed) constr := saes.Construction{key} roundKeys := constr.StretchedKey() // Apply UnShiftRows to round keys 10. constr.UnShiftRows(roundKeys[10]) hidden := func(round, pos int) table.DoubleToWord { if round == 0 { return tBoxMixCol{ [2]table.Byte{ common.InvTBox{constr, roundKeys[10][pos+0], roundKeys[9][pos+0]}, common.InvTBox{constr, roundKeys[10][pos+1], roundKeys[9][pos+1]}, }, unMixColumns, sideFromPos(pos), } } else if 0 < round && round < 9 { return tBoxMixCol{ [2]table.Byte{ common.InvTBox{constr, 0x00, roundKeys[9-round][pos+0]}, common.InvTBox{constr, 0x00, roundKeys[9-round][pos+1]}, }, unMixColumns, sideFromPos(pos), } } else { return tBox{ [2]table.Byte{ common.InvTBox{constr, 0x00, roundKeys[0][pos+0]}, common.InvTBox{constr, 0x00, roundKeys[0][pos+1]}, }, sideFromPos(pos), } } } common.GenerateMasks(&rs, opts, &inputMask, &outputMask) generateRoundMaterial(&rs, &out, hidden) generateBarriers(&rs, &out, &inputMask, &outputMask, &unShiftRows) return out, inputMask, outputMask }
// GenerateEncryptionKeys creates a white-boxed version of the AES key `key` for encryption, with any non-determinism // generated by `seed`. func GenerateEncryptionKeys(key, seed []byte, opts common.KeyGenerationOpts) (out Construction, inputMask, outputMask matrix.Matrix) { rs := random.NewSource("Xiao Encryption", seed) constr := saes.Construction{key} roundKeys := constr.StretchedKey() // Apply ShiftRows to round keys 0 to 9. for k := 0; k < 10; k++ { constr.ShiftRows(roundKeys[k]) } hidden := func(round, pos int) table.DoubleToWord { if round == 9 { return tBox{ [2]table.Byte{ common.TBox{constr, roundKeys[9][pos+0], roundKeys[10][pos+0]}, common.TBox{constr, roundKeys[9][pos+1], roundKeys[10][pos+1]}, }, sideFromPos(pos), } } else { return tBoxMixCol{ [2]table.Byte{ common.TBox{constr, roundKeys[round][pos+0], 0x00}, common.TBox{constr, roundKeys[round][pos+1], 0x00}, }, mixColumns, sideFromPos(pos), } } } common.GenerateMasks(&rs, opts, &inputMask, &outputMask) generateRoundMaterial(&rs, &out, hidden) generateBarriers(&rs, &out, &inputMask, &outputMask, &shiftRows) return out, inputMask, outputMask }
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{} }, ) }