1/* Copyright 2015 OpenMarket Ltd
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <cstdint>
17
18#include "olm/crypto.h"
19#include "olm/list.hh"
20#include "olm/error.h"
21
22// Note: exports in this file are only for unit tests. Nobody else should be
23// using this externally
24#include "olm/olm_export.h"
25
26struct _olm_cipher;
27
28namespace olm {
29
30/** length of a shared key: the root key R(i), chain key C(i,j), and message key
31 * M(i,j)). They are all only used to stuff into HMACs, so could be any length
32 * for that. The chain key and message key are both derived from SHA256
33 * operations, so their length is determined by that. */
34const std::size_t OLM_SHARED_KEY_LENGTH = SHA256_OUTPUT_LENGTH;
35
36typedef std::uint8_t SharedKey[OLM_SHARED_KEY_LENGTH];
37
38struct ChainKey {
39 std::uint32_t index;
40 SharedKey key;
41};
42
43struct MessageKey {
44 std::uint32_t index;
45 SharedKey key;
46};
47
48
49struct SenderChain {
50 _olm_curve25519_key_pair ratchet_key;
51 ChainKey chain_key;
52};
53
54
55struct ReceiverChain {
56 _olm_curve25519_public_key ratchet_key;
57 ChainKey chain_key;
58};
59
60
61struct SkippedMessageKey {
62 _olm_curve25519_public_key ratchet_key;
63 MessageKey message_key;
64};
65
66
67static std::size_t const MAX_RECEIVER_CHAINS = 5;
68static std::size_t const MAX_SKIPPED_MESSAGE_KEYS = 40;
69
70
71struct KdfInfo {
72 std::uint8_t const * root_info;
73 std::size_t root_info_length;
74 std::uint8_t const * ratchet_info;
75 std::size_t ratchet_info_length;
76};
77
78
79struct OLM_EXPORT Ratchet {
80
81 Ratchet(
82 KdfInfo const & kdf_info,
83 _olm_cipher const *ratchet_cipher
84 );
85
86 /** A some strings identifying the application to feed into the KDF. */
87 KdfInfo const & kdf_info;
88
89 /** The AEAD cipher to use for encrypting messages. */
90 _olm_cipher const *ratchet_cipher;
91
92 /** The last error that happened encrypting or decrypting a message. */
93 OlmErrorCode last_error;
94
95 /** The root key is used to generate chain keys from the ephemeral keys.
96 * A new root_key derived each time a new chain is started. */
97 SharedKey root_key;
98
99 /** The sender chain is used to send messages. Each time a new ephemeral
100 * key is received from the remote server we generate a new sender chain
101 * with a new ephemeral key when we next send a message. */
102 List<SenderChain, 1> sender_chain;
103
104 /** The receiver chain is used to decrypt received messages. We store the
105 * last few chains so we can decrypt any out of order messages we haven't
106 * received yet. */
107 List<ReceiverChain, MAX_RECEIVER_CHAINS> receiver_chains;
108
109 /** List of message keys we've skipped over when advancing the receiver
110 * chain. */
111 List<SkippedMessageKey, MAX_SKIPPED_MESSAGE_KEYS> skipped_message_keys;
112
113 /** Initialise the session using a shared secret and the public part of the
114 * remote's first ratchet key */
115 void initialise_as_bob(
116 std::uint8_t const * shared_secret, std::size_t shared_secret_length,
117 _olm_curve25519_public_key const & their_ratchet_key
118 );
119
120 /** Initialise the session using a shared secret and the public/private key
121 * pair for the first ratchet key */
122 void initialise_as_alice(
123 std::uint8_t const * shared_secret, std::size_t shared_secret_length,
124 _olm_curve25519_key_pair const & our_ratchet_key
125 );
126
127 /** The number of bytes of output the encrypt method will write for
128 * a given message length. */
129 std::size_t encrypt_output_length(
130 std::size_t plaintext_length
131 ) const;
132
133 /** The number of bytes of random data the encrypt method will need to
134 * encrypt a message. This will be 32 bytes if the session needs to
135 * generate a new ephemeral key, or will be 0 bytes otherwise.*/
136 std::size_t encrypt_random_length() const;
137
138 /** Encrypt some plain-text. Returns the length of the encrypted message
139 * or std::size_t(-1) on failure. On failure last_error will be set with
140 * an error code. The last_error will be NOT_ENOUGH_RANDOM if the number
141 * of random bytes is too small. The last_error will be
142 * OUTPUT_BUFFER_TOO_SMALL if the output buffer is too small. */
143 std::size_t encrypt(
144 std::uint8_t const * plaintext, std::size_t plaintext_length,
145 std::uint8_t const * random, std::size_t random_length,
146 std::uint8_t * output, std::size_t max_output_length
147 );
148
149 /** An upper bound on the number of bytes of plain-text the decrypt method
150 * will write for a given input message length. */
151 std::size_t decrypt_max_plaintext_length(
152 std::uint8_t const * input, std::size_t input_length
153 );
154
155 /** Decrypt a message. Returns the length of the decrypted plain-text or
156 * std::size_t(-1) on failure. On failure last_error will be set with an
157 * error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the
158 * plain-text buffer is too small. The last_error will be
159 * BAD_MESSAGE_VERSION if the message was encrypted with an unsupported
160 * version of the protocol. The last_error will be BAD_MESSAGE_FORMAT if
161 * the message headers could not be decoded. The last_error will be
162 * BAD_MESSAGE_MAC if the message could not be verified */
163 std::size_t decrypt(
164 std::uint8_t const * input, std::size_t input_length,
165 std::uint8_t * plaintext, std::size_t max_plaintext_length
166 );
167};
168
169
170std::size_t pickle_length(
171 Ratchet const & value
172);
173
174
175std::uint8_t * pickle(
176 std::uint8_t * pos,
177 Ratchet const & value
178);
179
180
181std::uint8_t const * unpickle(
182 std::uint8_t const * pos, std::uint8_t const * end,
183 Ratchet & value,
184 bool includes_chain_index
185);
186
187
188} // namespace olm
189