Exemple #1
0
    def visit_Compare(self, node):
        if __debug__:
            state.log.debug("infer %s", dump(node, True, True))

        if len(node.comparators) > 2:
            raise TastySyntaxError(
                "tastyc is not yet ready for more than 2 comparision items")

        left_node = node.left
        right_node = node.comparators[0]

        node.dims = list()
        node.bit_lengths = list()
        node.input_types = list()
        node.signeds = list()

        node.methodname = bases.CMPOP_METHODS[type(node.ops[0])]

        annotate_item_of_node(self, left_node, node, False)
        annotate_item_of_node(self, right_node, node)

        node_type = left_node.return_info[0]["type"]

        node.return_info = node_type.returns(node.methodname, node.input_types,
                                             node.bit_lengths, node.dims,
                                             node.signeds)

        node.initial_info = node.left.return_info[0]
Exemple #2
0
 def visit_Import(self, node):
     #state.log.debug("\nQualificator %s", dump(node, True, True))
     for _alias in node.names:
         if _alias.name == "tasty.types":
             raise TastySyntaxError("Found unallowed import statement: " \
                 "'import tasty.types' at line %r. " \
                 "Please delete this statement and rewrite your protocol " \
                 "for direct usage of tasty types." % node.lineno)
         if _alias.name == "tasty.types.conversions":
             raise TastySyntaxError("Found unallowed import statement: " \
                 "'import tasty.types.conversions' at line %r. " \
                 "Please delete this statement." % node.lineno)
         if _alias.name == "tasty.types.driver":
             raise TastySyntaxError("Found unallowed import statement: " \
                 "'import tasty.types.driver' at line %r. " \
                 "Please delete this statement." % node.lineno)
Exemple #3
0
    def map_inputs(self, inval, inmap):
        """
        first sanitize inputs, in the end, inval should be a list of
        input values and inmap should be a list of the coresponding
        input names:
        inval = dict, inmap = None:
          => Create inmap list and fill inval with correct values
        inval = list, inmap = list
          => everything fine
        inval = list, inmap = none
          => inmap = self.inputs
        then map the inputs in the order the circuit expects it
        """
        def do_map(c, inval, inmap):
            indict = {}

            # drop inputs with 0 input-wires
            c = [x for x in c if x[0]]

            for pos, i in enumerate(c):
                indict[i[1]] = (pos, i[0])

            ret = [None for i in xrange(len(c))]

            for val, m in zip(inval, inmap):
                ret[indict[m][0]] = val
            return ret

        c = self.circuit.inputs()

        # FIXME: @Immo: this is br0ken -> "inlist" unknown
        if isinstance(inval, dict):
            inmap = inval.keys()
            inval = [inval[i] for i in ilist]

        elif iter(inval):
            inval = tuple(inval)
            if not inmap:
                if not self.inputs:
                    raise TastySyntaxError("No input mapping specified. " \
                                           "You must either specify it on creation or on call!")
                inmap = self.inputs
        else:
            raise TastySyntaxError("Your argument must be a list of inputs")

        return do_map(c, inval, inmap)
Exemple #4
0
    def visit_For(self, node):
        """Creates a symbol_table entry for node.target and visits each
        body node.

        TASK: metatasty: Use stacked symbol_tables to store 'node.target'
        symbol table entry. This would give much more symbol_record accuracy.
        """

        if __debug__:
            state.log.debug("\ninfer %s", dump(node, True, True))
        fqnn = get_fqnn(node.target)

        target_rec = dict()
        if isinstance(node.iter, Call):
            if isinstance(node.iter.func, Name):
                if isinstance(node.iter.args[0], Num):
                    target_rec["type"] = types.Unsigned
                    target_rec["bitlen"] = mpz(
                        node.iter.args[0].n).bit_length()
                    target_rec["dim"] = [1]
                    target_rec["signed"] = False
                else:
                    arg_fqnn = get_fqnn(node.iter.args[0])
                    symbol_record = self.symbol_table.identify(arg_fqnn)
                    target_rec = symbol_record["kwargs"]
            else:
                raise TastySyntaxError(
                    "'for' not handled for iteration node type %s" %
                    type(node.iter.func))
        elif isinstance(node.iter, Attribute):
            arg_fqnn = get_fqnn(node.iter)
            symbol_record = self.symbol_table.identify(arg_fqnn)
            kwargs = symbol_record["kwargs"]
            node.iter.return_info = (kwargs, )

            iter_node_type = kwargs["type"]
            bit_lengths = (kwargs["bitlen"], )
            dims = (kwargs["dim"], )
            signeds = (kwargs["signed"], )
            node.target.return_info = iter_node_type.returns(
                "__getitem__", tuple(), bit_lengths, dims, signeds)
            target_rec = node.target.return_info[0]
        else:
            raise NotImplementedError(
                "'for' not handled for iteration node type %s" %
                type(node.iter))

        self.symbol_table.add_symbol(fqnn,
                                     kwargs=target_rec,
                                     lineno=node.lineno,
                                     colno=node.col_offset)

        #self.symbol_table.dump()
        for i in node.body:
            self.visit(i)
