def comb_attack(self): # dis generator solver_name = 'btor' solver_obf = Solver(name=solver_name) solver_key = Solver(name=solver_name) solver_oracle = Solver(name=solver_name) attack_formulas = FormulaGenerator(self.oracle_cir, self.obf_cir) f = attack_formulas.dip_gen_ckt # f = simplify(f) solver_obf.add_assertion(f) f = attack_formulas.key_inequality_ckt # f = simplify(f) solver_obf.add_assertion(f) iteration = 0 while 1: # query dip generator if solver_obf.solve(): dip_formula = [] dip_boolean = [] for l in self.obf_cir.input_wires: t = Symbol(l) if solver_obf.get_py_value(t): dip_formula.append(t) dip_boolean.append(TRUE()) else: dip_formula.append(Not(t)) dip_boolean.append(FALSE()) logging.info(dip_formula) # query oracle dip_out = [] for l in self.oracle_cir.output_wires: t = self.oracle_cir.wire_objs[l].formula solver_oracle.reset_assertions() solver_oracle.add_assertion(t) if solver_oracle.solve(dip_formula): dip_out.append(TRUE()) else: dip_out.append(FALSE()) logging.info(dip_out) # add dip checker f = [] for i in range(len(attack_formulas.dip_chk1)): f.append(And(Iff(dip_out[i], attack_formulas.dip_chk1[i]), Iff(dip_out[i], attack_formulas.dip_chk2[i]))) f = And(f) subs = {} for i in range(len(self.obf_cir.input_wires)): subs[Symbol(self.obf_cir.input_wires[i])] = dip_boolean[i] # f = simplify(f) f = substitute(f, subs) solver_obf.add_assertion(f) solver_key.add_assertion(f) iteration += 1 logging.warning('iteration: {}'.format(iteration)) else: logging.warning('print keys') if solver_key.solve(): key = '' for i in range(len(self.obf_cir.key_wires)): k = 'keyinput{}_0'.format(i) if solver_key.get_py_value(Symbol(k)): key += '1' else: key += '0' print("key=%s" % key) else: logging.critical('key solver returned UNSAT') return
def comb_attack(self): # dis generator solver_name = 'yices' solver_obf = Solver(name=solver_name) solver_key = Solver(name=solver_name) self.solver_oracle = Solver(name=solver_name) attack_formulas = FormulaGenerator(self.oracle_cir, self.obf_cir) f = attack_formulas.dip_gen_ckt # f = simplify(f) solver_obf.add_assertion(f) f = attack_formulas.key_inequality_ckt # f = simplify(f) solver_obf.add_assertion(f) for l in self.oracle_cir.wire_objs: self.solver_oracle.add_assertion(l.formula) dip_list = [] stateful_keys = [] iteration = 0 while 1: # query dip generator if solver_obf.solve(): dip_formula = [] dip_boolean = [] for l in self.oracle_cir.input_wires: s = Symbol(l.name) if solver_obf.get_py_value(s): dip_formula.append(s) dip_boolean.append(TRUE()) else: dip_formula.append(Not(s)) dip_boolean.append(FALSE()) logging.info(dip_formula) # query oracle dip_out = self.query_oracle(dip_formula) logging.info(dip_out) # check for stateful condition if dip_formula in dip_list: # ban stateful key logging.info("found a repeated dip!") # check outputs for both keys key = None for l in self.obf_cir.output_wires: s1 = Symbol(l.name + '@dc1') s2 = Symbol(l.name + '@dc2') if solver_obf.get_py_value( s1) != solver_obf.get_py_value(s2): if solver_obf.get_py_value( s1) != self.solver_oracle.get_py_value( Symbol(l.name)): key = '0' else: key = '1' break if key == None: logging.critical( 'something is wrong when banning keys') # find assigned keys key_list = [] for l in self.obf_cir.key_wires: k = Symbol(l.name + '_' + key) if solver_obf.get_py_value(k): key_list.append(k) else: key_list.append(Not(k)) stateful_keys.append(key_list) # ban the stateful key f = Not(And(key_list)) solver_obf.add_assertion(f) solver_key.add_assertion(f) if len(stateful_keys) % 5000 == 0: logging.warning('current stateful keys: {}'.format( len(stateful_keys))) continue else: dip_list.append(dip_formula) # add dip checker f = [] f.append( attack_formulas.gen_dip_chk(iteration * 2, '_0', dip_boolean)) f.append( attack_formulas.gen_dip_chk(iteration * 2 + 1, '_1', dip_boolean)) for i in range(len(self.obf_cir.output_wires)): l = self.obf_cir.output_wires[i].name f.append( And( Iff(dip_out[i], Symbol(l + '@{}'.format(iteration * 2))), Iff(dip_out[i], Symbol(l + '@{}'.format(iteration * 2 + 1))))) f = And(f) solver_obf.add_assertion(f) solver_key.add_assertion(f) iteration += 1 logging.warning('iteration: {}'.format(iteration)) else: logging.warning('print keys') logging.warning('stateful keys: {}'.format(len(stateful_keys))) if solver_key.solve(): key = '' for l in self.obf_cir.key_wires: if solver_key.get_py_value(Symbol(l.name + '_0')): key += '1' else: key += '0' print("key=%s" % key) else: logging.critical('key solver returned UNSAT') return