mirror of
https://github.com/oxen-io/session-android.git
synced 2025-10-26 07:59:49 +00:00
Only use MasterSecret for local message encryption.
Not for the axolotl store. // FREEBIE
This commit is contained in:
@@ -19,12 +19,16 @@ package org.thoughtcrime.securesms.database;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
@@ -60,57 +64,80 @@ public class EncryptingSmsDatabase extends SmsDatabase {
|
||||
return ciphertext;
|
||||
}
|
||||
|
||||
public long insertMessageOutbox(MasterSecret masterSecret, long threadId,
|
||||
public long insertMessageOutbox(MasterSecretUnion masterSecret, long threadId,
|
||||
OutgoingTextMessage message, boolean forceSms,
|
||||
long timestamp)
|
||||
{
|
||||
long type = Types.BASE_OUTBOX_TYPE;
|
||||
message = message.withBody(getEncryptedBody(masterSecret, message.getMessageBody()));
|
||||
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
message = message.withBody(getEncryptedBody(masterSecret.getMasterSecret().get(), message.getMessageBody()));
|
||||
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
} else {
|
||||
message = message.withBody(getAsymmetricEncryptedBody(masterSecret.getAsymmetricMasterSecret().get(), message.getMessageBody()));
|
||||
type |= Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
}
|
||||
|
||||
return insertMessageOutbox(threadId, message, type, forceSms, timestamp);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret,
|
||||
IncomingTextMessage message)
|
||||
public Pair<Long, Long> insertMessageInbox(@NonNull MasterSecretUnion masterSecret,
|
||||
@NonNull IncomingTextMessage message)
|
||||
{
|
||||
long type = Types.BASE_INBOX_TYPE;
|
||||
|
||||
if (masterSecret == null && message.isSecureMessage()) {
|
||||
type |= Types.ENCRYPTION_REMOTE_BIT;
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
return insertMessageInbox(masterSecret.getMasterSecret().get(), message);
|
||||
} else {
|
||||
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
message = message.withMessageBody(getEncryptedBody(masterSecret, message.getMessageBody()));
|
||||
return insertMessageInbox(masterSecret.getAsymmetricMasterSecret().get(), message);
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<Long, Long> insertMessageInbox(@NonNull MasterSecret masterSecret,
|
||||
@NonNull IncomingTextMessage message)
|
||||
{
|
||||
long type = Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
|
||||
message = message.withMessageBody(getEncryptedBody(masterSecret, message.getMessageBody()));
|
||||
|
||||
return insertMessageInbox(message, type);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertMessageInbox(AsymmetricMasterSecret masterSecret,
|
||||
IncomingTextMessage message)
|
||||
private Pair<Long, Long> insertMessageInbox(@NonNull AsymmetricMasterSecret masterSecret,
|
||||
@NonNull IncomingTextMessage message)
|
||||
{
|
||||
long type = Types.BASE_INBOX_TYPE;
|
||||
long type = Types.BASE_INBOX_TYPE | Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
|
||||
if (message.isSecureMessage()) {
|
||||
type |= Types.ENCRYPTION_REMOTE_BIT;
|
||||
} else {
|
||||
message = message.withMessageBody(getAsymmetricEncryptedBody(masterSecret, message.getMessageBody()));
|
||||
type |= Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
}
|
||||
message = message.withMessageBody(getAsymmetricEncryptedBody(masterSecret, message.getMessageBody()));
|
||||
|
||||
return insertMessageInbox(message, type);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> updateBundleMessageBody(MasterSecret masterSecret, long messageId, String body) {
|
||||
String encryptedBody = getEncryptedBody(masterSecret, body);
|
||||
return updateMessageBodyAndType(messageId, encryptedBody, Types.TOTAL_MASK,
|
||||
Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT | Types.SECURE_MESSAGE_BIT);
|
||||
public Pair<Long, Long> updateBundleMessageBody(MasterSecretUnion masterSecret, long messageId, String body) {
|
||||
long type = Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT;
|
||||
String encryptedBody;
|
||||
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
encryptedBody = getEncryptedBody(masterSecret.getMasterSecret().get(), body);
|
||||
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
} else {
|
||||
encryptedBody = getAsymmetricEncryptedBody(masterSecret.getAsymmetricMasterSecret().get(), body);
|
||||
type |= Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
}
|
||||
|
||||
return updateMessageBodyAndType(messageId, encryptedBody, Types.TOTAL_MASK, type);
|
||||
}
|
||||
|
||||
public void updateMessageBody(MasterSecret masterSecret, long messageId, String body) {
|
||||
String encryptedBody = getEncryptedBody(masterSecret, body);
|
||||
updateMessageBodyAndType(messageId, encryptedBody, Types.ENCRYPTION_MASK,
|
||||
Types.ENCRYPTION_SYMMETRIC_BIT);
|
||||
public void updateMessageBody(MasterSecretUnion masterSecret, long messageId, String body) {
|
||||
long type;
|
||||
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
body = getEncryptedBody(masterSecret.getMasterSecret().get(), body);
|
||||
type = Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
} else {
|
||||
body = getAsymmetricEncryptedBody(masterSecret.getAsymmetricMasterSecret().get(), body);
|
||||
type = Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
}
|
||||
|
||||
updateMessageBodyAndType(messageId, body, Types.ENCRYPTION_MASK, type);
|
||||
}
|
||||
|
||||
public Reader getMessages(MasterSecret masterSecret, int skip, int limit) {
|
||||
|
||||
@@ -29,8 +29,6 @@ import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.whispersystems.libaxolotl.IdentityKey;
|
||||
import org.whispersystems.libaxolotl.InvalidKeyException;
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -42,13 +40,11 @@ public class IdentityDatabase extends Database {
|
||||
private static final String ID = "_id";
|
||||
public static final String RECIPIENT = "recipient";
|
||||
public static final String IDENTITY_KEY = "key";
|
||||
public static final String MAC = "mac";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME +
|
||||
" (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
RECIPIENT + " INTEGER UNIQUE, " +
|
||||
IDENTITY_KEY + " TEXT, " +
|
||||
MAC + " TEXT);";
|
||||
IDENTITY_KEY + " TEXT);";
|
||||
|
||||
public IdentityDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
@@ -64,28 +60,19 @@ public class IdentityDatabase extends Database {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
public boolean isValidIdentity(MasterSecret masterSecret,
|
||||
long recipientId,
|
||||
public boolean isValidIdentity(long recipientId,
|
||||
IdentityKey theirIdentity)
|
||||
{
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
||||
Cursor cursor = null;
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = database.query(TABLE_NAME, null, RECIPIENT + " = ?",
|
||||
new String[] {recipientId+""}, null, null,null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
String serializedIdentity = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
|
||||
String mac = cursor.getString(cursor.getColumnIndexOrThrow(MAC));
|
||||
|
||||
if (!masterCipher.verifyMacFor(recipientId + serializedIdentity, Base64.decode(mac))) {
|
||||
Log.w("IdentityDatabase", "MAC failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
IdentityKey ourIdentity = new IdentityKey(Base64.decode(serializedIdentity), 0);
|
||||
String serializedIdentity = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
|
||||
IdentityKey ourIdentity = new IdentityKey(Base64.decode(serializedIdentity), 0);
|
||||
|
||||
return ourIdentity.equals(theirIdentity);
|
||||
} else {
|
||||
@@ -104,18 +91,14 @@ public class IdentityDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public void saveIdentity(MasterSecret masterSecret, long recipientId, IdentityKey identityKey)
|
||||
public void saveIdentity(long recipientId, IdentityKey identityKey)
|
||||
{
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
MasterCipher masterCipher = new MasterCipher(masterSecret);
|
||||
String identityKeyString = Base64.encodeBytes(identityKey.serialize());
|
||||
String macString = Base64.encodeBytes(masterCipher.getMacFor(recipientId +
|
||||
identityKeyString));
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
String identityKeyString = Base64.encodeBytes(identityKey.serialize());
|
||||
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(RECIPIENT, recipientId);
|
||||
contentValues.put(IDENTITY_KEY, identityKeyString);
|
||||
contentValues.put(MAC, macString);
|
||||
|
||||
database.replace(TABLE_NAME, null, contentValues);
|
||||
|
||||
@@ -129,17 +112,15 @@ public class IdentityDatabase extends Database {
|
||||
context.getContentResolver().notifyChange(CHANGE_URI, null);
|
||||
}
|
||||
|
||||
public Reader readerFor(MasterSecret masterSecret, Cursor cursor) {
|
||||
return new Reader(masterSecret, cursor);
|
||||
public Reader readerFor(Cursor cursor) {
|
||||
return new Reader(cursor);
|
||||
}
|
||||
|
||||
public class Reader {
|
||||
private final Cursor cursor;
|
||||
private final MasterCipher cipher;
|
||||
|
||||
public Reader(MasterSecret masterSecret, Cursor cursor) {
|
||||
public Reader(Cursor cursor) {
|
||||
this.cursor = cursor;
|
||||
this.cipher = new MasterCipher(masterSecret);
|
||||
}
|
||||
|
||||
public Identity getCurrent() {
|
||||
@@ -147,14 +128,9 @@ public class IdentityDatabase extends Database {
|
||||
Recipients recipients = RecipientFactory.getRecipientsForIds(context, new long[]{recipientId}, true);
|
||||
|
||||
try {
|
||||
String identityKeyString = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
|
||||
String mac = cursor.getString(cursor.getColumnIndexOrThrow(MAC));
|
||||
String identityKeyString = cursor.getString(cursor.getColumnIndexOrThrow(IDENTITY_KEY));
|
||||
IdentityKey identityKey = new IdentityKey(Base64.decode(identityKeyString), 0);
|
||||
|
||||
if (!cipher.verifyMacFor(recipientId + identityKeyString, Base64.decode(mac))) {
|
||||
return new Identity(recipients, null);
|
||||
}
|
||||
|
||||
IdentityKey identityKey = new IdentityKey(Base64.decode(identityKeyString), 0);
|
||||
return new Identity(recipients, identityKey);
|
||||
} catch (IOException e) {
|
||||
Log.w("IdentityDatabase", e);
|
||||
|
||||
@@ -32,8 +32,10 @@ import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.AsymmetricMasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailureList;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
@@ -357,12 +359,11 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
return cursor;
|
||||
}
|
||||
|
||||
public void updateResponseStatus(long messageId, int status) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(RESPONSE_STATUS, status);
|
||||
public Reader getDecryptInProgressMessages(MasterSecret masterSecret) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String where = MESSAGE_BOX + " & " + (Types.ENCRYPTION_ASYMMETRIC_BIT) + " != 0";
|
||||
|
||||
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {messageId + ""});
|
||||
return readerFor(masterSecret, db.query(TABLE_NAME, MMS_PROJECTION, where, null, null, null, null));
|
||||
}
|
||||
|
||||
private void updateMailboxBitmask(long id, long maskOff, long maskOn) {
|
||||
@@ -417,15 +418,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
notifyConversationListeners(getThreadIdForMessage(messageId));
|
||||
}
|
||||
|
||||
public void markDeliveryStatus(long messageId, int status) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(STATUS, status);
|
||||
|
||||
database.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {messageId + ""});
|
||||
notifyConversationListeners(getThreadIdForMessage(messageId));
|
||||
}
|
||||
|
||||
public void markAsNoSession(long messageId, long threadId) {
|
||||
updateMailboxBitmask(messageId, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_NO_SESSION_BIT);
|
||||
notifyConversationListeners(threadId);
|
||||
@@ -474,6 +466,36 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
database.update(TABLE_NAME, contentValues, null, null);
|
||||
}
|
||||
|
||||
public void updateMessageBody(MasterSecretUnion masterSecret, long messageId, String body) {
|
||||
body = getEncryptedBody(masterSecret, body);
|
||||
|
||||
long type;
|
||||
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
type = Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
} else {
|
||||
type = Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
}
|
||||
|
||||
updateMessageBodyAndType(messageId, body, Types.ENCRYPTION_MASK, type);
|
||||
}
|
||||
|
||||
private Pair<Long, Long> updateMessageBodyAndType(long messageId, String body, long maskOff, long maskOn) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.execSQL("UPDATE " + TABLE_NAME + " SET " + BODY + " = ?, " +
|
||||
MESSAGE_BOX + " = (" + MESSAGE_BOX + " & " + (Types.TOTAL_MASK - maskOff) + " | " + maskOn + ") " +
|
||||
"WHERE " + ID + " = ?",
|
||||
new String[] {body, messageId + ""});
|
||||
|
||||
long threadId = getThreadIdForMessage(messageId);
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId);
|
||||
notifyConversationListeners(threadId);
|
||||
notifyConversationListListeners();
|
||||
|
||||
return new Pair<>(messageId, threadId);
|
||||
}
|
||||
|
||||
public Optional<NotificationInd> getNotification(long messageId) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
@@ -544,15 +566,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
public Reader getNotificationsWithDownloadState(MasterSecret masterSecret, long state) {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
String selection = STATUS + " = ?";
|
||||
String[] selectionArgs = new String[]{state + ""};
|
||||
|
||||
Cursor cursor = database.query(TABLE_NAME, MMS_PROJECTION, selection, selectionArgs, null, null, null);
|
||||
return new Reader(masterSecret, cursor);
|
||||
}
|
||||
|
||||
public long copyMessageInbox(MasterSecret masterSecret, long messageId) throws MmsException {
|
||||
try {
|
||||
SendReq request = getOutgoingMessage(masterSecret, messageId);
|
||||
@@ -563,15 +576,17 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
contentValues.put(READ, 1);
|
||||
contentValues.put(DATE_RECEIVED, contentValues.getAsLong(DATE_SENT));
|
||||
|
||||
return insertMediaMessage(masterSecret, request.getPduHeaders(),
|
||||
return insertMediaMessage(new MasterSecretUnion(masterSecret), request.getPduHeaders(),
|
||||
request.getBody(), contentValues);
|
||||
} catch (NoSuchMessageException e) {
|
||||
throw new MmsException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret, IncomingMediaMessage retrieved,
|
||||
String contentLocation, long threadId, long mailbox)
|
||||
private Pair<Long, Long> insertMessageInbox(MasterSecretUnion masterSecret,
|
||||
IncomingMediaMessage retrieved,
|
||||
String contentLocation,
|
||||
long threadId, long mailbox)
|
||||
throws MmsException
|
||||
{
|
||||
PduHeaders headers = retrieved.getPduHeaders();
|
||||
@@ -614,35 +629,44 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
return new Pair<>(messageId, threadId);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertMessageInbox(MasterSecret masterSecret,
|
||||
public Pair<Long, Long> insertMessageInbox(MasterSecretUnion masterSecret,
|
||||
IncomingMediaMessage retrieved,
|
||||
String contentLocation, long threadId)
|
||||
throws MmsException
|
||||
{
|
||||
return insertMessageInbox(masterSecret, retrieved, contentLocation, threadId,
|
||||
Types.BASE_INBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT |
|
||||
(retrieved.isPushMessage() ? Types.PUSH_MESSAGE_BIT : 0));
|
||||
long type = Types.BASE_INBOX_TYPE;
|
||||
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
} else {
|
||||
type |= Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
}
|
||||
|
||||
if (retrieved.isPushMessage()) {
|
||||
type |= Types.PUSH_MESSAGE_BIT;
|
||||
}
|
||||
|
||||
return insertMessageInbox(masterSecret, retrieved, contentLocation, threadId, type);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertSecureMessageInbox(MasterSecret masterSecret,
|
||||
IncomingMediaMessage retrieved,
|
||||
String contentLocation, long threadId)
|
||||
throws MmsException
|
||||
{
|
||||
return insertMessageInbox(masterSecret, retrieved, contentLocation, threadId,
|
||||
Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT |
|
||||
Types.ENCRYPTION_REMOTE_BIT);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertSecureDecryptedMessageInbox(MasterSecret masterSecret,
|
||||
public Pair<Long, Long> insertSecureDecryptedMessageInbox(MasterSecretUnion masterSecret,
|
||||
IncomingMediaMessage retrieved,
|
||||
long threadId)
|
||||
throws MmsException
|
||||
{
|
||||
return insertMessageInbox(masterSecret, retrieved, "", threadId,
|
||||
Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT |
|
||||
Types.ENCRYPTION_SYMMETRIC_BIT |
|
||||
(retrieved.isPushMessage() ? Types.PUSH_MESSAGE_BIT : 0));
|
||||
long type = Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT;
|
||||
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
type |= Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
} else {
|
||||
type |= Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
}
|
||||
|
||||
if (retrieved.isPushMessage()) {
|
||||
type |= Types.PUSH_MESSAGE_BIT;
|
||||
}
|
||||
|
||||
return insertMessageInbox(masterSecret, retrieved, "", threadId, type);
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertMessageInbox(@NonNull NotificationInd notification) {
|
||||
@@ -680,11 +704,15 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
}
|
||||
|
||||
public long insertMessageOutbox(MasterSecret masterSecret, OutgoingMediaMessage message,
|
||||
public long insertMessageOutbox(@NonNull MasterSecretUnion masterSecret,
|
||||
@NonNull OutgoingMediaMessage message,
|
||||
long threadId, boolean forceSms, long timestamp)
|
||||
throws MmsException
|
||||
{
|
||||
long type = Types.BASE_OUTBOX_TYPE | Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
long type = Types.BASE_OUTBOX_TYPE;
|
||||
|
||||
if (masterSecret.getMasterSecret().isPresent()) type |= Types.ENCRYPTION_SYMMETRIC_BIT;
|
||||
else type |= Types.ENCRYPTION_ASYMMETRIC_BIT;
|
||||
|
||||
if (message.isSecure()) type |= Types.SECURE_MESSAGE_BIT;
|
||||
if (forceSms) type |= Types.MESSAGE_FORCE_SMS_BIT;
|
||||
@@ -727,14 +755,23 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
long messageId = insertMediaMessage(masterSecret, sendRequest.getPduHeaders(),
|
||||
long messageId = insertMediaMessage(masterSecret,
|
||||
sendRequest.getPduHeaders(),
|
||||
sendRequest.getBody(), contentValues);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
|
||||
return messageId;
|
||||
}
|
||||
|
||||
private long insertMediaMessage(MasterSecret masterSecret,
|
||||
private String getEncryptedBody(MasterSecretUnion masterSecret, String body) {
|
||||
if (masterSecret.getMasterSecret().isPresent()) {
|
||||
return new MasterCipher(masterSecret.getMasterSecret().get()).encryptBody(body);
|
||||
} else {
|
||||
return new AsymmetricMasterCipher(masterSecret.getAsymmetricMasterSecret().get()).encryptBody(body);
|
||||
}
|
||||
}
|
||||
|
||||
private long insertMediaMessage(MasterSecretUnion masterSecret,
|
||||
PduHeaders headers,
|
||||
PduBody body,
|
||||
ContentValues contentValues)
|
||||
@@ -744,12 +781,14 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
PartDatabase partsDatabase = DatabaseFactory.getPartDatabase(context);
|
||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
|
||||
if (Types.isSymmetricEncryption(contentValues.getAsLong(MESSAGE_BOX))) {
|
||||
if (Types.isSymmetricEncryption(contentValues.getAsLong(MESSAGE_BOX)) ||
|
||||
Types.isAsymmetricEncryption(contentValues.getAsLong(MESSAGE_BOX)))
|
||||
{
|
||||
String messageText = PartParser.getMessageText(body);
|
||||
body = PartParser.getSupportedMediaParts(body);
|
||||
|
||||
if (!TextUtils.isEmpty(messageText)) {
|
||||
contentValues.put(BODY, new MasterCipher(masterSecret).encryptBody(messageText));
|
||||
contentValues.put(BODY, getEncryptedBody(masterSecret, messageText));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1105,6 +1144,8 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
return new DisplayRecord.Body(masterCipher.decryptBody(body), true);
|
||||
} else if (!TextUtils.isEmpty(body) && masterCipher == null && Types.isSymmetricEncryption(box)) {
|
||||
return new DisplayRecord.Body(body, false);
|
||||
} else if (!TextUtils.isEmpty(body) && Types.isAsymmetricEncryption(box)) {
|
||||
return new DisplayRecord.Body(body, false);
|
||||
} else {
|
||||
return new DisplayRecord.Body(body == null ? "" : body, true);
|
||||
}
|
||||
|
||||
@@ -175,9 +175,7 @@ public interface MmsSmsColumns {
|
||||
}
|
||||
|
||||
public static boolean isDecryptInProgressType(long type) {
|
||||
return
|
||||
(type & ENCRYPTION_REMOTE_BIT) != 0 ||
|
||||
(type & ENCRYPTION_ASYMMETRIC_BIT) != 0;
|
||||
return (type & ENCRYPTION_ASYMMETRIC_BIT) != 0;
|
||||
}
|
||||
|
||||
public static boolean isNoRemoteSessionType(long type) {
|
||||
@@ -185,7 +183,8 @@ public interface MmsSmsColumns {
|
||||
}
|
||||
|
||||
public static boolean isLegacyType(long type) {
|
||||
return (type & ENCRYPTION_REMOTE_LEGACY_BIT) != 0;
|
||||
return (type & ENCRYPTION_REMOTE_LEGACY_BIT) != 0 ||
|
||||
(type & ENCRYPTION_REMOTE_BIT) != 0;
|
||||
}
|
||||
|
||||
public static long translateFromSystemBaseType(long theirType) {
|
||||
|
||||
@@ -30,6 +30,7 @@ import android.util.Pair;
|
||||
import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
|
||||
import org.thoughtcrime.securesms.crypto.EncryptingPartOutputStream;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
@@ -222,7 +223,7 @@ public class PartDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
void insertParts(MasterSecret masterSecret, long mmsId, PduBody body) throws MmsException {
|
||||
void insertParts(MasterSecretUnion masterSecret, long mmsId, PduBody body) throws MmsException {
|
||||
for (int i=0;i<body.getPartsNum();i++) {
|
||||
PduPart part = body.getPart(i);
|
||||
PartId partId = insertPart(masterSecret, part, mmsId, part.getThumbnail());
|
||||
@@ -432,13 +433,13 @@ public class PartDatabase extends Database {
|
||||
return part;
|
||||
}
|
||||
|
||||
private PartId insertPart(MasterSecret masterSecret, PduPart part, long mmsId, Bitmap thumbnail) throws MmsException {
|
||||
private PartId insertPart(MasterSecretUnion masterSecret, PduPart part, long mmsId, Bitmap thumbnail) throws MmsException {
|
||||
Log.w(TAG, "inserting part to mms " + mmsId);
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
Pair<File, Long> partData = null;
|
||||
|
||||
if (part.getData() != null || part.getDataUri() != null) {
|
||||
partData = writePartData(masterSecret, part);
|
||||
if ((part.getData() != null || part.getDataUri() != null) && masterSecret.getMasterSecret().isPresent()) {
|
||||
partData = writePartData(masterSecret.getMasterSecret().get(), part);
|
||||
Log.w(TAG, "Wrote part to file: " + partData.first.getAbsolutePath());
|
||||
}
|
||||
|
||||
@@ -453,12 +454,12 @@ public class PartDatabase extends Database {
|
||||
long partRowId = database.insert(TABLE_NAME, null, contentValues);
|
||||
PartId partId = new PartId(partRowId, part.getUniqueId());
|
||||
|
||||
if (thumbnail != null) {
|
||||
if (thumbnail != null && masterSecret.getMasterSecret().isPresent()) {
|
||||
Log.w(TAG, "inserting pre-generated thumbnail");
|
||||
ThumbnailData data = new ThumbnailData(thumbnail);
|
||||
updatePartThumbnail(masterSecret, partId, part, data.toDataStream(), data.getAspectRatio());
|
||||
updatePartThumbnail(masterSecret.getMasterSecret().get(), partId, part, data.toDataStream(), data.getAspectRatio());
|
||||
} else if (!part.isInProgress()) {
|
||||
thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret, partId));
|
||||
thumbnailExecutor.submit(new ThumbnailFetchCallable(masterSecret.getMasterSecret().get(), partId));
|
||||
}
|
||||
|
||||
return partId;
|
||||
|
||||
@@ -213,10 +213,6 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_NO_SESSION_BIT);
|
||||
}
|
||||
|
||||
public void markAsDecrypting(long id) {
|
||||
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_BIT);
|
||||
}
|
||||
|
||||
public void markAsLegacyVersion(long id) {
|
||||
updateTypeBitmask(id, Types.ENCRYPTION_MASK, Types.ENCRYPTION_REMOTE_LEGACY_BIT);
|
||||
}
|
||||
@@ -461,7 +457,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
public Cursor getDecryptInProgressMessages() {
|
||||
String where = TYPE + " & " + (Types.ENCRYPTION_REMOTE_BIT | Types.ENCRYPTION_ASYMMETRIC_BIT) + " != 0";
|
||||
String where = TYPE + " & " + (Types.ENCRYPTION_ASYMMETRIC_BIT) + " != 0";
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
return db.query(TABLE_NAME, MESSAGE_PROJECTION, where, null, null, null, null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user