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 );