olm.rst 14.3 KB
Newer Older
Mark Haines's avatar
Mark Haines committed
1
2
Olm: A Cryptographic Ratchet
============================
3

4
An implementation of the double cryptographic ratchet described by
Richard van der Hoff's avatar
Richard van der Hoff committed
5
https://github.com/trevp/double_ratchet/wiki.
6

7
8
9
10
11
12
13
14
15
16
Notation
--------

This document uses :math:`\parallel` to represent string concatenation. When
:math:`\parallel` appears on the right hand side of an :math:`=` it means that
the inputs are concatenated. When :math:`\parallel` appears on the left hand
side of an :math:`=` it means that the output is split.

When this document uses :math:`ECDH\left(K_A,\,K_B\right)` it means that each
party computes a Diffie-Hellman agreement using their private key and the
17
remote party's public key.
18
So party :math:`A` computes :math:`ECDH\left(K_B_public,\,K_A_private\right)`
Richard van der Hoff's avatar
Richard van der Hoff committed
19
and party :math:`B` computes :math:`ECDH\left(K_A_public,\,K_B_private\right)`.
20

21
22
23
24
25
Where this document uses :math:`HKDF\left(salt,\,IKM,\,info,\,L\right)` it
refers to the `HMAC-based key derivation function`_ with a salt value of
:math:`salt`, input key material of :math:`IKM`, context string :math:`info`,
and output keying material length of :math:`L` bytes.

26
27
28
29
30
31
The Olm Algorithm
-----------------

Initial setup
~~~~~~~~~~~~~

32
The setup takes four Curve25519_ inputs: Identity keys for Alice and Bob,
Mark Haines's avatar
Mark Haines committed
33
:math:`I_A` and :math:`I_B`, and ephemeral keys for Alice and Bob,
34
:math:`E_A` and :math:`E_B`. A shared secret, :math:`S`, is generated using
35
36
37
38
`Triple Diffie-Hellman`_. The initial 256 bit root key, :math:`R_0`, and 256
bit chain key, :math:`C_{0,0}`, are derived from the shared secret using an
HMAC-based Key Derivation Function using SHA-256_ as the hash function
(HKDF-SHA-256_) with default salt and ``"OLM_ROOT"`` as the info.
39
40
41
42
43

.. math::
    \begin{align}
        S&=ECDH\left(I_A,\,E_B\right)\;\parallel\;ECDH\left(E_A,\,I_B\right)\;
            \parallel\;ECDH\left(E_A,\,E_B\right)\\
44
45
        R_0\;\parallel\;C_{0,0}&=
             HKDF\left(0,\,S,\,\text{"OLM\_ROOT"},\,64\right)
46
47
48
49
50
51
    \end{align}

Advancing the root key
~~~~~~~~~~~~~~~~~~~~~~

Advancing a root key takes the previous root key, :math:`R_{i-1}`, and two
Mark Haines's avatar
Mark Haines committed
52
53
54
55
Curve25519 inputs: the previous ratchet key, :math:`T_{i-1}`, and the current
ratchet key :math:`T_i`. The even ratchet keys are generated by Alice.
The odd ratchet keys are generated by Bob. A shared secret is generated
using Diffie-Hellman on the ratchet keys. The next root key, :math:`R_i`, and
56
57
58
chain key, :math:`C_{i,0}`, are derived from the shared secret using
HKDF-SHA-256_ using :math:`R_{i-1}` as the salt and ``"OLM_RATCHET"`` as the
info.
59

Mark Haines's avatar
Mark Haines committed
60
61
62
63
.. math::
    \begin{align}
        R_i\;\parallel\;C_{i,0}&=HKDF\left(
            R_{i-1},\,
64
65
66
            ECDH\left(T_{i-1},\,T_i\right),\,
            \text{"OLM\_RATCHET"},\,
            64
Mark Haines's avatar
Mark Haines committed
67
68
69
70
71
72
73
        \right)
    \end{align}


Advancing the chain key
~~~~~~~~~~~~~~~~~~~~~~~

74
Advancing a chain key takes the previous chain key, :math:`C_{i,j-i}`. The next
75
76
chain key, :math:`C_{i,j}`, is the HMAC-SHA-256_ of ``"\x02"`` using the
previous chain key as the key.
Mark Haines's avatar
Mark Haines committed
77
78
79
80
81
82
83
84
85
86

.. math::
     \begin{align}
        C_{i,j}&=HMAC\left(C_{i,j-1},\,\text{"\textbackslash x02"}\right)
    \end{align}