Exemple #5
0
def handle_target_node(runner, target, value_node):
    if isinstance(target, Tuple):
        return_info = value_node.return_info
        if len(return_info) != len(target.elts):
            raise SyntaxError("wrong number of type " \
                "information records provided")
        for ix, i in enumerate(target.elts):
            i_fqnn = get_fqnn(i)
            runner.symbol_table.add_symbol(i_fqnn,
                                           kwargs=return_info[ix],
                                           lineno=target.lineno,
                                           colno=target.col_offset)
    elif (isinstance(target, Attribute) or isinstance(target, Name)
          or isinstance(target, Subscript)):
        fqnn = get_fqnn(target)

        try:
            kwargs = value_node.return_info[0]
        except AttributeError:
            kwargs = dict()

        value_node_rec = value_node.return_info[0]

        try:
            value_fqnn = get_fqnn(value_node)
            if value_fqnn[0] != fqnn[0]:
                raise TastySyntaxError(
                    "Syntax error at line %d: for sending and/or conversion please use the tasty operator '<<='"
                    % target.lineno)
        except FqnnError:
            pass

        if hasattr(value_node, "bitlen_not_finished"):
            runner.nodes_without_bitlen[fqnn] = value_node

        if hasattr(value_node, "signed_not_finished"):
            runner.nodes_without_signed[fqnn] = value_node

        if isinstance(target, Subscript):
            try_finish_bitlenless(runner, fqnn[:2], kwargs["bitlen"])
            try_finish_signed(runner, fqnn[:2], kwargs["signed"])

        if hasattr(value_node, "tasty_function"):
            kwargs["tasty_function"] = value_node.tasty_function
        try:
            runner.symbol_table.add_symbol(fqnn,
                                           kwargs=kwargs,
                                           lineno=target.lineno,
                                           colno=target.col_offset)
        except TastySyntaxError, e:
            if state.config.verbose >= 2:
                state.log.exception(e)
Exemple #6
0
def Plain_Garbled_send(src, dst, bitlen, dim, signed, force_bitlen=None, force_signed=None):
    _sendcost(bitlen * (state.config.symmetric_security_parameter + 1))
    if isclient():
        raise TastySyntaxError("Encrypting to Garbled and Sending to Server does not make sense")
    if state.precompute:
        tmp = Garbled(val=src, bitlen=bitlen, signed=signed)
        state.active_party.push_tmpattr(tmp)
    else:
        tmp = state.active_party.pop_tmpattr()
        tmp = Garbled(val=src, bitlen=bitlen, signed=signed)

    _sender_copy(tmp, dst) # attaches implicitly here
    _send(tmp)
Exemple #7
0
    def affects(methodname, input_types, role):
        """Used by tastyc transformation pass"""

        if __debug__:
            state.log.debug("GarbledCircuit.affects(%r, %r, %r)", methodname,
                            input_types, role)
        if methodname == "GarbledCircuit":
            return Value.S_SETUP | Value.C_SETUP | Value.C_ONLINE
        if methodname == "__call__":
            return Value.S_SETUP | Value.C_SETUP | Value.C_ONLINE
        else:
            raise TastySyntaxError(
                "A GarbledCircuit can only be created and evaluated")
Exemple #8
0
    def map_outputs(self, outputs, omap):

        # o is in form ((owires, oname, otype), (owires, oname, otype)...)
        o = self.circuit.outputs()
        odict = {}
        for pos, i in enumerate(o):
            odict[i[1]] = (pos)

        if not omap:
            if not self.outputs:
                raise TastySyntaxError("You must specify output order either " \
                                       "on creation or on call")
            omap = self.outputs

        return tuple(outputs[odict[i]] for i in omap)
Exemple #9
0
def Paillier_Garbled_receive(src, dst, bitlen, dim, signed, force_bitlen=None, force_signed=None):
    if force_bitlen is not None:
        bitlen = force_bitlen

    if force_signed is not None:
        signed = force_signed

    p = partyAttribute
    if not isclient():
        raise TastySyntaxError("Conversion from Homomorphic to Garbled from Client to Server does not make sense")
    masklen = bitlen + state.config.symmetric_security_parameter
    if state.precompute:
        # receive garbled Mask
        mgm = _receive(src, dst)
        mgm._bit_length = bitlen
        state.active_party.push_tmpattr(mgm)
        # prepare for creation of garbled masked plain value
        mgv = Garbled(bitlen = bitlen, val=p, signed=False)
        state.active_party.push_tmpattr(mgv)
        # prepare addition circuit to remove the mask
        ret = mgv.dropmsb_sub(mgm)
        # save shadow copy of resulting Garbled
        _set_dst(src, dst, ret)
        ret.set_bit_length(bitlen)
        # avoid warnings here, in online phase this is correct
        ret._signed = False
    else:
        mgm = state.active_party.pop_tmpattr()
        state.active_party._tmp_ = state.active_party.pop_tmpattr()
        # get the masked Homomorphic
        hval = _receive()
        hval._bit_length = masklen
        # decrypt the masked Homomorphic
        mpv = Unsigned(val=hval)
        mpv._value &= ((1<<bitlen)-1)
        if mpv.signed():
            raise NotImplementedError()
        mpv.set_bit_length(bitlen)
        # convert plain masked value into Garbled
        state.active_party._tmp_ = Garbled(val=mpv, bitlen=bitlen, signed=signed)
        # deblind the garbled value
        ret = state.active_party._tmp_.dropmsb_sub(mgm)
        # tasty calculates theoretical worst case bitlengths. Since we know better,
        # we can safely overwrite that
        _set_dst(src, dst, ret)
        ret.set_bit_length(bitlen)
        ret._signed = hval.signed()
