Smack Omemo causes system crashes when buddy prekeys is empty or corrupted

The problem is feedback from an aTalk user who encounters system crashes when opening aTalk chat windows for message sending (version 0.9.1). From the debug log sent from user, I came to the conclusion that the database stored prekeys for the intended chat buddy contains no or corrupted prekeys. There is no information provided why the buddy prekeys is empty or corrupted. On advice, user regenerates the omemo prekey for the account with the corrupted prekeys and the problem is resolved.

Attached below is an extraction of the user debug log for reference.

In aTalk, when a chat session is launched, it immediately performs a check isOmemoSupport() for the chat buddy; omemo message sending option is then enabled/disabled pending the check result. I have verified that under normal working conditions, launching of a chat session in aTalk will only perform isOmemoSupport() once. It seems that the system crashes on the third instance of isOmemoSupport(). I am unable to determine why isOmemoSupport() is performed multiple times as I am unable to duplication the failed conditions. From the debug log starting from
isOmemoSupport(), I found that the SignalOmemoService takes a different path on second/third instance after
"org.jivesoftware.smackx.omemo.signal.SignalOmemoService.processBundle(SignalOmemoService.java:104)".
This new execution path taken causes the system to crash.

As aTalk immediately crashes upon launches a chat session, and the root cause of the problem is embedded deep within the whispersystems.libsignal, I am still unable figure out how aTalk can prevent such system crashes; also there is no time for aTalk to pop-up a alert message to advice user to take appropriate action.
Any advice is appreciated.

12-19 13:33:11.137 E/aTalk   (20639): [1] org.jivesoftware.smackx.omemo.signal.SignalOmemoStoreConnector.getIdentityKeyPair() getIdentityKeyPair has failed: org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException: OMEMO Identity KeyPair is null for: swan@jabber.ccc.de:22579555
12-19 13:33:11.137 E/aTalk   (20639): org.jivesoftware.smackx.omemo.exceptions.CorruptedOmemoKeyException: OMEMO Identity KeyPair is null for: swan@jabber.ccc.de:22579555
12-19 13:33:11.137 E/aTalk   (20639): 	at org.atalk.crypto.omemo.SQLiteOmemoStore.loadOmemoIdentityKeyPair(SQLiteOmemoStore.java:472)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.atalk.crypto.omemo.SQLiteOmemoStore.loadOmemoIdentityKeyPair(SQLiteOmemoStore.java:50)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.signal.SignalOmemoStoreConnector.getIdentityKeyPair(SignalOmemoStoreConnector.java:72)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.whispersystems.libsignal.SessionBuilder.process(SessionBuilder.java:193)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.signal.SignalOmemoService.processBundle(SignalOmemoService.java:104)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.signal.SignalOmemoService.processBundle(SignalOmemoService.java:61)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoService.buildSessionFromOmemoBundle(OmemoService.java:690)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.atalk.persistance.DatabaseBackend.storeCachedDeviceList(DatabaseBackend.java:1298)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.atalk.crypto.omemo.SQLiteOmemoStore.storeCachedDeviceList(SQLiteOmemoStore.java:708)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoStore.mergeCachedDeviceList(OmemoStore.java:132)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoService.refreshDeviceList(OmemoService.java:533)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoManager.contactSupportsOmemo(OmemoManager.java:494)
12-19 13:33:11.137 E/aTalk   (20639): 	at org.atalk.crypto.CryptoFragment.isOmemoSupport(CryptoFragment.java:855)
.....

