powered by Jive Software

Smack 4.4.0 - Omemo throws an IllegalArgumentException when an omemo device published prekeys bundle with index='0'

When one of the omemoDevices published the key bundles with <signedPreKeyPublic signedPreKeyId=‘0’>. Omemo throws

java.lang.IllegalArgumentException: signedPreKeyId MUST be greater than 0

and terminates the sending of omemo message to other OmemoDevices. This means all omemoDevices with the same user account can no longer send Omemo messages to other contacts. This user is locked into an unrecoverable state.

Please refer to:
java.lang.IllegalArgumentException: signedPreKeyId MUST be greater than 0. #47

In conversations implementation, it just ignores this erroneous omemo device and strip this device from its recipient list with an message displays on chat to that effect:
"Message was not encrypted for this device."

Please consider conversation implementation for smack OMEMO.

08-24 08:37:55.487 32673-4267/org.atalk.android D/SMACK: RECV (0): 
    <iq xml:lang='en' to='user2@myserver.ltd/atalk' from='user2@myserver.ltd' type='result' id='2YL2F-321'>
      <pubsub xmlns='http://jabber.org/protocol/pubsub'>
        <items node='eu.siacs.conversations.axolotl.bundles:8870'>
          <item id='61E8C7EEE7D60'>
            <bundle xmlns='eu.siacs.conversations.axolotl'>
              <signedPreKeyPublic signedPreKeyId='0'>
                Bez7xfU8lVaXxjfiWuFVfoCdtHjGBzI4nays/p8dzAxe
              </signedPreKeyPublic>
              <signedPreKeySignature>
                +94sRJNK+ysxVVuqYVXQT0652Dm26xTt4C7EvFJ2oc7eY6kFVtt8G3fyhKGefgqFc2Tc5eOOyq/4+1WJim6Zjg==
              </signedPreKeySignature>
              <identityKey>
                BcuPpYfkfn3UnQ1mf0JUKUFLBknz6xv5QFWVoRxHc1MH
              </identityKey>
              <prekeys>
                <preKeyPublic preKeyId='0'>
                  BcgjrJk4KR9ghqGLoNEeccBm0NTcvBKebKtuAH4Tlk5c
                </preKeyPublic>
                <preKeyPublic preKeyId='1'>
                  BXmjl6Tuv+9+Osy7dQtCYq/fb+K3ssbJywimJgmIfER5
.....


08-24 08:37:55.537 32673-28327/org.atalk.android W/aTalk: [5] org.jivesoftware.smack.AbstractXMPPConnection.callConnectionClosedOnErrorListener() Connection XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0) closed with error
    java.lang.IllegalArgumentException: signedPreKeyId MUST be greater than 0.
        at org.jivesoftware.smackx.omemo.element.OmemoBundleElement.<init>(OmemoBundleElement.java:64)
        at org.jivesoftware.smackx.omemo.element.OmemoBundleElement_VAxolotl.<init>(OmemoBundleElement_VAxolotl.java:32)
        at org.jivesoftware.smackx.omemo.provider.OmemoBundleVAxolotlProvider.parse(OmemoBundleVAxolotlProvider.java:103)
        at org.jivesoftware.smackx.omemo.provider.OmemoBundleVAxolotlProvider.parse(OmemoBundleVAxolotlProvider.java:43)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:69)
        at org.jivesoftware.smackx.pubsub.provider.ItemProvider.parse(ItemProvider.java:69)
        at org.jivesoftware.smackx.pubsub.provider.ItemProvider.parse(ItemProvider.java:44)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.util.PacketParserUtils.parseExtensionElement(PacketParserUtils.java:869)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:956)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:951)
        at org.jivesoftware.smack.provider.EmbeddedExtensionProvider.parse(EmbeddedExtensionProvider.java:105)
        at org.jivesoftware.smack.provider.EmbeddedExtensionProvider.parse(EmbeddedExtensionProvider.java:86)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.util.PacketParserUtils.parseExtensionElement(PacketParserUtils.java:869)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:945)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:940)
        at org.jivesoftware.smackx.pubsub.provider.PubSubProvider.parse(PubSubProvider.java:49)
        at org.jivesoftware.smackx.pubsub.provider.PubSubProvider.parse(PubSubProvider.java:38)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.util.PacketParserUtils.parseIQ(PacketParserUtils.java:547)
        at org.jivesoftware.smack.util.PacketParserUtils.parseStanza(PacketParserUtils.java:116)
        at org.jivesoftware.smack.AbstractXMPPConnection.parseAndProcessStanza(AbstractXMPPConnection.java:1252)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$500(XMPPTCPConnection.java:136)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:936)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$300(XMPPTCPConnection.java:882)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:902)
        at java.lang.Thread.run(Thread.java:818)
1 Like

Yeah the 0 index prekeys are coming from conversejs.
Fixing PR.

1 Like

By the way, is index=0 allowed. There is no mention of index range in the XEP document.

I’m 90% sure that it was forbidden at one point, at least in the version of the XEP I read when I implemented OMEMO back then. But yes, the current XEP does not forbid index=0, so the implementation is now correct.

Thanks for reporting this.

Does it matter if one of the OmemoDevice of the same user start with index = 0 and another start with index = 1. Any conflict?

Forget to highlight is that when omemo throws

IllegalArgumentException: signedPreKeyId MUST be greater than 0.

The connection is also get disconnected i.e. callConnectionClosedOnErrorListener(). Why the connection closes with just IllegalArgumentException. Pretty serious!

2019-08-22 17:30:04.547 WARNING: [3245] org.jivesoftware.smack.AbstractXMPPConnection.callConnectionClosedOnErrorListener() Connection XMPPTCPConnection[myuser@mydomain.tld/atalk] (0) closed with error
java.lang.IllegalArgumentException: signedPreKeyId MUST be greater than 0.

