From 8a20d9c9478a6b064270877677e6af3d5dcc1481 Mon Sep 17 00:00:00 2001 From: Arne Date: Wed, 11 Sep 2024 12:18:07 +0200 Subject: [PATCH] Try to use BCPQC where possible --- build.gradle | 1 + .../crypto/axolotl/AxolotlService.java | 13 +- .../crypto/axolotl/XmppAxolotlMessage.java | 2 +- .../persistance/DatabaseBackend.java | 172 +++++++++--------- .../conversations/utils/CryptoHelper.java | 20 +- .../worker/ExportBackupWorker.java | 46 ++--- 6 files changed, 132 insertions(+), 122 deletions(-) diff --git a/build.gradle b/build.gradle index 9575b6ecb..668b08f9a 100644 --- a/build.gradle +++ b/build.gradle @@ -130,6 +130,7 @@ dependencies { implementation 'com.google.android.exoplayer:exoplayer-ui:2.19.1' implementation 'com.google.android.exoplayer:extension-mediasession:2.19.1' implementation 'com.github.natario1:Autocomplete:v1.1.0' + implementation group: 'org.bouncycastle', name: 'bcprov-ext-jdk18on', version: '1.78.1' } ext { diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java index 7a0e9457c..98def9c50 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java @@ -18,6 +18,7 @@ import com.google.common.util.concurrent.MoreExecutors; import com.google.common.util.concurrent.SettableFuture; import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider; import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKeyPair; import org.whispersystems.libsignal.InvalidKeyException; @@ -109,9 +110,17 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded { if (account == null || connectionService == null) { throw new IllegalArgumentException("account and service cannot be null"); } - if (Security.getProvider("BC") == null) { - Security.addProvider(new BouncyCastleProvider()); + // this way for adding bouncycastle to android + //Security.removeProvider("BC"); + + // Confirm that positioning this provider at the end works for your needs! + Security.addProvider(new BouncyCastleProvider()); + if (Security.getProvider("BCPQC") == null) { + Security.addProvider(new BouncyCastlePQCProvider()); } + //if (Security.getProvider("BC") == null) { + // Security.addProvider(new BouncyCastleProvider()); + //} this.mXmppConnectionService = connectionService; this.account = account; this.axolotlStore = new SQLiteAxolotlStore(this.account, this.mXmppConnectionService); diff --git a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java index 790e33bd6..42ddd3fbb 100644 --- a/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java +++ b/src/main/java/eu/siacs/conversations/crypto/axolotl/XmppAxolotlMessage.java @@ -36,7 +36,7 @@ public class XmppAxolotlMessage { private static final String KEYTYPE = "AES"; private static final String CIPHERMODE = "AES/GCM/NoPadding"; - private static final String PROVIDER = "BC"; + private static final String PROVIDER = "BCPQC"; private final List keys; private final Jid from; private final int sourceDeviceId; diff --git a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java index b40432d59..358135b1e 100644 --- a/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java +++ b/src/main/java/eu/siacs/conversations/persistance/DatabaseBackend.java @@ -237,48 +237,48 @@ public class DatabaseBackend extends SQLiteOpenHelper { if(monoclesVersion < 1) { // No cross-DB foreign keys unfortunately db.execSQL( - "CREATE TABLE monocles." + Message.TABLENAME + "(" + - Message.UUID + " TEXT PRIMARY KEY, " + - "subject TEXT" + - ")" + "CREATE TABLE monocles." + Message.TABLENAME + "(" + + Message.UUID + " TEXT PRIMARY KEY, " + + "subject TEXT" + + ")" ); db.execSQL("PRAGMA monocles.user_version = 1"); } if(monoclesVersion < 2) { db.execSQL( - "ALTER TABLE monocles." + Message.TABLENAME + " " + - "ADD COLUMN oobUri TEXT" + "ALTER TABLE monocles." + Message.TABLENAME + " " + + "ADD COLUMN oobUri TEXT" ); db.execSQL( - "ALTER TABLE monocles." + Message.TABLENAME + " " + - "ADD COLUMN fileParams TEXT" + "ALTER TABLE monocles." + Message.TABLENAME + " " + + "ADD COLUMN fileParams TEXT" ); db.execSQL("PRAGMA monocles.user_version = 2"); } if(monoclesVersion < 3) { db.execSQL( - "ALTER TABLE monocles." + Message.TABLENAME + " " + - "ADD COLUMN payloads TEXT" + "ALTER TABLE monocles." + Message.TABLENAME + " " + + "ADD COLUMN payloads TEXT" ); db.execSQL("PRAGMA monocles.user_version = 3"); } if(monoclesVersion < 4) { db.execSQL( - "CREATE TABLE monocles.cids (" + - "cid TEXT NOT NULL PRIMARY KEY," + - "path TEXT NOT NULL" + - ")" + "CREATE TABLE monocles.cids (" + + "cid TEXT NOT NULL PRIMARY KEY," + + "path TEXT NOT NULL" + + ")" ); db.execSQL("PRAGMA monocles.user_version = 4"); } if(monoclesVersion < 5) { db.execSQL( - "ALTER TABLE monocles." + Message.TABLENAME + " " + - "ADD COLUMN timeReceived NUMBER" + "ALTER TABLE monocles." + Message.TABLENAME + " " + + "ADD COLUMN timeReceived NUMBER" ); db.execSQL("CREATE INDEX monocles.message_time_received_index ON " + Message.TABLENAME + " (timeReceived)"); db.execSQL("PRAGMA monocles.user_version = 5"); @@ -286,43 +286,43 @@ public class DatabaseBackend extends SQLiteOpenHelper { if(monoclesVersion < 6) { db.execSQL( - "CREATE TABLE monocles.blocked_media (" + - "cid TEXT NOT NULL PRIMARY KEY" + - ")" + "CREATE TABLE monocles.blocked_media (" + + "cid TEXT NOT NULL PRIMARY KEY" + + ")" ); db.execSQL("PRAGMA monocles.user_version = 6"); } if(monoclesVersion < 7) { db.execSQL( - "ALTER TABLE monocles.cids " + - "ADD COLUMN url TEXT" + "ALTER TABLE monocles.cids " + + "ADD COLUMN url TEXT" ); db.execSQL("PRAGMA monocles.user_version = 7"); } if(monoclesVersion < 8) { db.execSQL( - "CREATE TABLE monocles.webxdc_updates (" + - "serial INTEGER PRIMARY KEY AUTOINCREMENT, " + - Message.CONVERSATION + " TEXT NOT NULL, " + - "sender TEXT NOT NULL, " + - "thread TEXT NOT NULL, " + - "threadParent TEXT, " + - "info TEXT, " + - "document TEXT, " + - "summary TEXT, " + - "payload TEXT" + - ")" + "CREATE TABLE monocles.webxdc_updates (" + + "serial INTEGER PRIMARY KEY AUTOINCREMENT, " + + Message.CONVERSATION + " TEXT NOT NULL, " + + "sender TEXT NOT NULL, " + + "thread TEXT NOT NULL, " + + "threadParent TEXT, " + + "info TEXT, " + + "document TEXT, " + + "summary TEXT, " + + "payload TEXT" + + ")" ); db.execSQL("CREATE INDEX monocles.webxdc_index ON webxdc_updates (" + Message.CONVERSATION + ", thread)"); db.execSQL("PRAGMA monocles.user_version = 8"); - } + } if(monoclesVersion < 9) { db.execSQL( - "ALTER TABLE monocles.webxdc_updates " + - "ADD COLUMN message_id TEXT" + "ALTER TABLE monocles.webxdc_updates " + + "ADD COLUMN message_id TEXT" ); db.execSQL("CREATE UNIQUE INDEX monocles.webxdc_message_id_index ON webxdc_updates (" + Message.CONVERSATION + ", message_id)"); db.execSQL("PRAGMA monocles.user_version = 9"); @@ -330,16 +330,16 @@ public class DatabaseBackend extends SQLiteOpenHelper { if(monoclesVersion < 10) { db.execSQL( - "CREATE TABLE monocles.muted_participants (" + - "muc_jid TEXT NOT NULL, " + - "occupant_id TEXT NOT NULL, " + - "nick TEXT NOT NULL," + - "PRIMARY KEY (muc_jid, occupant_id)" + - ")" + "CREATE TABLE monocles.muted_participants (" + + "muc_jid TEXT NOT NULL, " + + "occupant_id TEXT NOT NULL, " + + "nick TEXT NOT NULL," + + "PRIMARY KEY (muc_jid, occupant_id)" + + ")" ); db.execSQL( - "ALTER TABLE monocles." + Message.TABLENAME + " " + - "ADD COLUMN occupant_id TEXT" + "ALTER TABLE monocles." + Message.TABLENAME + " " + + "ADD COLUMN occupant_id TEXT" ); db.execSQL("PRAGMA monocles.user_version = 10"); } @@ -347,17 +347,17 @@ public class DatabaseBackend extends SQLiteOpenHelper { if(monoclesVersion < 11) { if (Build.VERSION.SDK_INT >= 34) { db.execSQL( - "ALTER TABLE monocles.muted_participants " + - "DROP COLUMN nick" + "ALTER TABLE monocles.muted_participants " + + "DROP COLUMN nick" ); } else { db.execSQL("DROP TABLE monocles.muted_participants"); db.execSQL( - "CREATE TABLE monocles.muted_participants (" + - "muc_jid TEXT NOT NULL, " + - "occupant_id TEXT NOT NULL, " + - "PRIMARY KEY (muc_jid, occupant_id)" + - ")" + "CREATE TABLE monocles.muted_participants (" + + "muc_jid TEXT NOT NULL, " + + "occupant_id TEXT NOT NULL, " + + "PRIMARY KEY (muc_jid, occupant_id)" + + ")" ); } db.execSQL("PRAGMA monocles.user_version = 11"); @@ -1098,11 +1098,11 @@ public class DatabaseBackend extends SQLiteOpenHelper { SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; cursor = db.rawQuery( - "SELECT * FROM " + Message.TABLENAME + " " + - "LEFT JOIN monocles." + Message.TABLENAME + - " USING (" + Message.UUID + ")" + - "WHERE " + Message.UUID + "=?", - new String[]{uuid} + "SELECT * FROM " + Message.TABLENAME + " " + + "LEFT JOIN monocles." + Message.TABLENAME + + " USING (" + Message.UUID + ")" + + "WHERE " + Message.UUID + "=?", + new String[]{uuid} ); while (cursor.moveToNext()) { try { @@ -1134,11 +1134,11 @@ public class DatabaseBackend extends SQLiteOpenHelper { SQLiteDatabase db = this.getReadableDatabase(); Cursor cursor; cursor = db.rawQuery( - "SELECT * FROM " + Message.TABLENAME + " " + - "LEFT JOIN monocles." + Message.TABLENAME + - " USING (" + Message.UUID + ")" + - "WHERE " + Message.UUID + " IN (" + TextUtils.join(",", template) + ") OR " + Message.SERVER_MSG_ID + " IN (" + TextUtils.join(",", template) + ") OR " + Message.REMOTE_MSG_ID + " IN (" + TextUtils.join(",", template) + ")", - params.toArray(new String[0]) + "SELECT * FROM " + Message.TABLENAME + " " + + "LEFT JOIN monocles." + Message.TABLENAME + + " USING (" + Message.UUID + ")" + + "WHERE " + Message.UUID + " IN (" + TextUtils.join(",", template) + ") OR " + Message.SERVER_MSG_ID + " IN (" + TextUtils.join(",", template) + ") OR " + Message.REMOTE_MSG_ID + " IN (" + TextUtils.join(",", template) + ")", + params.toArray(new String[0]) ); while (cursor.moveToNext()) { @@ -1162,32 +1162,32 @@ public class DatabaseBackend extends SQLiteOpenHelper { if (timestamp == -1) { String[] selectionArgs = {conversation.getUuid()}; cursor = db.rawQuery( - "SELECT * FROM " + Message.TABLENAME + " " + - "LEFT JOIN monocles." + Message.TABLENAME + - " USING (" + Message.UUID + ")" + - " WHERE " + Message.UUID + " IN (" + - "SELECT " + Message.UUID + " FROM " + Message.TABLENAME + - " WHERE " + Message.CONVERSATION + "=? " + - "ORDER BY " + Message.TIME_SENT + " DESC " + - "LIMIT " + String.valueOf(limit) + ") " + - "ORDER BY " + Message.TIME_SENT + " DESC ", - selectionArgs + "SELECT * FROM " + Message.TABLENAME + " " + + "LEFT JOIN monocles." + Message.TABLENAME + + " USING (" + Message.UUID + ")" + + " WHERE " + Message.UUID + " IN (" + + "SELECT " + Message.UUID + " FROM " + Message.TABLENAME + + " WHERE " + Message.CONVERSATION + "=? " + + "ORDER BY " + Message.TIME_SENT + " DESC " + + "LIMIT " + String.valueOf(limit) + ") " + + "ORDER BY " + Message.TIME_SENT + " DESC ", + selectionArgs ); } else { String[] selectionArgs = {conversation.getUuid(), Long.toString(timestamp)}; cursor = db.rawQuery( - "SELECT * FROM " + Message.TABLENAME + " " + - "LEFT JOIN monocles." + Message.TABLENAME + - " USING (" + Message.UUID + ")" + - " WHERE " + Message.UUID + " IN (" + - "SELECT " + Message.UUID + " FROM " + Message.TABLENAME + - " WHERE " + Message.CONVERSATION + "=? AND " + - Message.TIME_SENT + " getAccounts(SQLiteDatabase db) { final List list = new ArrayList<>(); try (final Cursor cursor = - db.query(Account.TABLENAME, null, null, null, null, null, null)) { + db.query(Account.TABLENAME, null, null, null, null, null, null)) { while (cursor != null && cursor.moveToNext()) { list.add(Account.fromCursor(cursor)); } @@ -1419,14 +1419,14 @@ public class DatabaseBackend extends SQLiteOpenHelper { contentValues.remove(Message.BODY); } return db.update(Message.TABLENAME, message.getContentValues(), Message.UUID + "=?", args) == 1 && - db.update("monocles." + Message.TABLENAME, message.getmonoclesContentValues(), Message.UUID + "=?", args) == 1; + db.update("monocles." + Message.TABLENAME, message.getmonoclesContentValues(), Message.UUID + "=?", args) == 1; } public boolean updateMessage(Message message, String uuid) { SQLiteDatabase db = this.getWritableDatabase(); String[] args = {uuid}; return db.update(Message.TABLENAME, message.getContentValues(), Message.UUID + "=?", args) == 1 && - db.update("monocles." + Message.TABLENAME, message.getmonoclesContentValues(), Message.UUID + "=?", args) == 1; + db.update("monocles." + Message.TABLENAME, message.getmonoclesContentValues(), Message.UUID + "=?", args) == 1; } @@ -1434,14 +1434,14 @@ public class DatabaseBackend extends SQLiteOpenHelper { SQLiteDatabase db = this.getWritableDatabase(); String[] args = {uuid}; return db.delete(Message.TABLENAME, Message.UUID + "=?", args) == 1 && - db.delete("monocles." + Message.TABLENAME, Message.UUID + "=?", args) == 1; + db.delete("monocles." + Message.TABLENAME, Message.UUID + "=?", args) == 1; } public void readRoster(Roster roster) { final SQLiteDatabase db = this.getReadableDatabase(); final String[] args = {roster.getAccount().getUuid()}; try (final Cursor cursor = - db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?", args, null, null, null)) { + db.query(Contact.TABLENAME, null, Contact.ACCOUNT + "=?", args, null, null, null)) { while (cursor.moveToNext()) { roster.initContact(Contact.fromCursor(cursor)); } diff --git a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java index 2a02d0ddf..7d34d34eb 100644 --- a/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/CryptoHelper.java @@ -273,8 +273,8 @@ public final class CryptoHelper { return switch (encryption) { case Message.ENCRYPTION_OTR -> R.string.encryption_choice_otr; case Message.ENCRYPTION_AXOLOTL, - Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE, - Message.ENCRYPTION_AXOLOTL_FAILED -> R.string.encryption_choice_omemo; + Message.ENCRYPTION_AXOLOTL_NOT_FOR_THIS_DEVICE, + Message.ENCRYPTION_AXOLOTL_FAILED -> R.string.encryption_choice_omemo; case Message.ENCRYPTION_PGP -> R.string.encryption_choice_pgp; default -> R.string.encryption_choice_unencrypted; }; @@ -290,14 +290,14 @@ public final class CryptoHelper { public static String multihashAlgo(Multihash.Type type) throws NoSuchAlgorithmException { switch(type) { - case sha1: - return "sha-1"; - case sha2_256: - return "sha-256"; - case sha2_512: - return "sha-512"; - default: - throw new NoSuchAlgorithmException("" + type); + case sha1: + return "sha-1"; + case sha2_256: + return "sha-256"; + case sha2_512: + return "sha-512"; + default: + throw new NoSuchAlgorithmException("" + type); } } diff --git a/src/main/java/eu/siacs/conversations/worker/ExportBackupWorker.java b/src/main/java/eu/siacs/conversations/worker/ExportBackupWorker.java index 0b893019e..35d241891 100644 --- a/src/main/java/eu/siacs/conversations/worker/ExportBackupWorker.java +++ b/src/main/java/eu/siacs/conversations/worker/ExportBackupWorker.java @@ -75,7 +75,7 @@ public class ExportBackupWorker extends Worker { public static final String KEYTYPE = "AES"; public static final String CIPHERMODE = "AES/GCM/NoPadding"; - public static final String PROVIDER = "BC"; + public static final String PROVIDER = "BCPQC"; public static final String MIME_TYPE = "application/vnd.conversations.backup"; @@ -104,12 +104,12 @@ public class ExportBackupWorker extends Worker { try { files = export(); } catch (final IOException - | InvalidKeySpecException - | InvalidAlgorithmParameterException - | InvalidKeyException - | NoSuchPaddingException - | NoSuchAlgorithmException - | NoSuchProviderException e) { + | InvalidKeySpecException + | InvalidAlgorithmParameterException + | InvalidKeyException + | NoSuchPaddingException + | NoSuchAlgorithmException + | NoSuchProviderException e) { Log.d(Config.LOGTAG, "could not create backup", e); return Result.failure(); } finally { @@ -142,12 +142,12 @@ public class ExportBackupWorker extends Worker { private List export() throws IOException, - InvalidKeySpecException, - InvalidAlgorithmParameterException, - InvalidKeyException, - NoSuchPaddingException, - NoSuchAlgorithmException, - NoSuchProviderException { + InvalidKeySpecException, + InvalidAlgorithmParameterException, + InvalidKeyException, + NoSuchPaddingException, + NoSuchAlgorithmException, + NoSuchProviderException { final Context context = getApplicationContext(); final var database = DatabaseBackend.getInstance(context); final var accounts = database.getAccounts(); @@ -202,13 +202,13 @@ public class ExportBackupWorker extends Worker { final int max, final int count) throws IOException, - InvalidKeySpecException, - InvalidAlgorithmParameterException, - InvalidKeyException, - NoSuchPaddingException, - NoSuchAlgorithmException, - NoSuchProviderException, - WorkStoppedException { + InvalidKeySpecException, + InvalidAlgorithmParameterException, + InvalidKeyException, + NoSuchPaddingException, + NoSuchAlgorithmException, + NoSuchProviderException, + WorkStoppedException { final var context = getApplicationContext(); final SecureRandom secureRandom = new SecureRandom(); Log.d( @@ -232,9 +232,9 @@ public class ExportBackupWorker extends Worker { WorkManager.getInstance(context).createCancelPendingIntent(getId()); notification.addAction( new NotificationCompat.Action.Builder( - R.drawable.ic_cancel_24dp, - context.getString(R.string.cancel), - cancelPendingIntent) + R.drawable.ic_cancel_24dp, + context.getString(R.string.cancel), + cancelPendingIntent) .build()); final Progress progress = new Progress(notification, max, count); final File directory = file.getParentFile();