1 module matrix.olm;
2 
3 struct OlmAccount;
4 struct OlmSession;
5 struct OlmUtility;
6 
7 import std.file : read;
8 
9 char[] read_random(size_t rnd_len) {
10 	return cast(char[]) read("/dev/urandom", rnd_len);
11 }
12 
13 extern (C):
14 // copy&pasted from olm.h
15 
16 /** Get the version number of the library.
17  * Arguments will be updated if non-null.
18  */
19 void olm_get_library_version(ubyte *major, ubyte *minor, ubyte *patch);
20 
21 /** The size of an account object in bytes */
22 size_t olm_account_size();
23 
24 /** The size of a session object in bytes */
25 size_t olm_session_size();
26 
27 /** The size of a utility object in bytes */
28 size_t olm_utility_size();
29 
30 /** Initialise an account object using the supplied memory
31  *  The supplied memory must be at least olm_account_size() bytes */
32 OlmAccount * olm_account(
33     void * memory
34 );
35 
36 /** Initialise a session object using the supplied memory
37  *  The supplied memory must be at least olm_session_size() bytes */
38 OlmSession * olm_session(
39     void * memory
40 );
41 
42 /** Initialise a utility object using the supplied memory
43  *  The supplied memory must be at least olm_utility_size() bytes */
44 OlmUtility * olm_utility(
45     void * memory
46 );
47 
48 /** The value that olm will return from a function if there was an error */
49 size_t olm_error();
50 
51 /** A null terminated string describing the most recent error to happen to an
52  * account */
53 const(char*) olm_account_last_error(
54     OlmAccount * account
55 );
56 
57 /** A null terminated string describing the most recent error to happen to a
58  * session */
59 const(char*) olm_session_last_error(
60     OlmSession * session
61 );
62 
63 /** A null terminated string describing the most recent error to happen to a
64  * utility */
65 const(char*) olm_utility_last_error(
66     OlmUtility * utility
67 );
68 
69 /** Clears the memory used to back this account */
70 size_t olm_clear_account(
71     OlmAccount * account
72 );
73 
74 /** Clears the memory used to back this session */
75 size_t olm_clear_session(
76     OlmSession * session
77 );
78 
79 /** Clears the memory used to back this utility */
80 size_t olm_clear_utility(
81     OlmUtility * utility
82 );
83 
84 /** Returns the number of bytes needed to store an account */
85 size_t olm_pickle_account_length(
86     OlmAccount * account
87 );
88 
89 /** Returns the number of bytes needed to store a session */
90 size_t olm_pickle_session_length(
91     OlmSession * session
92 );
93 
94 /** Stores an account as a base64 string. Encrypts the account using the
95  * supplied key. Returns the length of the pickled account on success.
96  * Returns olm_error() on failure. If the pickle output buffer
97  * is smaller than olm_pickle_account_length() then
98  * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
99 size_t olm_pickle_account(
100     OlmAccount * account,
101     const void * key, size_t key_length,
102     void * pickled, size_t pickled_length
103 );
104 
105 /** Stores a session as a base64 string. Encrypts the session using the
106  * supplied key. Returns the length of the pickled session on success.
107  * Returns olm_error() on failure. If the pickle output buffer
108  * is smaller than olm_pickle_session_length() then
109  * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
110 size_t olm_pickle_session(
111     OlmSession * session,
112     const void * key, size_t key_length,
113     void * pickled, size_t pickled_length
114 );
115 
116 /** Loads an account from a pickled base64 string. Decrypts the account using
117  * the supplied key. Returns olm_error() on failure. If the key doesn't
118  * match the one used to encrypt the account then olm_account_last_error()
119  * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
120  * olm_account_last_error() will be "INVALID_BASE64". The input pickled
121  * buffer is destroyed */
122 size_t olm_unpickle_account(
123     OlmAccount * account,
124     const(void)* key, size_t key_length,
125     void * pickled, size_t pickled_length
126 );
127 
128 /** Loads a session from a pickled base64 string. Decrypts the session using
129  * the supplied key. Returns olm_error() on failure. If the key doesn't
130  * match the one used to encrypt the account then olm_session_last_error()
131  * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
132  * olm_session_last_error() will be "INVALID_BASE64". The input pickled
133  * buffer is destroyed */
134 size_t olm_unpickle_session(
135     OlmSession * session,
136     const void * key, size_t key_length,
137     void * pickled, size_t pickled_length
138 );
139 
140 /** The number of random bytes needed to create an account.*/
141 size_t olm_create_account_random_length(
142     OlmAccount * account
143 );
144 
145 /** Creates a new account. Returns olm_error() on failure. If weren't
146  * enough random bytes then olm_account_last_error() will be
147  * "NOT_ENOUGH_RANDOM" */
148 size_t olm_create_account(
149     OlmAccount * account,
150     void * random, size_t random_length
151 );
152 
153 /** The size of the output buffer needed to hold the identity keys */
154 size_t olm_account_identity_keys_length(
155     OlmAccount * account
156 );
157 
158 /** Writes the public parts of the identity keys for the account into the
159  * identity_keys output buffer. Returns olm_error() on failure. If the
160  * identity_keys buffer was too small then olm_account_last_error() will be
161  * "OUTPUT_BUFFER_TOO_SMALL". */
162 size_t olm_account_identity_keys(
163     OlmAccount * account,
164     void * identity_keys, size_t identity_key_length
165 );
166 
167 
168 /** The length of an ed25519 signature encoded as base64. */
169 size_t olm_account_signature_length(
170     OlmAccount * account
171 );
172 
173 /** Signs a message with the ed25519 key for this account. Returns olm_error()
174  * on failure. If the signature buffer was too small then
175  * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
176 size_t olm_account_sign(
177     OlmAccount * account,
178     const void * message, size_t message_length,
179     void * signature, size_t signature_length
180 );
181 
182 /** The size of the output buffer needed to hold the one time keys */
183 size_t olm_account_one_time_keys_length(
184     OlmAccount * account
185 );
186 
187 /** Writes the public parts of the unpublished one time keys for the account
188  * into the one_time_keys output buffer.
189  * <p>
190  * The returned data is a JSON-formatted object with the single property
191  * <tt>curve25519</tt>, which is itself an object mapping key id to
192  * base64-encoded Curve25519 key. For example:
193  * <pre>
194  * {
195  *     curve25519: {
196  *         "AAAAAA": "wo76WcYtb0Vk/pBOdmduiGJ0wIEjW4IBMbbQn7aSnTo",
197  *         "AAAAAB": "LRvjo46L1X2vx69sS9QNFD29HWulxrmW11Up5AfAjgU"
198  *     }
199  * }
200  * </pre>
201  * Returns olm_error() on failure.
202  * <p>
203  * If the one_time_keys buffer was too small then olm_account_last_error()
204  * will be "OUTPUT_BUFFER_TOO_SMALL". */
205 size_t olm_account_one_time_keys(
206     OlmAccount * account,
207     void * one_time_keys, size_t one_time_keys_length
208 );
209 
210 /** Marks the current set of one time keys as being published. */
211 size_t olm_account_mark_keys_as_published(
212     OlmAccount * account
213 );
214 
215 /** The largest number of one time keys this account can store. */
216 size_t olm_account_max_number_of_one_time_keys(
217     OlmAccount * account
218 );
219 
220 /** The number of random bytes needed to generate a given number of new one
221  * time keys. */
222 size_t olm_account_generate_one_time_keys_random_length(
223     OlmAccount * account,
224     size_t number_of_keys
225 );
226 
227 /** Generates a number of new one time keys. If the total number of keys stored
228  * by this account exceeds max_number_of_one_time_keys() then the old keys are
229  * discarded. Returns olm_error() on error. If the number of random bytes is
230  * too small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */
231 size_t olm_account_generate_one_time_keys(
232     OlmAccount * account,
233     size_t number_of_keys,
234     void * random, size_t random_length
235 );
236 
237 /** The number of random bytes needed to create an outbound session */
238 size_t olm_create_outbound_session_random_length(
239     OlmSession * session
240 );
241 
242 /** Creates a new out-bound session for sending messages to a given identity_key
243  * and one_time_key. Returns olm_error() on failure. If the keys couldn't be
244  * decoded as base64 then olm_session_last_error() will be "INVALID_BASE64"
245  * If there weren't enough random bytes then olm_session_last_error() will
246  * be "NOT_ENOUGH_RANDOM". */
247 size_t olm_create_outbound_session(
248     OlmSession * session,
249     OlmAccount * account,
250     const void * their_identity_key, size_t their_identity_key_length,
251     const void * their_one_time_key, size_t their_one_time_key_length,
252     void * random, size_t random_length
253 );
254 
255 /** Create a new in-bound session for sending/receiving messages from an
256  * incoming PRE_KEY message. Returns olm_error() on failure. If the base64
257  * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
258  * If the message was for an unsupported protocol version then
259  * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
260  * couldn't be decoded then then olm_session_last_error() will be
261  * "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time
262  * key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */
263 size_t olm_create_inbound_session(
264     OlmSession * session,
265     OlmAccount * account,
266     void * one_time_key_message, size_t message_length
267 );
268 
269 /** Create a new in-bound session for sending/receiving messages from an
270  * incoming PRE_KEY message. Returns olm_error() on failure. If the base64
271  * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
272  * If the message was for an unsupported protocol version then
273  * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
274  * couldn't be decoded then then olm_session_last_error() will be
275  * "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time
276  * key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */
277 size_t olm_create_inbound_session_from(
278     OlmSession * session,
279     OlmAccount * account,
280     const void * their_identity_key, size_t their_identity_key_length,
281     void * one_time_key_message, size_t message_length
282 );
283 
284 /** The length of the buffer needed to return the id for this session. */
285 size_t olm_session_id_length(
286     OlmSession * session
287 );
288 
289 /** An identifier for this session. Will be the same for both ends of the
290  * conversation. If the id buffer is too small then olm_session_last_error()
291  * will be "OUTPUT_BUFFER_TOO_SMALL". */
292 size_t olm_session_id(
293     OlmSession * session,
294     void * id, size_t id_length
295 );
296 
297 int olm_session_has_received_message(
298     OlmSession *session
299 );
300 
301 /** Checks if the PRE_KEY message is for this in-bound session. This can happen
302  * if multiple messages are sent to this account before this account sends a
303  * message in reply. Returns 1 if the session matches. Returns 0 if the session
304  * does not match. Returns olm_error() on failure. If the base64
305  * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
306  * If the message was for an unsupported protocol version then
307  * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
308  * couldn't be decoded then then olm_session_last_error() will be
309  * "BAD_MESSAGE_FORMAT". */
310 size_t olm_matches_inbound_session(
311     OlmSession * session,
312     void * one_time_key_message, size_t message_length
313 );
314 
315 /** Checks if the PRE_KEY message is for this in-bound session. This can happen
316  * if multiple messages are sent to this account before this account sends a
317  * message in reply. Returns 1 if the session matches. Returns 0 if the session
318  * does not match. Returns olm_error() on failure. If the base64
319  * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
320  * If the message was for an unsupported protocol version then
321  * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
322  * couldn't be decoded then then olm_session_last_error() will be
323  * "BAD_MESSAGE_FORMAT". */
324 size_t olm_matches_inbound_session_from(
325     OlmSession * session,
326     const void * their_identity_key, size_t their_identity_key_length,
327     void * one_time_key_message, size_t message_length
328 );
329 
330 /** Removes the one time keys that the session used from the account. Returns
331  * olm_error() on failure. If the account doesn't have any matching one time
332  * keys then olm_account_last_error() will be "BAD_MESSAGE_KEY_ID". */
333 size_t olm_remove_one_time_keys(
334     OlmAccount * account,
335     OlmSession * session
336 );
337 
338 /** The type of the next message that olm_encrypt() will return. Returns
339  * OLM_MESSAGE_TYPE_PRE_KEY if the message will be a PRE_KEY message.
340  * Returns OLM_MESSAGE_TYPE_MESSAGE if the message will be a normal message.
341  * Returns olm_error on failure. */
342 size_t olm_encrypt_message_type(
343     OlmSession * session
344 );
345 
346 /** The number of random bytes needed to encrypt the next message. */
347 size_t olm_encrypt_random_length(
348     OlmSession * session
349 );
350 
351 /** The size of the next message in bytes for the given number of plain-text
352  * bytes. */
353 size_t olm_encrypt_message_length(
354     OlmSession * session,
355     size_t plaintext_length
356 );
357 
358 /** Encrypts a message using the session. Returns the length of the message in
359  * bytes on success. Writes the message as base64 into the message buffer.
360  * Returns olm_error() on failure. If the message buffer is too small then
361  * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If there
362  * weren't enough random bytes then olm_session_last_error() will be
363  * "NOT_ENOUGH_RANDOM". */
364 size_t olm_encrypt(
365     OlmSession * session,
366     const void * plaintext, size_t plaintext_length,
367     void * random, size_t random_length,
368     void * message, size_t message_length
369 );
370 
371 /** The maximum number of bytes of plain-text a given message could decode to.
372  * The actual size could be different due to padding. The input message buffer
373  * is destroyed. Returns olm_error() on failure. If the message base64
374  * couldn't be decoded then olm_session_last_error() will be
375  * "INVALID_BASE64". If the message is for an unsupported version of the
376  * protocol then olm_session_last_error() will be "BAD_MESSAGE_VERSION".
377  * If the message couldn't be decoded then olm_session_last_error() will be
378  * "BAD_MESSAGE_FORMAT". */
379 size_t olm_decrypt_max_plaintext_length(
380     OlmSession * session,
381     size_t message_type,
382     void * message, size_t message_length
383 );
384 
385 /** Decrypts a message using the session. The input message buffer is destroyed.
386  * Returns the length of the plain-text on success. Returns olm_error() on
387  * failure. If the plain-text buffer is smaller than
388  * olm_decrypt_max_plaintext_length() then olm_session_last_error()
389  * will be "OUTPUT_BUFFER_TOO_SMALL". If the base64 couldn't be decoded then
390  * olm_session_last_error() will be "INVALID_BASE64". If the message is for
391  * an unsupported version of the protocol then olm_session_last_error() will
392  *  be "BAD_MESSAGE_VERSION". If the message couldn't be decoded then
393  *  olm_session_last_error() will be BAD_MESSAGE_FORMAT".
394  *  If the MAC on the message was invalid then olm_session_last_error() will
395  *  be "BAD_MESSAGE_MAC". */
396 size_t olm_decrypt(
397     OlmSession * session,
398     size_t message_type,
399     void * message, size_t message_length,
400     void * plaintext, size_t max_plaintext_length
401 );
402 
403 /** The length of the buffer needed to hold the SHA-256 hash. */
404 size_t olm_sha256_length(
405    OlmUtility * utility
406 );
407 
408 /** Calculates the SHA-256 hash of the input and encodes it as base64. If the
409  * output buffer is smaller than olm_sha256_length() then
410  * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */
411 size_t olm_sha256(
412     OlmUtility * utility,
413     const void * input, size_t input_length,
414     void * output, size_t output_length
415 );
416 
417 /** Verify an ed25519 signature. If the key was too small then
418  * olm_session_last_error will be "INVALID_BASE64". If the signature was invalid
419  * then olm_session_last_error() will be "BAD_MESSAGE_MAC". */
420 size_t olm_ed25519_verify(
421     OlmUtility * utility,
422     const void * key, size_t key_length,
423     const void * message, size_t message_length,
424     void * signature, size_t signature_length
425 );