No, the prekeys are selected randomly per device anyways. The error only happened during parsing.

Fail early and fail hard :wink:

Thank, I have tested your fix and it works.

I have seen the network connection can get disconnected, it has to be reconnected by the ReconnectManager; or the user is being disconnected. On aTalk UI, the user sees that the affect account goes offline and then online again. The penalty seems to be a bit harsh for IllegalArgumentException. I would prefer just an error message shown to the user, and not to get the account disconnected.

Add a parsing exception callback to the connection and it won’t get disconnected.

I think I told you before about this and the rationale behind this.

Hi Flow,

Yes, thanks for helping me to recall that. aTalk implemented the callback at the time when it was trying to take care the non-standard stanza sent by Telephony gateway. I check and found actually the callback still retain in aTalk source.

        // Just ignore UnparseableStanza to avoid connection abort
        SmackConfiguration.setDefaultParsingExceptionCallback(packetData -> {
                    String errMsg = packetData.getContent().toString();
                    Timber.w(packetData.getParsingException(), "UnparseableStanza Error: %s", errMsg);
                }
        );

The problem is that the disconnection is now not due to ParsingException, OmemoBundelElement throws an IllegalArgumentException due to a range check on the index. This causes the connection to be disconnected deep in smack; What aTalk caught is an NotConnectedException.

if (signedPreKeyId <= 0) {
    throw new IllegalArgumentException("signedPreKeyId MUST be greater than or equal to 0.");
}
============ aTalk debug log on IllegalArgumentException() ===
08-27 10:10:51.800 30089-31252/org.atalk.android D/(AbstractProtocolProviderService.java:140)#fireRegistrationStateChanged: The provider state changed: RegistrationState = Registering => RegistrationState = Reconnecting. Reason: signedPreKeyId MUST be greater than or equal to 0.
08-27 10:10:51.810 30089-31252/org.atalk.android D/(AndroidLoginRenderer.java:247)#updateaTalkIconNotification: Not displaying status notification because there's no global notification icon available.
08-27 10:10:51.810 30089-31252/org.atalk.android D/SMACK: XMPPConnection closed due to an exception (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0))
    java.lang.IllegalArgumentException: signedPreKeyId MUST be greater than or equal to 0.
        at org.jivesoftware.smackx.omemo.element.OmemoBundleElement.<init>(OmemoBundleElement.java:64)
        at org.jivesoftware.smackx.omemo.element.OmemoBundleElement_VAxolotl.<init>(OmemoBundleElement_VAxolotl.java:32)
        at org.jivesoftware.smackx.omemo.provider.OmemoBundleVAxolotlProvider.parse(OmemoBundleVAxolotlProvider.java:103)
        at org.jivesoftware.smackx.omemo.provider.OmemoBundleVAxolotlProvider.parse(OmemoBundleVAxolotlProvider.java:43)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:69)
        at org.jivesoftware.smackx.pubsub.provider.ItemProvider.parse(ItemProvider.java:69)
        at org.jivesoftware.smackx.pubsub.provider.ItemProvider.parse(ItemProvider.java:44)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.util.PacketParserUtils.parseExtensionElement(PacketParserUtils.java:869)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:956)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:951)
        at org.jivesoftware.smack.provider.EmbeddedExtensionProvider.parse(EmbeddedExtensionProvider.java:105)
        at org.jivesoftware.smack.provider.EmbeddedExtensionProvider.parse(EmbeddedExtensionProvider.java:86)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.util.PacketParserUtils.parseExtensionElement(PacketParserUtils.java:869)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:945)
        at org.jivesoftware.smack.util.PacketParserUtils.addExtensionElement(PacketParserUtils.java:940)
        at org.jivesoftware.smackx.pubsub.provider.PubSubProvider.parse(PubSubProvider.java:49)
        at org.jivesoftware.smackx.pubsub.provider.PubSubProvider.parse(PubSubProvider.java:38)
        at org.jivesoftware.smack.provider.Provider.parse(Provider.java:79)
        at org.jivesoftware.smack.util.PacketParserUtils.parseIQ(PacketParserUtils.java:547)
        at org.jivesoftware.smack.util.PacketParserUtils.parseStanza(PacketParserUtils.java:116)
        at org.jivesoftware.smack.AbstractXMPPConnection.parseAndProcessStanza(AbstractXMPPConnection.java:1252)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection.access$500(XMPPTCPConnection.java:136)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:936)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$300(XMPPTCPConnection.java:882)
        at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:902)
        at java.lang.Thread.run(Thread.java:818)
08-27 10:10:52.830 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 12
08-27 10:10:53.830 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 11
08-27 10:10:54.840 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 10
08-27 10:10:55.840 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 9
08-27 10:10:56.850 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 8
08-27 10:10:57.850 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 7
08-27 10:10:58.860 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 6
08-27 10:10:59.860 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 5
08-27 10:11:00.870 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 4
08-27 10:11:01.880 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 3
08-27 10:11:02.880 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 2
08-27 10:11:03.880 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 1
08-27 10:11:04.890 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 0
08-27 10:11:04.900 30089-31253/org.atalk.android D/SMACK: XMPPConnection (XMPPTCPConnection[atalkuser2@convorb.im/atalk] (0)) will reconnect in 0
08-27 10:11:05.390 30089-31282/org.atalk.android D/SMACK: SENT (0): 
    <stream:stream xmlns='jabber:client' to='convorb.im' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>

Right, there was an IllegalArgumentException catch missing:

Thanks. problem fixed.