Exemple #10
0
def get_fqnn(node):
    """returns the fully qualified node name, but as a tuple

    e.g:
        None, 'foo' -> foo (fqnn via Name node)
        server, 'foo' -> server.foo (fqnn via Attribute node)
        None, 'foo[0]' -> foo[0] (fqnn via Subscript node)
    """

    if hasattr(node, "fqnn"):
        return node.fqnn
    if isinstance(node, BinOp):
        raise FqnnError("bad style")
    elif isinstance(node, Attribute):
        try:
            fqnn = node.fqnn = node.value.id, node.attr
            return fqnn
        except AttributeError:
            fqnn = node.fqnn = get_fqnn(node.value)
            return fqnn
    elif isinstance(node, Name):
        fqnn = node.fqnn = (node.id, )
        return fqnn
    elif isinstance(node, Subscript):
        if isinstance(node.value, Name):
            raise TastySyntaxError(
                "TASTYL only supports bounded subscriptions")
        if isinstance(node.slice.value, Name):
            fqnn = node.fqnn = (node.value.value.id, node.value.attr,
                                node.slice.value.id)
            return fqnn
        elif isinstance(node.slice.value, Num):
            fqnn = node.fqnn = (node.value.value.id, node.value.attr,
                                node.slice.value.n)
            return fqnn
        else:
            raise FqnnError(
                "Error in line %d: fqnn for type '%s' cannot be evaluated" %
                (node.lineno, type(node)))
    else:
        #if state.config.verbose >= 2:
        #state.log.error("fqnn for node type '%s' cannot be evaluated" %
        #type(node))
        #state.log.error(dump(node, True, True))
        raise FqnnError("Error in line %d: fqnn for type '%s' " \
            "cannot be evaluated" % (node.lineno, type(node)))
Exemple #11
0
 def visit_ImportFrom(self, node):
     #state.log.debug("\nQualificator %s", dump(node, True, True))
     if node.module == "tasty.types":
         for _alias in node.names:
             if _alias.name == "*":
                 bases.TastyCBase.imports.add("types")
             elif _alias.name == "conversions":
                 bases.TastyCBase.imports.add("conversions")
             elif _alias.name == state.config.driver_name:
                 raise TastySyntaxError("Found unallowed import statement: " \
                     "'from tasty.types import driver' at line %r. " \
                     "Please delete this statement." % node.lineno)
     if node.module == "tasty.types.driver":
         for _alias in node.names:
             if _alias.name == "IODriver":
                 bases.TastyCBase.imports.add("IODriver")
             elif _alias.name == "TestDriver":
                 bases.TastyCBase.imports.add("TestDriver")
