Beispiel #1
0
    def symbolic_execution(cls, *args, id_prefix="x", st=None):
        """Evaluate symbolically the function.

        It evalutes the composite function in the "stateful execution mode"
        (see symbolic_execution of Function).

        It returns two pairs (inner_output, inner_st), (outer_outer, outer_st)
        where each pair is the result of calling symbolic_execution
        on inner and outer respectively.

            >>> from arxpy.bitvector.core import Variable
            >>> from arxpy.bitvector.function import Function, CompositeFunction
            >>> class MyInner(Function):
            ...     input_widths = [8, 8]
            ...     output_widths = [8]
            ...     @classmethod
            ...     def eval(cls, a, b): return (a ^ b)
            >>> MyInner(1, 1)
            0x00
            >>> class MyOuter(Function):
            ...     input_widths = [8, 8]
            ...     output_widths = [8]
            ...     @classmethod
            ...     def eval(cls, c, d): return (c + d)
            >>> MyOuter(1, 1)
            0x02
            >>> class MyComposite(CompositeFunction):
            ...     input_widths = [8, 8, 8]
            ...     output_widths = [8]
            ...     inner_func = MyInner
            ...     outer_func = MyOuter
            >>> MyComposite(1, 1, 1)
            0x01
            >>> a, b, cd = Variable("a", 8), Variable("b", 8), Variable("cd", 8)
            >>> MyComposite.symbolic_execution(a, b, cd)  # doctest: +NORMALIZE_WHITESPACE
            ((x0, ExecutionState([(x0, b ^ cd), (x1, a + x0)])),
            (x1, ExecutionState([(x0, b ^ cd), (x1, a + x0)])))

        """
        if st is None:
            st = context.ExecutionState(id_prefix=id_prefix)

        inner_ninputs = len(cls.inner_func.input_widths)
        inner_args = args[-inner_ninputs:]
        inner_exec = cls.inner_func.symbolic_execution(*inner_args, st=st)

        new_args = args[:-inner_ninputs] + core.tuplify(inner_exec[0])

        self_exec = cls.outer_func.symbolic_execution(*new_args, st=st)

        return inner_exec, self_exec
Beispiel #2
0
    def __init__(self, func, diff_type, input_diff, prefix="d"):
        """Create a characteristic."""
        assert issubclass(func, function.Function)
        assert issubclass(diff_type, difference.Difference)

        input_diff = core.tuplify(input_diff)

        assert len(input_diff) == len(func.input_widths)
        assert all(isinstance(d, difference.DiffVar) for d in input_diff)
        assert all(not d.name.startswith(prefix) for d in input_diff)

        self.func = func
        self.diff_type = diff_type
        self.input_diff = input_diff
        self.prefix = prefix
        self.output_diff = None
        self.propagations = collections.OrderedDict()

        self._generate()
Beispiel #3
0
    def __new__(cls, *args, **options):
        assert len(cls.input_widths) == len(args)
        newargs = []
        for arg, width in zip(args, cls.input_widths):
            newargs.append(core.bitvectify(arg, width))
        args = newargs

        if all(isinstance(arg, core.Constant) for arg in args) or \
                options.pop("symbolic_inputs", False):
            result = cls.eval(*args)
        else:
            raise TypeError("expected bit-vector constant arguments")

        output = list(core.tuplify(result))
        assert len(cls.output_widths) == len(output)
        for i in range(len(output)):
            output[i] = core.bitvectify(output[i], cls.output_widths[i])

        if isinstance(result, collections.Sequence):
            return tuple(output)
        else:
            return output[0]
Beispiel #4
0
    def __init__(self,
                 func,
                 diff_type,
                 input_diff,
                 inner_prefix="i",
                 outer_prefix="o"):
        """Create a composite characteristic."""
        assert issubclass(func, function.CompositeFunction)

        self.func = func
        self.diff_type = diff_type

        input_diff = core.tuplify(input_diff)
        inner_ninputs = len(func.inner_func.input_widths)
        inner_input_diff = input_diff[-inner_ninputs:]

        self.inner_ch = Characteristic(func.inner_func, diff_type,
                                       inner_input_diff, inner_prefix)

        outer_input_diff = input_diff[:-inner_ninputs] + self.inner_ch.output_diff

        self.outer_ch = Characteristic(func.outer_func, diff_type,
                                       outer_input_diff, outer_prefix)
Beispiel #5
0
 def eval(cls, *args):
     inner_ninputs = len(cls.inner_func.input_widths)
     evaluated_inner = cls.inner_func(*args[-inner_ninputs:])
     evaluated_inner = core.tuplify(evaluated_inner)
     return cls.outer_func(*args[:-inner_ninputs], *evaluated_inner)
Beispiel #6
0
 def __init__(self, input_diff, output_diff):
     """Initialize the differential."""
     assert all(isinstance(d, DiffVar) for d in tuplify(input_diff))
     assert isinstance(output_diff, DiffVar)
     super().__init__(input_diff, output_diff)
