OMEMO: adapted to use Olm instead of Axolotl

* migration to olm
* moved the gcm auth tag into the OlmMessage
* various clarifications
* prekey messages are now marked with special attribute

Fixes #251
This commit is contained in:
Daniel Gultsch 2016-10-31 15:46:08 +01:00 committed by Sam Whited
parent 69205a8490
commit ac8cf918ee
1 changed files with 120 additions and 36 deletions

View File

@ -1,6 +1,6 @@
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE xep SYSTEM 'xep.dtd' [
<!ENTITY % ents SYSTEM 'xep.ent'>
<!ENTITY % ents SYSTEM "xep.ent">
%ents;
]>
<?xml-stylesheet type='text/xsl' href='xep.xsl'?>
@ -8,13 +8,7 @@
<header>
<title>OMEMO Encryption</title>
<abstract>This specification defines a protocol for end-to-end encryption in one-on-one chats that may have multiple clients per account.</abstract>
<legal>
<copyright>This XMPP Extension Protocol is copyright (c) 1999 - 2014 by the XMPP Standards Foundation (XSF).</copyright>
<permissions>Permission is hereby granted, free of charge, to any person obtaining a copy of this specification (the &quot;Specification&quot;), to make use of the Specification without restriction, including without limitation the rights to implement the Specification in a software program, deploy the Specification in a network service, and copy, modify, merge, publish, translate, distribute, sublicense, or sell copies of the Specification, and to permit persons to whom the Specification is furnished to do so, subject to the condition that the foregoing copyright notice and this permission notice shall be included in all copies or substantial portions of the Specification. Unless separate permission is granted, modified works that are redistributed shall not contain misleading information regarding the authors, title, number, or publisher of the Specification, and shall not claim endorsement of the modified works by the authors, any organization or project to which the authors belong, or the XMPP Standards Foundation.</permissions>
<warranty>## NOTE WELL: This Specification is provided on an &quot;AS IS&quot; BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. In no event shall the XMPP Standards Foundation or the authors of this Specification be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the Specification or the implementation, deployment, or other use of the Specification. ##</warranty>
<liability>In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall the XMPP Standards Foundation or any author of this Specification be liable for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising out of the use or inability to use the Specification (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if the XMPP Standards Foundation or such author has been advised of the possibility of such damages.</liability>
<conformance>This XMPP Extension Protocol has been contributed in full conformance with the XSF's Intellectual Property Rights Policy (a copy of which may be found at &lt;<link url='http://xmpp.org/extensions/ipr-policy.shtml'>http://xmpp.org/extensions/ipr-policy.shtml</link>&gt; or obtained by writing to XSF, P.O. Box 1641, Denver, CO 80201 USA).</conformance>
</legal>
&LEGALNOTICE;
<number>xxxx</number>
<status>ProtoXEP</status>
<type>Standards Track</type>
@ -26,13 +20,19 @@
</dependencies>
<supersedes/>
<supersededby/>
<shortname>NOT_YET_ASSIGNED</shortname>
<shortname>OMEMO</shortname>
<author>
<firstname>Andreas</firstname>
<surname>Straub</surname>
<email>andy@strb.org</email>
<jid>andy@strb.org</jid>
</author>
<revision>
<version>0.0.2</version>
<date>2016-09-22</date>
<initials>ssw, dg</initials>
<remark><p>Depend on Olm instead of Axolotl.</p></remark>
</revision>
<revision>
<version>0.0.1</version>
<date>2015-10-25</date>
@ -42,13 +42,55 @@
</header>
<section1 topic='Introduction' anchor='intro'>
<section2 topic='Motivation' anchor='intro-motivation'>
<p>There are two main end-to-end encryption schemes in common use in the XMPP ecosystem, Off-the-Record (OTR) messaging (&xep0364;) and OpenPGP (&xep0027;). OTR has significant usability drawbacks for inter-client mobility. As OTR sessions exist between exactly two clients, the chat history will not be synchronized across other clients of the involved parties. Furthermore, OTR chats are only possible if both participants are currently online, due to how the rolling key agreement scheme of OTR works. OpenPGP, while not suffering from these mobility issues, does not provide any kind of forward secrecy and is vulnerable to replay attacks. Additionally, PGP over XMPP uses a custom wireformat which is defined by convention rather than standardization, and involves quite a bit of external complexity.</p>
<p>This XEP defines a protocol that leverages axolotl encryption to provide multi-end to multi-end encryption, allowing messages to be synchronized securely across multiple clients, even if some of them are offline.</p>
<p>
There are two main end-to-end encryption schemes in common use in the XMPP
ecosystem, Off-the-Record (OTR) messaging (&xep0364;) and OpenPGP
(&xep0027;). OTR has significant usability drawbacks for inter-client
mobility. As OTR sessions exist between exactly two clients, the chat
history will not be synchronized across other clients of the involved
parties. Furthermore, OTR chats are only possible if both participants are
currently online, due to how the rolling key agreement scheme of OTR
works. OpenPGP, while not suffering from these mobility issues, does not
provide any kind of forward secrecy and is vulnerable to replay attacks.
Additionally, PGP over XMPP uses a custom wireformat which is defined by
convention rather than standardization, and involves quite a bit of
external complexity.
</p>
<p>
This XEP defines a protocol that leverages &olm; encryption to provide
multi-end to multi-end encryption, allowing messages to be synchronized
securely across multiple clients, even if some of them are offline. Olm
is a cryptographic double ratched protocol based on work by Trevor Perrin
and Moxie Marlinspike first published as the Axolotl protocol.
</p>
</section2>
<section2 topic='Overview' anchor='intro-overview'>
<p>The general idea behind this protocol is to maintain separate, long-standing axolotl-encrypted sessions with each device of each contact (as well as with each of our other devices), which are used as secure key transport channels. In this scheme, each message is encrypted with a fresh, randomly generated encryption key. An encrypted header is added to the message for each device that is supposed to receive it. These headers simply contain the key that the payload message is encrypted with, and they are seperately encrypted using the session corresponding to the counterpart device. The encrypted payload is sent together with the headers as a &lt;message&gt; stanza. Individual recipient devices can decrypt the header item intended for them, and use the contained payload key to decrypt the payload message.</p>
<p>As the encrypted payload is common to all recipients, it only has to be included once, reducing overhead. Furthermore, axolotl's transparent handling of messages that were lost or received out of order, as well as those sent while the recipient was offline, is maintained by this protocol. As a result, in combination with &xep0280; and &xep0313;, the desired property of inter-client history synchronization is achieved.</p>
<p>OMEMO version 0 uses v3 messages of the axolotl protocol. Instead of an axolotl key server, PEP (&xep0163;) is used to publish key data. </p>
<p>
The general idea behind this protocol is to maintain separate,
long-standing Olm-encrypted sessions with each device of each contact
(as well as with each of our other devices), which are used as secure key
transport channels. In this scheme, each message is encrypted with a
fresh, randomly generated encryption key. An encrypted header is added to
the message for each device that is supposed to receive it. These headers
simply contain the key that the payload message is encrypted with, and
they are seperately encrypted using the session corresponding to the
counterpart device. The encrypted payload is sent together with the
headers as a &lt;message&gt; stanza. Individual recipient devices can
decrypt the header item intended for them, and use the contained payload
key to decrypt the payload message.
</p>
<p>
As the encrypted payload is common to all recipients, it only has to be
included once, reducing overhead. Furthermore, Olm's transparent handling
of messages that were lost or received out of order, as well as those sent
while the recipient was offline, is maintained by this protocol. As a
result, in combination with &xep0280; and &xep0313;, the desired property
of inter-client history synchronization is achieved.
</p>
<p>
OMEMO currently uses version 1 Olm protocol. Instead of an Axolotl key
server, &xep0163; (PEP) is used to publish key data.
</p>
</section2>
</section1>
<section1 topic='Requirements' anchor='reqs'>
@ -72,18 +114,23 @@
</dl>
</section2>
<section2 topic='Axolotl-specific' anchor='glossary-axolotl'>
<section2 topic='Olm-specific' anchor='glossary-olm'>
<dl>
<di><dt>IdentityKey</dt><dd>Per-device public/private key pair used to authenticate communications</dd></di>
<di><dt>PreKey</dt><dd>A Diffie-Hellman public key, published in bulk and ahead of time</dd></di>
<di><dt>PreKeyWhisperMessage</dt><dd>An encrypted message that includes the initial key exchange. This is used to transparently build sessions with the first exchanged message.</dd></di>
<di><dt>WhisperMessage</dt><dd>An encrypted message</dd></di>
<di><dt>PreKeyOlmMessage</dt><dd>An encrypted message that includes the initial key exchange. This is used to transparently build sessions with the first exchanged message.</dd></di>
<di><dt>OlmMessage</dt><dd>An encrypted message</dd></di>
</dl>
</section2>
</section1>
<section1 topic='Use Cases' anchor='usecases'>
<section2 topic='Setup' anchor='usecases-setup'>
<p>The first thing that needs to happen if a client wants to start using OMEMO is they need to generate an IdentityKey and a Device ID. The IdentityKey is a <a href='http://cr.yp.to/ecdh/curve25519-20060209.pdf'>Curve25519</a> public/private Key pair. The Device ID is a randomly generated integer between 1 and 2^31 - 1. </p>
<p>
The first thing that needs to happen if a client wants to start using
OMEMO is they need to generate an IdentityKey and a Device ID. The
IdentityKey is a &curve25519; public/private Key pair. The Device ID is a
randomly generated integer between 1 and 2^31 - 1.
</p>
</section2>
<section2 topic='Discovering peer support' anchor='usecases-discovering'>
<p>In order to determine whether a given contact has devices that support OMEMO, the devicelist node in PEP is consulted. Devices MUST subscribe to 'urn:xmpp:omemo:0:devicelist' via PEP, so that they are informed whenever their contacts add a new device. They MUST cache the most up-to-date version of the devicelist.</p>
@ -166,16 +213,29 @@
<items node='urn:xmpp:omemo:0:bundles:31415'/>
</pubsub>
</iq>]]></example>
<p>A random preKeyPublic entry is selected, and used to build an axolotl session.</p>
<p>A random preKeyPublic entry is selected, and used to build an Olm session.</p>
</section2>
<section2 topic='Sending a message' anchor='usecases-messagesend'>
<p>In order to send a chat message, its &lt;body&gt; first has to be encrypted. The client MUST use fresh, randomly generated key/IV pairs with AES-128 in Galois/Counter Mode (GCM). For each intended recipient device, i.e. both own devices as well as devices associated with the contact, this key is encrypted using the corresponding long-standing axolotl session. Each encrypted payload key is tagged with the recipient device's ID. This is all serialized into a MessageElement, which is transmitted in a &lt;message&gt; as follows:</p>
<p>
In order to send a chat message, its &lt;body&gt; first has to be
encrypted. The client MUST use fresh, randomly generated key/IV pairs with
AES-128 in Galois/Counter Mode (GCM).
The 16 bytes key and the GCM authentication tag (The tag SHOULD have at least
128 bit) are concatenated and for each intended recipient device,
i.e. both own devices as well as devices associated with the contact, the
result of this concatenation is encrypted using the corresponding
long-standing Olm session. Each encrypted payload key/authentication tag
tuple is tagged with the recipient device's ID. The key element MUST be
tagged with a prekey attribute set to true if a PreKeyOlmMessage is being
used. This is all serialized into a MessageElement, which is transmitted
in a &lt;message&gt; as follows:
</p>
<example caption="Sending a message"><![CDATA[
<message to='juliet@capulet.lit' from='romeo@montague.lit' id='send1'>
<encrypted xmlns='urn:xmpp:omemo:0'>
<header sid='27183'>
<key rid='31415'>BASE64ENCODED...</key>
<key rid='12321'>BASE64ENCODED...</key>
<key prekey="true" rid='12321'>BASE64ENCODED...</key>
<!-- ... -->
<iv>BASE64ENCODED...</iv>
</header>
@ -185,12 +245,24 @@
</message>]]></example>
</section2>
<section2 topic='Sending a key' anchor='usecases-keysend'>
<p>The client may wish to transmit keying material to the contact. This first has to be generated. The client MUST generate a fresh, randomly generated key/IV pair. For each intended recipient device, i.e. both own devices as well as devices associated with the contact, this key is encrypted using the corresponding long-standing axolotl session. Each encrypted payload key is tagged with the recipient device's ID. This is all serialized into a KeyTransportElement, omitting the &lt;payload&gt; as follows:</p>
<p>
The client may wish to transmit keying material to the contact. This first
has to be generated. The client MUST generate a fresh, randomly generated
key/IV pair. The 16 bytes key and the GCM authentication tag (The tag
SHOULD have at least 128 bit) are concatenated and for each intended
recipient device, i.e. both own devices as well as devices associated
with the contact, this key is encrypted using the corresponding
long-standing Olm session. Each encrypted payload key/authentication tag
tuple is tagged with the recipient device's ID. The key element MUST be
tagged with a prekey attribute set to true if a PreKeyOlmMessage is being
used This is all serialized into a KeyTransportElement, omitting the
&lt;payload&gt; as follows:
</p>
<example caption="Sending a key"><![CDATA[
<encrypted xmlns='urn:xmpp:omemo:0'>
<header sid='27183'>
<key rid='31415'>BASE64ENCODED...</key>
<key rid='12321'>BASE64ENCODED...</key>
<key prekey="true" rid='12321'>BASE64ENCODED...</key>
<!-- ... -->
<iv>BASE64ENCODED...</iv>
</header>
@ -198,29 +270,40 @@
<p>This KeyTransportElement can then be sent over any applicable transport mechanism.</p>
</section2>
<section2 topic='Receiving a message' anchor='usecases-receiving'>
<p>When an OMEMO element is received, the client MUST check whether there is a &lt;key&gt; element with an rid attribute matching its own device ID. If this is not the case, the element MUST be silently discarded. If such an element exists, the client checks whether the element's contents are a PreKeyWhisperMessage.</p>
<p>When an OMEMO element is received, the client MUST check whether there is a &lt;key&gt; element with an rid attribute matching its own device ID. If this is not the case, the element MUST be silently discarded. If such an element exists, the client checks whether the element's contents are a PreKeyOlmMessage.</p>
<p>If this is the case, a new session is built from this received element. The client SHOULD then republish their bundle information, replacing the used PreKey, such that it won't be used again by a different client. If the client already has a session with the sender's device, it MUST replace this session with the newly built session. The client MUST delete the private key belonging to the PreKey after use.</p>
<p>If the element's contents are a WhisperMessage, and the client has a session with the sender's device, it tries to decrypt the WhisperMessage using this session. If the decryption fails or if the element's contents are not a WhisperMessage either, the OMEMO element MUST be silently discarded.</p>
<p>If the OMEMO element contains a &lt;payload&gt;, it is an OMEMO message element. The client tries to decrypt the base 64 encoded contents using the key extracted from the &lt;key&gt; element. If the decryption fails, the client MUST silently discard the OMEMO message. If it succeeds, the decrypted contents are treated as the &lt;body&gt; of the received message.</p>
<p>If the element's contents are a OlmMessage, and the client has a session with the sender's device, it tries to decrypt the OlmMessage using this session. If the decryption fails or if the element's contents are not a OlmMessage either, the OMEMO element MUST be silently discarded.</p>
<p>If the OMEMO element contains a &lt;payload&gt;, it is an OMEMO message element. The client tries to decrypt the base64 encoded contents using the key and the authentication tag extracted from the &lt;key&gt; element. If the decryption fails, the client MUST silently discard the OMEMO message. If it succeeds, the decrypted contents are treated as the &lt;body&gt; of the received message.</p>
<p>If the OMEMO element does not contain a &lt;payload&gt;, the client has received a KeyTransportElement. The key extracted from the &lt;key&gt; element can then be used for other purposes (e.g. encrypted file transfer).</p>
</section2>
</section1>
<section1 topic='Business Rules' anchor='rules'>
<p>Before publishing a freshly generated Device ID for the first time, a device MUST check whether that Device ID already exists, and if so, generate a new one.</p>
<p>Clients SHOULD NOT immediately fetch the bundle and build a session as soon as a new device is announced. Before the first message is exchanged, the contact does not know which PreKey has been used (or, in fact, that any PreKey was used at all). As they have not had a chance to remove the used PreKey from their bundle announcement, this could lead to collisions where both Alice and Bob pick the same PreKey to build a session with a specific device. As each PreKey SHOULD only be used once, the party that sends their initial PreKeyWhisperMessage later loses this race condition. This means that they think they have a valid session with the contact, when in reality their messages MAY be ignored by the other end. By postponing building sessions, the chance of such issues occurring can be drastically reduced. It is RECOMMENDED to construct sessions only immediately before sending a message. </p>
<p>As there are no explicit error messages in this protocol, if a client does receive a PreKeyWhisperMessage using an invalid PreKey, they SHOULD respond with a KeyTransportElement, sent in a &lt;message&gt; using a PreKeyWhisperMessage. By building a new session with the original sender this way, the invalid session of the original sender will get overwritten with this newly created, valid session.</p>
<p>If a PreKeyWhisperMessage is received as part of a &xep0313; catch-up and used to establish a new session with the sender, the client SHOULD postpone deletion of the private key corresponding to the used PreKey until after MAM catch-up is completed. If this is done, the client MUST then also send a KeyTransportMessage using a PreKeyWhisperMessage before sending any payloads using this session, to trigger re-keying. (as above) This practice can mitigate the previously mentioned race condition by preventing message loss.</p>
<p>Clients SHOULD NOT immediately fetch the bundle and build a session as soon as a new device is announced. Before the first message is exchanged, the contact does not know which PreKey has been used (or, in fact, that any PreKey was used at all). As they have not had a chance to remove the used PreKey from their bundle announcement, this could lead to collisions where both Alice and Bob pick the same PreKey to build a session with a specific device. As each PreKey SHOULD only be used once, the party that sends their initial PreKeyOlmMessage later loses this race condition. This means that they think they have a valid session with the contact, when in reality their messages MAY be ignored by the other end. By postponing building sessions, the chance of such issues occurring can be drastically reduced. It is RECOMMENDED to construct sessions only immediately before sending a message. </p>
<p>As there are no explicit error messages in this protocol, if a client does receive a PreKeyOlmMessage using an invalid PreKey, they SHOULD respond with a KeyTransportElement, sent in a &lt;message&gt; using a PreKeyOlmMessage. By building a new session with the original sender this way, the invalid session of the original sender will get overwritten with this newly created, valid session.</p>
<p>If a PreKeyOlmMessage is received as part of a &xep0313; catch-up and used to establish a new session with the sender, the client SHOULD postpone deletion of the private key corresponding to the used PreKey until after MAM catch-up is completed. If this is done, the client MUST then also send a KeyTransportMessage using a PreKeyOlmMessage before sending any payloads using this session, to trigger re-keying. (as above) This practice can mitigate the previously mentioned race condition by preventing message loss.</p>
<p>As the asynchronous nature of OMEMO allows decryption at a later time to currently offline devices client SHOULD include a &xep0334; &lt;store /&gt; hint in their OMEMO messages. Otherwise, server implementations of &xep0313; will generally not retain OMEMO messages, since they do not contain a &lt;body /&gt;</p>
</section1>
<section1 topic='Implementation Notes' anchor='impl'>
<p>For details on axoltol, see the <a href='https://github.com/trevp/axolotl/wiki'>specification</a> and <a href='https://github.com/WhisperSystems/libaxolotl-java'>reference implementation.</a></p>
<p>The axolotl library's reference implementation (and presumably its ports to various other platforms) uses a trust model that doesn't work very well with OMEMO. For this reason it may be desirable to have the library consider all keys trusted, effectively disabling its trust management. This makes it necessary to implement trust handling oneself.</p>
<!-- TODO: I think this is still true? -->
<p>
The Olm library's reference implementation (and presumably its ports to
various other platforms) uses a trust model that doesn't work very well with
OMEMO. For this reason it may be desirable to have the library consider all
keys trusted, effectively disabling its trust management. This makes it
necessary to implement trust handling oneself.
</p>
</section1>
<section1 topic='Security Considerations' anchor='security'>
<p>Clients MUST NOT use a newly built session to transmit data without user intervention. If a client were to opportunistically start using sessions for sending without asking the user whether to trust a device first, an attacker could publish a fake device for this user, which would then receive copies of all messages sent by/to this user. A client MAY use such "not (yet) trusted" sessions for decryption of received messages, but in that case it SHOULD indicate the untrusted nature of such messages to the user.</p>
<p>When prompting the user for a trust decision regarding a key, the client SHOULD present the user with a fingerprint in the form of a hex string, QR code, or other unique representation, such that it can be compared by the user.</p>
<p>While it is RECOMMENDED that clients postpone private key deletion until after MAM catch-up and this standards mandates that clients MUST NOT use duplicate-PreKey sessions for sending, clients MAY delete such keys immediately for security reasons. For additional information on potential security impacts of this decision, refer to <note>Menezes, Alfred, and Berkant Ustaoglu. "On reusing ephemeral keys in Diffie-Hellman key agreement protocols." International Journal of Applied Cryptography 2, no. 2 (2010): 154-158.</note>.</p>
<p>In order to be able to handle out-of-order messages, the axolotl stack has to cache the keys belonging to "skipped" messages that have not been seen yet. It is up to the implementor to decide how long and how many of such keys to keep around.</p>
<p>
In order to be able to handle out-of-order messages, the Olm stack has to
cache the keys belonging to "skipped" messages that have not been seen yet.
It is up to the implementor to decide how long and how many of such keys to
keep around.
</p>
</section1>
<section1 topic='IANA Considerations' anchor='iana'>
<p>This document requires no interaction with the Internet Assigned Numbers Authority (IANA). </p>
@ -250,7 +333,8 @@
<xs:complexType>
<xs:sequence>
<xs:element name="key" type="xs:base64Binary" maxOccurs="unbounded">
<xs:attribute name="rid" type="xs:integer"/>
<xs:attribute name="rid" type="xs:integer" use="required"/>
<xs:attribute name="prekey" type="xs:boolean"/>
</xs:element>
<xs:element name="iv" type="xs:base64Binary"/>
</xs:complexType>
@ -262,7 +346,7 @@
<xs:complexType>
<xs:sequence>
<xs:element name="device" maxOccurs="unbounded">
<xs:attribute name="id" type="integer"/>
<xs:attribute name="id" type="integer" use="required"/>
</xs:element>
</xs:sequence>
</xs:complexType>
@ -280,7 +364,7 @@
<xs:complexType>
<xs:sequence>
<xs:element name="preKeyPublic" type="base64Binary" maxOccurs="unbounded">
<xs:attribute name="id" type="integer"/>
<xs:attribute name="id" type="integer" use="required"/>
</xs:element>
</xs:sequence>
</xs:complexType>
@ -294,6 +378,6 @@
</section1>
<section1 topic='Acknowledgements' anchor='ack'>
<p>Big thanks to Daniel Gultsch for mentoring me during the development of this protocol. Thanks to Thijs Alkemade and Cornelius Aschermann for talking through some of the finer points of the protocol with me. And lastly I would also like to thank Sam Whited, Holger Weiss, and Florian Schmaus for their input on the standard.</p>
<p>Big thanks to Daniel Gultsch for mentoring me during the development of this protocol. Thanks to Thijs Alkemade and Cornelius Aschermann for talking through some of the finer points of the protocol with me. And lastly I would also like to thank Sam Whited, Holger Weiss, and Florian Schmaus for their input on the standard.</p>
</section1>
</xep>