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 | |
26 | struct _olm_cipher; |
27 | |
28 | namespace 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. */ |
34 | const std::size_t OLM_SHARED_KEY_LENGTH = SHA256_OUTPUT_LENGTH; |
35 | |
36 | typedef std::uint8_t SharedKey[OLM_SHARED_KEY_LENGTH]; |
37 | |
38 | struct ChainKey { |
39 | std::uint32_t index; |
40 | SharedKey key; |
41 | }; |
42 | |
43 | struct MessageKey { |
44 | std::uint32_t index; |
45 | SharedKey key; |
46 | }; |
47 | |
48 | |
49 | struct SenderChain { |
50 | _olm_curve25519_key_pair ratchet_key; |
51 | ChainKey chain_key; |
52 | }; |
53 | |
54 | |
55 | struct ReceiverChain { |
56 | _olm_curve25519_public_key ratchet_key; |
57 | ChainKey chain_key; |
58 | }; |
59 | |
60 | |
61 | struct SkippedMessageKey { |
62 | _olm_curve25519_public_key ratchet_key; |
63 | MessageKey message_key; |
64 | }; |
65 | |
66 | |
67 | static std::size_t const MAX_RECEIVER_CHAINS = 5; |
68 | static std::size_t const MAX_SKIPPED_MESSAGE_KEYS = 40; |
69 | |
70 | |
71 | struct 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 | |
79 | struct 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 | |
170 | std::size_t pickle_length( |
171 | Ratchet const & value |
172 | ); |
173 | |
174 | |
175 | std::uint8_t * pickle( |
176 | std::uint8_t * pos, |
177 | Ratchet const & value |
178 | ); |
179 | |
180 | |
181 | std::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 | |