def accept_e2e_bob(self, form): response = xmpp.Message() init = response.NT.init init.setNamespace(xmpp.NS_ESESSION_INIT) x = xmpp.DataForm(typ='result') for field in ('nonce', 'dhkeys', 'rshashes', 'identity', 'mac'): 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 exceptions.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 = '' srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped()) rshashes = [ base64.b64decode(rshash) for rshash in form.getField('rshashes').getValues() ] for (secret, verified) in srses: if self.hmac(self.n_o, secret) in rshashes: srs = secret break # other shared secret # (we're not using one) oss = '' 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, 'Shared Retained Secret') else: srshash = crypto.random_bytes(32) x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) x.addChild(node=xmpp.DataField(name='nonce', value=base64.b64encode(self.n_o))) x.addChild(node=xmpp.DataField(name='srshash', value=base64.b64encode(srshash))) 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()
def respond_e2e_bob(self, form, negotiated, not_acceptable): response = xmpp.Message() feature = response.NT.feature feature.setNamespace(xmpp.NS_FEATURE) x = xmpp.DataForm(typ='submit') x.addChild(node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) x.addChild(node=xmpp.DataField(name='accept', value='true')) for name in negotiated: # some fields are internal and should not be sent if not name in ('send_pubkey', 'recv_pubkey'): x.addChild( node=xmpp.DataField(name=name, value=negotiated[name])) self.negotiated = negotiated # the offset of the group we chose (need it to match up with the dhhash) group_order = 0 self.modp = int(form.getField('modp').getOptions()[group_order][1]) x.addChild(node=xmpp.DataField(name='modp', value=self.modp)) g = dh.generators[self.modp] p = dh.primes[self.modp] self.n_o = base64.b64decode(form['my_nonce']) dhhashes = form.getField('dhhashes').getValues() self.negotiated['He'] = base64.b64decode( dhhashes[group_order].encode('utf8')) bytes = int(self.n / 8) self.n_s = crypto.generate_nonce() # n-bit random number self.c_o = crypto.decode_mpi(crypto.random_bytes(bytes)) self.c_s = self.c_o ^ (2**(self.n - 1)) self.y = crypto.srand(2**(2 * self.n - 1), p - 1) self.d = crypto.powmod(g, self.y, p) to_add = { 'my_nonce': self.n_s, 'dhkeys': crypto.encode_mpi(self.d), 'counter': crypto.encode_mpi(self.c_o), 'nonce': self.n_o } for name in to_add: b64ed = base64.b64encode(to_add[name]) x.addChild(node=xmpp.DataField(name=name, value=b64ed)) self.form_o = ''.join( map(lambda el: xmpp.c14n.c14n(el), form.getChildren())) self.form_s = ''.join( map(lambda el: xmpp.c14n.c14n(el), x.getChildren())) self.status = 'responded-e2e' feature.addChild(node=x) if not_acceptable: response = xmpp.Error(response, xmpp.ERR_NOT_ACCEPTABLE) feature = xmpp.Node(xmpp.NS_FEATURE + ' feature') for f in not_acceptable: n = xmpp.Node('field') n['var'] = f feature.addChild(node=n) response.T.error.addChild(node=feature) self.send(response)
def accept_e2e_alice(self, form, negotiated): self.encryptable_stanzas = ['message'] self.sas_algs = 'sas28x5' self.cipher = AES self.hash_alg = SHA256 self.compression = None self.negotiated = negotiated accept = xmpp.Message() feature = accept.NT.feature feature.setNamespace(xmpp.NS_FEATURE) result = xmpp.DataForm(typ='result') self.c_s = crypto.decode_mpi(base64.b64decode(form['counter'])) self.c_o = self.c_s ^ (2**(self.n - 1)) self.n_o = base64.b64decode(form['my_nonce']) mod_p = int(form['modp']) p = dh.primes[mod_p] x = self.xes[mod_p] e = self.es[mod_p] self.d = crypto.decode_mpi(base64.b64decode(form['dhkeys'])) self.k = self.get_shared_secret(self.d, x, p) result.addChild( node=xmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) result.addChild(node=xmpp.DataField(name='accept', value='1')) result.addChild(node=xmpp.DataField(name='nonce', value=base64.b64encode(self.n_o))) self.kc_s, self.km_s, self.ks_s = self.generate_initiator_keys(self.k) if self.sigmai: self.kc_o, self.km_o, self.ks_o = self.generate_responder_keys( self.k) self.verify_identity(form, self.d, True, 'b') else: srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped()) rshashes = [self.hmac(self.n_s, rs) for (rs, v) in srses] if not rshashes: # we've never spoken before, but we'll pretend we have rshash_size = self.hash_alg.digest_size rshashes.append(crypto.random_bytes(rshash_size)) rshashes = [base64.b64encode(rshash) for rshash in rshashes] result.addChild( node=xmpp.DataField(name='rshashes', value=rshashes)) result.addChild(node=xmpp.DataField( name='dhkeys', value=base64.b64encode(crypto.encode_mpi(e)))) self.form_o = ''.join( map(lambda el: xmpp.c14n.c14n(el), form.getChildren())) # MUST securely destroy K unless it will be used later to generate the # final shared secret for datafield in self.make_identity(result, e): result.addChild(node=datafield) feature.addChild(node=result) self.send(accept) if self.sigmai: self.status = 'active' self.enable_encryption = True else: self.status = 'identified-alice'
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 = '' 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 = '' 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, '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))) x.addChild(node=nbxmpp.DataField(name='srshash', value=base64.b64encode( srshash))) 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() self.stop_archiving_for_session()
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 exceptions.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) if self.negotiated['recv_pubkey']: plaintext = self.decrypt(id_o) parsed = xmpp.Node(node='<node>' + plaintext + '</node>') if self.negotiated['recv_pubkey'] == 'hash': fingerprint = parsed.getTagData('fingerprint') # XXX find stored pubkey or terminate session raise 'unimplemented' else: if self.negotiated['sign_algs'] == (XmlDsig + 'rsa-sha256'): keyvalue = parsed.getTag(name='RSAKeyValue', namespace=XmlDsig) n, e = map( lambda x: crypto.decode_mpi( base64.b64decode(keyvalue.getTagData(x))), ('Modulus', 'Exponent')) eir_pubkey = RSA.construct((n, long(e))) pubkey_o = xmpp.c14n.c14n(keyvalue) else: # XXX DSA, etc. raise 'unimplemented' 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 = '' 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 content += self.form_o else: form_o2 = c7l_form content += self.form_o + 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 exceptions.NegotiationError, 'public key signature verification failed!' elif mac_o_calculated != mac_o: raise exceptions.NegotiationError, 'calculated mac_%s differs from received mac_%s' % ( i_o, i_o)
def respond_e2e_bob(self, form, negotiated, not_acceptable): """ 4.3 esession response (bob) """ response = nbxmpp.Message() feature = response.NT.feature feature.setNamespace(nbxmpp.NS_FEATURE) x = nbxmpp.DataForm(typ='submit') x.addChild(node=nbxmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) x.addChild(node=nbxmpp.DataField(name='accept', value='true')) for name in negotiated: # some fields are internal and should not be sent if not name in ('send_pubkey', 'recv_pubkey'): x.addChild(node=nbxmpp.DataField(name=name, value=negotiated[name])) self.negotiated = negotiated # the offset of the group we chose (need it to match up with the dhhash) group_order = 0 modp_f = form.getField('modp') if not modp_f: return self.modp = int(modp_f.getOptions()[group_order][1]) x.addChild(node=nbxmpp.DataField(name='modp', value=self.modp)) g = dh.generators[self.modp] p = dh.primes[self.modp] self.n_o = base64.b64decode(form['my_nonce']) dhhashes_f = form.getField('dhhashes') if not dhhashes_f: return dhhashes = dhhashes_f.getValues() self.negotiated['He'] = base64.b64decode(dhhashes[group_order].encode( 'utf8')) bytes = int(self.n / 8) self.n_s = crypto.generate_nonce() # n-bit random number self.c_o = crypto.decode_mpi(crypto.random_bytes(bytes)) self.c_s = self.c_o ^ (2 ** (self.n - 1)) self.y = crypto.srand(2 ** (2 * self.n - 1), p - 1) self.d = crypto.powmod(g, self.y, p) to_add = {'my_nonce': self.n_s, 'dhkeys': crypto.encode_mpi(self.d), 'counter': crypto.encode_mpi(self.c_o), 'nonce': self.n_o} for name in to_add: b64ed = base64.b64encode(to_add[name]) x.addChild(node=nbxmpp.DataField(name=name, value=b64ed)) self.form_o = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for \ el in form.getChildren()) self.form_s = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) for \ el in x.getChildren()) self.status = 'responded-e2e' feature.addChild(node=x) if not_acceptable: response = nbxmpp.Error(response, nbxmpp.ERR_NOT_ACCEPTABLE) feature = nbxmpp.Node(nbxmpp.NS_FEATURE + ' feature') for f in not_acceptable: n = nbxmpp.Node('field') n['var'] = f feature.addChild(node=n) response.T.error.addChild(node=feature) self.send(response)
def accept_e2e_alice(self, form, negotiated): """ 'Alice Accepts', continued """ self.encryptable_stanzas = ['message'] self.sas_algs = 'sas28x5' self.cipher = AES self.hash_alg = sha256 self.compression = None self.negotiated = negotiated accept = nbxmpp.Message() feature = accept.NT.feature feature.setNamespace(nbxmpp.NS_FEATURE) result = nbxmpp.DataForm(typ='result') self.c_s = crypto.decode_mpi(base64.b64decode(form['counter'])) self.c_o = self.c_s ^ (2 ** (self.n - 1)) self.n_o = base64.b64decode(form['my_nonce']) mod_p = int(form['modp']) p = dh.primes[mod_p] x = self.xes[mod_p] e = self.es[mod_p] self.d = crypto.decode_mpi(base64.b64decode(form['dhkeys'])) self.k = self.get_shared_secret(self.d, x, p) result.addChild(node=nbxmpp.DataField(name='FORM_TYPE', value='urn:xmpp:ssn')) result.addChild(node=nbxmpp.DataField(name='accept', value='1')) result.addChild(node=nbxmpp.DataField(name='nonce', value=base64.b64encode(self.n_o))) self.kc_s, self.km_s, self.ks_s = self.generate_initiator_keys(self.k) if self.sigmai: self.kc_o, self.km_o, self.ks_o = self.generate_responder_keys(self.k) self.verify_identity(form, self.d, True, 'b') else: srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped()) rshashes = [self.hmac(self.n_s, rs[0]) for rs in srses] if not rshashes: # we've never spoken before, but we'll pretend we have rshash_size = self.hash_alg().digest_size rshashes.append(crypto.random_bytes(rshash_size)) rshashes = [base64.b64encode(rshash) for rshash in rshashes] result.addChild(node=nbxmpp.DataField(name='rshashes', value=rshashes)) result.addChild(node=nbxmpp.DataField(name='dhkeys', value=base64.b64encode(crypto.encode_mpi(e)))) self.form_o = ''.join(nbxmpp.c14n.c14n(el, self._is_buggy_gajim()) \ for el in form.getChildren()) # MUST securely destroy K unless it will be used later to generate the # final shared secret for datafield in self.make_identity(result, e): result.addChild(node=datafield) feature.addChild(node=result) self.send(accept) if self.sigmai: self.status = 'active' self.enable_encryption = True else: self.status = 'identified-alice'
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) 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, long(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 = '' 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 content += self.form_o else: form_o2 = c7l_form content += self.form_o + 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))
def accept_e2e_bob(self, form): response = xmpp.Message() init = response.NT.init init.setNamespace(xmpp.NS_ESESSION_INIT) x = xmpp.DataForm(typ="result") for field in ("nonce", "dhkeys", "rshashes", "identity", "mac"): 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 exceptions.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 = "" srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped()) rshashes = [base64.b64decode(rshash) for rshash in form.getField("rshashes").getValues()] for (secret, verified) in srses: if self.hmac(self.n_o, secret) in rshashes: srs = secret break # other shared secret # (we're not using one) oss = "" 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, "Shared Retained Secret") else: srshash = crypto.random_bytes(32) x.addChild(node=xmpp.DataField(name="FORM_TYPE", value="urn:xmpp:ssn")) x.addChild(node=xmpp.DataField(name="nonce", value=base64.b64encode(self.n_o))) x.addChild(node=xmpp.DataField(name="srshash", value=base64.b64encode(srshash))) 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()
def accept_e2e_alice(self, form, negotiated): self.encryptable_stanzas = ["message"] self.sas_algs = "sas28x5" self.cipher = AES self.hash_alg = SHA256 self.compression = None self.negotiated = negotiated accept = xmpp.Message() feature = accept.NT.feature feature.setNamespace(xmpp.NS_FEATURE) result = xmpp.DataForm(typ="result") self.c_s = crypto.decode_mpi(base64.b64decode(form["counter"])) self.c_o = self.c_s ^ (2 ** (self.n - 1)) self.n_o = base64.b64decode(form["my_nonce"]) mod_p = int(form["modp"]) p = dh.primes[mod_p] x = self.xes[mod_p] e = self.es[mod_p] self.d = crypto.decode_mpi(base64.b64decode(form["dhkeys"])) self.k = self.get_shared_secret(self.d, x, p) result.addChild(node=xmpp.DataField(name="FORM_TYPE", value="urn:xmpp:ssn")) result.addChild(node=xmpp.DataField(name="accept", value="1")) result.addChild(node=xmpp.DataField(name="nonce", value=base64.b64encode(self.n_o))) self.kc_s, self.km_s, self.ks_s = self.generate_initiator_keys(self.k) if self.sigmai: self.kc_o, self.km_o, self.ks_o = self.generate_responder_keys(self.k) self.verify_identity(form, self.d, True, "b") else: srses = secrets.secrets().retained_secrets(self.conn.name, self.jid.getStripped()) rshashes = [self.hmac(self.n_s, rs) for (rs, v) in srses] if not rshashes: # we've never spoken before, but we'll pretend we have rshash_size = self.hash_alg.digest_size rshashes.append(crypto.random_bytes(rshash_size)) rshashes = [base64.b64encode(rshash) for rshash in rshashes] result.addChild(node=xmpp.DataField(name="rshashes", value=rshashes)) result.addChild(node=xmpp.DataField(name="dhkeys", value=base64.b64encode(crypto.encode_mpi(e)))) self.form_o = "".join(map(lambda el: xmpp.c14n.c14n(el), form.getChildren())) # MUST securely destroy K unless it will be used later to generate the # final shared secret for datafield in self.make_identity(result, e): result.addChild(node=datafield) feature.addChild(node=result) self.send(accept) if self.sigmai: self.status = "active" self.enable_encryption = True else: self.status = "identified-alice"
def respond_e2e_bob(self, form, negotiated, not_acceptable): response = xmpp.Message() feature = response.NT.feature feature.setNamespace(xmpp.NS_FEATURE) x = xmpp.DataForm(typ="submit") x.addChild(node=xmpp.DataField(name="FORM_TYPE", value="urn:xmpp:ssn")) x.addChild(node=xmpp.DataField(name="accept", value="true")) for name in negotiated: # some fields are internal and should not be sent if not name in ("send_pubkey", "recv_pubkey"): x.addChild(node=xmpp.DataField(name=name, value=negotiated[name])) self.negotiated = negotiated # the offset of the group we chose (need it to match up with the dhhash) group_order = 0 self.modp = int(form.getField("modp").getOptions()[group_order][1]) x.addChild(node=xmpp.DataField(name="modp", value=self.modp)) g = dh.generators[self.modp] p = dh.primes[self.modp] self.n_o = base64.b64decode(form["my_nonce"]) dhhashes = form.getField("dhhashes").getValues() self.negotiated["He"] = base64.b64decode(dhhashes[group_order].encode("utf8")) bytes = int(self.n / 8) self.n_s = crypto.generate_nonce() # n-bit random number self.c_o = crypto.decode_mpi(crypto.random_bytes(bytes)) self.c_s = self.c_o ^ (2 ** (self.n - 1)) self.y = crypto.srand(2 ** (2 * self.n - 1), p - 1) self.d = crypto.powmod(g, self.y, p) to_add = { "my_nonce": self.n_s, "dhkeys": crypto.encode_mpi(self.d), "counter": crypto.encode_mpi(self.c_o), "nonce": self.n_o, } for name in to_add: b64ed = base64.b64encode(to_add[name]) x.addChild(node=xmpp.DataField(name=name, value=b64ed)) self.form_o = "".join(map(lambda el: xmpp.c14n.c14n(el), form.getChildren())) self.form_s = "".join(map(lambda el: xmpp.c14n.c14n(el), x.getChildren())) self.status = "responded-e2e" feature.addChild(node=x) if not_acceptable: response = xmpp.Error(response, xmpp.ERR_NOT_ACCEPTABLE) feature = xmpp.Node(xmpp.NS_FEATURE + " feature") for f in not_acceptable: n = xmpp.Node("field") n["var"] = f feature.addChild(node=n) response.T.error.addChild(node=feature) self.send(response)
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 exceptions.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) if self.negotiated["recv_pubkey"]: plaintext = self.decrypt(id_o) parsed = xmpp.Node(node="<node>" + plaintext + "</node>") if self.negotiated["recv_pubkey"] == "hash": fingerprint = parsed.getTagData("fingerprint") # XXX find stored pubkey or terminate session raise "unimplemented" else: if self.negotiated["sign_algs"] == (XmlDsig + "rsa-sha256"): keyvalue = parsed.getTag(name="RSAKeyValue", namespace=XmlDsig) n, e = map( lambda x: crypto.decode_mpi(base64.b64decode(keyvalue.getTagData(x))), ("Modulus", "Exponent") ) eir_pubkey = RSA.construct((n, long(e))) pubkey_o = xmpp.c14n.c14n(keyvalue) else: # XXX DSA, etc. raise "unimplemented" 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 = "" 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 content += self.form_o else: form_o2 = c7l_form content += self.form_o + 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 exceptions.NegotiationError, "public key signature verification failed!" elif mac_o_calculated != mac_o: raise exceptions.NegotiationError, "calculated mac_%s differs from received mac_%s" % (i_o, i_o)