Exemple #1
0
    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
Exemple #2
0
    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