Exemple #12
0
def PaillierVec_GarbledVec_receive(src, dst, source_bitlen, source_dim, signed, force_bitlen=None, force_signed=None):
    p = partyAttribute
    if force_bitlen and (force_signed or (signed and not force_signed == False)):
        raise NotImplementedError("forcing bitlen on signeds is not supported now")

    if force_bitlen:
        source_bitlen = force_bitlen

    overallbitlen = reduce(operator.mul, source_dim, 1) * source_bitlen
    cpc = state.config.asymmetric_security_parameter - state.config.symmetric_security_parameter - 1
    chunksize = (cpc - 1) / source_bitlen
    chunkpayloadbits = chunksize * source_bitlen
    chunks = (overallbitlen - 1) / chunkpayloadbits  + 1

    lastchunksize = overallbitlen % (chunksize * source_bitlen)


    if lastchunksize:
        chunksizes = (chunks - 1) * (chunkpayloadbits, ) + (lastchunksize, )
        masks = nogen(get_randomm(0, 2**(chunkpayloadbits + state.config.symmetric_security_parameter) - 1, chunks - 1)) + (mpz(rand.randint(0, 2**(lastchunksize + state.config.symmetric_security_parameter) - 1)),)
    else:
        chunksizes = chunks * (chunkpayloadbits, )
        masks = nogen(get_randomm(0, 2**(chunkpayloadbits + state.config.symmetric_security_parameter)- 1, chunks))


    if state.precompute:
        if force_signed is not None:
            signed = force_signed

         # receive garbled Mask
        mgms = _receive(src, dst)
        for mgm, size in zip(mgms, chunksizes):
            mgm._bit_length = size

        # prepare for creation of garbled masked plain value
        state.active_party.push_tmpval(mgms)

        # precompute first chunkpayloadbits for the garbled masked value
        mgvs = []
        for i in chunksizes:
            mgv = Garbled(bitlen=i, val=p, signed=False)
            state.passive_party.push_tmpattr(mgv)
            mgvs.append(mgv)

        # precompute the unmasking and unpacking
        rets = []
        for mgv, mgm, chunksize in zip (mgvs, mgms, chunksizes):
            ret = mgv.unpack(mgm, source_bitlen, chunksize, signed)
            state.active_party.push_tmpattr(ret)
            rets.extend(ret)

        rets.reverse()

        vec = GarbledVec(bitlen=source_bitlen, dim=source_dim, val=rets, signed=signed)

        # save shadow copy of resulting GarbledVec
        _set_dst(src, dst, vec)

    else: # online phase
        if force_signed is not None:
            signed = force_signed

        if not isclient():
            raise TastySyntaxError("Conversion from Homomorphic to Garbled from Client to Server does not make sense")

        # receive masked homomorphic values
        mhvs = _receive()
        for i, chunksize in zip(mhvs, chunksizes):
            i._bit_length = chunksize


        # decrypt masked garbled values
        mvs = nogen(Unsigned(val=i) for i in mhvs)

        # get the masked garbled values from tmpval-stack
        mgms = state.active_party.pop_tmpval()

        # compute first chunksize bits of garbled masked values
        mgvs = []
        for mv, chunksize in zip(mvs, chunksizes):
            state.passive_party._tmp_ = mgv = state.passive_party.pop_tmpattr()
            mv._value &= (1<<chunksize) - 1
            mv.set_bit_length(chunksize)
            state.passive_party._tmp_ = Garbled(val=mv, bitlen=chunksize, signed=signed)
            mgvs.append(state.passive_party._tmp_)


        # unpacking and unblinding
        rets = []
        for mgm, mgv, chunksize in zip(mgms, mgvs, chunksizes):
            state.active_party._tmp_ = state.active_party.pop_tmpattr()
            state.active_party._tmp_ = mgv.unpack(mgm, source_bitlen, chunksize, signed)
            rets.extend(state.active_party._tmp_)

        rets.reverse()

        vec = GarbledVec(bitlen=source_bitlen, dim=source_dim, val=rets, signed = rets[0].signed())
        _set_dst(src, dst, vec)
Exemple #13
0
def PaillierVec_GarbledVec_send(src, dst, source_bitlen, source_dim, signed, force_bitlen=None, force_signed=None):

    if force_bitlen and (force_signed or (signed and not force_signed == False)):
        raise NotImplementedError("forcing bitlen on signeds is not supported now")

    if force_bitlen is not None:
        diff = source_bitlen - force_bitlen
        source_bitlen = force_bitlen
    else:
        diff = 0

    p = partyAttribute
    if not isserver():
        raise TastySyntaxError("Conversion from Homomorphic to Garbled from Client to Server does not make sense")
    # number of maximal bits in content
    overallbitlen = _dimtimes(source_dim) * source_bitlen
    # we have asymmetric_security_parameter bits to pack into, but need symmetric_security_parameter bits to blind
    cpc = state.config.asymmetric_security_parameter - state.config.symmetric_security_parameter - 1

    chunksize = cpc / source_bitlen
    chunkpayloadbits = chunksize * source_bitlen
    chunks = (overallbitlen - 1) / chunkpayloadbits  + 1
    lastchunksize = overallbitlen % chunkpayloadbits
    Homomorphic = tasty.types.Homomorphic
    HomomorphicVec = tasty.types.HomomorphicVec


    if lastchunksize:
        chunksizes = (chunks - 1) * (chunkpayloadbits, ) + (lastchunksize, )
    else:
        chunksizes = chunks * (chunkpayloadbits, )

    if state.precompute:

        if lastchunksize:
            masks = nogen(get_randomm(0, 2**(chunkpayloadbits + state.config.symmetric_security_parameter) - 1, chunks - 1)) + (mpz(rand.randint(0, 2**(lastchunksize + state.config.symmetric_security_parameter) - 1)),)
        else:
            masks = nogen(get_randomm(0, 2**(chunkpayloadbits + state.config.symmetric_security_parameter)- 1, chunks))


        if force_signed is not None:
            signed = force_signed

        # generate Mask values
        umasks = nogen(Unsigned(val=v, bitlen=l + state.config.symmetric_security_parameter) for v, l in zip(masks, chunksizes))

        # homomorphically encrypt masks
        hmasks = tuple(tasty.types.Homomorphic(val=mask, signed=False) for mask in umasks)
        state.active_party.push_tmpval(hmasks)

        # garble first chunkpayloadbits of the masks (manual construction of garbled! Voodoo!)
        mgms = []
        for mask, chunksize in zip(masks, chunksizes):
            state.passive_party._tmp_ = Garbled(bitlen=chunksize, signed=False, val=p)
            zv = Garbled.get_zero_value(state.passive_party._tmp_.gid)
            state.passive_party._tmp_[:] = plain2garbled(value2bits(mask & (1<<chunksize) - 1, chunksize), zv, state.R)
            mgms.append(state.passive_party._tmp_)

        state.passive_party.push_tmpval(mgms)


        #raise NotImplementedError("COSTS")