Beispiel #7
0
 def __init__(self, input_diff, output_diff):
     """Initialize the Differential with given input/output differences."""
     input_diff = core.tuplify(input_diff)
     assert len(input_diff) == sum(self.op.arity)
     self.input_diff = input_diff
     self.output_diff = output_diff
Beispiel #8
0
    def propagate(cls, op, input_diff, output_diff=None):
        """Propagate an input difference variable through a bit-vector op.

            >>> from arxpy.bitvector.core import Variable, Constant
            >>> from arxpy.bitvector.operation import BvAdd, BvXor
            >>> from arxpy.diffcrypt.difference import XorDiff, DiffVar
            >>> d1, d2 = DiffVar("d1", 8), DiffVar("d2", 8)
            >>> XorDiff.propagate(BvXor, [d1, d2])
            d1 ^ d2
            >>> d3 = DiffVar("d3", 8)
            >>> XorDiff.propagate(BvAdd, [d1, d2], d3)
            xdp+((d1, d2), d3)

        Deterministic propagations return bit-vector terms while
        probabilistic propagations return Differential objects.

        """
        input_diff = core.tuplify(input_diff)
        assert len(input_diff) == sum(op.arity)

        msg = "unknown XOR propagation of {}({})".format(
            type(op).__name__,
            [d.vrepr() if isinstance(d, core.Term) else d for d in input_diff])

        if op == operation.BvNot:
            x = input_diff[0]
            if isinstance(x, DiffVar):
                return x
            else:
                raise NotImplementedError(msg)

        if op == operation.BvXor:
            newdiffs = []
            for d in input_diff:
                if isinstance(d, DiffVar):
                    newdiffs.append(d)
                elif isinstance(d, (core.Constant, core.Variable)):
                    newdiffs.append(core.Constant(0, d.width))
                else:
                    raise NotImplementedError(msg)

            return op(*newdiffs)

        if op in [operation.RotateLeft, operation.RotateRight]:
            x, r = input_diff
            if isinstance(x, DiffVar):
                return op(x, r)
            else:
                raise NotImplementedError(msg)

        if op == operation.Extract:
            x, i, j = input_diff
            if isinstance(x, DiffVar):
                return op(x, i, j)
            else:
                raise NotImplementedError(msg)

        if op == operation.Concat:
            if all(isinstance(d, DiffVar) for d in input_diff):
                return op(*input_diff)
            else:
                raise NotImplementedError(msg)

        if op == operation.BvAdd:
            if all(isinstance(d, DiffVar) for d in input_diff):
                from arxpy.diffcrypt import differential
                return differential.XDBvAdd(input_diff, output_diff)
            else:
                raise NotImplementedError(msg)

        if hasattr(op, "differential"):
            return op.differential(cls)(input_diff, output_diff)

        raise NotImplementedError(msg)
Beispiel #9
0
    def propagate(cls, op, input_diff, output_diff=None):
        """Propagate an input difference variable through a bit-vector op.

            >>> from arxpy.bitvector.core import Variable, Constant
            >>> from arxpy.bitvector.operation import BvAdd, BvXor
            >>> from arxpy.diffcrypt.difference import RXDiff, DiffVar
            >>> d1, d2 = DiffVar("d1", 8), DiffVar("d2", 8)
            >>> RXDiff.propagate(BvXor, [d1, d2])
            d1 ^ d2
            >>> d3 = DiffVar("d3", 8)
            >>> RXDiff.propagate(BvAdd, [d1, d2], d3)
            rxdp+((d1, d2), d3)

        Deterministic propagations return bit-vector terms while
        probabilistic propagations return Differential objects.
        """
        input_diff = core.tuplify(input_diff)
        assert len(input_diff) == sum(op.arity)

        msg = "unknown RX propagation of {}({})".format(
            type(op).__name__,
            [d.vrepr() if isinstance(d, core.Term) else d for d in input_diff])

        if op == operation.BvNot:
            x = input_diff[0]
            if isinstance(x, DiffVar):
                return x
            else:
                raise NotImplementedError(msg)

        if op == operation.BvXor:
            if all(isinstance(d, DiffVar) for d in input_diff):
                return op(*input_diff)
            else:
                x, y = input_diff
                if isinstance(x, core.Constant) and isinstance(y, DiffVar):
                    cte, var = x, y
                elif isinstance(y, core.Constant) and isinstance(x, DiffVar):
                    cte, var = y, x
                else:
                    raise NotImplementedError(msg)

                cte = operation.BvXor(cte, operation.RotateLeft(cte, 1))
                return operation.BvXor(var, cte)

        if op in [operation.RotateLeft, operation.RotateRight]:
            x, r = input_diff
            if isinstance(x, DiffVar):
                return op(x, r)
            else:
                raise NotImplementedError(msg)

        if op == operation.BvAdd:
            if all(isinstance(d, DiffVar) for d in input_diff):
                from arxpy.diffcrypt import differential
                return differential.RXDBvAdd(input_diff, output_diff)
            else:
                raise NotImplementedError(msg)

        if hasattr(op, "differential"):
            return op.differential(cls)(input_diff, output_diff)

        raise NotImplementedError(msg)