Search in sources :

Example 1 with InvalidMessageException

use of org.whispersystems.libsignal.InvalidMessageException in project Signal-Android by WhisperSystems.

the class ConversationActivity method sendMessage.

private void sendMessage() {
    try {
        Recipients recipients = getRecipients();
        if (recipients == null) {
            throw new RecipientFormattingException("Badly formatted");
        }
        boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
        int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
        long expiresIn = recipients.getExpireMessages() * 1000;
        Log.w(TAG, "isManual Selection: " + sendButton.isManualSelection());
        Log.w(TAG, "forceSms: " + forceSms);
        if ((!recipients.isSingleRecipient() || recipients.isEmailRecipient()) && !isMmsEnabled) {
            handleManualMmsRequired();
        } else if (attachmentManager.isAttachmentPresent() || !recipients.isSingleRecipient() || recipients.isGroupRecipient() || recipients.isEmailRecipient()) {
            sendMediaMessage(forceSms, expiresIn, subscriptionId);
        } else {
            sendTextMessage(forceSms, expiresIn, subscriptionId);
        }
    } catch (RecipientFormattingException ex) {
        Toast.makeText(ConversationActivity.this, R.string.ConversationActivity_recipient_is_not_a_valid_sms_or_email_address_exclamation, Toast.LENGTH_LONG).show();
        Log.w(TAG, ex);
    } catch (InvalidMessageException ex) {
        Toast.makeText(ConversationActivity.this, R.string.ConversationActivity_message_is_empty_exclamation, Toast.LENGTH_SHORT).show();
        Log.w(TAG, ex);
    }
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) Recipients(org.thoughtcrime.securesms.recipients.Recipients) RecipientFormattingException(org.thoughtcrime.securesms.recipients.RecipientFormattingException)

Example 2 with InvalidMessageException

use of org.whispersystems.libsignal.InvalidMessageException in project Signal-Android by WhisperSystems.

the class TextSecurePreKeyStore method loadSignedPreKeys.

@Override
public List<SignedPreKeyRecord> loadSignedPreKeys() {
    synchronized (FILE_LOCK) {
        File directory = getSignedPreKeyDirectory();
        List<SignedPreKeyRecord> results = new LinkedList<>();
        for (File signedPreKeyFile : directory.listFiles()) {
            try {
                if (!"index.dat".equals(signedPreKeyFile.getName())) {
                    results.add(new SignedPreKeyRecord(loadSerializedRecord(signedPreKeyFile)));
                }
            } catch (IOException | InvalidMessageException e) {
                Log.w(TAG, e);
            }
        }
        return results;
    }
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) IOException(java.io.IOException) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File) SignedPreKeyRecord(org.whispersystems.libsignal.state.SignedPreKeyRecord) LinkedList(java.util.LinkedList)

Example 3 with InvalidMessageException

use of org.whispersystems.libsignal.InvalidMessageException in project Signal-Android by WhisperSystems.

the class TextSecureSessionStore method loadSession.

@Override
public SessionRecord loadSession(@NonNull SignalProtocolAddress address) {
    synchronized (FILE_LOCK) {
        try {
            FileInputStream in = new FileInputStream(getSessionFile(address));
            int versionMarker = readInteger(in);
            if (versionMarker > CURRENT_VERSION) {
                throw new AssertionError("Unknown version: " + versionMarker);
            }
            byte[] serialized = readBlob(in);
            in.close();
            if (versionMarker < PLAINTEXT_VERSION && masterSecret != null) {
                serialized = new MasterCipher(masterSecret).decryptBytes(serialized);
            } else if (versionMarker < PLAINTEXT_VERSION) {
                throw new AssertionError("Session didn't get migrated: (" + versionMarker + "," + address + ")");
            }
            if (versionMarker == SINGLE_STATE_VERSION) {
                SessionStructure sessionStructure = SessionStructure.parseFrom(serialized);
                SessionState sessionState = new SessionState(sessionStructure);
                return new SessionRecord(sessionState);
            } else if (versionMarker >= ARCHIVE_STATES_VERSION) {
                return new SessionRecord(serialized);
            } else {
                throw new AssertionError("Unknown version: " + versionMarker);
            }
        } catch (InvalidMessageException | IOException e) {
            Log.w(TAG, "No existing session information found.");
            return new SessionRecord();
        }
    }
}
Also used : SessionStructure(org.whispersystems.libsignal.state.StorageProtos.SessionStructure) SessionState(org.whispersystems.libsignal.state.SessionState) InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) MasterCipher(org.thoughtcrime.securesms.crypto.MasterCipher) IOException(java.io.IOException) FileInputStream(java.io.FileInputStream) SessionRecord(org.whispersystems.libsignal.state.SessionRecord)

