aecb771ab5
Ever since Android 9+ switched to Conscrypt we can no longer efficiently encrypt (and decrypt) large files with AES-GCM. We did’t notice this before because when using 16 byte IVs even modern Androids will fall back to bouncy castle. However the 'bug'/'feature' in Conscrypt surfaced when we switched over to 12 byte IVs (which uses Conscrypt on Android 9+) Switching back entirely to 16 byte IVs is undesirable as this would break compatibility with Monal. So we end up with a weird compromise where we use 12 byte for normale plain text OMEMO messages and 'small' files where the inefficiencies aren’t a problem. The result of this commit is that Monal won’t be able to receive our files larger than 768KiB. However the alternative is that Conversations would always OOM when attempting to send larger files (where large depends on the available RAM.) fixes #3653
91 lines
2.2 KiB
Java
91 lines
2.2 KiB
Java
package eu.siacs.conversations.entities;
|
|
|
|
import android.util.Log;
|
|
|
|
import java.io.File;
|
|
|
|
import eu.siacs.conversations.Config;
|
|
import eu.siacs.conversations.utils.MimeUtils;
|
|
|
|
public class DownloadableFile extends File {
|
|
|
|
private static final long serialVersionUID = 2247012619505115863L;
|
|
|
|
private long expectedSize = 0;
|
|
private byte[] sha1sum;
|
|
private byte[] aeskey;
|
|
private byte[] iv;
|
|
|
|
public DownloadableFile(String path) {
|
|
super(path);
|
|
}
|
|
|
|
public long getSize() {
|
|
return super.length();
|
|
}
|
|
|
|
public long getExpectedSize() {
|
|
return this.expectedSize;
|
|
}
|
|
|
|
public String getMimeType() {
|
|
String path = this.getAbsolutePath();
|
|
int start = path.lastIndexOf('.') + 1;
|
|
if (start < path.length()) {
|
|
String mime = MimeUtils.guessMimeTypeFromExtension(path.substring(start));
|
|
return mime == null ? "" : mime;
|
|
} else {
|
|
return "";
|
|
}
|
|
}
|
|
|
|
public void setExpectedSize(long size) {
|
|
this.expectedSize = size;
|
|
}
|
|
|
|
public byte[] getSha1Sum() {
|
|
return this.sha1sum;
|
|
}
|
|
|
|
public void setSha1Sum(byte[] sum) {
|
|
this.sha1sum = sum;
|
|
}
|
|
|
|
public void setKeyAndIv(byte[] keyIvCombo) {
|
|
// originally, we used a 16 byte IV, then found for aes-gcm a 12 byte IV is ideal
|
|
// this code supports reading either length, with sending 12 byte IV to be done in future
|
|
if (keyIvCombo.length == 48) {
|
|
this.aeskey = new byte[32];
|
|
this.iv = new byte[16];
|
|
System.arraycopy(keyIvCombo, 0, this.iv, 0, 16);
|
|
System.arraycopy(keyIvCombo, 16, this.aeskey, 0, 32);
|
|
} else if (keyIvCombo.length == 44) {
|
|
this.aeskey = new byte[32];
|
|
this.iv = new byte[12];
|
|
System.arraycopy(keyIvCombo, 0, this.iv, 0, 12);
|
|
System.arraycopy(keyIvCombo, 12, this.aeskey, 0, 32);
|
|
} else if (keyIvCombo.length >= 32) {
|
|
this.aeskey = new byte[32];
|
|
this.iv = new byte[]{ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf };
|
|
System.arraycopy(keyIvCombo, 0, aeskey, 0, 32);
|
|
}
|
|
Log.d(Config.LOGTAG,"using "+this.iv.length+"-byte IV for file transmission");
|
|
}
|
|
|
|
public void setKey(byte[] key) {
|
|
this.aeskey = key;
|
|
}
|
|
|
|
public void setIv(byte[] iv) {
|
|
this.iv = iv;
|
|
}
|
|
|
|
public byte[] getKey() {
|
|
return this.aeskey;
|
|
}
|
|
|
|
public byte[] getIv() {
|
|
return this.iv;
|
|
}
|
|
}
|