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
29extern "C" {
30#endif
31
32static const size_t OLM_MESSAGE_TYPE_PRE_KEY = 0;
33static const size_t OLM_MESSAGE_TYPE_MESSAGE = 1;
34
35typedef struct OlmAccount OlmAccount;
36typedef struct OlmSession OlmSession;
37typedef struct OlmUtility OlmUtility;
38
39/** Get the version number of the library.
40 * Arguments will be updated if non-null.
41 */
42OLM_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 */
45OLM_EXPORT size_t olm_account_size(void);
46
47/** The size of a session object in bytes */
48OLM_EXPORT size_t olm_session_size(void);
49
50/** The size of a utility object in bytes */
51OLM_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 */
55OLM_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 */
61OLM_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 */
67OLM_EXPORT OlmUtility * olm_utility(
68 void * memory
69);
70
71/** The value that olm will return from a function if there was an error */
72OLM_EXPORT size_t olm_error(void);
73
74/** A null terminated string describing the most recent error to happen to an
75 * account */
76OLM_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 */
81OLM_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 */
87OLM_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 */
92OLM_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 */
98OLM_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 */
103OLM_EXPORT enum OlmErrorCode olm_utility_last_error_code(
104 OlmUtility const * utility
105);
106
107/** Clears the memory used to back this account */
108OLM_EXPORT size_t olm_clear_account(
109 OlmAccount * account
110);
111
112/** Clears the memory used to back this session */
113OLM_EXPORT size_t olm_clear_session(
114 OlmSession * session
115);
116
117/** Clears the memory used to back this utility */
118OLM_EXPORT size_t olm_clear_utility(
119 OlmUtility * utility
120);
121
122/** Returns the number of bytes needed to store an account */
123OLM_EXPORT size_t olm_pickle_account_length(
124 OlmAccount const * account
125);
126
127/** Returns the number of bytes needed to store a session */
128OLM_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" */
137OLM_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" */
148OLM_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 */
160OLM_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 */
172OLM_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.*/
179OLM_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" */
186OLM_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 */
192OLM_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". */
200OLM_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. */
207OLM_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" */
214OLM_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 */
221OLM_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". */
243OLM_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. */
255OLM_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. */
260OLM_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. */
266OLM_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". */
275OLM_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. */
282OLM_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". */
289OLM_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. */
296OLM_EXPORT size_t olm_account_fallback_key_length(
297 OlmAccount const * account
298);
299
300/** Deprecated: use olm_account_unpublished_fallback_key instead */
301OLM_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. */
308OLM_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 */
314OLM_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 */
324OLM_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 */
330OLM_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". */
339OLM_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". */
355OLM_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. */
364OLM_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. */
372OLM_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". */
379OLM_EXPORT size_t olm_session_id(
380 OlmSession * session,
381 void * id, size_t id_length
382);
383
384OLM_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 */
395OLM_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". */
406OLM_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". */
420OLM_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". */
429OLM_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. */
438OLM_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. */
443OLM_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. */
449OLM_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". */
460OLM_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". */
475OLM_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". */
492OLM_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. */
500OLM_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". */
507OLM_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". */
516OLM_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