Ejemplo n.º 1
0
    def make_dhfield(self, modp_options, sigmai):
        dhs = []

        for modp in modp_options:
            p = dh.primes[modp]
            g = dh.generators[modp]

            x = crypto.srand(2**(2 * self.n - 1), p - 1)

            # FIXME this may be a source of performance issues
            e = crypto.powmod(g, x, p)

            self.xes[modp] = x
            self.es[modp] = e

            if sigmai:
                dhs.append(
                    base64.b64encode(crypto.encode_mpi(e)).decode('utf-8'))
                name = 'dhkeys'
            else:
                He = crypto.sha256(crypto.encode_mpi(e))
                dhs.append(base64.b64encode(He).decode('utf-8'))
                name = 'dhhashes'

        return nbxmpp.DataField(name=name, typ='hidden', value=dhs)
Ejemplo n.º 2
0
    def final_steps_alice(self, form):
        srs = b''
        srses = secrets.secrets().retained_secrets(self.conn.name,
                                                   self.jid.getStripped())

        try:
            srshash = base64.b64decode(form['srshash'])
        except IndexError:
            return

        for s in srses:
            secret = s[0]
            if self.hmac(secret, b'Shared Retained Secret') == srshash:
                srs = secret
                break

        oss = b''
        k = crypto.sha256(self.k + srs + oss)
        del self.k

        self.do_retained_secret(k, srs)

        # ks_s doesn't need to be calculated here
        self.kc_s, self.km_s, self.ks_s = self.generate_initiator_keys(k)
        self.kc_o, self.km_o, self.ks_o = self.generate_responder_keys(k)

        # 4.6.2 Verifying Bob's Identity
        self.verify_identity(form, self.d, False, 'b')
        # Note: If Alice discovers an error then she SHOULD ignore any encrypted
        # content she received in the stanza.

        if self.negotiated['logging'] == 'mustnot':
            self.loggable = False

        self.status = 'active'
        self.enable_encryption = True

        if self.control:
            self.control.print_esession_details()
Ejemplo n.º 3
0
    def verify_identity(self, form, dh_i, sigmai, i_o):
        m_o = base64.b64decode(form['mac'])
        id_o = base64.b64decode(form['identity'])

        m_o_calculated = self.hmac(self.km_o,
                                   crypto.encode_mpi(self.c_o) + id_o)

        if m_o_calculated != m_o:
            raise NegotiationError(
                'calculated m_%s differs from received m_%s' % (i_o, i_o))

        if i_o == 'a' and self.sas_algs == 'sas28x5':
            # we don't need to calculate this if there's a verified retained secret
            # (but we do anyways)
            self.sas = crypto.sas_28x5(m_o, self.form_s.encode('utf-8'))

        if self.negotiated['recv_pubkey']:
            plaintext = self.decrypt(id_o)
            parsed = nbxmpp.Node(node='<node>' + plaintext + '</node>')

            if self.negotiated['recv_pubkey'] == 'hash':
                # fingerprint = parsed.getTagData('fingerprint')
                # FIXME find stored pubkey or terminate session
                raise NotImplementedError()
            else:
                if self.negotiated['sign_algs'] == (XmlDsig + 'rsa-sha256'):
                    keyvalue = parsed.getTag(name='RSAKeyValue',
                                             namespace=XmlDsig)

                    n, e = (crypto.decode_mpi(
                        base64.b64decode(keyvalue.getTagData(x)))
                            for x in ('Modulus', 'Exponent'))
                    eir_pubkey = RSA.construct((n, int(e)))

                    pubkey_o = nbxmpp.c14n.c14n(keyvalue,
                                                self._is_buggy_gajim())
                else:
                    # FIXME DSA, etc.
                    raise NotImplementedError()

            enc_sig = parsed.getTag(name='SignatureValue',
                                    namespace=XmlDsig).getData()
            signature = (crypto.decode_mpi(base64.b64decode(enc_sig)), )
        else:
            mac_o = self.decrypt(id_o)
            pubkey_o = b''

        c7l_form = self.c7lize_mac_id(form)

        content = self.n_s + self.n_o + crypto.encode_mpi(dh_i) + pubkey_o

        if sigmai:
            self.form_o = c7l_form.encode('utf-8')
            content += self.form_o
        else:
            form_o2 = c7l_form.encode('utf-8')
            content += self.form_o.encode('utf-8') + form_o2

        mac_o_calculated = self.hmac(self.ks_o, content)

        if self.negotiated['recv_pubkey']:
            hash_ = crypto.sha256(mac_o_calculated)

            if not eir_pubkey.verify(hash_, signature):
                raise NegotiationError(
                    'public key signature verification failed!')

        elif mac_o_calculated != mac_o:
            raise NegotiationError(
                'calculated mac_%s differs from received mac_%s' % (i_o, i_o))