12-19 13:33:11.178 E/aTalk   (20639): [1] util.UtilActivator.uncaughtException().95 An uncaught exception occurred in thread=Thread[main,5,main] and message was: Null values!
12-19 13:33:11.178 E/aTalk   (20639): java.lang.IllegalArgumentException: Null values!
12-19 13:33:11.178 E/aTalk   (20639): 	at org.whispersystems.libsignal.ratchet.AliceSignalProtocolParameters.<init>(AliceSignalProtocolParameters.java:38)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.whispersystems.libsignal.ratchet.AliceSignalProtocolParameters.<init>(AliceSignalProtocolParameters.java:14)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.whispersystems.libsignal.ratchet.AliceSignalProtocolParameters$Builder.create(AliceSignalProtocolParameters.java:110)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.whispersystems.libsignal.SessionBuilder.process(SessionBuilder.java:201)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.signal.SignalOmemoService.processBundle(SignalOmemoService.java:104)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.signal.SignalOmemoService.processBundle(SignalOmemoService.java:61)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoService.buildSessionFromOmemoBundle(OmemoService.java:690)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.atalk.persistance.DatabaseBackend.storeCachedDeviceList(DatabaseBackend.java:1298)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.atalk.crypto.omemo.SQLiteOmemoStore.storeCachedDeviceList(SQLiteOmemoStore.java:708)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoStore.mergeCachedDeviceList(OmemoStore.java:132)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoService.refreshDeviceList(OmemoService.java:533)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoManager.contactSupportsOmemo(OmemoManager.java:494)
12-19 13:33:11.178 E/aTalk   (20639): 	at org.atalk.crypto.CryptoFragment.isOmemoSupport(CryptoFragment.java:855)
.....
12-19 13:33:11.179 E/aTalk   (20639): [1] org.atalk.android.plugin.errorhandler.ExceptionHandler.uncaughtException().78 uncaughtException occurred, killing the process...
12-19 13:33:11.179 E/aTalk   (20639): java.lang.IllegalArgumentException: Null values!
12-19 13:33:11.179 E/aTalk   (20639): 	at org.whispersystems.libsignal.ratchet.AliceSignalProtocolParameters.<init>(AliceSignalProtocolParameters.java:38)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.whispersystems.libsignal.ratchet.AliceSignalProtocolParameters.<init>(AliceSignalProtocolParameters.java:14)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.whispersystems.libsignal.ratchet.AliceSignalProtocolParameters$Builder.create(AliceSignalProtocolParameters.java:110)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.whispersystems.libsignal.SessionBuilder.process(SessionBuilder.java:201)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.signal.SignalOmemoService.processBundle(SignalOmemoService.java:104)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.signal.SignalOmemoService.processBundle(SignalOmemoService.java:61)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoService.buildSessionFromOmemoBundle(OmemoService.java:690)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.atalk.persistance.DatabaseBackend.storeCachedDeviceList(DatabaseBackend.java:1298)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.atalk.crypto.omemo.SQLiteOmemoStore.storeCachedDeviceList(SQLiteOmemoStore.java:708)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoStore.mergeCachedDeviceList(OmemoStore.java:132)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoService.refreshDeviceList(OmemoService.java:533)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.jivesoftware.smackx.omemo.OmemoManager.contactSupportsOmemo(OmemoManager.java:494)
12-19 13:33:11.179 E/aTalk   (20639): 	at org.atalk.crypto.CryptoFragment.isOmemoSupport(CryptoFragment.java:855)
.....

12-19 13:33:11.183 I/System  (20639): exec(logcat -v time -f /data/data/org.atalk.android/files/log/atalk-crash-logcat.txt @ de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative:-2)
12-19 13:33:11.207 D/Process (20639): killProcess, pid=20639
1 Like

I’m aware of that issue and I’m working on a solution. For the mean time, you could manually check, whether there are PreKeys available for each device of your contact. If not, you can manually fetch and process the users bundle via OmemoManager.buildSessionsWith(BareJid contact).

Thank for the information. In aTalk v0.9.1 release, actually I have included the step to fetch new prekeys for active device when missing using method buildSessionFromOmemoBundle(). However seems this is not working for this case.

	public void storeCachedDeviceList(OmemoManager omemoManager, BareJid contact, CachedDeviceList deviceList)
            throws CannotEstablishOmemoSessionException, CorruptedOmemoKeyException
	{
		if (contact == null) {
			return;
		}

		final SQLiteDatabase db = this.getWritableDatabase();
		ContentValues values = new ContentValues();

		// Active devices
		values.put(SQLiteOmemoStore.ACTIVE, 1);
		Set<Integer> activeDevices = deviceList.getActiveDevices();
		for (int deviceId : activeDevices) {
			String[] selectionArgs = {contact.toString(), Integer.toString(deviceId)};

			int row = db.update(SQLiteOmemoStore.IDENTITIES_TABLE_NAME, values,
					SQLiteOmemoStore.BARE_JID + "=? AND " + SQLiteOmemoStore.DEVICE_ID + "=?",
					selectionArgs);
			if (row == 0) {
				logger.warn("Identities table contains no activeDevice (fetch new): " + contact + ":" + deviceId);
				// create the identities & preKeys for missing deviceId
				OmemoDevice omemoDevice = new OmemoDevice(contact, deviceId);

				// may throws CannotEstablishOmemoSessionException, CorruptedOmemoKeyException
				OmemoService.getInstance().buildSessionFromOmemoBundle(omemoManager, omemoDevice, false);
			}
		}

		// Inactive devices
		values.put(SQLiteOmemoStore.ACTIVE, 0);
		Set<Integer> inActiveDevices = deviceList.getInactiveDevices();
		for (int deviceId : inActiveDevices) {
			String[] selectionArgs = {contact.toString(), Integer.toString(deviceId)};

			int row = db.update(SQLiteOmemoStore.IDENTITIES_TABLE_NAME, values,
					SQLiteOmemoStore.BARE_JID + "=? AND " + SQLiteOmemoStore.DEVICE_ID + "=?",
					selectionArgs);
			if (row == 0) {
				logger.warn("Identities table contains no inactiveDevice: " + contact + ":" + deviceId);
				new Exception().printStackTrace();
			}
		}
	}