Example 4 with InvalidMessageException

use of org.whispersystems.libsignal.InvalidMessageException in project Signal-Android by WhisperSystems.

the class DatabaseFactory method onApplicationLevelUpgrade.

public void onApplicationLevelUpgrade(Context context, MasterSecret masterSecret, int fromVersion, DatabaseUpgradeActivity.DatabaseUpgradeListener listener) {
    SQLiteDatabase db = databaseHelper.getWritableDatabase();
    db.beginTransaction();
    if (fromVersion < DatabaseUpgradeActivity.NO_MORE_KEY_EXCHANGE_PREFIX_VERSION) {
        String KEY_EXCHANGE = "?TextSecureKeyExchange";
        String PROCESSED_KEY_EXCHANGE = "?TextSecureKeyExchangd";
        String STALE_KEY_EXCHANGE = "?TextSecureKeyExchangs";
        int ROW_LIMIT = 500;
        MasterCipher masterCipher = new MasterCipher(masterSecret);
        int smsCount = 0;
        int threadCount = 0;
        int skip = 0;
        Cursor cursor = db.query("sms", new String[] { "COUNT(*)" }, "type & " + 0x80000000 + " != 0", null, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            smsCount = cursor.getInt(0);
            cursor.close();
        }
        cursor = db.query("thread", new String[] { "COUNT(*)" }, "snippet_type & " + 0x80000000 + " != 0", null, null, null, null);
        if (cursor != null && cursor.moveToFirst()) {
            threadCount = cursor.getInt(0);
            cursor.close();
        }
        Cursor smsCursor = null;
        Log.w("DatabaseFactory", "Upgrade count: " + (smsCount + threadCount));
        do {
            Log.w("DatabaseFactory", "Looping SMS cursor...");
            if (smsCursor != null)
                smsCursor.close();
            smsCursor = db.query("sms", new String[] { "_id", "type", "body" }, "type & " + 0x80000000 + " != 0", null, null, null, "_id", skip + "," + ROW_LIMIT);
            while (smsCursor != null && smsCursor.moveToNext()) {
                listener.setProgress(smsCursor.getPosition() + skip, smsCount + threadCount);
                try {
                    String body = masterCipher.decryptBody(smsCursor.getString(smsCursor.getColumnIndexOrThrow("body")));
                    long type = smsCursor.getLong(smsCursor.getColumnIndexOrThrow("type"));
                    long id = smsCursor.getLong(smsCursor.getColumnIndexOrThrow("_id"));
                    if (body.startsWith(KEY_EXCHANGE)) {
                        body = body.substring(KEY_EXCHANGE.length());
                        body = masterCipher.encryptBody(body);
                        type |= 0x8000;
                        db.execSQL("UPDATE sms SET body = ?, type = ? WHERE _id = ?", new String[] { body, type + "", id + "" });
                    } else if (body.startsWith(PROCESSED_KEY_EXCHANGE)) {
                        body = body.substring(PROCESSED_KEY_EXCHANGE.length());
                        body = masterCipher.encryptBody(body);
                        type |= (0x8000 | 0x2000);
                        db.execSQL("UPDATE sms SET body = ?, type = ? WHERE _id = ?", new String[] { body, type + "", id + "" });
                    } else if (body.startsWith(STALE_KEY_EXCHANGE)) {
                        body = body.substring(STALE_KEY_EXCHANGE.length());
                        body = masterCipher.encryptBody(body);
                        type |= (0x8000 | 0x4000);
                        db.execSQL("UPDATE sms SET body = ?, type = ? WHERE _id = ?", new String[] { body, type + "", id + "" });
                    }
                } catch (InvalidMessageException e) {
                    Log.w("DatabaseFactory", e);
                }
            }
            skip += ROW_LIMIT;
        } while (smsCursor != null && smsCursor.getCount() > 0);
        Cursor threadCursor = null;
        skip = 0;
        do {
            Log.w("DatabaseFactory", "Looping thread cursor...");
            if (threadCursor != null)
                threadCursor.close();
            threadCursor = db.query("thread", new String[] { "_id", "snippet_type", "snippet" }, "snippet_type & " + 0x80000000 + " != 0", null, null, null, "_id", skip + "," + ROW_LIMIT);
            while (threadCursor != null && threadCursor.moveToNext()) {
                listener.setProgress(smsCount + threadCursor.getPosition(), smsCount + threadCount);
                try {
                    String snippet = threadCursor.getString(threadCursor.getColumnIndexOrThrow("snippet"));
                    long snippetType = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("snippet_type"));
                    long id = threadCursor.getLong(threadCursor.getColumnIndexOrThrow("_id"));
                    if (!TextUtils.isEmpty(snippet)) {
                        snippet = masterCipher.decryptBody(snippet);
                    }
                    if (snippet.startsWith(KEY_EXCHANGE)) {
                        snippet = snippet.substring(KEY_EXCHANGE.length());
                        snippet = masterCipher.encryptBody(snippet);
                        snippetType |= 0x8000;
                        db.execSQL("UPDATE thread SET snippet = ?, snippet_type = ? WHERE _id = ?", new String[] { snippet, snippetType + "", id + "" });
                    } else if (snippet.startsWith(PROCESSED_KEY_EXCHANGE)) {
                        snippet = snippet.substring(PROCESSED_KEY_EXCHANGE.length());
                        snippet = masterCipher.encryptBody(snippet);
                        snippetType |= (0x8000 | 0x2000);
                        db.execSQL("UPDATE thread SET snippet = ?, snippet_type = ? WHERE _id = ?", new String[] { snippet, snippetType + "", id + "" });
                    } else if (snippet.startsWith(STALE_KEY_EXCHANGE)) {
                        snippet = snippet.substring(STALE_KEY_EXCHANGE.length());
                        snippet = masterCipher.encryptBody(snippet);
                        snippetType |= (0x8000 | 0x4000);
                        db.execSQL("UPDATE thread SET snippet = ?, snippet_type = ? WHERE _id = ?", new String[] { snippet, snippetType + "", id + "" });
                    }
                } catch (InvalidMessageException e) {
                    Log.w("DatabaseFactory", e);
                }
            }
            skip += ROW_LIMIT;
        } while (threadCursor != null && threadCursor.getCount() > 0);
        if (smsCursor != null)
            smsCursor.close();
        if (threadCursor != null)
            threadCursor.close();
    }
    if (fromVersion < DatabaseUpgradeActivity.MMS_BODY_VERSION) {
        Log.w("DatabaseFactory", "Update MMS bodies...");
        MasterCipher masterCipher = new MasterCipher(masterSecret);
        Cursor mmsCursor = db.query("mms", new String[] { "_id" }, "msg_box & " + 0x80000000L + " != 0", null, null, null, null);
        Log.w("DatabaseFactory", "Got MMS rows: " + (mmsCursor == null ? "null" : mmsCursor.getCount()));
        while (mmsCursor != null && mmsCursor.moveToNext()) {
            listener.setProgress(mmsCursor.getPosition(), mmsCursor.getCount());
            long mmsId = mmsCursor.getLong(mmsCursor.getColumnIndexOrThrow("_id"));
            String body = null;
            int partCount = 0;
            Cursor partCursor = db.query("part", new String[] { "_id", "ct", "_data", "encrypted" }, "mid = ?", new String[] { mmsId + "" }, null, null, null);
            while (partCursor != null && partCursor.moveToNext()) {
                String contentType = partCursor.getString(partCursor.getColumnIndexOrThrow("ct"));
                if (ContentType.isTextType(contentType)) {
                    try {
                        long partId = partCursor.getLong(partCursor.getColumnIndexOrThrow("_id"));
                        String dataLocation = partCursor.getString(partCursor.getColumnIndexOrThrow("_data"));
                        boolean encrypted = partCursor.getInt(partCursor.getColumnIndexOrThrow("encrypted")) == 1;
                        File dataFile = new File(dataLocation);
                        InputStream is;
                        if (encrypted)
                            is = new DecryptingPartInputStream(dataFile, masterSecret);
                        else
                            is = new FileInputStream(dataFile);
                        body = (body == null) ? Util.readFullyAsString(is) : body + " " + Util.readFullyAsString(is);
                        //noinspection ResultOfMethodCallIgnored
                        dataFile.delete();
                        db.delete("part", "_id = ?", new String[] { partId + "" });
                    } catch (IOException e) {
                        Log.w("DatabaseFactory", e);
                    }
                } else if (ContentType.isAudioType(contentType) || ContentType.isImageType(contentType) || ContentType.isVideoType(contentType)) {
                    partCount++;
                }
            }
            if (!TextUtils.isEmpty(body)) {
                body = masterCipher.encryptBody(body);
                db.execSQL("UPDATE mms SET body = ?, part_count = ? WHERE _id = ?", new String[] { body, partCount + "", mmsId + "" });
            } else {
                db.execSQL("UPDATE mms SET part_count = ? WHERE _id = ?", new String[] { partCount + "", mmsId + "" });
            }
            Log.w("DatabaseFactory", "Updated body: " + body + " and part_count: " + partCount);
        }
    }
    if (fromVersion < DatabaseUpgradeActivity.TOFU_IDENTITIES_VERSION) {
        File sessionDirectory = new File(context.getFilesDir() + File.separator + "sessions");
        if (sessionDirectory.exists() && sessionDirectory.isDirectory()) {
            File[] sessions = sessionDirectory.listFiles();
            if (sessions != null) {
                for (File session : sessions) {
                    String name = session.getName();
                    if (name.matches("[0-9]+")) {
                        long recipientId = Long.parseLong(name);
                        IdentityKey identityKey = null;
                        if (identityKey != null) {
                            MasterCipher masterCipher = new MasterCipher(masterSecret);
                            String identityKeyString = Base64.encodeBytes(identityKey.serialize());
                            String macString = Base64.encodeBytes(masterCipher.getMacFor(recipientId + identityKeyString));
                            db.execSQL("REPLACE INTO identities (recipient, key, mac) VALUES (?, ?, ?)", new String[] { recipientId + "", identityKeyString, macString });
                        }
                    }
                }
            }
        }
    }
    if (fromVersion < DatabaseUpgradeActivity.ASYMMETRIC_MASTER_SECRET_FIX_VERSION) {
        if (!MasterSecretUtil.hasAsymmericMasterSecret(context)) {
            MasterSecretUtil.generateAsymmetricMasterSecret(context, masterSecret);
            MasterCipher masterCipher = new MasterCipher(masterSecret);
            Cursor cursor = null;
            try {
                cursor = db.query(SmsDatabase.TABLE_NAME, new String[] { SmsDatabase.ID, SmsDatabase.BODY, SmsDatabase.TYPE }, SmsDatabase.TYPE + " & ? == 0", new String[] { String.valueOf(SmsDatabase.Types.ENCRYPTION_MASK) }, null, null, null);
                while (cursor.moveToNext()) {
                    long id = cursor.getLong(0);
                    String body = cursor.getString(1);
                    long type = cursor.getLong(2);
                    String encryptedBody = masterCipher.encryptBody(body);
                    ContentValues update = new ContentValues();
                    update.put(SmsDatabase.BODY, encryptedBody);
                    update.put(SmsDatabase.TYPE, type | SmsDatabase.Types.ENCRYPTION_SYMMETRIC_BIT);
                    db.update(SmsDatabase.TABLE_NAME, update, SmsDatabase.ID + " = ?", new String[] { String.valueOf(id) });
                }
            } finally {
                if (cursor != null)
                    cursor.close();
            }
        }
    }
    db.setTransactionSuccessful();
    db.endTransaction();
    //    DecryptingQueue.schedulePendingDecrypts(context, masterSecret);
    MessageNotifier.updateNotification(context, masterSecret);
}
Also used : ContentValues(android.content.ContentValues) InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) IdentityKey(org.whispersystems.libsignal.IdentityKey) FileInputStream(java.io.FileInputStream) DecryptingPartInputStream(org.thoughtcrime.securesms.crypto.DecryptingPartInputStream) InputStream(java.io.InputStream) MasterCipher(org.thoughtcrime.securesms.crypto.MasterCipher) IOException(java.io.IOException) Cursor(android.database.Cursor) FileInputStream(java.io.FileInputStream) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) File(java.io.File) DecryptingPartInputStream(org.thoughtcrime.securesms.crypto.DecryptingPartInputStream)

