1 | /* Copyright 2015, 2016 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 | #ifndef OLM_H_ |
17 | #define OLM_H_ |
18 | |
19 | #include <stddef.h> |
20 | #include <stdint.h> |
21 | |
22 | #include "olm/error.h" |
23 | #include "olm/inbound_group_session.h" |
24 | #include "olm/outbound_group_session.h" |
25 | |
26 | #include "olm/olm_export.h" |
27 | |
28 | #ifdef __cplusplus |
29 | extern "C" { |
30 | #endif |
31 | |
32 | static const size_t OLM_MESSAGE_TYPE_PRE_KEY = 0; |
33 | static const size_t OLM_MESSAGE_TYPE_MESSAGE = 1; |
34 | |
35 | typedef struct OlmAccount OlmAccount; |
36 | typedef struct OlmSession OlmSession; |
37 | typedef struct OlmUtility OlmUtility; |
38 | |
39 | /** Get the version number of the library. |
40 | * Arguments will be updated if non-null. |
41 | */ |
42 | OLM_EXPORT void olm_get_library_version(uint8_t *major, uint8_t *minor, uint8_t *patch); |
43 | |
44 | /** The size of an account object in bytes */ |
45 | OLM_EXPORT size_t olm_account_size(void); |
46 | |
47 | /** The size of a session object in bytes */ |
48 | OLM_EXPORT size_t olm_session_size(void); |
49 | |
50 | /** The size of a utility object in bytes */ |
51 | OLM_EXPORT size_t olm_utility_size(void); |
52 | |
53 | /** Initialise an account object using the supplied memory |
54 | * The supplied memory must be at least olm_account_size() bytes */ |
55 | OLM_EXPORT OlmAccount * olm_account( |
56 | void * memory |
57 | ); |
58 | |
59 | /** Initialise a session object using the supplied memory |
60 | * The supplied memory must be at least olm_session_size() bytes */ |
61 | OLM_EXPORT OlmSession * olm_session( |
62 | void * memory |
63 | ); |
64 | |
65 | /** Initialise a utility object using the supplied memory |
66 | * The supplied memory must be at least olm_utility_size() bytes */ |
67 | OLM_EXPORT OlmUtility * olm_utility( |
68 | void * memory |
69 | ); |
70 | |
71 | /** The value that olm will return from a function if there was an error */ |
72 | OLM_EXPORT size_t olm_error(void); |
73 | |
74 | /** A null terminated string describing the most recent error to happen to an |
75 | * account */ |
76 | OLM_EXPORT const char * olm_account_last_error( |
77 | OlmAccount const * account |
78 | ); |
79 | |
80 | /** An error code describing the most recent error to happen to an account */ |
81 | OLM_EXPORT enum OlmErrorCode olm_account_last_error_code( |
82 | OlmAccount const * account |
83 | ); |
84 | |
85 | /** A null terminated string describing the most recent error to happen to a |
86 | * session */ |
87 | OLM_EXPORT const char * olm_session_last_error( |
88 | OlmSession const * session |
89 | ); |
90 | |
91 | /** An error code describing the most recent error to happen to a session */ |
92 | OLM_EXPORT enum OlmErrorCode olm_session_last_error_code( |
93 | OlmSession const * session |
94 | ); |
95 | |
96 | /** A null terminated string describing the most recent error to happen to a |
97 | * utility */ |
98 | OLM_EXPORT const char * olm_utility_last_error( |
99 | OlmUtility const * utility |
100 | ); |
101 | |
102 | /** An error code describing the most recent error to happen to a utility */ |
103 | OLM_EXPORT enum OlmErrorCode olm_utility_last_error_code( |
104 | OlmUtility const * utility |
105 | ); |
106 | |
107 | /** Clears the memory used to back this account */ |
108 | OLM_EXPORT size_t olm_clear_account( |
109 | OlmAccount * account |
110 | ); |
111 | |
112 | /** Clears the memory used to back this session */ |
113 | OLM_EXPORT size_t olm_clear_session( |
114 | OlmSession * session |
115 | ); |
116 | |
117 | /** Clears the memory used to back this utility */ |
118 | OLM_EXPORT size_t olm_clear_utility( |
119 | OlmUtility * utility |
120 | ); |
121 | |
122 | /** Returns the number of bytes needed to store an account */ |
123 | OLM_EXPORT size_t olm_pickle_account_length( |
124 | OlmAccount const * account |
125 | ); |
126 | |
127 | /** Returns the number of bytes needed to store a session */ |
128 | OLM_EXPORT size_t olm_pickle_session_length( |
129 | OlmSession const * session |
130 | ); |
131 | |
132 | /** Stores an account as a base64 string. Encrypts the account using the |
133 | * supplied key. Returns the length of the pickled account on success. |
134 | * Returns olm_error() on failure. If the pickle output buffer |
135 | * is smaller than olm_pickle_account_length() then |
136 | * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ |
137 | OLM_EXPORT size_t olm_pickle_account( |
138 | OlmAccount * account, |
139 | void const * key, size_t key_length, |
140 | void * pickled, size_t pickled_length |
141 | ); |
142 | |
143 | /** Stores a session as a base64 string. Encrypts the session using the |
144 | * supplied key. Returns the length of the pickled session on success. |
145 | * Returns olm_error() on failure. If the pickle output buffer |
146 | * is smaller than olm_pickle_session_length() then |
147 | * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ |
148 | OLM_EXPORT size_t olm_pickle_session( |
149 | OlmSession * session, |
150 | void const * key, size_t key_length, |
151 | void * pickled, size_t pickled_length |
152 | ); |
153 | |
154 | /** Loads an account from a pickled base64 string. Decrypts the account using |
155 | * the supplied key. Returns olm_error() on failure. If the key doesn't |
156 | * match the one used to encrypt the account then olm_account_last_error() |
157 | * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then |
158 | * olm_account_last_error() will be "INVALID_BASE64". The input pickled |
159 | * buffer is destroyed */ |
160 | OLM_EXPORT size_t olm_unpickle_account( |
161 | OlmAccount * account, |
162 | void const * key, size_t key_length, |
163 | void * pickled, size_t pickled_length |
164 | ); |
165 | |
166 | /** Loads a session from a pickled base64 string. Decrypts the session using |
167 | * the supplied key. Returns olm_error() on failure. If the key doesn't |
168 | * match the one used to encrypt the account then olm_session_last_error() |
169 | * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then |
170 | * olm_session_last_error() will be "INVALID_BASE64". The input pickled |
171 | * buffer is destroyed */ |
172 | OLM_EXPORT size_t olm_unpickle_session( |
173 | OlmSession * session, |
174 | void const * key, size_t key_length, |
175 | void * pickled, size_t pickled_length |
176 | ); |
177 | |
178 | /** The number of random bytes needed to create an account.*/ |
179 | OLM_EXPORT size_t olm_create_account_random_length( |
180 | OlmAccount const * account |
181 | ); |
182 | |
183 | /** Creates a new account. Returns olm_error() on failure. If there weren't |
184 | * enough random bytes then olm_account_last_error() will be |
185 | * "NOT_ENOUGH_RANDOM" */ |
186 | OLM_EXPORT size_t olm_create_account( |
187 | OlmAccount * account, |
188 | void * random, size_t random_length |
189 | ); |
190 | |
191 | /** The size of the output buffer needed to hold the identity keys */ |
192 | OLM_EXPORT size_t olm_account_identity_keys_length( |
193 | OlmAccount const * account |
194 | ); |
195 | |
196 | /** Writes the public parts of the identity keys for the account into the |
197 | * identity_keys output buffer. Returns olm_error() on failure. If the |
198 | * identity_keys buffer was too small then olm_account_last_error() will be |
199 | * "OUTPUT_BUFFER_TOO_SMALL". */ |
200 | OLM_EXPORT size_t olm_account_identity_keys( |
201 | OlmAccount * account, |
202 | void * identity_keys, size_t identity_key_length |
203 | ); |
204 | |
205 | |
206 | /** The length of an ed25519 signature encoded as base64. */ |
207 | OLM_EXPORT size_t olm_account_signature_length( |
208 | OlmAccount const * account |
209 | ); |
210 | |
211 | /** Signs a message with the ed25519 key for this account. Returns olm_error() |
212 | * on failure. If the signature buffer was too small then |
213 | * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ |
214 | OLM_EXPORT size_t olm_account_sign( |
215 | OlmAccount * account, |
216 | void const * message, size_t message_length, |
217 | void * signature, size_t signature_length |
218 | ); |
219 | |
220 | /** The size of the output buffer needed to hold the one time keys */ |
221 | OLM_EXPORT size_t olm_account_one_time_keys_length( |
222 | OlmAccount const * account |
223 | ); |
224 | |
225 | /** Writes the public parts of the unpublished one time keys for the account |
226 | * into the one_time_keys output buffer. |
227 | * <p> |
228 | * The returned data is a JSON-formatted object with the single property |
229 | * <tt>curve25519</tt>, which is itself an object mapping key id to |
230 | * base64-encoded Curve25519 key. For example: |
231 | * <pre> |
232 | * { |
233 | * curve25519: { |
234 | * "AAAAAA": "wo76WcYtb0Vk/pBOdmduiGJ0wIEjW4IBMbbQn7aSnTo", |
235 | * "AAAAAB": "LRvjo46L1X2vx69sS9QNFD29HWulxrmW11Up5AfAjgU" |
236 | * } |
237 | * } |
238 | * </pre> |
239 | * Returns olm_error() on failure. |
240 | * <p> |
241 | * If the one_time_keys buffer was too small then olm_account_last_error() |
242 | * will be "OUTPUT_BUFFER_TOO_SMALL". */ |
243 | OLM_EXPORT size_t olm_account_one_time_keys( |
244 | OlmAccount * account, |
245 | void * one_time_keys, size_t one_time_keys_length |
246 | ); |
247 | |
248 | /** Marks the current set of one time keys and fallback key as being published |
249 | * Once marked as published, the one time keys will no longer be returned by |
250 | * olm_account_one_time_keys(), and the fallback key will no longer be returned |
251 | * by olm_account_unpublished_fallback_key(). |
252 | * |
253 | * Returns the number of one-time keys that were marked as published. Note that |
254 | * this count does not include the fallback key. */ |
255 | OLM_EXPORT size_t olm_account_mark_keys_as_published( |
256 | OlmAccount * account |
257 | ); |
258 | |
259 | /** The largest number of one time keys this account can store. */ |
260 | OLM_EXPORT size_t olm_account_max_number_of_one_time_keys( |
261 | OlmAccount const * account |
262 | ); |
263 | |
264 | /** The number of random bytes needed to generate a given number of new one |
265 | * time keys. */ |
266 | OLM_EXPORT size_t olm_account_generate_one_time_keys_random_length( |
267 | OlmAccount const * account, |
268 | size_t number_of_keys |
269 | ); |
270 | |
271 | /** Generates a number of new one time keys. If the total number of keys stored |
272 | * by this account exceeds max_number_of_one_time_keys() then the old keys are |
273 | * discarded. Returns olm_error() on error. If the number of random bytes is |
274 | * too small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */ |
275 | OLM_EXPORT size_t olm_account_generate_one_time_keys( |
276 | OlmAccount * account, |
277 | size_t number_of_keys, |
278 | void * random, size_t random_length |
279 | ); |
280 | |
281 | /** The number of random bytes needed to generate a fallback key. */ |
282 | OLM_EXPORT size_t olm_account_generate_fallback_key_random_length( |
283 | OlmAccount const * account |
284 | ); |
285 | |
286 | /** Generates a new fallback key. Only one previous fallback key is |
287 | * stored. Returns olm_error() on error. If the number of random bytes is too |
288 | * small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */ |
289 | OLM_EXPORT size_t olm_account_generate_fallback_key( |
290 | OlmAccount * account, |
291 | void * random, size_t random_length |
292 | ); |
293 | |
294 | /** The number of bytes needed to hold the fallback key as returned by |
295 | * olm_account_fallback_key. */ |
296 | OLM_EXPORT size_t olm_account_fallback_key_length( |
297 | OlmAccount const * account |
298 | ); |
299 | |
300 | /** Deprecated: use olm_account_unpublished_fallback_key instead */ |
301 | OLM_EXPORT size_t olm_account_fallback_key( |
302 | OlmAccount * account, |
303 | void * fallback_key, size_t fallback_key_size |
304 | ); |
305 | |
306 | /** The number of bytes needed to hold the unpublished fallback key as returned |
307 | * by olm_account_unpublished fallback_key. */ |
308 | OLM_EXPORT size_t olm_account_unpublished_fallback_key_length( |
309 | OlmAccount const * account |
310 | ); |
311 | |
312 | /** Returns the fallback key (if present, and if unpublished) into the |
313 | * fallback_key buffer */ |
314 | OLM_EXPORT size_t olm_account_unpublished_fallback_key( |
315 | OlmAccount * account, |
316 | void * fallback_key, size_t fallback_key_size |
317 | ); |
318 | |
319 | /** Forget about the old fallback key. This should be called once you are |
320 | * reasonably certain that you will not receive any more messages that use |
321 | * the old fallback key (e.g. 5 minutes after the new fallback key has been |
322 | * published). |
323 | */ |
324 | OLM_EXPORT void olm_account_forget_old_fallback_key( |
325 | OlmAccount * account |
326 | ); |
327 | |
328 | |
329 | /** The number of random bytes needed to create an outbound session */ |
330 | OLM_EXPORT size_t olm_create_outbound_session_random_length( |
331 | OlmSession const * session |
332 | ); |
333 | |
334 | /** Creates a new out-bound session for sending messages to a given identity_key |
335 | * and one_time_key. Returns olm_error() on failure. If the keys couldn't be |
336 | * decoded as base64 then olm_session_last_error() will be "INVALID_BASE64" |
337 | * If there weren't enough random bytes then olm_session_last_error() will |
338 | * be "NOT_ENOUGH_RANDOM". */ |
339 | OLM_EXPORT size_t olm_create_outbound_session( |
340 | OlmSession * session, |
341 | OlmAccount const * account, |
342 | void const * their_identity_key, size_t their_identity_key_length, |
343 | void const * their_one_time_key, size_t their_one_time_key_length, |
344 | void * random, size_t random_length |
345 | ); |
346 | |
347 | /** Create a new in-bound session for sending/receiving messages from an |
348 | * incoming PRE_KEY message. Returns olm_error() on failure. If the base64 |
349 | * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64". |
350 | * If the message was for an unsupported protocol version then |
351 | * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message |
352 | * couldn't be decoded then olm_session_last_error() will be |
353 | * "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time |
354 | * key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */ |
355 | OLM_EXPORT size_t olm_create_inbound_session( |
356 | OlmSession * session, |
357 | OlmAccount * account, |
358 | void * one_time_key_message, size_t message_length |
359 | ); |
360 | |
361 | /** Same as olm_create_inbound_session, but ensures that the identity key |
362 | * in the pre-key message matches the expected identity key, supplied via the |
363 | * `their_identity_key` parameter. Fails early if there is no match. */ |
364 | OLM_EXPORT size_t olm_create_inbound_session_from( |
365 | OlmSession * session, |
366 | OlmAccount * account, |
367 | void const * their_identity_key, size_t their_identity_key_length, |
368 | void * one_time_key_message, size_t message_length |
369 | ); |
370 | |
371 | /** The length of the buffer needed to return the id for this session. */ |
372 | OLM_EXPORT size_t olm_session_id_length( |
373 | OlmSession const * session |
374 | ); |
375 | |
376 | /** An identifier for this session. Will be the same for both ends of the |
377 | * conversation. If the id buffer is too small then olm_session_last_error() |
378 | * will be "OUTPUT_BUFFER_TOO_SMALL". */ |
379 | OLM_EXPORT size_t olm_session_id( |
380 | OlmSession * session, |
381 | void * id, size_t id_length |
382 | ); |
383 | |
384 | OLM_EXPORT int olm_session_has_received_message( |
385 | OlmSession const *session |
386 | ); |
387 | |
388 | /** |
389 | * Write a null-terminated string describing the internal state of an olm |
390 | * session to the buffer provided for debugging and logging purposes. If the |
391 | * buffer is not large enough to hold the entire string, it will be truncated |
392 | * and will end with "...". A buffer length of 600 will be enough to hold any |
393 | * output. |
394 | */ |
395 | OLM_EXPORT void olm_session_describe(OlmSession * session, char *buf, size_t buflen); |
396 | |
397 | /** Checks if the PRE_KEY message is for this in-bound session. This can happen |
398 | * if multiple messages are sent to this account before this account sends a |
399 | * message in reply. The one_time_key_message buffer is destroyed. Returns 1 if |
400 | * the session matches. Returns 0 if the session does not match. Returns |
401 | * olm_error() on failure. If the base64 couldn't be decoded then |
402 | * olm_session_last_error will be "INVALID_BASE64". If the message was for an |
403 | * unsupported protocol version then olm_session_last_error() will be |
404 | * "BAD_MESSAGE_VERSION". If the message couldn't be decoded then then |
405 | * olm_session_last_error() will be "BAD_MESSAGE_FORMAT". */ |
406 | OLM_EXPORT size_t olm_matches_inbound_session( |
407 | OlmSession * session, |
408 | void * one_time_key_message, size_t message_length |
409 | ); |
410 | |
411 | /** Checks if the PRE_KEY message is for this in-bound session. This can happen |
412 | * if multiple messages are sent to this account before this account sends a |
413 | * message in reply. The one_time_key_message buffer is destroyed. Returns 1 if |
414 | * the session matches. Returns 0 if the session does not match. Returns |
415 | * olm_error() on failure. If the base64 couldn't be decoded then |
416 | * olm_session_last_error will be "INVALID_BASE64". If the message was for an |
417 | * unsupported protocol version then olm_session_last_error() will be |
418 | * "BAD_MESSAGE_VERSION". If the message couldn't be decoded then then |
419 | * olm_session_last_error() will be "BAD_MESSAGE_FORMAT". */ |
420 | OLM_EXPORT size_t olm_matches_inbound_session_from( |
421 | OlmSession * session, |
422 | void const * their_identity_key, size_t their_identity_key_length, |
423 | void * one_time_key_message, size_t message_length |
424 | ); |
425 | |
426 | /** Removes the one time keys that the session used from the account. Returns |
427 | * olm_error() on failure. If the account doesn't have any matching one time |
428 | * keys then olm_account_last_error() will be "BAD_MESSAGE_KEY_ID". */ |
429 | OLM_EXPORT size_t olm_remove_one_time_keys( |
430 | OlmAccount * account, |
431 | OlmSession * session |
432 | ); |
433 | |
434 | /** The type of the next message that olm_encrypt() will return. Returns |
435 | * OLM_MESSAGE_TYPE_PRE_KEY if the message will be a PRE_KEY message. |
436 | * Returns OLM_MESSAGE_TYPE_MESSAGE if the message will be a normal message. |
437 | * Returns olm_error on failure. */ |
438 | OLM_EXPORT size_t olm_encrypt_message_type( |
439 | OlmSession const * session |
440 | ); |
441 | |
442 | /** The number of random bytes needed to encrypt the next message. */ |
443 | OLM_EXPORT size_t olm_encrypt_random_length( |
444 | OlmSession const * session |
445 | ); |
446 | |
447 | /** The size of the next message in bytes for the given number of plain-text |
448 | * bytes. */ |
449 | OLM_EXPORT size_t olm_encrypt_message_length( |
450 | OlmSession const * session, |
451 | size_t plaintext_length |
452 | ); |
453 | |
454 | /** Encrypts a message using the session. Returns the length of the message in |
455 | * bytes on success. Writes the message as base64 into the message buffer. |
456 | * Returns olm_error() on failure. If the message buffer is too small then |
457 | * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If there |
458 | * weren't enough random bytes then olm_session_last_error() will be |
459 | * "NOT_ENOUGH_RANDOM". */ |
460 | OLM_EXPORT size_t olm_encrypt( |
461 | OlmSession * session, |
462 | void const * plaintext, size_t plaintext_length, |
463 | void * random, size_t random_length, |
464 | void * message, size_t message_length |
465 | ); |
466 | |
467 | /** The maximum number of bytes of plain-text a given message could decode to. |
468 | * The actual size could be different due to padding. The input message buffer |
469 | * is destroyed. Returns olm_error() on failure. If the message base64 |
470 | * couldn't be decoded then olm_session_last_error() will be |
471 | * "INVALID_BASE64". If the message is for an unsupported version of the |
472 | * protocol then olm_session_last_error() will be "BAD_MESSAGE_VERSION". |
473 | * If the message couldn't be decoded then olm_session_last_error() will be |
474 | * "BAD_MESSAGE_FORMAT". */ |
475 | OLM_EXPORT size_t olm_decrypt_max_plaintext_length( |
476 | OlmSession * session, |
477 | size_t message_type, |
478 | void * message, size_t message_length |
479 | ); |
480 | |
481 | /** Decrypts a message using the session. The input message buffer is destroyed. |
482 | * Returns the length of the plain-text on success. Returns olm_error() on |
483 | * failure. If the plain-text buffer is smaller than |
484 | * olm_decrypt_max_plaintext_length() then olm_session_last_error() |
485 | * will be "OUTPUT_BUFFER_TOO_SMALL". If the base64 couldn't be decoded then |
486 | * olm_session_last_error() will be "INVALID_BASE64". If the message is for |
487 | * an unsupported version of the protocol then olm_session_last_error() will |
488 | * be "BAD_MESSAGE_VERSION". If the message couldn't be decoded then |
489 | * olm_session_last_error() will be BAD_MESSAGE_FORMAT". |
490 | * If the MAC on the message was invalid then olm_session_last_error() will |
491 | * be "BAD_MESSAGE_MAC". */ |
492 | OLM_EXPORT size_t olm_decrypt( |
493 | OlmSession * session, |
494 | size_t message_type, |
495 | void * message, size_t message_length, |
496 | void * plaintext, size_t max_plaintext_length |
497 | ); |
498 | |
499 | /** The length of the buffer needed to hold the SHA-256 hash. */ |
500 | OLM_EXPORT size_t olm_sha256_length( |
501 | OlmUtility const * utility |
502 | ); |
503 | |
504 | /** Calculates the SHA-256 hash of the input and encodes it as base64. If the |
505 | * output buffer is smaller than olm_sha256_length() then |
506 | * olm_utility_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */ |
507 | OLM_EXPORT size_t olm_sha256( |
508 | OlmUtility * utility, |
509 | void const * input, size_t input_length, |
510 | void * output, size_t output_length |
511 | ); |
512 | |
513 | /** Verify an ed25519 signature. If the key was too small then |
514 | * olm_utility_last_error() will be "INVALID_BASE64". If the signature was invalid |
515 | * then olm_utility_last_error() will be "BAD_MESSAGE_MAC". */ |
516 | OLM_EXPORT size_t olm_ed25519_verify( |
517 | OlmUtility * utility, |
518 | void const * key, size_t key_length, |
519 | void const * message, size_t message_length, |
520 | void * signature, size_t signature_length |
521 | ); |
522 | |
523 | #ifdef __cplusplus |
524 | } |
525 | #endif |
526 | |
527 | #endif /* OLM_H_ */ |
528 | |