Send OMEMO-encrypted messages and files using 12 byte IV
This commit is contained in:
parent
f6943a4c82
commit
cd5b639a82
|
@ -52,14 +52,8 @@ public class OmemoFileDecryptor : FileDecryptor, Object {
|
||||||
MatchInfo match_info;
|
MatchInfo match_info;
|
||||||
this.url_regex.match(omemo_http_receive_data.original_url, 0, out match_info);
|
this.url_regex.match(omemo_http_receive_data.original_url, 0, out match_info);
|
||||||
uint8[] iv_and_key = hex_to_bin(match_info.fetch(2).up());
|
uint8[] iv_and_key = hex_to_bin(match_info.fetch(2).up());
|
||||||
uint8[] iv, key;
|
uint8[] iv = iv_and_key[0:iv_and_key.length-16];
|
||||||
if (iv_and_key.length == 44) {
|
uint8[] key = iv_and_key[iv_and_key.length-16:iv_and_key.length];
|
||||||
iv = iv_and_key[0:12];
|
|
||||||
key = iv_and_key[12:44];
|
|
||||||
} else {
|
|
||||||
iv = iv_and_key[0:16];
|
|
||||||
key = iv_and_key[16:48];
|
|
||||||
}
|
|
||||||
|
|
||||||
file_transfer.encryption = Encryption.OMEMO;
|
file_transfer.encryption = Encryption.OMEMO;
|
||||||
debug("Decrypting file %s from %s", file_transfer.file_name, file_transfer.server_file_name);
|
debug("Decrypting file %s from %s", file_transfer.file_name, file_transfer.server_file_name);
|
||||||
|
|
|
@ -20,13 +20,15 @@ public class OmemoFileEncryptor : Dino.FileEncryptor, Object {
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileMeta encrypt_file(Conversation conversation, FileTransfer file_transfer) throws FileSendError {
|
public FileMeta encrypt_file(Conversation conversation, FileTransfer file_transfer) throws FileSendError {
|
||||||
|
const uint KEY_SIZE = 32;
|
||||||
|
const uint IV_SIZE = 12;
|
||||||
var omemo_http_file_meta = new OmemoHttpFileMeta();
|
var omemo_http_file_meta = new OmemoHttpFileMeta();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//Create a key and use it to encrypt the file
|
//Create a key and use it to encrypt the file
|
||||||
uint8[] iv = new uint8[16];
|
uint8[] iv = new uint8[IV_SIZE];
|
||||||
Plugin.get_context().randomize(iv);
|
Plugin.get_context().randomize(iv);
|
||||||
uint8[] key = new uint8[32];
|
uint8[] key = new uint8[KEY_SIZE];
|
||||||
Plugin.get_context().randomize(key);
|
Plugin.get_context().randomize(key);
|
||||||
|
|
||||||
SymmetricCipher cipher = new SymmetricCipher("AES-GCM");
|
SymmetricCipher cipher = new SymmetricCipher("AES-GCM");
|
||||||
|
|
|
@ -12,6 +12,8 @@ private const string AES_128_GCM_URI = "urn:xmpp:ciphers:aes-128-gcm-nopadding";
|
||||||
public class Module : XmppStreamModule, Jet.EnvelopEncoding {
|
public class Module : XmppStreamModule, Jet.EnvelopEncoding {
|
||||||
public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0396_jet_omemo");
|
public static Xmpp.ModuleIdentity<Module> IDENTITY = new Xmpp.ModuleIdentity<Module>(NS_URI, "0396_jet_omemo");
|
||||||
private Omemo.Plugin plugin;
|
private Omemo.Plugin plugin;
|
||||||
|
const uint KEY_SIZE = 16;
|
||||||
|
const uint IV_SIZE = 12;
|
||||||
|
|
||||||
public Module(Omemo.Plugin plugin) {
|
public Module(Omemo.Plugin plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
@ -21,7 +23,7 @@ public class Module : XmppStreamModule, Jet.EnvelopEncoding {
|
||||||
if (stream.get_module(Jet.Module.IDENTITY) != null) {
|
if (stream.get_module(Jet.Module.IDENTITY) != null) {
|
||||||
stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI);
|
stream.get_module(ServiceDiscovery.Module.IDENTITY).add_feature(stream, NS_URI);
|
||||||
stream.get_module(Jet.Module.IDENTITY).register_envelop_encoding(this);
|
stream.get_module(Jet.Module.IDENTITY).register_envelop_encoding(this);
|
||||||
stream.get_module(Jet.Module.IDENTITY).register_cipher(new AesGcmCipher(16, AES_128_GCM_URI));
|
stream.get_module(Jet.Module.IDENTITY).register_cipher(new AesGcmCipher(KEY_SIZE, IV_SIZE, AES_128_GCM_URI));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,17 +116,19 @@ public class Module : XmppStreamModule, Jet.EnvelopEncoding {
|
||||||
}
|
}
|
||||||
|
|
||||||
public class AesGcmCipher : Jet.Cipher, Object {
|
public class AesGcmCipher : Jet.Cipher, Object {
|
||||||
private int key_size;
|
private uint key_size;
|
||||||
|
private uint default_iv_size;
|
||||||
private string uri;
|
private string uri;
|
||||||
public AesGcmCipher(int key_size, string uri) {
|
public AesGcmCipher(uint key_size, uint default_iv_size, string uri) {
|
||||||
this.key_size = key_size;
|
this.key_size = key_size;
|
||||||
|
this.default_iv_size = default_iv_size;
|
||||||
this.uri = uri;
|
this.uri = uri;
|
||||||
}
|
}
|
||||||
public string get_cipher_uri() {
|
public string get_cipher_uri() {
|
||||||
return uri;
|
return uri;
|
||||||
}
|
}
|
||||||
public Jet.TransportSecret generate_random_secret() {
|
public Jet.TransportSecret generate_random_secret() {
|
||||||
uint8[] iv = new uint8[16];
|
uint8[] iv = new uint8[default_iv_size];
|
||||||
Omemo.Plugin.get_context().randomize(iv);
|
Omemo.Plugin.get_context().randomize(iv);
|
||||||
uint8[] key = new uint8[key_size];
|
uint8[] key = new uint8[key_size];
|
||||||
Omemo.Plugin.get_context().randomize(key);
|
Omemo.Plugin.get_context().randomize(key);
|
||||||
|
|
|
@ -145,6 +145,8 @@ public class TrustManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public EncryptState encrypt(MessageStanza message, Jid self_jid, Gee.List<Jid> recipients, XmppStream stream, Account account) {
|
public EncryptState encrypt(MessageStanza message, Jid self_jid, Gee.List<Jid> recipients, XmppStream stream, Account account) {
|
||||||
|
const uint KEY_SIZE = 16;
|
||||||
|
const uint IV_SIZE = 12;
|
||||||
EncryptState status = new EncryptState();
|
EncryptState status = new EncryptState();
|
||||||
if (!Plugin.ensure_context()) return status;
|
if (!Plugin.ensure_context()) return status;
|
||||||
if (message.to == null) return status;
|
if (message.to == null) return status;
|
||||||
|
@ -153,9 +155,9 @@ public class TrustManager {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//Create a key and use it to encrypt the message
|
//Create a key and use it to encrypt the message
|
||||||
uint8[] key = new uint8[16];
|
uint8[] key = new uint8[KEY_SIZE];
|
||||||
Plugin.get_context().randomize(key);
|
Plugin.get_context().randomize(key);
|
||||||
uint8[] iv = new uint8[16];
|
uint8[] iv = new uint8[IV_SIZE];
|
||||||
Plugin.get_context().randomize(iv);
|
Plugin.get_context().randomize(iv);
|
||||||
|
|
||||||
uint8[] aes_encrypt_result = aes_encrypt(Cipher.AES_GCM_NOPADDING, key, iv, message.body.data);
|
uint8[] aes_encrypt_result = aes_encrypt(Cipher.AES_GCM_NOPADDING, key, iv, message.body.data);
|
||||||
|
|
|
@ -5,7 +5,7 @@ using Signal;
|
||||||
|
|
||||||
namespace Dino.Plugins.Omemo {
|
namespace Dino.Plugins.Omemo {
|
||||||
|
|
||||||
private const string NS_URI = "eu.siacs.conversations.axolotl";
|
internal const string NS_URI = "eu.siacs.conversations.axolotl";
|
||||||
private const string NODE_DEVICELIST = NS_URI + ".devicelist";
|
private const string NODE_DEVICELIST = NS_URI + ".devicelist";
|
||||||
private const string NODE_BUNDLES = NS_URI + ".bundles";
|
private const string NODE_BUNDLES = NS_URI + ".bundles";
|
||||||
private const string NODE_VERIFICATION = NS_URI + ".verification";
|
private const string NODE_VERIFICATION = NS_URI + ".verification";
|
||||||
|
|
|
@ -211,8 +211,6 @@ int signal_vala_encrypt(signal_buffer **output,
|
||||||
int algo, mode, error_code = SG_ERR_UNKNOWN;
|
int algo, mode, error_code = SG_ERR_UNKNOWN;
|
||||||
if (aes_cipher(cipher, key_len, &algo, &mode)) return SG_ERR_INVAL;
|
if (aes_cipher(cipher, key_len, &algo, &mode)) return SG_ERR_INVAL;
|
||||||
|
|
||||||
if (iv_len != 16 && iv_len != 12) return SG_ERR_INVAL;
|
|
||||||
|
|
||||||
gcry_cipher_hd_t ctx = {0};
|
gcry_cipher_hd_t ctx = {0};
|
||||||
|
|
||||||
if (gcry_cipher_open(&ctx, algo, mode, 0)) return SG_ERR_NOMEM;
|
if (gcry_cipher_open(&ctx, algo, mode, 0)) return SG_ERR_NOMEM;
|
||||||
|
@ -294,8 +292,6 @@ int signal_vala_decrypt(signal_buffer **output,
|
||||||
if (aes_cipher(cipher, key_len, &algo, &mode)) return SG_ERR_INVAL;
|
if (aes_cipher(cipher, key_len, &algo, &mode)) return SG_ERR_INVAL;
|
||||||
if (ciphertext_len == 0) return SG_ERR_INVAL;
|
if (ciphertext_len == 0) return SG_ERR_INVAL;
|
||||||
|
|
||||||
if (iv_len != 16 && iv_len != 12) return SG_ERR_INVAL;
|
|
||||||
|
|
||||||
gcry_cipher_hd_t ctx = {0};
|
gcry_cipher_hd_t ctx = {0};
|
||||||
|
|
||||||
if (gcry_cipher_open(&ctx, algo, mode, 0)) return SG_ERR_NOMEM;
|
if (gcry_cipher_open(&ctx, algo, mode, 0)) return SG_ERR_NOMEM;
|
||||||
|
|
Loading…
Reference in a new issue