def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SPECK with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize == 16: self.rot_alpha = 7 self.rot_beta = 2 elif "rotationconstants" in parameters: self.rot_alpha = parameters["rotationconstants"][0] self.rot_beta = parameters["rotationconstants"][1] with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Speck w={} alpha={} beta={} " "rounds={}\n\n\n".format(wordsize, self.rot_alpha, self.rot_beta, rounds)) # Setup variable # x = left, y = right # w = weight x = ["x{}".format(i) for i in range(rounds + 1)] y = ["y{}".format(i) for i in range(rounds + 1)] w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) # Ignore MSB stpcommands.setupWeightComputation(stp_file, weight, w, wordsize, 1) for i in range(rounds): self.setupSpeckRound(stp_file, x[i], y[i], x[i+1], y[i+1], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x + y, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) stpcommands.assertVariableValue(stp_file, y[0], y[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for Salsa with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Salsa w={}" "rounds={}\n\n\n".format(wordsize, rounds)) # Setup variables a = ["a{}r{}".format(j, i) for i in range(rounds + 1) for j in range(16)] b = ["b{}r{}".format(j, i) for i in range(rounds) for j in range(16)] w = ["w{}r{}".format(j, i) for i in range(rounds) for j in range(16)] stpcommands.setupVariables(stp_file, a, wordsize) stpcommands.setupVariables(stp_file, b, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) # Ignore MSB stpcommands.setupWeightComputation(stp_file, weight, w, wordsize, 1) for rnd in range(rounds): if rnd % 2 != 0: #Rowround for row in range(4): a_in = [a[(i + row) % 4 + 4 * row + 16 * rnd] for i in range(4)] a_out = [a[(i + row) % 4 + 4 * row + 16 * (rnd + 1)] for i in range(4)] tmp_b = [b[i + 4 * row + 16 * rnd] for i in range(4)] tmp_w = [w[i + 4 * row + 16 * rnd] for i in range(4)] self.setupQuarterRound(stp_file, a_in, tmp_b, a_out, tmp_w, wordsize) else: #Columnround for col in range(4): a_in = [a[(i * 4 + 4 * col + col) % 16 + 16 * rnd] for i in range(4)] a_out = [a[(i * 4 + 4 * col + col) % 16 + 16 * (rnd + 1)] for i in range(4)] tmp_b = [b[i * 4 + col + 16 * rnd] for i in range(4)] tmp_w = [w[i * 4 + col + 16 * rnd] for i in range(4)] self.setupQuarterRound(stp_file, a_in, tmp_b, a_out, tmp_w, wordsize) #stp_file.write("ASSERT(({}[31:31]) = 0b0);\n".format(a[0])) # No all zero characteristic stpcommands.assertNonZero(stp_file, a, wordsize) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a differnetial trail for Skinny with the given parameters. """ blocksize = parameters["blocksize"] wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if blocksize != 64: print("Only blocksize of 64-bit supported.") exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% Skinny w={}" "rounds={}\n\n\n".format(blocksize, rounds)) stp_file.write(header) # Setup variables sc = ["SC{}".format(i) for i in range(rounds + 1)] sr = ["SR{}".format(i) for i in range(rounds)] mc = ["MC{}".format(i) for i in range(rounds)] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, sc, blocksize) stpcommands.setupVariables(stp_file, sr, blocksize) stpcommands.setupVariables(stp_file, mc, blocksize) stpcommands.setupVariables(stp_file, w, blocksize) stpcommands.setupWeightComputation(stp_file, weight, w, blocksize) for i in range(rounds): self.setupSkinnyRound(stp_file, sc[i], sr[i], mc[i], sc[i+1], w[i], blocksize) # No all zero characteristic stpcommands.assertNonZero(stp_file, sc, blocksize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, sc[0], sc[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, blocksize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for PRESENT with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize != 64: print("Only wordsize of 64-bit supported.") exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% PRESENT w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables s = ["S{}".format(i) for i in range(rounds + 1)] p = ["P{}".format(i) for i in range(rounds)] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, s, wordsize) stpcommands.setupVariables(stp_file, p, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in range(rounds): self.setupPresentRound(stp_file, s[i], p[i], s[i+1], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, s, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, s[0], s[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file for Ascon. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] sboxsize = 5 # TODO: support arbitrary sizes capacity = 0 rate = (wordsize * sboxsize) - capacity if "rate" in parameters: rate = parameters["rate"] if "capacity" in parameters: capacity = parameters["capacity"] assert (rate + capacity) == wordsize * sboxsize with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Ascon w={} rate={} " "capacity={} round={}\n\n\n".format(wordsize, rate, capacity, rounds)) # Setup variables # 5 x wordsize state s = ["s{}{}".format(x, i) for i in range(rounds+1) for x in range(sboxsize)] # Output after S-box Linear part 1 a = ["a{}{}".format(x, i) for i in range(rounds+1) for x in range(sboxsize)] # Output after S-box Non-Linear part b = ["b{}{}".format(x, i) for i in range(rounds+1) for x in range(sboxsize)] # Output after S-box Linear part 2 c = ["c{}{}".format(x, i) for i in range(rounds+1) for x in range(sboxsize)] # Inputs/Output to the S-box xin = ["inx{}{}{}".format(y, z, i) for i in range(rounds) for y in range(sboxsize) for z in range (wordsize)] xout = ["outx{}{}{}".format(y, z, i) for i in range(rounds) for y in range(sboxsize) for z in range (wordsize)] andout = ["andout{}{}{}".format(y, z, i) for i in range(rounds) for y in range(sboxsize) for z in range (wordsize)] # w = weight w = ["w{}".format(i) for i in range(rounds)] tmp = ["tmp{}{}{}".format(y, z, i) for i in range(rounds) for y in range(sboxsize) for z in range (wordsize)] stpcommands.setupVariables(stp_file, s, wordsize) stpcommands.setupVariables(stp_file, a, wordsize) stpcommands.setupVariables(stp_file, b, wordsize) stpcommands.setupVariables(stp_file, c, wordsize) stpcommands.setupVariables(stp_file, w, 16) stpcommands.setupVariables(stp_file, tmp, sboxsize) stpcommands.setupWeightComputationSum(stp_file, weight, w, wordsize) stpcommands.setupVariables(stp_file, xin, sboxsize) stpcommands.setupVariables(stp_file, xout, sboxsize) stpcommands.setupVariables(stp_file, andout, sboxsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, s, wordsize) # Fix variables for capacity, only works if rate/capacity is # multiple of wordsize. for i in range(rate // wordsize, (rate + capacity) // wordsize): stpcommands.assertVariableValue(stp_file, s[i], "0hex{}".format("0"*(wordsize // 4))) for rnd in range(rounds): self.setupAsconRound(stp_file, rnd, s, a, b, c, wordsize, tmp, w, xin, xout, andout) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SPARX with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% SPARX w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables # x0, x1 = left, y0, y1 = right x0 = ["X0{}".format(i) for i in range(rounds + 1)] x1 = ["X1{}".format(i) for i in range(rounds + 1)] x0_after_A0 = ["X0A0{}".format(i) for i in range(rounds)] x1_after_A0 = ["X1A0{}".format(i) for i in range(rounds)] x0_after_A1 = ["X0A1{}".format(i) for i in range(rounds)] x1_after_A1 = ["X1A1{}".format(i) for i in range(rounds)] x0_after_A2 = ["X0A2{}".format(i) for i in range(rounds)] x1_after_A2 = ["X1A2{}".format(i) for i in range(rounds)] x0_after_L = ["X0L{}".format(i) for i in range(rounds)] x1_after_L = ["X1L{}".format(i) for i in range(rounds)] y0 = ["Y0{}".format(i) for i in range(rounds + 1)] y1 = ["Y1{}".format(i) for i in range(rounds + 1)] y0_after_A0 = ["Y0A0{}".format(i) for i in range(rounds)] y1_after_A0 = ["Y1A0{}".format(i) for i in range(rounds)] y0_after_A1 = ["Y0A1{}".format(i) for i in range(rounds)] y1_after_A1 = ["Y1A1{}".format(i) for i in range(rounds)] y0_after_A2 = ["Y0A2{}".format(i) for i in range(rounds)] y1_after_A2 = ["Y1A2{}".format(i) for i in range(rounds)] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x0, wordsize) stpcommands.setupVariables(stp_file, x1, wordsize) stpcommands.setupVariables(stp_file, x0_after_A0, wordsize) stpcommands.setupVariables(stp_file, x1_after_A0, wordsize) stpcommands.setupVariables(stp_file, x0_after_A1, wordsize) stpcommands.setupVariables(stp_file, x1_after_A1, wordsize) stpcommands.setupVariables(stp_file, x0_after_A2, wordsize) stpcommands.setupVariables(stp_file, x1_after_A2, wordsize) stpcommands.setupVariables(stp_file, x0_after_L, wordsize) stpcommands.setupVariables(stp_file, x1_after_L, wordsize) stpcommands.setupVariables(stp_file, y0, wordsize) stpcommands.setupVariables(stp_file, y1, wordsize) stpcommands.setupVariables(stp_file, y0_after_A0, wordsize) stpcommands.setupVariables(stp_file, y1_after_A0, wordsize) stpcommands.setupVariables(stp_file, y0_after_A1, wordsize) stpcommands.setupVariables(stp_file, y1_after_A1, wordsize) stpcommands.setupVariables(stp_file, y0_after_A2, wordsize) stpcommands.setupVariables(stp_file, y1_after_A2, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in range(rounds): self.setupSPARXRound( stp_file, x0[i], x1[i], y0[i], y1[i], x0_after_A0[i], x1_after_A0[i], x0_after_A1[i], x1_after_A1[i], x0_after_A2[i], x1_after_A2[i], x0_after_L[i], x1_after_L[i], y0_after_A0[i], y1_after_A0[i], y0_after_A1[i], y1_after_A1[i], y0_after_A2[i], y1_after_A2[i], x0[i + 1], x1[i + 1], y0[i + 1], y1[i + 1], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x0 + x1 + y0 + y1, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x0[0], x0[rounds]) stpcommands.assertVariableValue(stp_file, x1[0], x1[rounds]) stpcommands.assertVariableValue(stp_file, y0[0], y0[rounds]) stpcommands.assertVariableValue(stp_file, y1[0], y1[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for PRINCE with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize != 4: print("PRINCE only supports a wordsize of 4 bits.") exit(1) if (rounds - 1) % 2 != 0: print( "PRINCE only supports a multiple of 2 as the number of rounds." ) exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% Prince w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables # State is represented as nibbles # 0 4 8 12 # 1 5 9 13 # 2 6 10 14 # 3 7 11 15 sb = [ "SB{}r{}".format(j, i) for i in range(rounds + 1) for j in range(16) ] sr = [ "SR{}r{}".format(j, i) for i in range(rounds) for j in range(16) ] mc = [ "MC{}r{}".format(j, i) for i in range(rounds) for j in range(16) ] # wn = weight of each S-box wn = [ "wn{}r{}".format(j, i) for i in range(rounds + 1) for j in range(16) ] # One Extra for middle round stpcommands.setupVariables(stp_file, sb, wordsize) stpcommands.setupVariables(stp_file, sr, wordsize) stpcommands.setupVariables(stp_file, mc, wordsize) stpcommands.setupVariables(stp_file, wn, wordsize) stpcommands.setupWeightComputation(stp_file, weight, wn, wordsize) # Forward rounds for rnd in range(rounds // 2): si = 16 * rnd ei = 16 * (rnd + 1) self.setupPrinceForwardRound(stp_file, sb[si:ei], sr[si:ei], mc[si:ei], sb[ei:ei + 16], wn[si:ei], wordsize) # Middle round si = 16 * (rounds // 2) ei = 16 * ((rounds // 2) + 1) self.setupPrinceMiddleRound(stp_file, sb[si:ei], sr[si:ei], mc[si:ei], sb[ei:ei + 16], wn[si:ei], wn[ei:ei + 16], wordsize) # Backward round for rnd in range(rounds // 2 + 1, rounds): si = 16 * rnd ei = 16 * (rnd + 1) self.setupPrinceBackwardRound(stp_file, sb[si:ei], sr[si:ei], mc[si:ei], sb[ei:ei + 16], wn[si + 16:ei + 16], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, sb, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, sb[0], sb[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for ChasKey with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] self.num_messages = parameters["nummessages"] with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% ChasKeyMac w={} rounds={}" "\n\n\n".format(wordsize, rounds)) # Setup variables # state = v0, v1, v2, v3 # intermediate values = a0, a1, a2, a3 v0 = ["v0{}".format(i) for i in range((rounds + 1) * self.num_messages)] v1 = ["v1{}".format(i) for i in range((rounds + 1) * self.num_messages)] v2 = ["v2{}".format(i) for i in range((rounds + 1) * self.num_messages)] v3 = ["v3{}".format(i) for i in range((rounds + 1) * self.num_messages)] # w = weight of each modular addition w0 = ["w0{}".format(i) for i in range(rounds * self.num_messages)] w1 = ["w1{}".format(i) for i in range(rounds * self.num_messages)] stpcommands.setupVariables(stp_file, v0, wordsize) stpcommands.setupVariables(stp_file, v1, wordsize) stpcommands.setupVariables(stp_file, v2, wordsize) stpcommands.setupVariables(stp_file, v3, wordsize) stpcommands.setupVariables(stp_file, w0, wordsize) stpcommands.setupVariables(stp_file, w1, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w0 + w1, wordsize, 1) #Minimize Weight in middle rounds #stpcommands.limitWeight(stp_file, 10, w0[2:4] + w1[2:4], wordsize, 1) for i in range(rounds): self.setupChasKeyRound(stp_file, i, v0[i], v1[i], v2[i], v3[i], v0[i + 1], v1[i + 1], v2[i + 1], v3[i + 1], w0[i], w1[i], wordsize) # Message Collision stpcommands.assertNonZero(stp_file, v0 + v1 + v2 + v3, wordsize) # zeroString = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, v0[rounds], zeroString) # stpcommands.assertVariableValue(stp_file, v1[rounds], zeroString) # stpcommands.assertVariableValue(stp_file, v2[rounds], zeroString) # stpcommands.assertVariableValue(stp_file, v3[rounds], zeroString) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file for SIMON. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] # Replace with custom if set in parameters. if "rotationconstants" in parameters: self.rot_alpha = parameters["rotationconstants"][0] self.rot_beta = parameters["rotationconstants"][1] self.rot_gamma = parameters["rotationconstants"][2] self.num_messages = parameters["nummessages"] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% Simon w={} alpha={} beta={}" " gamma={} rounds={}\n\n\n".format(wordsize, self.rot_alpha, self.rot_beta, self.rot_gamma, rounds)) stp_file.write(header) # Setup key key = ["key{}".format(i) for i in range(rounds + 1)] tmp_key = ["tmpkey{}".format(i) for i in range(rounds + 1)] stpcommands.setupVariables(stp_file, key, wordsize) stpcommands.setupVariables(stp_file, tmp_key, wordsize) #TODO Add constant addition self.setupKeySchedule(stp_file, key, tmp_key, rounds, wordsize) # Setup variables # x = left, y = right for msg in range(self.num_messages): x = ["x{}r{}".format(msg, i) for i in range(rounds + 1)] y = ["y{}r{}".format(msg, i) for i in range(rounds + 1)] and_out = ["andout{}r{}".format(msg, i) for i in range(rounds + 1)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, and_out, wordsize) #Setup Rounds for i in range(rounds): self.setupSimonRound(stp_file, x[i], y[i], x[i+1], y[i+1], and_out[i], key[i], wordsize) #Differences between x_0 and x_i for msg in range(1, self.num_messages): delta_x = ["dx{}r{}".format(msg, i) for i in range(rounds + 1)] delta_y = ["dy{}r{}".format(msg, i) for i in range(rounds + 1)] stpcommands.setupVariables(stp_file, delta_x, wordsize) stpcommands.setupVariables(stp_file, delta_y, wordsize) for i in range(rounds + 1): stp_file.write("ASSERT({} = BVXOR({}, {}));\n".format( delta_x[i], "x0r{}".format(i), "x{}r{}".format(msg, i))) stp_file.write("ASSERT({} = BVXOR({}, {}));\n".format( delta_y[i], "y0r{}".format(i), "y{}r{}".format(msg, i))) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SIMON with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] # Replace with custom if set in parameters. if "rotationconstants" in parameters: self.rot_alpha = parameters["rotationconstants"][0] self.rot_beta = parameters["rotationconstants"][1] self.rot_gamma = parameters["rotationconstants"][2] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% Simon w={} alpha={} beta={}" " gamma={} rounds={}\n\n\n".format(wordsize, self.rot_alpha, self.rot_beta, self.rot_gamma, rounds)) stp_file.write(header) # Setup variables # x = left, y = right x = ["x{}".format(i) for i in range(rounds + 1)] y = ["y{}".format(i) for i in range(rounds + 1)] and_out = ["andout{}".format(i) for i in range(rounds + 1)] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, and_out, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in range(rounds): self.setupSimonRound(stp_file, x[i], y[i], x[i+1], y[i+1], and_out[i], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x + y, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) stpcommands.assertVariableValue(stp_file, y[0], y[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SPARX with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% SPARX w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables # x0, x1 = left, y0, y1 = right x0 = ["X0{}".format(i) for i in range(rounds + 1)] x1 = ["X1{}".format(i) for i in range(rounds + 1)] x0_after_A = ["X0A{}".format(i) for i in range(rounds + 1)] x1_after_A = ["X1A{}".format(i) for i in range(rounds + 1)] x0_after_L = ["X0L{}".format(i) for i in range(rounds + 1)] x1_after_L = ["X1L{}".format(i) for i in range(rounds + 1)] y0 = ["Y0{}".format(i) for i in range(rounds + 1)] y1 = ["Y1{}".format(i) for i in range(rounds + 1)] y0_after_A = ["Y0A{}".format(i) for i in range(rounds + 1)] y1_after_A = ["Y1A{}".format(i) for i in range(rounds + 1)] # w = weight wleft = ["wl{}".format(i) for i in range(rounds)] wright = ["wr{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x0, wordsize) stpcommands.setupVariables(stp_file, x1, wordsize) stpcommands.setupVariables(stp_file, x0_after_A, wordsize) stpcommands.setupVariables(stp_file, x1_after_A, wordsize) stpcommands.setupVariables(stp_file, x0_after_L, wordsize) stpcommands.setupVariables(stp_file, x1_after_L, wordsize) stpcommands.setupVariables(stp_file, y0, wordsize) stpcommands.setupVariables(stp_file, y1, wordsize) stpcommands.setupVariables(stp_file, y0_after_A, wordsize) stpcommands.setupVariables(stp_file, y1_after_A, wordsize) stpcommands.setupVariables(stp_file, wleft, wordsize) stpcommands.setupVariables(stp_file, wright, wordsize) # Ignore MSB stpcommands.setupWeightComputation(stp_file, weight, wleft + wright, wordsize, 1) for i in range(rounds): if i < 2: if ((i + 1) % 2) == 0: #do round function left (SPECKEY) self.setupSPECKEYRound(stp_file, x0[i], x1[i], x0_after_A[i], x1_after_A[i], wleft[i], wordsize) #do round function right (SPECKEY) self.setupSPECKEYRound(stp_file, y0[i], y1[i], y0_after_A[i], y1_after_A[i], wright[i], wordsize) #every step do L-box and feistel self.setupSPARXRound(stp_file, x0_after_A[i], x1_after_A[i], y0_after_A[i], y1_after_A[i], x0_after_L[i], x1_after_L[i], x0[i + 1], x1[i + 1], y0[i + 1], y1[i + 1]) else: #do round function left (SPECKEY) self.setupSPECKEYRound(stp_file, x0[i], x1[i], x0[i + 1], x1[i + 1], wleft[i], wordsize) #do round function right (SPECKEY) self.setupSPECKEYRound(stp_file, y0[i], y1[i], y0[i + 1], y1[i + 1], wright[i], wordsize) else: if ((i - 1) % self.rounds_per_step) == 0: #do round function left (SPECKEY) self.setupSPECKEYRound(stp_file, x0[i], x1[i], x0_after_A[i], x1_after_A[i], wleft[i], wordsize) #do round function right (SPECKEY) self.setupSPECKEYRound(stp_file, y0[i], y1[i], y0_after_A[i], y1_after_A[i], wright[i], wordsize) #every step do L-box and feistel self.setupSPARXRound(stp_file, x0_after_A[i], x1_after_A[i], y0_after_A[i], y1_after_A[i], x0_after_L[i], x1_after_L[i], x0[i + 1], x1[i + 1], y0[i + 1], y1[i + 1]) else: #do round function left (SPECKEY) self.setupSPECKEYRound(stp_file, x0[i], x1[i], x0[i + 1], x1[i + 1], wleft[i], wordsize) #do round function right (SPECKEY) self.setupSPECKEYRound(stp_file, y0[i], y1[i], y0[i + 1], y1[i + 1], wright[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x0 + x1 + y0 + y1, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x0[0], x0[rounds]) stpcommands.assertVariableValue(stp_file, x1[0], x1[rounds]) stpcommands.assertVariableValue(stp_file, y0[0], y0[rounds]) stpcommands.assertVariableValue(stp_file, y1[0], y1[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for BAT nibble with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize == 32: p = [7, 4, 1, 6, 3, 0, 5, 2] elif wordsize == 64: p = [14, 15, 8, 9, 2, 3, 12, 13, 6, 7, 0, 1, 10, 11, 4, 5] else: raise Exception("Wrong wordsize!") self.PERM = GenPerm.GenNibblePerms(wordsize, p) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP: BAT linear actsbox\n" "% w = {} alpha = {} beta = {}\n" "% rounds = {}\n\n".format( wordsize, self.rot_alpha, self.rot_beta, rounds)) stp_file.write(header) # Setup variables # x = left, y = right x = ["x{}".format(i) for i in range(rounds + 1)] y = ["y{}".format(i) for i in range(rounds + 1)] in_S = ["inS{}".format(i) for i in range(rounds)] bef_P = ["befP{}".format(i) for i in range(rounds)] aft_P = ["aftP{}".format(i) for i in range(rounds)] # w = weight w = ["sumw{}".format(i) for i in range(rounds)] w_i_0 = ["wiR{}".format(i) for i in range(rounds)] w_i_1 = ["wi1R{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, in_S, wordsize) stpcommands.setupVariables(stp_file, bef_P, wordsize) stpcommands.setupVariables(stp_file, aft_P, wordsize) stpcommands.setupVariables(stp_file, w, 16) stpcommands.setupVariables(stp_file, w_i_0, wordsize // 4) stpcommands.setupVariables(stp_file, w_i_1, wordsize // 4) stpcommands.setupWeightComputationSum(stp_file, weight, w, 16) self.SBOX_ACT_ASSERT(stp_file) for i in range(rounds): self.setupRound(stp_file, x[i], y[i], x[i+1], y[i+1], in_S[i], bef_P[i], aft_P[i], w[i], w_i_0[i], w_i_1[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, [x[0], y[0]], wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) stpcommands.assertVariableValue(stp_file, y[0], y[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for NOEKEON with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% NOEKEON w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables # a0 = ["A0{}".format(i) for i in range(rounds + 1)] a1 = ["A1{}".format(i) for i in range(rounds + 1)] a2 = ["A2{}".format(i) for i in range(rounds + 1)] a3 = ["A3{}".format(i) for i in range(rounds + 1)] theta0 = ["T0{}".format(i) for i in range(rounds)] theta1 = ["T1{}".format(i) for i in range(rounds)] theta2 = ["T2{}".format(i) for i in range(rounds)] theta3 = ["T3{}".format(i) for i in range(rounds)] pi10 = ["PI10{}".format(i) for i in range(rounds)] pi11 = ["PI11{}".format(i) for i in range(rounds)] pi12 = ["PI12{}".format(i) for i in range(rounds)] pi13 = ["PI13{}".format(i) for i in range(rounds)] gamma0 = ["G0{}".format(i) for i in range(rounds)] gamma1 = ["G1{}".format(i) for i in range(rounds)] gamma2 = ["G2{}".format(i) for i in range(rounds)] gamma3 = ["G3{}".format(i) for i in range(rounds)] pi20 = ["PI20{}".format(i) for i in range(rounds)] pi21 = ["PI21{}".format(i) for i in range(rounds)] pi22 = ["PI22{}".format(i) for i in range(rounds)] pi23 = ["PI23{}".format(i) for i in range(rounds)] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, a0, wordsize) stpcommands.setupVariables(stp_file, a1, wordsize) stpcommands.setupVariables(stp_file, a2, wordsize) stpcommands.setupVariables(stp_file, a3, wordsize) stpcommands.setupVariables(stp_file, theta0, wordsize) stpcommands.setupVariables(stp_file, theta1, wordsize) stpcommands.setupVariables(stp_file, theta2, wordsize) stpcommands.setupVariables(stp_file, theta3, wordsize) stpcommands.setupVariables(stp_file, pi10, wordsize) stpcommands.setupVariables(stp_file, pi11, wordsize) stpcommands.setupVariables(stp_file, pi12, wordsize) stpcommands.setupVariables(stp_file, pi13, wordsize) stpcommands.setupVariables(stp_file, pi20, wordsize) stpcommands.setupVariables(stp_file, pi21, wordsize) stpcommands.setupVariables(stp_file, pi22, wordsize) stpcommands.setupVariables(stp_file, pi23, wordsize) stpcommands.setupVariables(stp_file, gamma0, wordsize) stpcommands.setupVariables(stp_file, gamma1, wordsize) stpcommands.setupVariables(stp_file, gamma2, wordsize) stpcommands.setupVariables(stp_file, gamma3, wordsize) stpcommands.setupVariables(stp_file, w, wordsize * 4) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize * 4) for i in range(rounds): self.setupNoekeonRound(stp_file, a0[i], a1[i], a2[i], a3[i], theta0[i], theta1[i], theta2[i], theta3[i], gamma0[i], gamma1[i], gamma2[i], gamma3[i], pi10[i], pi11[i], pi12[i], pi13[i], pi20[i], pi21[i], pi22[i], pi23[i], a0[i + 1], a1[i + 1], a2[i + 1], a3[i + 1], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, a0 + a1 + a2 + a3, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, a0[0], a0[rounds]) stpcommands.assertVariableValue(stp_file, a1[0], a1[rounds]) stpcommands.assertVariableValue(stp_file, a2[0], a2[rounds]) stpcommands.assertVariableValue(stp_file, a3[0], a3[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SipHash with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] self.num_messages = parameters["nummessages"] with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Siphash w={} " "rounds={}\n\n\n".format(wordsize, rounds)) # Setup variables # state = v0, v1, v2, v3 # intermediate values = a0, a1, a2, a3 v0 = ["v0{}".format(i) for i in range((rounds + 1) * self.num_messages)] v1 = ["v1{}".format(i) for i in range((rounds + 1) * self.num_messages)] v2 = ["v2{}".format(i) for i in range((rounds + 1) * self.num_messages)] v3 = ["v3{}".format(i) for i in range((rounds + 1) * self.num_messages)] a0 = ["a0{}".format(i) for i in range((rounds + 1) * self.num_messages)] a1 = ["a1{}".format(i) for i in range((rounds + 1) * self.num_messages)] a2 = ["a2{}".format(i) for i in range((rounds + 1) * self.num_messages)] a3 = ["a3{}".format(i) for i in range((rounds + 1) * self.num_messages)] m = ["m{}".format(i) for i in range(self.num_messages)] # w = weight of each modular addition w0 = ["w0{}".format(i) for i in range(rounds * self.num_messages)] w1 = ["w1{}".format(i) for i in range(rounds * self.num_messages)] w2 = ["w2{}".format(i) for i in range(rounds * self.num_messages)] w3 = ["w3{}".format(i) for i in range(rounds * self.num_messages)] stpcommands.setupVariables(stp_file, v0 + v1 + v2 + v3, wordsize) stpcommands.setupVariables(stp_file, a0 + a1 + a2 + a3, wordsize) stpcommands.setupVariables(stp_file, w0 + w1 + w2 + w3, wordsize) stpcommands.setupVariables(stp_file, m, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w0 + w1 + w2 + w3, wordsize, 1) for block in range(self.num_messages): self.setupSipBlock(stp_file, block, rounds, m, v0, v1, v2, v3, a0, a1, a2, a3, w0, w1, w2, w3, wordsize) # TODO: There are many different attack scenarios interesting here, # but no interface exists at the moment to support this # without using different "ciphers". ## Uncomment to search for internal collision # zero_string = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, v0[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v1[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v2[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v3[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v0[0], zero_string) # stpcommands.assertVariableValue(stp_file, v1[0], zero_string) # stpcommands.assertVariableValue(stp_file, v2[0], zero_string) # stpcommands.assertVariableValue(stp_file, v3[0], zero_string) # stpcommands.assertNonZero(stp_file, m, wordsize) # stp_file.write(self.getStringForCollision(v0[rounds], v1[rounds], # v2[rounds], v3[rounds], wordsize)) ## Uncomment to search for internal collision for a single block # zero_string = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, v0[rounds], zero_string) # #stpcommands.assertVariableValue(stp_file, v1[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v2[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v3[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v0[0], zero_string) # stpcommands.assertVariableValue(stp_file, v1[0], zero_string) # stpcommands.assertVariableValue(stp_file, v2[0], zero_string) # stpcommands.assertVariableValue(stp_file, v3[0], v1[rounds]) # stpcommands.assertVariableValue(stp_file, m[0], zero_string) # stpcommands.assertVariableValue(stp_file, m[1], zero_string) # stpcommands.assertNonZero(stp_file, [v3[0]], wordsize) # stp_file.write(self.getStringForCollision(v0[rounds], v1[rounds], # v2[rounds], v3[rounds], wordsize)) ## Uncomment to search for Key Collisions # stpcommands.assertNonZero(stp_file, [v0[0], v1[0]], wordsize) # stpcommands.assertVariableValue(stp_file, v0[0], v3[0]) # stpcommands.assertVariableValue(stp_file, v1[0], v2[0]) # stp_file.write(self.getStringForCollision(v0[rounds], v1[rounds], # v2[rounds], v3[rounds], wordsize)) ## Uncomment to search for message collision stpcommands.assertNonZero(stp_file, m, wordsize) zero_string = "0hex" + "0"*(wordsize / 4) stpcommands.assertVariableValue(stp_file, v0[0], zero_string) stpcommands.assertVariableValue(stp_file, v1[0], zero_string) stpcommands.assertVariableValue(stp_file, v2[0], zero_string) stpcommands.assertVariableValue(stp_file, v3[0], zero_string) stp_file.write(self.getStringForCollision(v0[rounds*self.num_messages], v1[rounds*self.num_messages], v2[rounds*self.num_messages], v3[rounds*self.num_messages], wordsize)) ## Uncomment to search for characteristic / distinguisher # for i in m: # zero_string = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, i, zero_string) # stpcommands.assertNonZero(stp_file, v0 + v1 + v2 + v3, wordsize) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file for SIMON. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] # Replace with custom if set in parameters. if "rotationconstants" in parameters: self.rot_alpha = parameters["rotationconstants"][0] self.rot_beta = parameters["rotationconstants"][1] self.rot_gamma = parameters["rotationconstants"][2] self.num_messages = parameters["nummessages"] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% Simon w={} alpha={} beta={}" " gamma={} rounds={}\n\n\n".format( wordsize, self.rot_alpha, self.rot_beta, self.rot_gamma, rounds)) stp_file.write(header) # Setup key key = ["key{}".format(i) for i in range(rounds + 1)] tmp_key = ["tmpkey{}".format(i) for i in range(rounds + 1)] stpcommands.setupVariables(stp_file, key, wordsize) stpcommands.setupVariables(stp_file, tmp_key, wordsize) #TODO Add constant addition self.setupKeySchedule(stp_file, key, tmp_key, rounds, wordsize) # Setup variables # x = left, y = right for msg in range(self.num_messages): x = ["x{}r{}".format(msg, i) for i in range(rounds + 1)] y = ["y{}r{}".format(msg, i) for i in range(rounds + 1)] and_out = [ "andout{}r{}".format(msg, i) for i in range(rounds + 1) ] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, and_out, wordsize) #Setup Rounds for i in range(rounds): self.setupSimonRound(stp_file, x[i], y[i], x[i + 1], y[i + 1], and_out[i], key[i], wordsize) #Differences between x_0 and x_i for msg in range(1, self.num_messages): delta_x = ["dx{}r{}".format(msg, i) for i in range(rounds + 1)] delta_y = ["dy{}r{}".format(msg, i) for i in range(rounds + 1)] stpcommands.setupVariables(stp_file, delta_x, wordsize) stpcommands.setupVariables(stp_file, delta_y, wordsize) for i in range(rounds + 1): stp_file.write("ASSERT({} = BVXOR({}, {}));\n".format( delta_x[i], "x0r{}".format(i), "x{}r{}".format(msg, i))) stp_file.write("ASSERT({} = BVXOR({}, {}));\n".format( delta_y[i], "y0r{}".format(i), "y{}r{}".format(msg, i))) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a differential trail for Gimli with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if "rotationconstants" in parameters: self.d = parameters["rotationconstants"][0] self.e = parameters["rotationconstants"][1] self.f = parameters["rotationconstants"][2] with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Gimli w={}" "rounds={}\n\n\n".format(wordsize, rounds)) # Setup variables x = ["x{}r{}".format(j, i) for i in range(rounds + 1) for j in range(4)] xsb = ["xsb{}r{}".format(j, i) for i in range(rounds) for j in range(4)] y = ["y{}r{}".format(j, i) for i in range(rounds + 1) for j in range(4)] ysb = ["ysb{}r{}".format(j, i) for i in range(rounds) for j in range(4)] z = ["z{}r{}".format(j, i) for i in range(rounds + 1) for j in range(4)] zsb = ["zsb{}r{}".format(j, i) for i in range(rounds + 1) for j in range(4)] w = ["rw{}".format(i) for i in range(rounds)] wp = ["rwp{}r{}".format(j, i) for i in range(rounds) for j in range(4)] xtmp = ["xtmp{}r{}".format(j, i) for i in range(rounds) for j in range(4)] ytmp = ["ytmp{}r{}".format(j, i) for i in range(rounds) for j in range(4)] ztmp = ["ztmp{}r{}".format(j, i) for i in range(rounds) for j in range(4)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, z, wordsize) stpcommands.setupVariables(stp_file, xtmp, wordsize) stpcommands.setupVariables(stp_file, ytmp, wordsize) stpcommands.setupVariables(stp_file, ztmp, wordsize) stpcommands.setupVariables(stp_file, xsb, wordsize) stpcommands.setupVariables(stp_file, ysb, wordsize) stpcommands.setupVariables(stp_file, zsb, wordsize) stpcommands.setupVariables(stp_file, wp, wordsize) stpcommands.setupVariables(stp_file, w, 16) for rnd in range(rounds): stp_file.write(stpcommands.getWeightString(wp[4*rnd:4*rnd + 4], wordsize, 0, w[rnd]) + "\n") stpcommands.setupWeightComputationSum(stp_file, weight, w, wordsize) # Rounds for rnd in range(rounds): if ((rnd) & 3) == 0: # Small Swap for perm in range(4): self.setupRound(stp_file, x[4*rnd + perm], y[4*rnd + perm], z[4*rnd + perm], xtmp[4*rnd + perm], ytmp[4*rnd + perm], ztmp[4*rnd + perm], xsb[4*rnd + perm], ysb[4*rnd + perm], zsb[4*rnd + perm], wp[4*rnd + perm], wordsize) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1)], xtmp[4*rnd + 1])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1)], ytmp[4*rnd])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1)], ztmp[4*rnd])) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1) + 1], xtmp[4*rnd])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1) + 1], ytmp[4*rnd + 1])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1) + 1], ztmp[4*rnd + 1])) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1) + 2], xtmp[4*rnd + 3])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1) + 2], ytmp[4*rnd + 2])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1) + 2], ztmp[4*rnd + 2])) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1) + 3], xtmp[4*rnd + 2])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1) + 3], ytmp[4*rnd + 3])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1) + 3], ztmp[4*rnd + 3])) elif ((rnd) & 3) == 2: # Big Swap for perm in range(4): self.setupRound(stp_file, x[4*rnd + perm], y[4*rnd + perm], z[4*rnd + perm], xtmp[4*rnd + perm], ytmp[4*rnd + perm], ztmp[4*rnd + perm], xsb[4*rnd + perm], ysb[4*rnd + perm], zsb[4*rnd + perm], wp[4*rnd + perm], wordsize) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1)], xtmp[4*rnd + 2])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1)], ytmp[4*rnd])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1)], ztmp[4*rnd])) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1) + 1], xtmp[4*rnd + 3])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1) + 1], ytmp[4*rnd + 1])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1) + 1], ztmp[4*rnd + 1])) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1) + 2], xtmp[4*rnd])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1) + 2], ytmp[4*rnd + 2])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1) + 2], ztmp[4*rnd + 2])) stp_file.write("ASSERT({} = {});\n".format(x[4*(rnd + 1) + 3], xtmp[4*rnd + 1])) stp_file.write("ASSERT({} = {});\n".format(y[4*(rnd + 1) + 3], ytmp[4*rnd + 3])) stp_file.write("ASSERT({} = {});\n".format(z[4*(rnd + 1) + 3], ztmp[4*rnd + 3])) else: # No Swap for perm in range(4): self.setupRound(stp_file, x[4*rnd + perm], y[4*rnd + perm], z[4*rnd + perm], x[4*(rnd + 1) + perm], y[4*(rnd + 1) + perm], z[4*(rnd + 1) + perm], xsb[4*rnd + perm], ysb[4*rnd + perm], zsb[4*rnd + perm], wp[4*rnd + perm], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x + y + z, wordsize) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for trifle with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] self.rounds = rounds weight = parameters["sweight"] if wordsize != 128: print("Only wordsize of 128-bit supported.") exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% trifle w={} " "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables """ x(r) is a variable modeling the 128-bit input difference to the (r+1)'th round y(r) is a variable modeling the 128-bit output difference from SubNibbles of the (r+1)'th round Example: x0 = x0[127, ..., 0] x0[3:0] : nibble 0 x0[127:124] : nibble 31 """ # note that the last integer index in the name of a variable \ # always shows the round's number in the CryptoSMT x = ["x%d" % i for i in range(rounds + 1)] y = ["y%d" % i for i in range(rounds)] k = ["k%d" % i for i in range(rounds + 1)] # w = weight w = ["w%d" % i for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, k, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in range(rounds): self.setupTrifleRound(stp_file, x[i], y[i], k[i], k[i + 1], x[i + 1], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, [x[0]], wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) stpcommands.assertVariableValue(stp_file, k[0], k[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for CRAFT with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize != 64: print("Only wordsize of 64-bit supported.") exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% CRAFT w={} " "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables """ x(roundNumber), other variables are like this one. x(r) is a variable modeling the 64-bit input difference to the (r+1)'th round y(r) is a variable modeling the 64-bit output difference from MixColumn of the (r+1)'th round z(r) is a variable modeling the 64-bit output difference from PermuteNibble of the (r+1)'th round x(r+1) is a variable modeling the 64-bit output differenece from the (r+1)'th round Example: x0 = x0[63, 62, ..., 0] x0[3:0]: nibble 0 x0[63:60]: nibble 15 It is supposed that the input difference is as bellow: [x[3:0], x[7:4], ..., x[63:60]] """ # note that the last integer index in the name of a variable \ # always shows the round's number in the CryptoSMT x = ["x%d" % i for i in range(2)] y = ["y%d" % i for i in range(2)] z = ["z%d" % i for i in range(3)] # w = weight w = ["w%d" % i for i in range(2)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, z, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in [1, 6, 10, 14]: self.setupMembership(stp_file, "z0", i) for i in [1, 6, 10, 14]: self.setupMembership(stp_file, "z2", i) for i in range(2): self.setupSbox(stp_file, z[i], x[i], w[i], wordsize) self.setupMixColumn(stp_file, x[i], y[i], wordsize) self.setupPermuteNibble(stp_file, y[i], z[i + 1], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, [z[0]], wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SIMON in the related-key scenario with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] # Replace with custom if set in parameters. if "rotationconstants" in parameters: self.rot_alpha = parameters["rotationconstants"][0] self.rot_beta = parameters["rotationconstants"][1] self.rot_gamma = parameters["rotationconstants"][2] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% Simon w={} alpha={} beta={}" " gamma={} rounds={}\n\n\n".format( wordsize, self.rot_alpha, self.rot_beta, self.rot_gamma, rounds)) stp_file.write(header) # Setup variable # x = left, y = right x = ["x{}".format(i) for i in range(rounds + 1)] y = ["y{}".format(i) for i in range(rounds + 1)] k = ["k{}".format(i) for i in range(rounds)] and_out = ["andout{}".format(i) for i in range(rounds + 1)] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, k, wordsize) stpcommands.setupVariables(stp_file, and_out, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) #Key Schedule self.setupSimonKey(stp_file, k, rounds, wordsize) for i in range(rounds): self.setupSimonRound(stp_file, x[i], y[i], k[i], x[i + 1], y[i + 1], and_out[i], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x + y, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) stpcommands.assertVariableValue(stp_file, y[0], y[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for CRAFT with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize != 64: print("Only wordsize of 64-bit supported.") exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% CRAFT w={} " "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables """ x(roundNumber), other variables are like this one. x(r) is a 64-bit variable modeling the 64-bit input difference to the (r+1)'th round y(r) is a 64-bit variable modeling the 64-bit output difference from MixColumn of the (r+1)'th round z(r) is a 64-bit variable modeling the 64-bit difference after AddRoundkey of the (r+1)'th round x(r+1) is a 64-bit variable modeling the 64-bit output differenece from the (r+1)'th round Example: x0 = x0[63, 62, ..., 0] x0[3:0]: nibble 0 x0[63:60]: nibble 15 """ # note that the last integer index in the name of a variable \ # always shows the round's number in the CryptoSMT x = ["x%d" % i for i in range(rounds + 1)] y = ["y%d" % i for i in range(rounds)] z = ["z%d" % i for i in range(rounds)] t = ["t0"] k0 = ["k0"] k1 = ["k1"] k2 = ["k2"] k3 = ["k3"] tk0 = ["tk0"] tk1 = ["tk1"] tk2 = ["tk2"] tk3 = ["tk3"] tk = [tk0[0], tk1[0], tk2[0], tk3[0]] # w = weight w = ["w%d" % i for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, z, wordsize) stpcommands.setupVariables(stp_file, tk0, wordsize) stpcommands.setupVariables(stp_file, tk1, wordsize) stpcommands.setupVariables(stp_file, tk2, wordsize) stpcommands.setupVariables(stp_file, tk3, wordsize) stpcommands.setupVariables(stp_file, t, wordsize) stpcommands.setupVariables(stp_file, k0, wordsize) stpcommands.setupVariables(stp_file, k1, wordsize) stpcommands.setupVariables(stp_file, k2, wordsize) stpcommands.setupVariables(stp_file, k3, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) # initialize tweakeys command = self.init_tweakey(k0[0], k1[0], t[0]) stp_file.write(command) # write rounds constraints for i in range(rounds): self.setupCraftRound(stp_file, x[i], y[i], z[i], tk[(i + 1) % 4], x[i+1], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for Salsa with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Salsa w={}" "rounds={}\n\n\n".format(wordsize, rounds)) # Setup variables a = [ "a{}r{}".format(j, i) for i in range(rounds + 1) for j in range(16) ] b = [ "b{}r{}".format(j, i) for i in range(rounds) for j in range(16) ] w = [ "w{}r{}".format(j, i) for i in range(rounds) for j in range(16) ] stpcommands.setupVariables(stp_file, a, wordsize) stpcommands.setupVariables(stp_file, b, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) # Ignore MSB stpcommands.setupWeightComputation(stp_file, weight, w, wordsize, 1) for rnd in range(rounds): if rnd % 2 != 0: #Rowround for row in range(4): a_in = [ a[(i + row) % 4 + 4 * row + 16 * rnd] for i in range(4) ] a_out = [ a[(i + row) % 4 + 4 * row + 16 * (rnd + 1)] for i in range(4) ] tmp_b = [b[i + 4 * row + 16 * rnd] for i in range(4)] tmp_w = [w[i + 4 * row + 16 * rnd] for i in range(4)] self.setupQuarterRound(stp_file, a_in, tmp_b, a_out, tmp_w, wordsize) else: #Columnround for col in range(4): a_in = [ a[(i * 4 + 4 * col + col) % 16 + 16 * rnd] for i in range(4) ] a_out = [ a[(i * 4 + 4 * col + col) % 16 + 16 * (rnd + 1)] for i in range(4) ] tmp_b = [b[i * 4 + col + 16 * rnd] for i in range(4)] tmp_w = [w[i * 4 + col + 16 * rnd] for i in range(4)] self.setupQuarterRound(stp_file, a_in, tmp_b, a_out, tmp_w, wordsize) #stp_file.write("ASSERT(({}[31:31]) = 0b0);\n".format(a[0])) # No all zero characteristic stpcommands.assertNonZero(stp_file, a, wordsize) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for CRAFT with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize != 64: print("Only wordsize of 64-bit supported.") exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% CRAFT w={} " "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables """ x(roundNumber), other variables are like this one. x(r) is a variable modeling the 64-bit input difference to the (r+1)'th round y(r) is a variable modeling the 64-bit output difference from MixColumn of the (r+1)'th round z(r) is a variable modeling the 64-bit output difference from PermuteNibble of the (r+1)'th round x(r+1) is a variable modeling the 64-bit output differenece from the (r+1)'th round Example: x0 = x0[63, 62, ..., 0] x0[3:0]: nibble 0 x0[63:60]: nibble 15 It is supposed that the input difference is as bellow: [x[3:0], x[7:4], ..., x[63:60]] """ # note that the last integer index in the name of a variable \ # always shows the round's number in the CryptoSMT x = ["x%d" % i for i in range(rounds + 1)] y = ["y%d" % i for i in range(rounds)] z = ["z%d" % i for i in range(rounds)] # w = weight w = ["w%d" % i for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, z, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in range(rounds): self.setupCraftRound(stp_file, x[i], y[i], z[i], x[i+1], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SipHash with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] self.num_messages = parameters["nummessages"] with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Siphash w={} " "rounds={}\n\n\n".format(wordsize, rounds)) # Setup variables # state = v0, v1, v2, v3 # intermediate values = a0, a1, a2, a3 v0 = [ "v0{}".format(i) for i in range((rounds + 1) * self.num_messages) ] v1 = [ "v1{}".format(i) for i in range((rounds + 1) * self.num_messages) ] v2 = [ "v2{}".format(i) for i in range((rounds + 1) * self.num_messages) ] v3 = [ "v3{}".format(i) for i in range((rounds + 1) * self.num_messages) ] a0 = [ "a0{}".format(i) for i in range((rounds + 1) * self.num_messages) ] a1 = [ "a1{}".format(i) for i in range((rounds + 1) * self.num_messages) ] a2 = [ "a2{}".format(i) for i in range((rounds + 1) * self.num_messages) ] a3 = [ "a3{}".format(i) for i in range((rounds + 1) * self.num_messages) ] m = ["m{}".format(i) for i in range(self.num_messages)] # w = weight of each modular addition w0 = ["w0{}".format(i) for i in range(rounds * self.num_messages)] w1 = ["w1{}".format(i) for i in range(rounds * self.num_messages)] w2 = ["w2{}".format(i) for i in range(rounds * self.num_messages)] w3 = ["w3{}".format(i) for i in range(rounds * self.num_messages)] stpcommands.setupVariables(stp_file, v0 + v1 + v2 + v3, wordsize) stpcommands.setupVariables(stp_file, a0 + a1 + a2 + a3, wordsize) stpcommands.setupVariables(stp_file, w0 + w1 + w2 + w3, wordsize) stpcommands.setupVariables(stp_file, m, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w0 + w1 + w2 + w3, wordsize, 1) for block in range(self.num_messages): self.setupSipBlock(stp_file, block, rounds, m, v0, v1, v2, v3, a0, a1, a2, a3, w0, w1, w2, w3, wordsize) # TODO: There are many different attack scenarios interesting here, # but no interface exists at the moment to support this # without using different "ciphers". ## Uncomment to search for internal collision # zero_string = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, v0[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v1[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v2[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v3[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v0[0], zero_string) # stpcommands.assertVariableValue(stp_file, v1[0], zero_string) # stpcommands.assertVariableValue(stp_file, v2[0], zero_string) # stpcommands.assertVariableValue(stp_file, v3[0], zero_string) # stpcommands.assertNonZero(stp_file, m, wordsize) # stp_file.write(self.getStringForCollision(v0[rounds], v1[rounds], # v2[rounds], v3[rounds], wordsize)) ## Uncomment to search for internal collision for a single block # zero_string = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, v0[rounds], zero_string) # #stpcommands.assertVariableValue(stp_file, v1[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v2[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v3[rounds], zero_string) # stpcommands.assertVariableValue(stp_file, v0[0], zero_string) # stpcommands.assertVariableValue(stp_file, v1[0], zero_string) # stpcommands.assertVariableValue(stp_file, v2[0], zero_string) # stpcommands.assertVariableValue(stp_file, v3[0], v1[rounds]) # stpcommands.assertVariableValue(stp_file, m[0], zero_string) # stpcommands.assertVariableValue(stp_file, m[1], zero_string) # stpcommands.assertNonZero(stp_file, [v3[0]], wordsize) # stp_file.write(self.getStringForCollision(v0[rounds], v1[rounds], # v2[rounds], v3[rounds], wordsize)) ## Uncomment to search for Key Collisions # stpcommands.assertNonZero(stp_file, [v0[0], v1[0]], wordsize) # stpcommands.assertVariableValue(stp_file, v0[0], v3[0]) # stpcommands.assertVariableValue(stp_file, v1[0], v2[0]) # stp_file.write(self.getStringForCollision(v0[rounds], v1[rounds], # v2[rounds], v3[rounds], wordsize)) ## Uncomment to search for message collision stpcommands.assertNonZero(stp_file, m, wordsize) zero_string = "0hex" + "0" * (wordsize / 4) stpcommands.assertVariableValue(stp_file, v0[0], zero_string) stpcommands.assertVariableValue(stp_file, v1[0], zero_string) stpcommands.assertVariableValue(stp_file, v2[0], zero_string) stpcommands.assertVariableValue(stp_file, v3[0], zero_string) stp_file.write( self.getStringForCollision(v0[rounds * self.num_messages], v1[rounds * self.num_messages], v2[rounds * self.num_messages], v3[rounds * self.num_messages], wordsize)) ## Uncomment to search for characteristic / distinguisher # for i in m: # zero_string = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, i, zero_string) # stpcommands.assertNonZero(stp_file, v0 + v1 + v2 + v3, wordsize) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for SPARX with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% SPARX w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables x0l = ["X0L{}".format(i) for i in range(rounds + 1)] x0r = ["X0R{}".format(i) for i in range(rounds + 1)] x1l = ["X1L{}".format(i) for i in range(rounds + 1)] x1r = ["X1R{}".format(i) for i in range(rounds + 1)] x2l = ["X2L{}".format(i) for i in range(rounds + 1)] x2r = ["X2R{}".format(i) for i in range(rounds + 1)] x3l = ["X3L{}".format(i) for i in range(rounds + 1)] x3r = ["X3R{}".format(i) for i in range(rounds + 1)] x0l_after_A = ["X0LA{}".format(i) for i in range(rounds + 1)] x0r_after_A = ["X0RA{}".format(i) for i in range(rounds + 1)] x1l_after_A = ["X1LA{}".format(i) for i in range(rounds + 1)] x1r_after_A = ["X1RA{}".format(i) for i in range(rounds + 1)] x2l_after_A = ["X2LA{}".format(i) for i in range(rounds + 1)] x2r_after_A = ["X2RA{}".format(i) for i in range(rounds + 1)] x3l_after_A = ["X3LA{}".format(i) for i in range(rounds + 1)] x3r_after_A = ["X3RA{}".format(i) for i in range(rounds + 1)] x0l_after_L = ["LX0L{}".format(i) for i in range(rounds + 1)] x0r_after_L = ["LX0R{}".format(i) for i in range(rounds + 1)] x1l_after_L = ["LX1L{}".format(i) for i in range(rounds + 1)] x1r_after_L = ["LX1R{}".format(i) for i in range(rounds + 1)] # w = weight wx0 = ["wx0{}".format(i) for i in range(rounds)] wx1 = ["wx1{}".format(i) for i in range(rounds)] wx2 = ["wx2{}".format(i) for i in range(rounds)] wx3 = ["wx3{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x0l, wordsize) stpcommands.setupVariables(stp_file, x0r, wordsize) stpcommands.setupVariables(stp_file, x1l, wordsize) stpcommands.setupVariables(stp_file, x1r, wordsize) stpcommands.setupVariables(stp_file, x2l, wordsize) stpcommands.setupVariables(stp_file, x2r, wordsize) stpcommands.setupVariables(stp_file, x3l, wordsize) stpcommands.setupVariables(stp_file, x3r, wordsize) stpcommands.setupVariables(stp_file, x0l_after_A, wordsize) stpcommands.setupVariables(stp_file, x0r_after_A, wordsize) stpcommands.setupVariables(stp_file, x1l_after_A, wordsize) stpcommands.setupVariables(stp_file, x1r_after_A, wordsize) stpcommands.setupVariables(stp_file, x2l_after_A, wordsize) stpcommands.setupVariables(stp_file, x2r_after_A, wordsize) stpcommands.setupVariables(stp_file, x3l_after_A, wordsize) stpcommands.setupVariables(stp_file, x3r_after_A, wordsize) stpcommands.setupVariables(stp_file, x0l_after_L, wordsize) stpcommands.setupVariables(stp_file, x0r_after_L, wordsize) stpcommands.setupVariables(stp_file, x1l_after_L, wordsize) stpcommands.setupVariables(stp_file, x1r_after_L, wordsize) stpcommands.setupVariables(stp_file, wx0, wordsize) stpcommands.setupVariables(stp_file, wx1, wordsize) stpcommands.setupVariables(stp_file, wx2, wordsize) stpcommands.setupVariables(stp_file, wx3, wordsize) # Ignore MSB stpcommands.setupWeightComputation(stp_file, weight, wx0 + wx1 + wx2 + wx3, wordsize, 1) for i in range(rounds): if ((i + 1) % self.rounds_per_step) == 0: #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x0l[i], x0r[i], x0l_after_A[i], x0r_after_A[i], wx0[i], wordsize) #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x1l[i], x1r[i], x1l_after_A[i], x1r_after_A[i], wx1[i], wordsize) #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x2l[i], x2r[i], x2l_after_A[i], x2r_after_A[i], wx2[i], wordsize) #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x3l[i], x3r[i], x3l_after_A[i], x3r_after_A[i], wx3[i], wordsize) #every step do L-box and feistel self.setupSPARXRound( stp_file, x0l_after_A[i], x0r_after_A[i], x1l_after_A[i], x1r_after_A[i], x2l_after_A[i], x2r_after_A[i], x3l_after_A[i], x3r_after_A[i], x0l_after_L[i], x0r_after_L[i], x1l_after_L[i], x1r_after_L[i], x0l[i + 1], x0r[i + 1], x1l[i + 1], x1r[i + 1], x2l[i + 1], x2r[i + 1], x3l[i + 1], x3r[i + 1]) else: #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x0l[i], x0r[i], x0l[i + 1], x0r[i + 1], wx0[i], wordsize) #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x1l[i], x1r[i], x1l[i + 1], x1r[i + 1], wx1[i], wordsize) #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x2l[i], x2r[i], x2l[i + 1], x2r[i + 1], wx2[i], wordsize) #do round function (SPECKEY) self.setupSPECKEYRound(stp_file, x3l[i], x3r[i], x3l[i + 1], x3r[i + 1], wx3[i], wordsize) # No all zero characteristic stpcommands.assertNonZero( stp_file, x0l + x0r + x1l + x1r + x2l + x2r + x3l + x3r, wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x0l[0], x0l[rounds]) stpcommands.assertVariableValue(stp_file, x0r[0], x0r[rounds]) stpcommands.assertVariableValue(stp_file, x1l[0], x1l[rounds]) stpcommands.assertVariableValue(stp_file, x1r[0], x1r[rounds]) stpcommands.assertVariableValue(stp_file, x2l[0], x2l[rounds]) stpcommands.assertVariableValue(stp_file, x2r[0], x2r[rounds]) stpcommands.assertVariableValue(stp_file, x3l[0], x3l[rounds]) stpcommands.assertVariableValue(stp_file, x3r[0], x3r[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for ChasKey with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] self.num_messages = parameters["nummessages"] with open(stp_filename, "w") as stp_file: stp_file.write("% Input File for STP\n% ChasKeyMac w={} rounds={}" "\n\n\n".format(wordsize, rounds)) # Setup variables # state = v0, v1, v2, v3 # intermediate values = a0, a1, a2, a3 v0 = ["v0{}".format(i) for i in range((rounds + 1) * self.num_messages)] v1 = ["v1{}".format(i) for i in range((rounds + 1) * self.num_messages)] v2 = ["v2{}".format(i) for i in range((rounds + 1) * self.num_messages)] v3 = ["v3{}".format(i) for i in range((rounds + 1) * self.num_messages)] # w = weight of each modular addition w0 = ["w0{}".format(i) for i in range(rounds * self.num_messages)] w1 = ["w1{}".format(i) for i in range(rounds * self.num_messages)] stpcommands.setupVariables(stp_file, v0, wordsize) stpcommands.setupVariables(stp_file, v1, wordsize) stpcommands.setupVariables(stp_file, v2, wordsize) stpcommands.setupVariables(stp_file, v3, wordsize) stpcommands.setupVariables(stp_file, w0, wordsize) stpcommands.setupVariables(stp_file, w1, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w0 + w1, wordsize, 1) # Minimize Weight in middle rounds # stpcommands.limitWeight(stp_file, 10, w0[2:4] + w1[2:4], wordsize, 1) for i in range(rounds): self.setupChasKeyRound( stp_file, i, v0[i], v1[i], v2[i], v3[i], v0[i + 1], v1[i + 1], v2[i + 1], v3[i + 1], w0[i], w1[i], wordsize, ) # Message Collision stpcommands.assertNonZero(stp_file, v0 + v1 + v2 + v3, wordsize) # zeroString = "0hex" + "0"*(wordsize / 4) # stpcommands.assertVariableValue(stp_file, v0[rounds], zeroString) # stpcommands.assertVariableValue(stp_file, v1[rounds], zeroString) # stpcommands.assertVariableValue(stp_file, v2[rounds], zeroString) # stpcommands.assertVariableValue(stp_file, v3[rounds], zeroString) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for CRAFT with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize != 64: print("Only wordsize of 64-bit supported.") exit(1) with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% CRAFT w={} " "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables """ x(roundNumber), other variables are like this one. x(r) is a variable modeling the 64-bit input difference to the (r+1)'th round y(r) is a variable modeling the 64-bit output difference from MixColumn of the (r+1)'th round z(r) is a variable modeling the 64-bit output difference from PermuteNibble of the (r+1)'th round x(r+1) is a variable modeling the 64-bit output differenece from the (r+1)'th round Example: x0 = x0[63, 62, ..., 0] x0[3:0]: nibble 0 x0[63:60]: nibble 15 It is supposed that the input difference is as bellow: [x[3:0], x[7:4], ..., x[63:60]] """ # note that the last integer index in the name of a variable \ # always shows the round's number in the CryptoSMT x = ["x%d" % i for i in range(7)] y = ["y%d" % i for i in range(7)] z = ["z%d" % i for i in range(7)] # w = weight w = ["w%d" % i for i in range(6)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, z, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) # - z4[15:12] in {0x5, 0x7, 0xA, 0xD, 0xF} # - z4[19:16] in {0x5, 0x7, 0xA, 0xD, 0xF} # - z4[35:32] in {0x5, 0x7, 0xA, 0xD, 0xF} # - z4[51:48] in {0x5, 0x7, 0xA, 0xD, 0xF} """ ASSERT((z4[14:14] | ~z4[12:12]) & (~z4[14:14] | z4[12:12]) & (z4[13:13] | z4[12:12]) & (z4[15:15] | z4[12:12]) = 0bin1); ASSERT((z4[18:18] | ~z4[16:16]) & (~z4[18:18] | z4[16:16]) & (z4[17:17] | z4[16:16]) & (z4[19:19] | z4[16:16]) = 0bin1); ASSERT((z4[34:34] | ~z4[32:32]) & (~z4[34:34] | z4[32:32]) & (z4[33:33] | z4[32:32]) & (z4[35:35] | z4[32:32]) = 0bin1); ASSERT((z4[50:50] | ~z4[48:48]) & (~z4[50:50] | z4[48:48]) & (z4[49:49] | z4[48:48]) & (z4[51:51] | z4[48:48]) = 0bin1); """ for i in [3, 4, 8, 12]: self.setupMembership(stp_file, "z4", i) for i in range(6): self.setupMixColumn(stp_file, x[i], y[i], wordsize) self.setupPermuteNibble(stp_file, y[i], z[i], wordsize) self.setupSbox(stp_file, z[i], x[i + 1], w[i], wordsize) self.setupMixColumn(stp_file, x[6], y[6], wordsize) self.setupPermuteNibble(stp_file, y[6], z[6], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, [x[0]], wordsize) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for BAT diff pattern with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize == 32: self.PERM = [7, 4, 1, 6, 3, 0, 5, 2] elif wordsize == 64: self.PERM = [14, 15, 8, 9, 2, 3, 12, 13, 6, 7, 0, 1, 10, 11, 4, 5] else: raise Exception("Wrong wordsize!") with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP: BAT diff pattern\n" "% w = {} alpha = {} beta = {}\n" "% rounds = {}\n\n".format(wordsize, self.rot_alpha, self.rot_beta, rounds)) stp_file.write(header) # Setup variables # x as left, y as right x = ["x{}".format(i) for i in range(rounds + 1)] y = ["y{}".format(i) for i in range(rounds + 1)] in_G0 = ["inG0{}".format(i) for i in range(rounds)] in_G1 = ["inG1{}".format(i) for i in range(rounds)] xor_G = ["xorG{}".format(i) for i in range(rounds)] perm_G = ["permG{}".format(i) for i in range(rounds)] # w = weight w = ["sumw{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize // 4) stpcommands.setupVariables(stp_file, y, wordsize // 4) stpcommands.setupVariables(stp_file, in_G0, wordsize // 4) stpcommands.setupVariables(stp_file, in_G1, wordsize // 4) stpcommands.setupVariables(stp_file, xor_G, wordsize // 4) stpcommands.setupVariables(stp_file, perm_G, wordsize // 4) stpcommands.setupVariables(stp_file, w, 16) stpcommands.setupWeightComputationSum(stp_file, weight, w, 16) for i in range(rounds): self.setupRound(stp_file, x[i], y[i], x[i + 1], y[i + 1], in_G0[i], in_G1[i], xor_G[i], perm_G[i], w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, [x[0], y[0]], wordsize // 4) # Iterative characteristics only # Input difference = Output difference if parameters["iterative"]: stpcommands.assertVariableValue(stp_file, x[0], x[rounds]) stpcommands.assertVariableValue(stp_file, y[0], y[rounds]) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) for char in parameters["blockedCharacteristics"]: stpcommands.blockCharacteristic(stp_file, char, wordsize // 4) stpcommands.setupQuery(stp_file) return