Example 5 with InvalidMessageException

use of org.whispersystems.libsignal.InvalidMessageException in project Signal-Android by WhisperSystems.

the class DraftDatabase method getDrafts.

public List<Draft> getDrafts(MasterCipher masterCipher, long threadId) {
    SQLiteDatabase db = databaseHelper.getReadableDatabase();
    List<Draft> results = new LinkedList<Draft>();
    Cursor cursor = null;
    try {
        cursor = db.query(TABLE_NAME, null, THREAD_ID + " = ?", new String[] { threadId + "" }, null, null, null);
        while (cursor != null && cursor.moveToNext()) {
            try {
                String encryptedType = cursor.getString(cursor.getColumnIndexOrThrow(DRAFT_TYPE));
                String encryptedValue = cursor.getString(cursor.getColumnIndexOrThrow(DRAFT_VALUE));
                results.add(new Draft(masterCipher.decryptBody(encryptedType), masterCipher.decryptBody(encryptedValue)));
            } catch (InvalidMessageException ime) {
                Log.w("DraftDatabase", ime);
            }
        }
        return results;
    } finally {
        if (cursor != null)
            cursor.close();
    }
}
Also used : InvalidMessageException(org.whispersystems.libsignal.InvalidMessageException) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Cursor(android.database.Cursor) LinkedList(java.util.LinkedList)