Creating a message key
~~~~~~~~~~~~~~~~~~~~~~

Creating a message key takes the current chain key, :math:`C_{i,j}`. The
87
88
89
message key, :math:`M_{i,j}`, is the HMAC-SHA-256_ of ``"\x01"`` using the
current chain key as the key. The message keys where :math:`i` is even are used
by Alice to encrypt messages. The message keys where :math:`i` is odd are used
Mark Haines's avatar
Mark Haines committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
by Bob to encrypt messages.

.. math::
    \begin{align}
        M_{i,j}&=HMAC\left(C_{i,j},\,\text{"\textbackslash x01"}\right)
    \end{align}


The Olm Protocol
----------------

Creating an outbound session
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

104
105
Bob publishes the public parts of his identity key, :math:`I_B`, and some
single-use one-time keys :math:`E_B`.
Mark Haines's avatar
Mark Haines committed
106
107

Alice downloads Bob's identity key, :math:`I_B`, and a one-time key,
108
109
110
:math:`E_B`. She generates a new single-use key, :math:`E_A`, and computes a
root key, :math:`R_0`, and a chain key :math:`C_{0,0}`. She also generates a
new ratchet key :math:`T_0`.
Mark Haines's avatar
Mark Haines committed
111
112
113
114

Sending the first pre-key messages
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

115
116
117
118
Alice computes a message key, :math:`M_{0,j}`, and a new chain key,
:math:`C_{0,j+1}`, using the current chain key. She replaces the current chain
key with the new one.

Mark Haines's avatar
Mark Haines committed
119
Alice encrypts her plain-text with the message key, :math:`M_{0,j}`, using an
120
authenticated encryption scheme (see below) to get a cipher-text,
121
122
123
124
125
126
127
128
129
:math:`X_{0,j}`.

She then sends the following to Bob:
 * The public part of her identity key, :math:`I_A`
 * The public part of her single-use key, :math:`E_A`
 * The public part of Bob's single-use key, :math:`E_B`
 * The current chain index, :math:`j`
 * The public part of her ratchet key, :math:`T_0`
 * The cipher-text, :math:`X_{0,j}`
Mark Haines's avatar
Mark Haines committed
130
131
132
133
134
135
136

Alice will continue to send pre-key messages until she receives a message from
Bob.

Creating an inbound session from a pre-key message
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

137
Bob receives a pre-key message as above.
138
139
140
141
142
143
144

Bob looks up the private part of his single-use key, :math:`E_B`. He can now
compute the root key, :math:`R_0`, and the chain key, :math:`C_{0,0}`, from
:math:`I_A`, :math:`E_A`, :math:`I_B`, and :math:`E_B`.

Bob then advances the chain key :math:`j` times, to compute the chain key used
by the message, :math:`C_{0,j}`. He now creates the
Mark Haines's avatar
Mark Haines committed
145
message key, :math:`M_{0,j}`, and attempts to decrypt the cipher-text,
Mark Haines's avatar
Mark Haines committed
146
:math:`X_{0,j}`. If the cipher-text's authentication is correct then Bob can
147
discard the private part of his single-use one-time key, :math:`E_B`.
Mark Haines's avatar
Mark Haines committed
148

149
150
151
Bob stores Alice's initial ratchet key, :math:`T_0`, until he wants to
send a message.

152
153
154
155
156
Sending normal messages
~~~~~~~~~~~~~~~~~~~~~~~

Once a message has been received from the other side, a session is considered
established, and a more compact form is used.
Mark Haines's avatar
Mark Haines committed
157

158
159
To send a message, the user checks if they have a sender chain key,
:math:`C_{i,j}`. Alice uses chain keys where :math:`i` is even. Bob uses chain
Mark Haines's avatar
Mark Haines committed
160
keys where :math:`i` is odd. If the chain key doesn't exist then a new ratchet
161
162
163
164
165
key :math:`T_i` is generated and a new root key :math:`R_i` and chain key
:math:`C_{i,0}` are computed using :math:`R_{i-1}`, :math:`T_{i-1}` and
:math:`T_i`.

A message key,
Mark Haines's avatar
Mark Haines committed
166
167
168
:math:`M_{i,j}` is computed from the current chain key, :math:`C_{i,j}`, and
the chain key is replaced with the next chain key, :math:`C_{i,j+1}`. The
plain-text is encrypted with :math:`M_{i,j}`, using an authenticated encryption
169
170
171
172
173
174
scheme (see below) to get a cipher-text, :math:`X_{i,j}`.

