def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a preimage for Keccak. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] # Default rate and capacity capacity = 160 rate = (wordsize * 25) - capacity if "rate" in parameters: rate = parameters["rate"] if "capacity" in parameters: capacity = parameters["capacity"] assert (rate + capacity) == wordsize * 25 with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Keccak w={} rate={} " "capacity={}\n\n\n".format(wordsize, rate, capacity, rounds)) # Setup variables # 5x5 lanes of wordsize s = ["s{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5)] a = ["a{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5)] b = ["b{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5)] c = ["c{}{}".format(x, i) for i in range(rounds + 1) for x in range(5)] d = ["d{}{}".format(x, i) for i in range(rounds + 1) for x in range(5)] 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, d, 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.setupKeccakRound(stp_file, rnd, s, a, b, c, d, wordsize) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file to find a characteristic for LBlock 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% LBlock w={}" "rounds={}\n\n\n".format(wordsize,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)] f_out = ["fout{}".format(i) for i in range(rounds + 1)] s_out = ["sout{}".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, f_out, wordsize) stpcommands.setupVariables(stp_file, s_out, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in range(rounds): self.setupLBlockRound(stp_file, x[i], y[i], x[i+1], y[i+1], f_out[i], s_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 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)] sc = ["x{}".format(i) for i in range(rounds + 1)] sr = ["y{}".format(i) for i in range(rounds)] mc = ["z{}".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 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 Midori with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["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% MIDORI w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables sb = ["SB{}".format(i) for i in range(rounds + 1)] sc = ["SC{}".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, sb, wordsize) stpcommands.setupVariables(stp_file, sc, wordsize) stpcommands.setupVariables(stp_file, mc, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) stpcommands.setupWeightComputation(stp_file, weight, w, wordsize) for i in range(rounds): self.setupMidoriRound(stp_file, sb[i], sc[i], mc[i], sb[i+1], w[i], 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 TWINE 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% TWINE w={}" "rounds={}\n\n\n".format(wordsize, rounds)) stp_file.write(header) # Setup variables # x = input, s = S-Box layer output, p = permutation layer input x = ["X{}".format(i) for i in range(rounds + 1)] s = ["S{}".format(i) for i in range(rounds)] p = ["P{}".format(i) for i in range(rounds)] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) 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.setupTwineRound(stp_file, x[i], s[i], p[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 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 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 characteristic for ChaCha 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) # 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 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 to find a characteristic for RECTANGLE with the given parameters. """ blocksize = parameters["blocksize"] wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] with open(stp_filename, 'w') as stp_file: header = ("% Input File for STP\n% Rectangle 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)] # 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, w, blocksize) stpcommands.setupWeightComputation(stp_file, weight, w, blocksize) for i in range(rounds): self.setupRectangleRound(stp_file, sc[i], sr[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 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 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 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 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 for Keccak. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] capacity = 160 rate = (wordsize * 25) - capacity if "rate" in parameters: rate = parameters["rate"] if "capacity" in parameters: capacity = parameters["capacity"] assert (rate + capacity) == wordsize * 25 with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Keccak w={} rate={} " "capacity={}\n\n\n".format(wordsize, rate, capacity, rounds)) # Setup variables # 5x5 lanes of wordsize s = [ "s{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5) ] b = [ "b{}{}{}".format(x, y, i) for i in range(rounds) for y in range(5) for x in range(5) ] c = ["c{}{}".format(x, i) for i in range(rounds) for x in range(5)] d = ["d{}{}".format(x, i) for i in range(rounds) for x in range(5)] xin = [ "xin{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) for z in range(wordsize) ] xout = [ "xout{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) for z in range(wordsize) ] andOut = [ "andOut{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) 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(5) for z in range(wordsize) ] stpcommands.setupVariables(stp_file, s, wordsize) stpcommands.setupVariables(stp_file, b, wordsize) stpcommands.setupVariables(stp_file, c, wordsize) stpcommands.setupVariables(stp_file, d, wordsize) stpcommands.setupVariables(stp_file, w, 16) stpcommands.setupVariables(stp_file, tmp, 5) stpcommands.setupWeightComputationSum(stp_file, weight, w, wordsize) stpcommands.setupVariables(stp_file, xin, 5) stpcommands.setupVariables(stp_file, xout, 5) stpcommands.setupVariables(stp_file, andOut, 5) # 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.setupKeccakRound(stp_file, rnd, s, b, c, d, wordsize, tmp, w, xin, xout, andOut) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) stpcommands.setupQuery(stp_file) return
def createSTP(self, stp_filename, parameters): """ Creates an STP file for Ketje. """ 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% Ketje w={} rounds={}" "\n\n\n".format(wordsize, rounds)) # Setup variables # 5x5 lanes of wordsize s = ["s{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5)] a = ["a{}{}{}".format(x, y, i) for i in range(rounds) for y in range(5) for x in range(5)] b = ["b{}{}{}".format(x, y, i) for i in range(rounds) for y in range(5) for x in range(5)] c = ["c{}{}".format(x, i) for i in range(rounds + 1) for x in range(5)] d = ["d{}{}".format(x, i) for i in range(rounds + 1) for x in range(5)] m = ["m{}{}".format(x, i) for i in range(rounds +1) for x in range(2)] xin = ["xin{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) for z in range (wordsize)] xout = ["xout{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) for z in range (wordsize)] andOut = ["andOut{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) 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(5) 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, d, wordsize) stpcommands.setupVariables(stp_file, w, 16) stpcommands.setupVariables(stp_file, tmp, 5) stpcommands.setupWeightComputationSum(stp_file, weight, w, wordsize) stpcommands.setupVariables(stp_file, xin, 5) stpcommands.setupVariables(stp_file, xout, 5) stpcommands.setupVariables(stp_file, andOut, 5) stpcommands.setupVariables(stp_file, m, wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, a, wordsize) for rnd in range(rounds): self.setupKeccakRound(stp_file, rnd, s, a, b, c, d, wordsize, tmp, w, m, xin, xout, andOut) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) 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 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 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 preimage for Keccak. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] # Default rate and capacity capacity = 160 rate = (wordsize * 25) - capacity if "rate" in parameters: rate = parameters["rate"] if "capacity" in parameters: capacity = parameters["capacity"] assert (rate + capacity) == wordsize * 25 with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Keccak w={} rate={} " "capacity={}\n\n\n".format(wordsize, rate, capacity, rounds)) # Setup variables # 5x5 lanes of wordsize s = [ "s{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5) ] a = [ "a{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5) ] b = [ "b{}{}{}".format(x, y, i) for i in range(rounds + 1) for y in range(5) for x in range(5) ] c = [ "c{}{}".format(x, i) for i in range(rounds + 1) for x in range(5) ] d = [ "d{}{}".format(x, i) for i in range(rounds + 1) for x in range(5) ] 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, d, 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.setupKeccakRound(stp_file, rnd, s, a, b, c, d, wordsize) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) 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 CHAM 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% CHAM w={} " "rounds={}\n\n\n".format(wordsize, rounds)) # Setup variable # w = weight x0 = ["X0{}".format(i) for i in range(rounds + 1)] x1 = ["X1{}".format(i) for i in range(rounds + 1)] x2 = ["X2{}".format(i) for i in range(rounds + 1)] x3 = ["X3{}".format(i) for i in range(rounds + 1)] x0x1 = ["X0X1{}".format(i) for i in range(rounds + 1)] 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, x2, wordsize) stpcommands.setupVariables(stp_file, x3, wordsize) stpcommands.setupVariables(stp_file, x0x1, wordsize) stpcommands.setupVariables(stp_file, w, wordsize) # Ignore MSB stpcommands.setupWeightComputation(stp_file, weight, w, wordsize, 1) rot_x0 = 0 rot_x1 = 0 for i in range(rounds): if ((i+1) % 2) == 0: #even rounds rot_x1 = 8 rot_x0 = 1 else: #odd rounds rot_x1 = 1 rot_x0 = 8 self.setupCHAMRound(stp_file, x0[i], x1[i], x2[i], x3[i], x0[i+1], x1[i+1], x2[i+1], x3[i+1], x0x1[i], rot_x0, rot_x1, w[i], wordsize) # No all zero characteristic stpcommands.assertNonZero(stp_file, x0 + x1 + x2 + x3, 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, x2[0], x2[rounds]) stpcommands.assertVariableValue(stp_file, x3[0], x3[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(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 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_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): #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]) # 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 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 for Keccak. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] capacity = 160 rate = (wordsize * 25) - capacity if "rate" in parameters: rate = parameters["rate"] if "capacity" in parameters: capacity = parameters["capacity"] assert (rate + capacity) == wordsize * 25 with open(stp_filename, 'w') as stp_file: stp_file.write("% Input File for STP\n% Keccak w={} rate={} " "capacity={}\n\n\n".format(wordsize, rate, capacity, rounds)) # Setup variables # 5x5 lanes of wordsize s = ["s{}{}{}".format(x, y, i) for i in range(rounds+1) for y in range(5) for x in range(5)] b = ["b{}{}{}".format(x, y, i) for i in range(rounds) for y in range(5) for x in range(5)] c = ["c{}{}".format(x, i) for i in range(rounds) for x in range(5)] d = ["d{}{}".format(x, i) for i in range(rounds) for x in range(5)] xin = ["xin{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) for z in range (wordsize)] xout = ["xout{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) for z in range (wordsize)] andOut = ["andOut{}{}{}".format(y, z, i) for i in range(rounds) for y in range(5) 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(5) for z in range (wordsize)] stpcommands.setupVariables(stp_file, s, wordsize) stpcommands.setupVariables(stp_file, b, wordsize) stpcommands.setupVariables(stp_file, c, wordsize) stpcommands.setupVariables(stp_file, d, wordsize) stpcommands.setupVariables(stp_file, w, 16) stpcommands.setupVariables(stp_file, tmp, 5) stpcommands.setupWeightComputationSum(stp_file, weight, w, wordsize) stpcommands.setupVariables(stp_file, xin, 5) stpcommands.setupVariables(stp_file, xout, 5) stpcommands.setupVariables(stp_file, andOut, 5) # 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.setupKeccakRound(stp_file, rnd, s, b, c, d, wordsize, tmp, w, xin, xout, andOut) for key, value in parameters["fixedVariables"].items(): stpcommands.assertVariableValue(stp_file, key, value) 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 + 2) % 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 SIMON with the given parameters. """ blocksize = parameters["blocksize"] wordsize = parameters["wordsize"] keysize = parameters["keysize"] tweaksize = parameters["tweaksize"] rounds = parameters["rounds"] weight = parameters["sweight"] if blocksize != 64: print("Only blocksize of 64-bit supported.") exit(1) if (keysize + tweaksize) % 64 != 0: print("Tweakeysize must be a multiple of 64-bits") exit(1) # calculate the number of Tweakey words # // -> integer division nrOfTK = (keysize + tweaksize) // 64 #print(nrOfTK) 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)] atk = ["ATK{}".format(i) for i in range(rounds)] sr = ["SR{}".format(i) for i in range(rounds)] mc = ["MC{}".format(i) for i in range(rounds)] tk = [ "TK{}{}".format(i, j) for j in range(rounds) for i in range(nrOfTK) ] tk_after_pt = [ "TKP{}{}".format(i, j) for j in range(rounds) for i in range(nrOfTK) ] # w = weight w = ["w{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, sc, blocksize) stpcommands.setupVariables(stp_file, atk, blocksize) stpcommands.setupVariables(stp_file, sr, blocksize) stpcommands.setupVariables(stp_file, mc, blocksize) stpcommands.setupVariables(stp_file, tk, blocksize) stpcommands.setupVariables(stp_file, tk_after_pt, blocksize) stpcommands.setupVariables(stp_file, w, blocksize) stpcommands.setupWeightComputation(stp_file, weight, w, blocksize) self.setupTweakeySchedule(stp_file, tk, tk_after_pt, rounds, blocksize, nrOfTK) for i in range(rounds): if nrOfTK == 1: self.setupSkinnyRound(stp_file, sc[i], atk[i], sr[i], mc[i], sc[i + 1], w[i], blocksize, nrOfTK, tk[i]) if nrOfTK == 2: self.setupSkinnyRound(stp_file, sc[i], atk[i], sr[i], mc[i], sc[i + 1], w[i], blocksize, nrOfTK, tk[i], tk[i + (rounds)]) if nrOfTK == 3: self.setupSkinnyRound(stp_file, sc[i], atk[i], sr[i], mc[i], sc[i + 1], w[i], blocksize, nrOfTK, tk[i], tk[i + (rounds)], tk[i + (2 * rounds)]) # 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 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 BAT diff pattern 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 diff 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 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)] out_G0 = ["outG0{}".format(i) for i in range(rounds)] out_G1 = ["outG1{}".format(i) for i in range(rounds)] rot_G0 = ["rotG0{}".format(i) for i in range(rounds)] rot_G1 = ["rotG1{}".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)] act_flag = ["actflag{}".format(i) for i in range(rounds)] stpcommands.setupVariables(stp_file, x, wordsize) stpcommands.setupVariables(stp_file, y, wordsize) stpcommands.setupVariables(stp_file, out_G0, wordsize) stpcommands.setupVariables(stp_file, out_G1, wordsize) stpcommands.setupVariables(stp_file, rot_G0, wordsize) stpcommands.setupVariables(stp_file, rot_G1, wordsize) stpcommands.setupVariables(stp_file, xor_G, wordsize) stpcommands.setupVariables(stp_file, perm_G, wordsize) stpcommands.setupVariables(stp_file, w, 16) stpcommands.setupVariables(stp_file, act_flag, 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], out_G0[i], out_G1[i], rot_G0[i], rot_G1[i], xor_G[i], perm_G[i], act_flag[i], w[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 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 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 Qarma with the given parameters. """ wordsize = parameters["wordsize"] rounds = parameters["rounds"] weight = parameters["sweight"] if wordsize != 4: print("Qarma only supports a wordsize of 4 bits.") exit(1) if (rounds - 1) % 2 != 0: print("Qarma 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% Qarma 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.setupQarmaForwardRound(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.setupQarmaMiddleRound(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.setupQarmaBackwardRound(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 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