Ejemplo n.º 4
0
    def get_shared_secret(self, e, y, p):
        if (not 1 < e < (p - 1)):
            raise NegotiationError('invalid DH value')

        return crypto.sha256(crypto.encode_mpi(crypto.powmod(e, y, p)))
Ejemplo n.º 5
0
 def sign(self, string):
     if self.negotiated['sign_algs'] == (XmlDsig + 'rsa-sha256'):
         hash_ = crypto.sha256(string)
         return crypto.encode_mpi(app.pubkey.sign(hash_, '')[0])
Ejemplo n.º 6
0
    def accept_e2e_bob(self, form):
        """
        4.5 esession accept (bob)
        """
        response = nbxmpp.Message()

        init = response.NT.init
        init.setNamespace(nbxmpp.NS_ESESSION_INIT)

        x = nbxmpp.DataForm(typ='result')

        for field in ('nonce', 'dhkeys', 'rshashes', 'identity', 'mac'):
            # FIXME: will do nothing in real world...
            assert field in form.asDict(), "alice's form didn't have a %s field" \
                    % field

        # 4.5.1 generating provisory session keys
        e = crypto.decode_mpi(base64.b64decode(form['dhkeys']))
        p = dh.primes[self.modp]

        if crypto.sha256(crypto.encode_mpi(e)) != self.negotiated['He']:
            raise NegotiationError('SHA256(e) != He')

        k = self.get_shared_secret(e, self.y, p)
        self.kc_o, self.km_o, self.ks_o = self.generate_initiator_keys(k)

        # 4.5.2 verifying alice's identity
        self.verify_identity(form, e, False, 'a')

        # 4.5.4 generating bob's final session keys
        srs = b''

        srses = secrets.secrets().retained_secrets(self.conn.name,
                                                   self.jid.getStripped())
        rshashes = [
            base64.b64decode(rshash)
            for rshash in form.getField('rshashes').getValues()
        ]

        for s in srses:
            secret = s[0]
            if self.hmac(self.n_o, secret) in rshashes:
                srs = secret
                break

        # other shared secret
        # (we're not using one)
        oss = b''

        k = crypto.sha256(k + srs + oss)

        self.kc_s, self.km_s, self.ks_s = self.generate_responder_keys(k)
        self.kc_o, self.km_o, self.ks_o = self.generate_initiator_keys(k)

        # 4.5.5
        if srs:
            srshash = self.hmac(srs, b'Shared Retained Secret')
        else:
            srshash = crypto.random_bytes(32)

        x.addChild(
            node=nbxmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn'))
        x.addChild(node=nbxmpp.DataField(
            name='nonce', value=base64.b64encode(self.n_o).decode('utf-8')))
        x.addChild(node=nbxmpp.DataField(
            name='srshash', value=base64.b64encode(srshash).decode('utf-8')))

        for datafield in self.make_identity(x, self.d):
            x.addChild(node=datafield)

        init.addChild(node=x)

        self.send(response)

        self.do_retained_secret(k, srs)

        if self.negotiated['logging'] == 'mustnot':
            self.loggable = False

        self.status = 'active'
        self.enable_encryption = True

        if self.control:
            self.control.print_esession_details()