The user then sends the following to the recipient:
 * The current chain index, :math:`j`
 * The public part of the current ratchet key, :math:`T_i`
 * The cipher-text, :math:`X_{i,j}`
Mark Haines's avatar
Mark Haines committed
175
176
177
178

Receiving messages
~~~~~~~~~~~~~~~~~~

179
The user receives a message as above with the sender's current chain index, :math:`j`,
180
181
182
the sender's ratchet key, :math:`T_i`, and the cipher-text, :math:`X_{i,j}`.

The user checks if they have a receiver chain with the correct
Mark Haines's avatar
Mark Haines committed
183
:math:`i` by comparing the ratchet key, :math:`T_i`. If the chain doesn't exist
184
185
186
187
188
then they compute a new root key, :math:`R_i`, and a new receiver chain, with
chain key :math:`C_{i,0}`, using :math:`R_{i-1}`, :math:`T_{i-1}` and
:math:`T_i`.

If the :math:`j` of the message is less than
Mark Haines's avatar
Mark Haines committed
189
190
191
192
193
the current chain index on the receiver then the message may only be decrypted
if the receiver has stored a copy of the message key :math:`M_{i,j}`. Otherwise
the receiver computes the chain key, :math:`C_{i,j}`. The receiver computes the
message key, :math:`M_{i,j}`, from the chain key and attempts to decrypt the
cipher-text, :math:`X_{i,j}`.
194

Mark Haines's avatar
Mark Haines committed
195
If the decryption succeeds the receiver updates the chain key for :math:`T_i`
Mark Haines's avatar
Mark Haines committed
196
197
198
199
with :math:`C_{i,j+1}` and stores the message keys that were skipped in the
process so that they can decode out of order messages. If the receiver created
a new receiver chain then they discard their current sender chain so that
they will create a new chain when they next send a message.
200
201
202
203

The Olm Message Format
----------------------

204
205
206
Olm uses two types of messages. The underlying transport protocol must provide
a means for recipients to distinguish between them.

207
208
209
210
211
212
213
214
215
216
217
218
Normal Messages
~~~~~~~~~~~~~~~

Olm messages start with a one byte version followed by a variable length
payload followed by a fixed length message authentication code.

.. code::

   +--------------+------------------------------------+-----------+
   | Version Byte | Payload Bytes                      | MAC Bytes |
   +--------------+------------------------------------+-----------+

219
The version byte is ``"\x03"``.
Mark Haines's avatar
Mark Haines committed
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
The payload consists of key-value pairs where the keys are integers and the
values are integers and strings. The keys are encoded as a variable length
integer tag where the 3 lowest bits indicates the type of the value:
0 for integers, 2 for strings. If the value is an integer then the tag is
followed by the value encoded as a variable length integer. If the value is
a string then the tag is followed by the length of the string encoded as
a variable length integer followed by the string itself.

Olm uses a variable length encoding for integers. Each integer is encoded as a
sequence of bytes with the high bit set followed by a byte with the high bit
clear. The seven low bits of each byte store the bits of the integer. The least
significant bits are stored in the first byte.

=========== ===== ======== ================================================
    Name     Tag    Type                     Meaning
=========== ===== ======== ================================================
237
238
Ratchet-Key  0x0A String   The public part of the ratchet key, :math:`T_{i}`,
                           of the message
Mark Haines's avatar
Mark Haines committed
239
Chain-Index  0x10 Integer  The chain index, :math:`j`, of the message
240
241
242
Cipher-Text  0x22 String   The cipher-text, :math:`X_{i,j}`, of the message
=========== ===== ======== ================================================

Mark Haines's avatar
Mark Haines committed
243
The length of the MAC is determined by the authenticated encryption algorithm
244
being used. (Olm version 1 uses HMAC-SHA-256, truncated to 8 bytes). The
245
MAC protects all of the bytes preceding the MAC.
Mark Haines's avatar
Mark Haines committed
246
247
248
249
250
251
252
253
254
255
256
257
258

Pre-Key Messages
~~~~~~~~~~~~~~~~

Olm pre-key messages start with a one byte version followed by a variable
length payload.

.. code::

   +--------------+------------------------------------+
   | Version Byte | Payload Bytes                      |
   +--------------+------------------------------------+

259
The version byte is ``"\x03"``.
Mark Haines's avatar
Mark Haines committed
260
261
262
263
264
265

The payload uses the same key-value format as for normal messages.

============ ===== ======== ================================================
    Name      Tag    Type                     Meaning
