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 #include "olm/olm.h"
16 #include "olm/session.hh"
17 #include "olm/account.hh"
18 #include "olm/cipher.h"
19 #include "olm/pickle_encoding.h"
20 #include "olm/utility.hh"
21 #include "olm/base64.hh"
22 #include "olm/memory.hh"
23
24 #include <new>
25 #include <cstring>
26
27 namespace {
28
to_c(olm::Account * account)29 static OlmAccount * to_c(olm::Account * account) {
30 return reinterpret_cast<OlmAccount *>(account);
31 }
32
to_c(olm::Session * session)33 static OlmSession * to_c(olm::Session * session) {
34 return reinterpret_cast<OlmSession *>(session);
35 }
36
to_c(olm::Utility * utility)37 static OlmUtility * to_c(olm::Utility * utility) {
38 return reinterpret_cast<OlmUtility *>(utility);
39 }
40
from_c(OlmAccount * account)41 static olm::Account * from_c(OlmAccount * account) {
42 return reinterpret_cast<olm::Account *>(account);
43 }
44
from_c(OlmAccount const * account)45 static const olm::Account * from_c(OlmAccount const * account) {
46 return reinterpret_cast<olm::Account const *>(account);
47 }
48
from_c(OlmSession * session)49 static olm::Session * from_c(OlmSession * session) {
50 return reinterpret_cast<olm::Session *>(session);
51 }
52
from_c(OlmSession const * session)53 static const olm::Session * from_c(OlmSession const * session) {
54 return reinterpret_cast<const olm::Session *>(session);
55 }
56
from_c(OlmUtility * utility)57 static olm::Utility * from_c(OlmUtility * utility) {
58 return reinterpret_cast<olm::Utility *>(utility);
59 }
60
from_c(OlmUtility const * utility)61 static const olm::Utility * from_c(OlmUtility const * utility) {
62 return reinterpret_cast<const olm::Utility *>(utility);
63 }
64
from_c(void * bytes)65 static std::uint8_t * from_c(void * bytes) {
66 return reinterpret_cast<std::uint8_t *>(bytes);
67 }
68
from_c(void const * bytes)69 static std::uint8_t const * from_c(void const * bytes) {
70 return reinterpret_cast<std::uint8_t const *>(bytes);
71 }
72
b64_output_length(size_t raw_length)73 std::size_t b64_output_length(
74 size_t raw_length
75 ) {
76 return olm::encode_base64_length(raw_length);
77 }
78
b64_output_pos(std::uint8_t * output,size_t raw_length)79 std::uint8_t * b64_output_pos(
80 std::uint8_t * output,
81 size_t raw_length
82 ) {
83 return output + olm::encode_base64_length(raw_length) - raw_length;
84 }
85
b64_output(std::uint8_t * output,size_t raw_length)86 std::size_t b64_output(
87 std::uint8_t * output, size_t raw_length
88 ) {
89 std::size_t base64_length = olm::encode_base64_length(raw_length);
90 std::uint8_t * raw_output = output + base64_length - raw_length;
91 olm::encode_base64(raw_output, raw_length, output);
92 return base64_length;
93 }
94
b64_input(std::uint8_t * input,size_t b64_length,OlmErrorCode & last_error)95 std::size_t b64_input(
96 std::uint8_t * input, size_t b64_length,
97 OlmErrorCode & last_error
98 ) {
99 std::size_t raw_length = olm::decode_base64_length(b64_length);
100 if (raw_length == std::size_t(-1)) {
101 last_error = OlmErrorCode::OLM_INVALID_BASE64;
102 return std::size_t(-1);
103 }
104 olm::decode_base64(input, b64_length, input);
105 return raw_length;
106 }
107
108 } // namespace
109
110
111 extern "C" {
112
olm_get_library_version(uint8_t * major,uint8_t * minor,uint8_t * patch)113 void olm_get_library_version(uint8_t *major, uint8_t *minor, uint8_t *patch) {
114 if (major != NULL) *major = OLMLIB_VERSION_MAJOR;
115 if (minor != NULL) *minor = OLMLIB_VERSION_MINOR;
116 if (patch != NULL) *patch = OLMLIB_VERSION_PATCH;
117 }
118
olm_error(void)119 size_t olm_error(void) {
120 return std::size_t(-1);
121 }
122
123
olm_account_last_error(const OlmAccount * account)124 const char * olm_account_last_error(
125 const OlmAccount * account
126 ) {
127 auto error = from_c(account)->last_error;
128 return _olm_error_to_string(error);
129 }
130
olm_account_last_error_code(const OlmAccount * account)131 enum OlmErrorCode olm_account_last_error_code(
132 const OlmAccount * account
133 ) {
134 return from_c(account)->last_error;
135 }
136
olm_session_last_error(const OlmSession * session)137 const char * olm_session_last_error(
138 const OlmSession * session
139 ) {
140 auto error = from_c(session)->last_error;
141 return _olm_error_to_string(error);
142 }
143
olm_session_last_error_code(OlmSession const * session)144 enum OlmErrorCode olm_session_last_error_code(
145 OlmSession const * session
146 ) {
147 return from_c(session)->last_error;
148 }
149
olm_utility_last_error(OlmUtility const * utility)150 const char * olm_utility_last_error(
151 OlmUtility const * utility
152 ) {
153 auto error = from_c(utility)->last_error;
154 return _olm_error_to_string(error);
155 }
156
olm_utility_last_error_code(OlmUtility const * utility)157 enum OlmErrorCode olm_utility_last_error_code(
158 OlmUtility const * utility
159 ) {
160 return from_c(utility)->last_error;
161 }
162
olm_account_size(void)163 size_t olm_account_size(void) {
164 return sizeof(olm::Account);
165 }
166
167
olm_session_size(void)168 size_t olm_session_size(void) {
169 return sizeof(olm::Session);
170 }
171
olm_utility_size(void)172 size_t olm_utility_size(void) {
173 return sizeof(olm::Utility);
174 }
175
olm_account(void * memory)176 OlmAccount * olm_account(
177 void * memory
178 ) {
179 olm::unset(memory, sizeof(olm::Account));
180 return to_c(new(memory) olm::Account());
181 }
182
183
olm_session(void * memory)184 OlmSession * olm_session(
185 void * memory
186 ) {
187 olm::unset(memory, sizeof(olm::Session));
188 return to_c(new(memory) olm::Session());
189 }
190
191
olm_utility(void * memory)192 OlmUtility * olm_utility(
193 void * memory
194 ) {
195 olm::unset(memory, sizeof(olm::Utility));
196 return to_c(new(memory) olm::Utility());
197 }
198
199
olm_clear_account(OlmAccount * account)200 size_t olm_clear_account(
201 OlmAccount * account
202 ) {
203 /* Clear the memory backing the account */
204 olm::unset(account, sizeof(olm::Account));
205 /* Initialise a fresh account object in case someone tries to use it */
206 new(account) olm::Account();
207 return sizeof(olm::Account);
208 }
209
210
olm_clear_session(OlmSession * session)211 size_t olm_clear_session(
212 OlmSession * session
213 ) {
214 /* Clear the memory backing the session */
215 olm::unset(session, sizeof(olm::Session));
216 /* Initialise a fresh session object in case someone tries to use it */
217 new(session) olm::Session();
218 return sizeof(olm::Session);
219 }
220
221
olm_clear_utility(OlmUtility * utility)222 size_t olm_clear_utility(
223 OlmUtility * utility
224 ) {
225 /* Clear the memory backing the session */
226 olm::unset(utility, sizeof(olm::Utility));
227 /* Initialise a fresh session object in case someone tries to use it */
228 new(utility) olm::Utility();
229 return sizeof(olm::Utility);
230 }
231
232
olm_pickle_account_length(OlmAccount const * account)233 size_t olm_pickle_account_length(
234 OlmAccount const * account
235 ) {
236 return _olm_enc_output_length(pickle_length(*from_c(account)));
237 }
238
239
olm_pickle_session_length(OlmSession const * session)240 size_t olm_pickle_session_length(
241 OlmSession const * session
242 ) {
243 return _olm_enc_output_length(pickle_length(*from_c(session)));
244 }
245
246
olm_pickle_account(OlmAccount * account,void const * key,size_t key_length,void * pickled,size_t pickled_length)247 size_t olm_pickle_account(
248 OlmAccount * account,
249 void const * key, size_t key_length,
250 void * pickled, size_t pickled_length
251 ) {
252 olm::Account & object = *from_c(account);
253 std::size_t raw_length = pickle_length(object);
254 if (pickled_length < _olm_enc_output_length(raw_length)) {
255 object.last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
256 return size_t(-1);
257 }
258 pickle(_olm_enc_output_pos(from_c(pickled), raw_length), object);
259 return _olm_enc_output(from_c(key), key_length, from_c(pickled), raw_length);
260 }
261
262
olm_pickle_session(OlmSession * session,void const * key,size_t key_length,void * pickled,size_t pickled_length)263 size_t olm_pickle_session(
264 OlmSession * session,
265 void const * key, size_t key_length,
266 void * pickled, size_t pickled_length
267 ) {
268 olm::Session & object = *from_c(session);
269 std::size_t raw_length = pickle_length(object);
270 if (pickled_length < _olm_enc_output_length(raw_length)) {
271 object.last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
272 return size_t(-1);
273 }
274 pickle(_olm_enc_output_pos(from_c(pickled), raw_length), object);
275 return _olm_enc_output(from_c(key), key_length, from_c(pickled), raw_length);
276 }
277
278
olm_unpickle_account(OlmAccount * account,void const * key,size_t key_length,void * pickled,size_t pickled_length)279 size_t olm_unpickle_account(
280 OlmAccount * account,
281 void const * key, size_t key_length,
282 void * pickled, size_t pickled_length
283 ) {
284 olm::Account & object = *from_c(account);
285 std::uint8_t * input = from_c(pickled);
286 std::size_t raw_length = _olm_enc_input(
287 from_c(key), key_length, input, pickled_length, &object.last_error
288 );
289 if (raw_length == std::size_t(-1)) {
290 return std::size_t(-1);
291 }
292
293 std::uint8_t const * pos = input;
294 std::uint8_t const * end = pos + raw_length;
295
296 pos = unpickle(pos, end, object);
297
298 if (!pos) {
299 /* Input was corrupted. */
300 if (object.last_error == OlmErrorCode::OLM_SUCCESS) {
301 object.last_error = OlmErrorCode::OLM_CORRUPTED_PICKLE;
302 }
303 return std::size_t(-1);
304 } else if (pos != end) {
305 /* Input was longer than expected. */
306 object.last_error = OlmErrorCode::OLM_PICKLE_EXTRA_DATA;
307 return std::size_t(-1);
308 }
309
310 return pickled_length;
311 }
312
313
olm_unpickle_session(OlmSession * session,void const * key,size_t key_length,void * pickled,size_t pickled_length)314 size_t olm_unpickle_session(
315 OlmSession * session,
316 void const * key, size_t key_length,
317 void * pickled, size_t pickled_length
318 ) {
319 olm::Session & object = *from_c(session);
320 std::uint8_t * input = from_c(pickled);
321 std::size_t raw_length = _olm_enc_input(
322 from_c(key), key_length, input, pickled_length, &object.last_error
323 );
324 if (raw_length == std::size_t(-1)) {
325 return std::size_t(-1);
326 }
327
328 std::uint8_t const * pos = input;
329 std::uint8_t const * end = pos + raw_length;
330
331 pos = unpickle(pos, end, object);
332
333 if (!pos) {
334 /* Input was corrupted. */
335 if (object.last_error == OlmErrorCode::OLM_SUCCESS) {
336 object.last_error = OlmErrorCode::OLM_CORRUPTED_PICKLE;
337 }
338 return std::size_t(-1);
339 } else if (pos != end) {
340 /* Input was longer than expected. */
341 object.last_error = OlmErrorCode::OLM_PICKLE_EXTRA_DATA;
342 return std::size_t(-1);
343 }
344
345 return pickled_length;
346 }
347
348
olm_create_account_random_length(OlmAccount const * account)349 size_t olm_create_account_random_length(
350 OlmAccount const * account
351 ) {
352 return from_c(account)->new_account_random_length();
353 }
354
355
olm_create_account(OlmAccount * account,void * random,size_t random_length)356 size_t olm_create_account(
357 OlmAccount * account,
358 void * random, size_t random_length
359 ) {
360 size_t result = from_c(account)->new_account(from_c(random), random_length);
361 olm::unset(random, random_length);
362 return result;
363 }
364
365
olm_account_identity_keys_length(OlmAccount const * account)366 size_t olm_account_identity_keys_length(
367 OlmAccount const * account
368 ) {
369 return from_c(account)->get_identity_json_length();
370 }
371
372
olm_account_identity_keys(OlmAccount * account,void * identity_keys,size_t identity_key_length)373 size_t olm_account_identity_keys(
374 OlmAccount * account,
375 void * identity_keys, size_t identity_key_length
376 ) {
377 return from_c(account)->get_identity_json(
378 from_c(identity_keys), identity_key_length
379 );
380 }
381
382
olm_account_signature_length(OlmAccount const * account)383 size_t olm_account_signature_length(
384 OlmAccount const * account
385 ) {
386 return b64_output_length(from_c(account)->signature_length());
387 }
388
389
olm_account_sign(OlmAccount * account,void const * message,size_t message_length,void * signature,size_t signature_length)390 size_t olm_account_sign(
391 OlmAccount * account,
392 void const * message, size_t message_length,
393 void * signature, size_t signature_length
394 ) {
395 std::size_t raw_length = from_c(account)->signature_length();
396 if (signature_length < b64_output_length(raw_length)) {
397 from_c(account)->last_error =
398 OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
399 return std::size_t(-1);
400 }
401 from_c(account)->sign(
402 from_c(message), message_length,
403 b64_output_pos(from_c(signature), raw_length), raw_length
404 );
405 return b64_output(from_c(signature), raw_length);
406 }
407
408
olm_account_one_time_keys_length(OlmAccount const * account)409 size_t olm_account_one_time_keys_length(
410 OlmAccount const * account
411 ) {
412 return from_c(account)->get_one_time_keys_json_length();
413 }
414
415
olm_account_one_time_keys(OlmAccount * account,void * one_time_keys_json,size_t one_time_key_json_length)416 size_t olm_account_one_time_keys(
417 OlmAccount * account,
418 void * one_time_keys_json, size_t one_time_key_json_length
419 ) {
420 return from_c(account)->get_one_time_keys_json(
421 from_c(one_time_keys_json), one_time_key_json_length
422 );
423 }
424
425
olm_account_mark_keys_as_published(OlmAccount * account)426 size_t olm_account_mark_keys_as_published(
427 OlmAccount * account
428 ) {
429 return from_c(account)->mark_keys_as_published();
430 }
431
432
olm_account_max_number_of_one_time_keys(OlmAccount const * account)433 size_t olm_account_max_number_of_one_time_keys(
434 OlmAccount const * account
435 ) {
436 return from_c(account)->max_number_of_one_time_keys();
437 }
438
439
olm_account_generate_one_time_keys_random_length(OlmAccount const * account,size_t number_of_keys)440 size_t olm_account_generate_one_time_keys_random_length(
441 OlmAccount const * account,
442 size_t number_of_keys
443 ) {
444 return from_c(account)->generate_one_time_keys_random_length(number_of_keys);
445 }
446
447
olm_account_generate_one_time_keys(OlmAccount * account,size_t number_of_keys,void * random,size_t random_length)448 size_t olm_account_generate_one_time_keys(
449 OlmAccount * account,
450 size_t number_of_keys,
451 void * random, size_t random_length
452 ) {
453 size_t result = from_c(account)->generate_one_time_keys(
454 number_of_keys,
455 from_c(random), random_length
456 );
457 olm::unset(random, random_length);
458 return result;
459 }
460
461
olm_account_generate_fallback_key_random_length(OlmAccount const * account)462 size_t olm_account_generate_fallback_key_random_length(
463 OlmAccount const * account
464 ) {
465 return from_c(account)->generate_fallback_key_random_length();
466 }
467
468
olm_account_generate_fallback_key(OlmAccount * account,void * random,size_t random_length)469 size_t olm_account_generate_fallback_key(
470 OlmAccount * account,
471 void * random, size_t random_length
472 ) {
473 size_t result = from_c(account)->generate_fallback_key(
474 from_c(random), random_length
475 );
476 olm::unset(random, random_length);
477 return result;
478 }
479
480
olm_account_fallback_key_length(OlmAccount const * account)481 size_t olm_account_fallback_key_length(
482 OlmAccount const * account
483 ) {
484 return from_c(account)->get_fallback_key_json_length();
485 }
486
487
olm_account_fallback_key(OlmAccount * account,void * fallback_key_json,size_t fallback_key_json_length)488 size_t olm_account_fallback_key(
489 OlmAccount * account,
490 void * fallback_key_json, size_t fallback_key_json_length
491 ) {
492 return from_c(account)->get_fallback_key_json(
493 from_c(fallback_key_json), fallback_key_json_length
494 );
495 }
496
497
olm_create_outbound_session_random_length(OlmSession const * session)498 size_t olm_create_outbound_session_random_length(
499 OlmSession const * session
500 ) {
501 return from_c(session)->new_outbound_session_random_length();
502 }
503
504
olm_create_outbound_session(OlmSession * session,OlmAccount const * account,void const * their_identity_key,size_t their_identity_key_length,void const * their_one_time_key,size_t their_one_time_key_length,void * random,size_t random_length)505 size_t olm_create_outbound_session(
506 OlmSession * session,
507 OlmAccount const * account,
508 void const * their_identity_key, size_t their_identity_key_length,
509 void const * their_one_time_key, size_t their_one_time_key_length,
510 void * random, size_t random_length
511 ) {
512 std::uint8_t const * id_key = from_c(their_identity_key);
513 std::uint8_t const * ot_key = from_c(their_one_time_key);
514 std::size_t id_key_length = their_identity_key_length;
515 std::size_t ot_key_length = their_one_time_key_length;
516
517 if (olm::decode_base64_length(id_key_length) != CURVE25519_KEY_LENGTH
518 || olm::decode_base64_length(ot_key_length) != CURVE25519_KEY_LENGTH
519 ) {
520 from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
521 return std::size_t(-1);
522 }
523 _olm_curve25519_public_key identity_key;
524 _olm_curve25519_public_key one_time_key;
525
526 olm::decode_base64(id_key, id_key_length, identity_key.public_key);
527 olm::decode_base64(ot_key, ot_key_length, one_time_key.public_key);
528
529 size_t result = from_c(session)->new_outbound_session(
530 *from_c(account), identity_key, one_time_key,
531 from_c(random), random_length
532 );
533 olm::unset(random, random_length);
534 return result;
535 }
536
537
olm_create_inbound_session(OlmSession * session,OlmAccount * account,void * one_time_key_message,size_t message_length)538 size_t olm_create_inbound_session(
539 OlmSession * session,
540 OlmAccount * account,
541 void * one_time_key_message, size_t message_length
542 ) {
543 std::size_t raw_length = b64_input(
544 from_c(one_time_key_message), message_length, from_c(session)->last_error
545 );
546 if (raw_length == std::size_t(-1)) {
547 return std::size_t(-1);
548 }
549 return from_c(session)->new_inbound_session(
550 *from_c(account), nullptr, from_c(one_time_key_message), raw_length
551 );
552 }
553
554
olm_create_inbound_session_from(OlmSession * session,OlmAccount * account,void const * their_identity_key,size_t their_identity_key_length,void * one_time_key_message,size_t message_length)555 size_t olm_create_inbound_session_from(
556 OlmSession * session,
557 OlmAccount * account,
558 void const * their_identity_key, size_t their_identity_key_length,
559 void * one_time_key_message, size_t message_length
560 ) {
561 std::uint8_t const * id_key = from_c(their_identity_key);
562 std::size_t id_key_length = their_identity_key_length;
563
564 if (olm::decode_base64_length(id_key_length) != CURVE25519_KEY_LENGTH) {
565 from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
566 return std::size_t(-1);
567 }
568 _olm_curve25519_public_key identity_key;
569 olm::decode_base64(id_key, id_key_length, identity_key.public_key);
570
571 std::size_t raw_length = b64_input(
572 from_c(one_time_key_message), message_length, from_c(session)->last_error
573 );
574 if (raw_length == std::size_t(-1)) {
575 return std::size_t(-1);
576 }
577 return from_c(session)->new_inbound_session(
578 *from_c(account), &identity_key,
579 from_c(one_time_key_message), raw_length
580 );
581 }
582
583
olm_session_id_length(OlmSession const * session)584 size_t olm_session_id_length(
585 OlmSession const * session
586 ) {
587 return b64_output_length(from_c(session)->session_id_length());
588 }
589
olm_session_id(OlmSession * session,void * id,size_t id_length)590 size_t olm_session_id(
591 OlmSession * session,
592 void * id, size_t id_length
593 ) {
594 std::size_t raw_length = from_c(session)->session_id_length();
595 if (id_length < b64_output_length(raw_length)) {
596 from_c(session)->last_error =
597 OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
598 return std::size_t(-1);
599 }
600 std::size_t result = from_c(session)->session_id(
601 b64_output_pos(from_c(id), raw_length), raw_length
602 );
603 if (result == std::size_t(-1)) {
604 return result;
605 }
606 return b64_output(from_c(id), raw_length);
607 }
608
609
olm_session_has_received_message(OlmSession const * session)610 int olm_session_has_received_message(
611 OlmSession const * session
612 ) {
613 return from_c(session)->received_message;
614 }
615
olm_session_describe(OlmSession * session,char * buf,size_t buflen)616 void olm_session_describe(
617 OlmSession * session, char *buf, size_t buflen
618 ) {
619 from_c(session)->describe(buf, buflen);
620 }
621
olm_matches_inbound_session(OlmSession * session,void * one_time_key_message,size_t message_length)622 size_t olm_matches_inbound_session(
623 OlmSession * session,
624 void * one_time_key_message, size_t message_length
625 ) {
626 std::size_t raw_length = b64_input(
627 from_c(one_time_key_message), message_length, from_c(session)->last_error
628 );
629 if (raw_length == std::size_t(-1)) {
630 return std::size_t(-1);
631 }
632 bool matches = from_c(session)->matches_inbound_session(
633 nullptr, from_c(one_time_key_message), raw_length
634 );
635 return matches ? 1 : 0;
636 }
637
638
olm_matches_inbound_session_from(OlmSession * session,void const * their_identity_key,size_t their_identity_key_length,void * one_time_key_message,size_t message_length)639 size_t olm_matches_inbound_session_from(
640 OlmSession * session,
641 void const * their_identity_key, size_t their_identity_key_length,
642 void * one_time_key_message, size_t message_length
643 ) {
644 std::uint8_t const * id_key = from_c(their_identity_key);
645 std::size_t id_key_length = their_identity_key_length;
646
647 if (olm::decode_base64_length(id_key_length) != CURVE25519_KEY_LENGTH) {
648 from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
649 return std::size_t(-1);
650 }
651 _olm_curve25519_public_key identity_key;
652 olm::decode_base64(id_key, id_key_length, identity_key.public_key);
653
654 std::size_t raw_length = b64_input(
655 from_c(one_time_key_message), message_length, from_c(session)->last_error
656 );
657 if (raw_length == std::size_t(-1)) {
658 return std::size_t(-1);
659 }
660 bool matches = from_c(session)->matches_inbound_session(
661 &identity_key, from_c(one_time_key_message), raw_length
662 );
663 return matches ? 1 : 0;
664 }
665
666
olm_remove_one_time_keys(OlmAccount * account,OlmSession * session)667 size_t olm_remove_one_time_keys(
668 OlmAccount * account,
669 OlmSession * session
670 ) {
671 size_t result = from_c(account)->remove_key(
672 from_c(session)->bob_one_time_key
673 );
674 if (result == std::size_t(-1)) {
675 from_c(account)->last_error = OlmErrorCode::OLM_BAD_MESSAGE_KEY_ID;
676 }
677 return result;
678 }
679
680
olm_encrypt_message_type(OlmSession const * session)681 size_t olm_encrypt_message_type(
682 OlmSession const * session
683 ) {
684 return size_t(from_c(session)->encrypt_message_type());
685 }
686
687
olm_encrypt_random_length(OlmSession const * session)688 size_t olm_encrypt_random_length(
689 OlmSession const * session
690 ) {
691 return from_c(session)->encrypt_random_length();
692 }
693
694
olm_encrypt_message_length(OlmSession const * session,size_t plaintext_length)695 size_t olm_encrypt_message_length(
696 OlmSession const * session,
697 size_t plaintext_length
698 ) {
699 return b64_output_length(
700 from_c(session)->encrypt_message_length(plaintext_length)
701 );
702 }
703
704
olm_encrypt(OlmSession * session,void const * plaintext,size_t plaintext_length,void * random,size_t random_length,void * message,size_t message_length)705 size_t olm_encrypt(
706 OlmSession * session,
707 void const * plaintext, size_t plaintext_length,
708 void * random, size_t random_length,
709 void * message, size_t message_length
710 ) {
711 std::size_t raw_length = from_c(session)->encrypt_message_length(
712 plaintext_length
713 );
714 if (message_length < b64_output_length(raw_length)) {
715 from_c(session)->last_error =
716 OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
717 return std::size_t(-1);
718 }
719 std::size_t result = from_c(session)->encrypt(
720 from_c(plaintext), plaintext_length,
721 from_c(random), random_length,
722 b64_output_pos(from_c(message), raw_length), raw_length
723 );
724 olm::unset(random, random_length);
725 if (result == std::size_t(-1)) {
726 return result;
727 }
728 return b64_output(from_c(message), raw_length);
729 }
730
731
olm_decrypt_max_plaintext_length(OlmSession * session,size_t message_type,void * message,size_t message_length)732 size_t olm_decrypt_max_plaintext_length(
733 OlmSession * session,
734 size_t message_type,
735 void * message, size_t message_length
736 ) {
737 std::size_t raw_length = b64_input(
738 from_c(message), message_length, from_c(session)->last_error
739 );
740 if (raw_length == std::size_t(-1)) {
741 return std::size_t(-1);
742 }
743 return from_c(session)->decrypt_max_plaintext_length(
744 olm::MessageType(message_type), from_c(message), raw_length
745 );
746 }
747
748
olm_decrypt(OlmSession * session,size_t message_type,void * message,size_t message_length,void * plaintext,size_t max_plaintext_length)749 size_t olm_decrypt(
750 OlmSession * session,
751 size_t message_type,
752 void * message, size_t message_length,
753 void * plaintext, size_t max_plaintext_length
754 ) {
755 std::size_t raw_length = b64_input(
756 from_c(message), message_length, from_c(session)->last_error
757 );
758 if (raw_length == std::size_t(-1)) {
759 return std::size_t(-1);
760 }
761 return from_c(session)->decrypt(
762 olm::MessageType(message_type), from_c(message), raw_length,
763 from_c(plaintext), max_plaintext_length
764 );
765 }
766
767
olm_sha256_length(OlmUtility const * utility)768 size_t olm_sha256_length(
769 OlmUtility const * utility
770 ) {
771 return b64_output_length(from_c(utility)->sha256_length());
772 }
773
774
olm_sha256(OlmUtility * utility,void const * input,size_t input_length,void * output,size_t output_length)775 size_t olm_sha256(
776 OlmUtility * utility,
777 void const * input, size_t input_length,
778 void * output, size_t output_length
779 ) {
780 std::size_t raw_length = from_c(utility)->sha256_length();
781 if (output_length < b64_output_length(raw_length)) {
782 from_c(utility)->last_error =
783 OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
784 return std::size_t(-1);
785 }
786 std::size_t result = from_c(utility)->sha256(
787 from_c(input), input_length,
788 b64_output_pos(from_c(output), raw_length), raw_length
789 );
790 if (result == std::size_t(-1)) {
791 return result;
792 }
793 return b64_output(from_c(output), raw_length);
794 }
795
796
olm_ed25519_verify(OlmUtility * utility,void const * key,size_t key_length,void const * message,size_t message_length,void * signature,size_t signature_length)797 size_t olm_ed25519_verify(
798 OlmUtility * utility,
799 void const * key, size_t key_length,
800 void const * message, size_t message_length,
801 void * signature, size_t signature_length
802 ) {
803 if (olm::decode_base64_length(key_length) != CURVE25519_KEY_LENGTH) {
804 from_c(utility)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
805 return std::size_t(-1);
806 }
807 _olm_ed25519_public_key verify_key;
808 olm::decode_base64(from_c(key), key_length, verify_key.public_key);
809 std::size_t raw_signature_length = b64_input(
810 from_c(signature), signature_length, from_c(utility)->last_error
811 );
812 if (raw_signature_length == std::size_t(-1)) {
813 return std::size_t(-1);
814 }
815 return from_c(utility)->ed25519_verify(
816 verify_key,
817 from_c(message), message_length,
818 from_c(signature), raw_signature_length
819 );
820 }
821
822 }
823