#        _sendcost(chunks * chunksize[0]

        # send garbled masks to client
        _send(mgms)

        # precompute the first chunkpayloadbits for the garbled masked value
        mgvs = []
        for chunksize in chunksizes:
            mgv = Garbled(bitlen=chunksize, passive=True, val=p, signed=False)
            state.passive_party.push_tmpattr(mgv)
            mgvs.append(mgv)


        # precompute the unmasking and unpacking
        rets = []
        for mgv, mgm, chunksize in zip(mgvs, mgms, chunksizes):
            ret = mgv.unpack(mgm, source_bitlen, chunksize, signed)
            state.passive_party.push_tmpattr(ret)
            rets.extend(ret)

        rets.reverse() # packing works exactly in the oposite direction then unpacking, so reverse here to get original result back

        vec = GarbledVec(bitlen=source_bitlen, dim=source_dim, val=rets)

        # save shadow copy of resulting GarbledVec
        _set_dst(src, dst, vec)

    else: # online phase
        assert signed == src.signed(), "the analyzer disagrees with the typesystems signedness"

        if force_signed is not None:
            signed = force_signed

        if not isserver():
            raise TastySyntaxError("Conversion from Homomorphic to Garbled from Client to Server does not make sense")

        # Pack the values with respecting the force_signed and force_bitlen
        hmasks = state.active_party.pop_tmpval()
        if force_signed is not None: # we must change it to the forced sign
            origsigned = src.signed()
            src._signed = force_signed
            for i in src:
                i._signed = force_signed

        packed, _, _ = src.pack(-(state.config.symmetric_security_parameter + 1), force_bitlen=force_bitlen)

        if force_signed is not None: # no change in the source, so revert changes done before pack()
            src._signed = origsigned
            for i in src:
                i._signed = origsigned

        assert len(packed) == len(hmasks), "packing error (%d packed chunks, but %d expected (%r, %r))"%(len(packed), len(hmasks), hmasks, packed)

        # mask the packed values
        for i, j in zip(packed, hmasks):
            i += j

        # send packed values to client
        _send(packed)

        # retrive garbled masks from tmpval-stack
        mgms = state.passive_party.pop_tmpval()

        # passive part for generation of garbled masked values
        mgvs = []
        for chunksize in chunksizes:
            state.passive_party._tmp_ = state.passive_party.pop_tmpattr()
            state.passive_party._tmp_ = Garbled(val=p, bitlen=chunksize, passive=True, signed=False)
            mgvs.append(state.passive_party._tmp_)


        # passive part of unblinding and unpacking
#        rets = []
        for mgm, mgv, chunksize in zip(mgms, mgvs, chunksizes):
            state.passive_party._tmp_ = state.passive_party.pop_tmpattr()
Exemple #14
0
def Paillier_Garbled_send(src, dst, bitlen, dim, signed, force_bitlen=None, force_signed=None):
    if force_bitlen is not None:
        diff = bitlen - force_bitlen
        bitlen = force_bitlen
    else:
        diff = 0

    masklen = bitlen + state.config.symmetric_security_parameter #
    p = partyAttribute
    if not isserver():
        raise TastySyntaxError("Conversion from Homomorphic to Garbled from Client to Server does not make sense")
    if state.precompute:
        if force_signed is not None:
            signed = force_signed

        if signed:
            mask = Unsigned(val=rand.randint(2**bitlen - 1, 2**masklen - 1), bitlen=masklen)
        # generate the Homomorphic blinding mask and store
        else:
            mask = Unsigned(val=rand.randint(0, 2**masklen - 1), bitlen=masklen)

        hmask = tasty.types.Homomorphic(val=mask, signed=False)
        state.active_party.push_tmpattr(hmask)
        # Generate the Garbled Blinding Mask
        mgm = Garbled(bitlen=bitlen, signed=False, val=p)
        mgm.plainmask = mask # save the mask to be able to access it in online phase
        state.passive_party.push_tmpattr(mgm) # save the new Garbled
        zv = Garbled.get_zero_value(mgm.gid)
        mgm[:] = plain2garbled(value2bits(mask.get_value() & ((1<<bitlen) - 1), bitlen), zv, state.R)
        _sendcost(state.config.symmetric_security_parameter * bitlen)
        _send(mgm)
        # Precompute the garbled for the masked plain value
        mgv = Garbled(bitlen=bitlen, passive=True, val=p, signed=False)
        state.passive_party.push_tmpattr(mgv)
        # prepare the addition circuit to remove the mask
        ret = mgv.dropmsb_sub(mgm)
        # save shadow copy of resulting Garbled
        _set_dst(src, dst, ret)
        ret.set_bit_length(bitlen)
        ret._signed = False # avoid warning here
    else:
        assert signed == src.signed(), "the analyzer disagrees with the typesystems signedness"
        if force_signed is not None:
            signed = force_signed

        hmask = state.active_party.pop_tmpattr()
        mgm = state.passive_party.pop_tmpattr()
        state.passive_party._tmp_ = state.passive_party.pop_tmpattr()
        # blind the homomorphic and send to other party
        hval = src + hmask
        hval._bit_length -= diff # force_bitlen
        _sendcost(state.config.asymmetric_security_parameter * 2)
        _send(hval)
        # help to encrypt the masked value into Garbled
        state.passive_party._tmp_ = Garbled(bitlen=masklen + 1, passive=True, val=p, signed=signed)
        # help removing the mask
        ret = state.passive_party._tmp_.dropmsb_sub(mgm)
        # tasty calculates theoretical worst case bitlengths. Since we know better,
        # we can safely overwrite that
        _set_dst(src, dst, ret)
        ret.set_bit_length(bitlen)
        ret._signed = hval.signed()
