cheogram/src/main/java/eu/siacs/conversations/entities/DownloadableFile.java
Daniel Gultsch aecb771ab5 use 16 byte IVs for http upload files larger than 768KiB
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
2020-03-08 13:13:19 +01:00

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;
}
}