aboutsummaryrefslogtreecommitdiff
path: root/plugins/omemo/src/jingle
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2021-04-25 19:49:10 +0200
committerfiaxh <git@lightrise.org>2021-04-29 16:13:25 +0200
commit421f43dd8bd993eb88581e1b5011cc061ceb4fc8 (patch)
tree6495066b5e608188d8837dbcc133c5adc8e57c45 /plugins/omemo/src/jingle
parent5d85b6cdb0165d863aadd25d9a73707b8f5cc83e (diff)
downloaddino-421f43dd8bd993eb88581e1b5011cc061ceb4fc8.tar.gz
dino-421f43dd8bd993eb88581e1b5011cc061ceb4fc8.zip
Add support for OMEMO call encryption
Diffstat (limited to 'plugins/omemo/src/jingle')
-rw-r--r--plugins/omemo/src/jingle/jet_omemo.vala82
1 files changed, 23 insertions, 59 deletions
diff --git a/plugins/omemo/src/jingle/jet_omemo.vala b/plugins/omemo/src/jingle/jet_omemo.vala
index 14307be2..afcdfcd6 100644
--- a/plugins/omemo/src/jingle/jet_omemo.vala
+++ b/plugins/omemo/src/jingle/jet_omemo.vala
@@ -7,18 +7,15 @@ using Xmpp;
using Xmpp.Xep;
namespace Dino.Plugins.JetOmemo {
+
private const string NS_URI = "urn:xmpp:jingle:jet-omemo:0";
private const string AES_128_GCM_URI = "urn:xmpp:ciphers:aes-128-gcm-nopadding";
+
public class Module : XmppStreamModule, Jet.EnvelopEncoding {
public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0396_jet_omemo");
- private Omemo.Plugin plugin;
const uint KEY_SIZE = 16;
const uint IV_SIZE = 12;
- public Module(Omemo.Plugin plugin) {
- this.plugin = plugin;
- }
-
public override void attach(XmppStream stream) {
if (stream.get_module(Jet.Module.IDENTITY) != null) {
stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI);
@@ -44,71 +41,38 @@ public class Module : XmppStreamModule, Jet.EnvelopEncoding {
}
public Jet.TransportSecret decode_envolop(XmppStream stream, Jid local_full_jid, Jid peer_full_jid, StanzaNode security) throws Jingle.IqError {
- Store store = stream.get_module(Omemo.StreamModule.IDENTITY).store;
StanzaNode? encrypted = security.get_subnode("encrypted", Omemo.NS_URI);
if (encrypted == null) throw new Jingle.IqError.BAD_REQUEST("Invalid JET-OMEMO envelop: missing encrypted element");
- StanzaNode? header = encrypted.get_subnode("header", Omemo.NS_URI);
- if (header == null) throw new Jingle.IqError.BAD_REQUEST("Invalid JET-OMEMO envelop: missing header element");
- string? iv_node = header.get_deep_string_content("iv");
- if (header == null) throw new Jingle.IqError.BAD_REQUEST("Invalid JET-OMEMO envelop: missing iv element");
- uint8[] iv = Base64.decode((!)iv_node);
- foreach (StanzaNode key_node in header.get_subnodes("key")) {
- if (key_node.get_attribute_int("rid") == store.local_registration_id) {
- string? key_node_content = key_node.get_string_content();
-
- uint8[] key;
- Address address = new Address(peer_full_jid.bare_jid.to_string(), header.get_attribute_int("sid"));
- if (key_node.get_attribute_bool("prekey")) {
- PreKeySignalMessage msg = Omemo.Plugin.get_context().deserialize_pre_key_signal_message(Base64.decode((!)key_node_content));
- SessionCipher cipher = store.create_session_cipher(address);
- key = cipher.decrypt_pre_key_signal_message(msg);
- } else {
- SignalMessage msg = Omemo.Plugin.get_context().deserialize_signal_message(Base64.decode((!)key_node_content));
- SessionCipher cipher = store.create_session_cipher(address);
- key = cipher.decrypt_signal_message(msg);
- }
- address.device_id = 0; // TODO: Hack to have address obj live longer
-
- uint8[] authtag = null;
- if (key.length >= 32) {
- int authtaglength = key.length - 16;
- authtag = new uint8[authtaglength];
- uint8[] new_key = new uint8[16];
- Memory.copy(authtag, (uint8*)key + 16, 16);
- Memory.copy(new_key, key, 16);
- key = new_key;
- }
- // TODO: authtag?
- return new Jet.TransportSecret(key, iv);
+
+ Xep.Omemo.OmemoDecryptor decryptor = stream.get_module(Xep.Omemo.OmemoDecryptor.IDENTITY);
+
+ Xmpp.Xep.Omemo.ParsedData? data = decryptor.parse_node(encrypted);
+ if (data == null) throw new Jingle.IqError.BAD_REQUEST("Invalid JET-OMEMO envelop: bad encrypted element");
+
+ foreach (Bytes encr_key in data.our_potential_encrypted_keys.keys) {
+ data.is_prekey = data.our_potential_encrypted_keys[encr_key];
+ data.encrypted_key = encr_key.get_data();
+
+ try {
+ uint8[] key = decryptor.decrypt_key(data, peer_full_jid.bare_jid);
+ return new Jet.TransportSecret(key, data.iv);
+ } catch (GLib.Error e) {
+ debug("Decrypting JET key from %s/%d failed: %s", peer_full_jid.bare_jid.to_string(), data.sid, e.message);
}
}
throw new Jingle.IqError.NOT_ACCEPTABLE("Not encrypted for targeted device");
}
public void encode_envelop(XmppStream stream, Jid local_full_jid, Jid peer_full_jid, Jet.SecurityParameters security_params, StanzaNode security) {
- ArrayList<Account> accounts = plugin.app.stream_interactor.get_accounts();
Store store = stream.get_module(Omemo.StreamModule.IDENTITY).store;
- Account? account = null;
- foreach (Account compare in accounts) {
- if (compare.bare_jid.equals_bare(local_full_jid)) {
- account = compare;
- break;
- }
- }
- if (account == null) {
- // TODO
- critical("Sending from offline account %s", local_full_jid.to_string());
- }
- StanzaNode header_node;
- StanzaNode encrypted_node = new StanzaNode.build("encrypted", Omemo.NS_URI).add_self_xmlns()
- .put_node(header_node = new StanzaNode.build("header", Omemo.NS_URI)
- .put_attribute("sid", store.local_registration_id.to_string())
- .put_node(new StanzaNode.build("iv", Omemo.NS_URI)
- .put_node(new StanzaNode.text(Base64.encode(security_params.secret.initialization_vector)))));
+ var encryption_data = new Xep.Omemo.EncryptionData(store.local_registration_id);
+ encryption_data.iv = security_params.secret.initialization_vector;
+ encryption_data.keytag = security_params.secret.transport_key;
+ Xep.Omemo.OmemoEncryptor encryptor = stream.get_module(Xep.Omemo.OmemoEncryptor.IDENTITY);
+ encryptor.encrypt_key_to_recipient(stream, encryption_data, peer_full_jid.bare_jid);
- plugin.trust_manager.encrypt_key(header_node, security_params.secret.transport_key, local_full_jid.bare_jid, new ArrayList<Jid>.wrap(new Jid[] {peer_full_jid.bare_jid}), stream, account);
- security.put_node(encrypted_node);
+ security.put_node(encryption_data.get_encrypted_node());
}
public override string get_ns() { return NS_URI; }