Exemple #15
0
def ModularVec_ModularVec_send(src, dst, bitlen, dim, signed, force_bitlen=None, force_signed=None):
    if force_bitlen is not None or force_signed is not None:
        raise TastySyntaxError("Modular is always unsigned with bitlength of the asymmetric security parameter")
    _sendcost(state.config.asymmetric_security_parameter * _dimtimes(dim))
    _send(src, dst)
Exemple #16
0
    def visit_constructor(self, node):
        """here we inspect constructor invocations."""

        if __debug__:
            state.log.debug("\ninfer ctor %s", dump(node, True, True))

        node.call_type = CALL_TYPE_CTOR
        node.methodname = node.node_type.__name__

        self.visit(node.func)
        for i in node.keywords:
            self.visit(i)

        if hasattr(node, "keywords_data"):
            raise InternalError(
                "trying to overwrite keywords_data attribute twice")

        # keyword name -> object
        # real objects of ast representation
        node.keywords_data = dict()

        # keyword name -> keyword node
        # used for fast access to keyword nodes
        node.keywords_map = dict()

        if node.args:
            raise TastySyntaxError(
                "Tasty type constructors must not use positional arguments")

        for ix, kw in enumerate(node.keywords):
            value = kw.value
            key = kw.arg
            node.keywords_map[key] = kw
            node.keywords_data[key] = value

            if isinstance(value, Num):
                evaled = eval_num_arg(value)
                node.keywords_data[key] = evaled["val"]
                evaled["type"] = node.node_type
                kw.return_info = (evaled, )
            elif isinstance(value, Attribute):
                symbol_record = self.symbol_table.identify(get_fqnn(value))
                kwargs = copy.deepcopy(symbol_record["kwargs"])
                kw.return_info = (kwargs, )
            elif isinstance(value, List):
                eval_value = eval_arg(value)
                node.keywords_data[key] = eval_value["val"]
                kw.return_info = (eval_value, )
            elif isinstance(value, Tuple):
                eval_value = eval_arg(value)
                node.keywords_data[key] = eval_value["val"]
                kw.return_info = (eval_value, )
            elif isinstance(value, Name):
                if value.id == "None":
                    raise TastySyntaxError(
                        "'None' not allowed as constructor argument")
                elif value.id == "True":
                    kw.return_info = ({
                        "type": bool,
                        "bitlen": None,
                        "dim": None,
                        "signed": None
                    }, )
                    node.keywords_data[key] = True
                elif value.id == "False":
                    kw.return_info = ({
                        "type": bool,
                        "bitlen": None,
                        "dim": None,
                        "signed": None
                    }, )
                    node.keywords_data[key] = False
                else:
                    raise NotImplementedError("argument %r not handled" %
                                              value.id)
            elif (isinstance(value, UnaryOp) or isinstance(value, BinOp)
                  or isinstance(value, BoolOp)
                  or isinstance(value, Subscript)):
                kw.return_info = kw.value.return_info
            else:
                raise NotImplementedError("unhandled node type %s" %
                                          type(value))

        val = node.keywords_map.get("val")
        if val:
            kwargs = val.return_info[0]
            for k, v in kwargs.iteritems():
                if (k not in node.keywords_data
                        and k not in ("force_signed", "force_bitlen")):
                    node.keywords_data[k] = v

        if "dim" not in node.keywords_data:
            if (issubclass(node.node_type, types.PlainType)
                    or issubclass(node.node_type, types.GarbledType)
                    or issubclass(node.node_type, types.HomomorphicType)):
                node.keywords_data["dim"] = [1]
            elif issubclass(node.node_type, types.Vec):
                # otherwise inspect val kwargs for dims
                val_node = node.keywords_data["val"]
                if isinstance(val, Attribute):
                    symbol_record = self.symbol_table.identify(
                        get_fqnn(val_node))
                    kwargs = symbol_record["kwargs"]
                    node.keywords_data["dim"] = kwargs["dim"]
                else:
                    raise NotImplementedError("not implemented for %s" %
                                              type(val))

        dim = node.keywords_data["dim"]
        try:
            iter(dim)
        except TypeError:
            node.keywords_data["dim"] = dim = [dim]
        except KeyError:
            raise

        if "force_bitlen" in node.keywords_data:
            node.keywords_data["bitlen"] = node.keywords_data["force_bitlen"]

        if "force_signed" in node.keywords_data:
            node.keywords_data["signed"] = node.keywords_data["force_signed"]

        if not "signed" in node.keywords_data:
            try:
                val = node.keywords_data["val"]
                node.keywords_data["signed"] = val.return_info[0]["signed"]
            except KeyError:
                node.signed_not_finished = True

        if "bitlen" not in node.keywords_data:
            if node.node_type in (types.Modular, types.ModularVec):
                node.keywords_data["bitlen"] = \
                    state.config.asymmetric_security_parameter
            elif issubclass(node.node_type, types.TastyFunction):
                pass
            else:
                #node.keywords_data["bitlen"] = e
                # the type declaration is not yet completed. Later we must
                # ensure correct tasty type initialization and set in node
                # and symbol table if present
                node.bitlen_not_finished = True
                if __debug__:
                    state.log.debug("bitlen_not_finished")

        force_bitlen = node.keywords_data.get("force_bitlen")
        if force_bitlen:
            node.keywords_data["bitlen"] = force_bitlen

        force_signed = node.keywords_data.get("force_signed")
        if force_signed:
            node.keywords_data["signed"] = True

        val_return_rec = None
        bit_lengths = None
        dims = None

        if val:
            #propagate_kwargs(node)
            val_return_rec = val.return_info[0]
            input_types = (val_return_rec["type"], )
            bit_lengths = (node.keywords_data["bitlen"],
                           val_return_rec["bitlen"])
            dims = (node.keywords_data["dim"], val_return_rec["dim"])
            signeds = (node.keywords_data.get("signed"),
                       val_return_rec["signed"])
        else:
            input_types = tuple()
            bit_lengths = (node.keywords_data.get("bitlen"), )
            dims = (node.keywords_data["dim"], )
            signeds = (node.keywords_data.get("signed"), None)

        # in this special case we must populate input_types, bit_lengths, dims
        # and signeds after calling returns()
        node.return_info = node.node_type.returns(node.methodname, input_types,
                                                  bit_lengths, dims, signeds)
        return_rec = node.return_info[0]

        if val:
            node.input_types = (val_return_rec["type"], )
            node.bit_lengths = (return_rec["bitlen"], val_return_rec["bitlen"])
            node.dims = (return_rec["dim"], val_return_rec["dim"])
            node.signeds = (return_rec["signed"], val_return_rec["signed"])
        else:
            node.input_types = tuple()
            node.bit_lengths = (return_rec["bitlen"], )
            node.dims = (return_rec["dim"], )
            node.signeds = (return_rec["signed"], )

        if isinstance(node.parent, Attribute):
            copy_type_info(node.parent, node)

        assert hasattr(node, "return_info")
        assert hasattr(node, "node_type")
        assert (isinstance(node.keywords_data, dict))
        assert "dim" in node.keywords_data
        assert type(node.return_info[0]["dim"]) != dict

        node.initial_info = node.return_info[0]