Aggregations

InvalidMessageException (org.whispersystems.libsignal.InvalidMessageException)18 IOException (java.io.IOException)7 File (java.io.File)4 InputStream (java.io.InputStream)3 MasterCipher (org.thoughtcrime.securesms.crypto.MasterCipher)3 SignalServiceAttachmentPointer (org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer)3 MmsException (ws.com.google.android.mms.MmsException)3 Cursor (android.database.Cursor)2 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)2 Pair (android.util.Pair)2 FileInputStream (java.io.FileInputStream)2 LinkedList (java.util.LinkedList)2 AsymmetricMasterSecret (org.thoughtcrime.securesms.crypto.AsymmetricMasterSecret)2 EncryptingSmsDatabase (org.thoughtcrime.securesms.database.EncryptingSmsDatabase)2 GroupDatabase (org.thoughtcrime.securesms.database.GroupDatabase)2 MmsDatabase (org.thoughtcrime.securesms.database.MmsDatabase)2 Recipients (org.thoughtcrime.securesms.recipients.Recipients)2 DuplicateMessageException (org.whispersystems.libsignal.DuplicateMessageException)2 IdentityKey (org.whispersystems.libsignal.IdentityKey)2 InvalidKeyException (org.whispersystems.libsignal.InvalidKeyException)2