============ ===== ======== ================================================
266
267
268
269
270
271
One-Time-Key  0x0A String   The public part of Bob's single-use key,
                            :math:`E_b`.
Base-Key      0x12 String   The public part of Alice's single-use key,
                            :math:`E_a`.
Identity-Key  0x1A String   The public part of Alice's identity key,
                            :math:`I_a`.
Mark Haines's avatar
Mark Haines committed
272
273
274
275
276
277
Message       0x22 String   An embedded Olm message with its own version and
                            MAC.
============ ===== ======== ================================================

Olm Authenticated Encryption
----------------------------
278

Mark Haines's avatar
Mark Haines committed
279
280
Version 1
~~~~~~~~~
281

Matthew Hodgson's avatar
Matthew Hodgson committed
282
Version 1 of Olm uses AES-256_ in CBC_ mode with `PKCS#7`_ padding for
283
284
285
286
encryption and HMAC-SHA-256_ (truncated to 64 bits) for authentication.  The
256 bit AES key, 256 bit HMAC key, and 128 bit AES IV are derived from the
message key using HKDF-SHA-256_ using the default salt and an info of
``"OLM_KEYS"``.
287
288
289
290
291

.. math::

    \begin{align}
    AES\_KEY_{i,j}\;\parallel\;HMAC\_KEY_{i,j}\;\parallel\;AES\_IV_{i,j}
292
        &= HKDF\left(0,\,M_{i,j},\text{"OLM\_KEYS"},\,80\right) \\
293
    \end{align}
294

295
296
297
298
The plain-text is encrypted with AES-256, using the key :math:`AES\_KEY_{i,j}`
and the IV :math:`AES\_IV_{i,j}` to give the cipher-text, :math:`X_{i,j}`.

Then the entire message (including the Version Byte and all Payload Bytes) are
299
passed through HMAC-SHA-256. The first 8 bytes of the MAC are appended to the message.
300

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
Message authentication concerns
-------------------------------

To avoid unknown key-share attacks, the application must include identifying
data for the sending and receiving user in the plain-text of (at least) the
pre-key messages. Such data could be a user ID, a telephone number;
alternatively it could be the public part of a keypair which the relevant user
has proven ownership of.

.. admonition:: Example attacks

   1. Alice publishes her public Curve25519 identity key, :math:`I_A`. Eve
      publishes the same identity key, claiming it as her own. Bob downloads
      Eve's keys, and associates :math:`I_A` with Eve. Alice sends a message to
      Bob; Eve intercepts it before forwarding it to Bob. Bob believes the
      message came from Eve rather than Alice.

      This is prevented if Alice includes her user ID in the plain-text of the
      pre-key message, so that Bob can see that the message was sent by Alice
      originally.

   2. Bob publishes his public Curve25519 identity key, :math:`I_B`. Eve
      publishes the same identity key, claiming it as her own. Alice downloads
      Eve's keys, and associates :math:`I_B` with Eve. Alice sends a message to
      Eve; Eve cannot decrypt it, but forwards it to Bob. Bob believes the
      Alice sent the message to him, wheras Alice intended it to go to Eve.

      This is prevented by Alice including the user ID of the intended recpient
      (Eve) in the plain-text of the pre-key message. Bob can now tell that the
      message was meant for Eve rather than him.

332
333
334
335
336
337
338
339
340
341
342
343
344
345
IPR
---

The Olm specification (this document) is hereby placed in the public domain.

Feedback
--------

Can be sent to mark at matrix.org.

Acknowledgements
----------------

The ratchet that Olm implements was designed by Trevor Perrin and Moxie
346
347
Marlinspike - details at https://github.com/trevp/double_ratchet/wiki.  Olm is
an entirely new implementation written by the Matrix.org team.
348

349
350
.. _`Curve25519`: http://cr.yp.to/ecdh.html
.. _`Triple Diffie-Hellman`: https://whispersystems.org/blog/simplifying-otr-deniability/
351
.. _`HMAC-based key derivation function`: https://tools.ietf.org/html/rfc5869
352
353
354
355
356
.. _`HKDF-SHA-256`: https://tools.ietf.org/html/rfc5869
.. _`HMAC-SHA-256`: https://tools.ietf.org/html/rfc2104
.. _`SHA-256`: https://tools.ietf.org/html/rfc6234
.. _`AES-256`: http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
.. _`CBC`: http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
Matthew Hodgson's avatar
Matthew Hodgson committed
357
.. _`PKCS#7`: https://tools.ietf.org/html/rfc2315