Exemple #17
0
    def visit_AugAssign(self, node):
        """ checking for tasty operators with previously undefined targets and
        annotates them with the type information of the source"""

        if __debug__:
            state.log.debug("\ninfer %s", dump(node, True, True))

        left_node = node.target
        right_node = node.value
        fqnn = get_fqnn(left_node)

        if isinstance(node.op, LShift):
            # special treatment, since semantic redefined as sending operator
            # with optional type conversion

            if not isinstance(node.target, Attribute):
                raise TastySyntaxError("Can only send to a party")

            if node.value.passive:
                direction = "receive"
            else:
                direction = "send"

            try:
                # processing bound party attribute, both sides have same type
                right_fqnn = get_fqnn(right_node)
                symbol_record = self.symbol_table.identify(right_fqnn)
                dest_return_rec = symbol_record["kwargs"]
                dest_type = dest_return_rec["type"]
                dest_bitlen = dest_return_rec["bitlen"]
                dest_dim = dest_return_rec["dim"]
                dest_signed = dest_return_rec["signed"]
                node.input_types = (dest_type, dest_type)
                node.bit_lengths = (dest_bitlen, dest_bitlen)
                node.dims = (dest_dim, dest_dim)
                node.signeds = (dest_signed, dest_signed)
                node.return_info = ((dest_type, dest_bitlen, dest_dim,
                                     dest_signed), )
                node.methodname = "%s_%s_%s" % (dest_type.__name__,
                                                dest_type.__name__, direction)
            except (FqnnError, UnknownSymbolError):
                if not isinstance(right_node, Call):
                    raise TastySyntaxError("value of tasty operator must be " \
                    "a constructor call of a type of TASTY or a " \
                    "bound PartyAttribute, got %r" %
                    type(right_node))

                # tasty operator including type conversion

                self.visit(right_node)

                node.return_info = right_node.return_info
                dest_return_rec = right_node.return_info[0]

                src_node = right_node.keywords_map["val"]
                src_return_rec = src_node.return_info[0]
                src_type = src_return_rec["type"]
                dest_type = dest_return_rec["type"]

                node.input_types = (dest_return_rec["type"],
                                    src_return_rec["type"])
                node.bit_lengths = (dest_return_rec["bitlen"],
                                    src_return_rec["bitlen"])
                node.dims = (dest_return_rec["dim"], src_return_rec["dim"])
                node.signeds = (dest_return_rec["signed"],
                                src_return_rec["signed"])
                node.methodname = "%s_%s_%s" % (src_type.__name__,
                                                dest_type.__name__, direction)

            try_finish_bitlenless(self, fqnn, dest_return_rec["bitlen"])
            try_finish_signed(self, fqnn, dest_return_rec["signed"])

            node.initial_info = node.return_info[0]

            self.symbol_table.add_symbol(fqnn,
                                         kwargs=dest_return_rec,
                                         lineno=node.lineno,
                                         colno=node.col_offset)
        else:
            # normal pythonic operator behaviour

            fqnn = get_fqnn(left_node)

            node.dims = list()
            node.bit_lengths = list()
            node.input_types = list()
            node.signeds = list()

            annotate_item_of_node(self, left_node, node, False)
            annotate_item_of_node(self, right_node, node)

            node.methodname = bases.AUGASSIGN_METHODS[type(node.op)]

            node.return_info = left_node.return_info[0]["type"].returns(
                node.methodname, node.input_types, node.bit_lengths, node.dims,
                node.signeds)

            kwargs = node.return_info[0]

            self.symbol_table.add_symbol(fqnn,
                                         kwargs=kwargs,
                                         lineno=node.lineno,
                                         colno=node.col_offset)
Exemple #18
0
    def visit_method(self, node):
        """here we inspect function and method calls"""

        if __debug__:
            state.log.debug("\ninfer method %d %s", id(node),
                            dump(node, True, True))
        node.call_type = CALL_TYPE_METHOD

        # handling method of party attribute
        if (isinstance(node.func, Attribute)
                and isinstance(node.func.value, Attribute)):
            attribute_symbol_record = self.symbol_table.identify(
                get_fqnn(node.func.value))
            node.func.return_info = node.func.value.return_info = \
                (attribute_symbol_record["kwargs"],)

        self.visit(node.func)
        for i in node.args:
            self.visit(i)

        if hasattr(node, "attr"):
            if node.attr == "input":
                node.methodname = "input"
            elif node.attr == "output":
                node.methodname = "output"
            else:
                raise NotImplementedError()
            assert hasattr(node, "methodname")
            return

        if hasattr(node.func, "attr"):
            if node.func.attr == "input":
                cnode = node.func.value
                node.methodname = "input"
                if (hasattr(cnode, "call_type")
                        and cnode.call_type == CALL_TYPE_CTOR):
                    add_keyword(cnode, "empty", True)
                copy_type_info(node, node.func)
                node.initial_info = cnode.return_info[0]
                node.input_types = tuple()
                node.dims = tuple()
                return
            elif node.func.attr in ("output", "setup_output"):
                node.methodname = node.func.attr
                return

        retrieve_node_args(node)

        symbol_table = self.symbol_table

        # handles methods of bounded party attributes
        if isinstance(node.func, Attribute):
            if hasattr(node.func.value, "call_type"
                       ) and node.func.value.call_type == CALL_TYPE_CTOR:
                attribute_node_type = node.func.value.node_type
                attribute_kwargs = node.func.value.return_info[0]
            elif (isinstance(node.func.value, Attribute)
                  or isinstance(node.func.value, Call)):
                fqnn = find_fqnn(node.func.value)
                attribute_symbol_record = symbol_table.identify(fqnn)
                attribute_kwargs = attribute_symbol_record["kwargs"]
                attribute_node_type = attribute_kwargs["type"]
            elif isinstance(node.func.value, Subscript):
                attribute_kwargs = node.func.value.return_info[0]
                attribute_node_type = attribute_kwargs["type"]
            node.methodname = methodname = node.func.attr
            node.input_types = list()
            node.bit_lengths = [attribute_kwargs["bitlen"]]
            node.dims = [attribute_kwargs["dim"]]
            node.signeds = [attribute_kwargs["signed"]]
            node.input_types.extend(
                [arg.return_info[0]["type"] for arg in node.args])
            node.dims.extend([arg.return_info[0]["dim"] for arg in node.args])
            node.bit_lengths.extend(
                [arg.return_info[0]["bitlen"] for arg in node.args])
            node.return_info = attribute_node_type.returns(
                node.methodname, node.input_types, node.bit_lengths, node.dims,
                node.signeds)
            node.initial_info = attribute_kwargs
        else:
            raise TastySyntaxError(
                "expected a method of a subclass of Value or Vec, got '%s'" %
                type(node.func))

        if isinstance(node.parent, Attribute):
            copy_type_info(node.parent, node)
        assert hasattr(node, "return_info")
        assert hasattr(node, "initial_info")
        assert hasattr(node, "methodname")
        assert type(node.return_info[0]) == dict
        assert type(node.initial_info) == dict
Exemple #19
0
def Plain_send(src, dst, bitlen, dim, signed, force_bitlen=None, force_signed=None):
    if force_signed is not None:
        raise TastySyntaxError("use Signed/Unsigned for determination of sign in Plain types")
    _sendcost(bitlen)
    _send(src)
Exemple #20
0
 def check(self):
     if self.nodes_without_bitlen:
         raise TastySyntaxError("Following variables are declared without " \
             " bitlen and are not finished by either reassignment or " \
             "item assignment: %r" % self.nodes_without_bitlen)