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
27namespace {
28
29static OlmAccount * to_c(olm::Account * account) {
30 return reinterpret_cast<OlmAccount *>(account);
31}
32
33static OlmSession * to_c(olm::Session * session) {
34 return reinterpret_cast<OlmSession *>(session);
35}
36
37static OlmUtility * to_c(olm::Utility * utility) {
38 return reinterpret_cast<OlmUtility *>(utility);
39}
40
41static olm::Account * from_c(OlmAccount * account) {
42 return reinterpret_cast<olm::Account *>(account);
43}
44
45static const olm::Account * from_c(OlmAccount const * account) {
46 return reinterpret_cast<olm::Account const *>(account);
47}
48
49static olm::Session * from_c(OlmSession * session) {
50 return reinterpret_cast<olm::Session *>(session);
51}
52
53static const olm::Session * from_c(OlmSession const * session) {
54 return reinterpret_cast<const olm::Session *>(session);
55}
56
57static olm::Utility * from_c(OlmUtility * utility) {
58 return reinterpret_cast<olm::Utility *>(utility);
59}
60
61static const olm::Utility * from_c(OlmUtility const * utility) {
62 return reinterpret_cast<const olm::Utility *>(utility);
63}
64
65static std::uint8_t * from_c(void * bytes) {
66 return reinterpret_cast<std::uint8_t *>(bytes);
67}
68
69static std::uint8_t const * from_c(void const * bytes) {
70 return reinterpret_cast<std::uint8_t const *>(bytes);
71}
72
73std::size_t b64_output_length(
74 size_t raw_length
75) {
76 return olm::encode_base64_length(input_length: raw_length);
77}
78
79std::uint8_t * b64_output_pos(
80 std::uint8_t * output,
81 size_t raw_length
82) {
83 return output + olm::encode_base64_length(input_length: raw_length) - raw_length;
84}
85
86std::size_t b64_output(
87 std::uint8_t * output, size_t raw_length
88) {
89 std::size_t base64_length = olm::encode_base64_length(input_length: raw_length);
90 std::uint8_t * raw_output = output + base64_length - raw_length;
91 olm::encode_base64(input: raw_output, input_length: raw_length, output);
92 return base64_length;
93}
94
95std::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(input_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, input_length: b64_length, output: input);
105 return raw_length;
106}
107
108} // namespace
109
110
111extern "C" {
112
113void 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
119size_t olm_error(void) {
120 return std::size_t(-1);
121}
122
123
124const 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
131enum OlmErrorCode olm_account_last_error_code(
132 const OlmAccount * account
133) {
134 return from_c(account)->last_error;
135}
136
137const 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
144enum OlmErrorCode olm_session_last_error_code(
145 OlmSession const * session
146) {
147 return from_c(session)->last_error;
148}
149
150const 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
157enum OlmErrorCode olm_utility_last_error_code(
158 OlmUtility const * utility
159) {
160 return from_c(utility)->last_error;
161}
162
163size_t olm_account_size(void) {
164 return sizeof(olm::Account);
165}
166
167
168size_t olm_session_size(void) {
169 return sizeof(olm::Session);
170}
171
172size_t olm_utility_size(void) {
173 return sizeof(olm::Utility);
174}
175
176OlmAccount * olm_account(
177 void * memory
178) {
179 olm::unset(buffer: memory, buffer_length: sizeof(olm::Account));
180 return to_c(account: new(memory) olm::Account());
181}
182
183
184OlmSession * olm_session(
185 void * memory
186) {
187 olm::unset(buffer: memory, buffer_length: sizeof(olm::Session));
188 return to_c(session: new(memory) olm::Session());
189}
190
191
192OlmUtility * olm_utility(
193 void * memory
194) {
195 olm::unset(buffer: memory, buffer_length: sizeof(olm::Utility));
196 return to_c(utility: new(memory) olm::Utility());
197}
198
199
200size_t olm_clear_account(
201 OlmAccount * account
202) {
203 /* Clear the memory backing the account */
204 olm::unset(buffer: account, buffer_length: 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
211size_t olm_clear_session(
212 OlmSession * session
213) {
214 /* Clear the memory backing the session */
215 olm::unset(buffer: session, buffer_length: 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
222size_t olm_clear_utility(
223 OlmUtility * utility
224) {
225 /* Clear the memory backing the session */
226 olm::unset(buffer: utility, buffer_length: 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
233size_t olm_pickle_account_length(
234 OlmAccount const * account
235) {
236 return _olm_enc_output_length(raw_length: pickle_length(value: *from_c(account)));
237}
238
239
240size_t olm_pickle_session_length(
241 OlmSession const * session
242) {
243 return _olm_enc_output_length(raw_length: pickle_length(value: *from_c(session)));
244}
245
246
247size_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(value: 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(pos: _olm_enc_output_pos(output: from_c(bytes: pickled), raw_length), value: object);
259 return _olm_enc_output(key: from_c(bytes: key), key_length, pickle: from_c(bytes: pickled), raw_length);
260}
261
262
263size_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(value: 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(pos: _olm_enc_output_pos(output: from_c(bytes: pickled), raw_length), value: object);
275 return _olm_enc_output(key: from_c(bytes: key), key_length, pickle: from_c(bytes: pickled), raw_length);
276}
277
278
279size_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(bytes: pickled);
286 std::size_t raw_length = _olm_enc_input(
287 key: from_c(bytes: key), key_length, input, b64_length: pickled_length, last_error: &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, value&: 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
314size_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(bytes: pickled);
321 std::size_t raw_length = _olm_enc_input(
322 key: from_c(bytes: key), key_length, input, b64_length: pickled_length, last_error: &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, value&: 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
349size_t olm_create_account_random_length(
350 OlmAccount const * account
351) {
352 return from_c(account)->new_account_random_length();
353}
354
355
356size_t olm_create_account(
357 OlmAccount * account,
358 void * random, size_t random_length
359) {
360 size_t result = from_c(account)->new_account(random: from_c(bytes: random), random_length);
361 olm::unset(buffer: random, buffer_length: random_length);
362 return result;
363}
364
365
366size_t olm_account_identity_keys_length(
367 OlmAccount const * account
368) {
369 return from_c(account)->get_identity_json_length();
370}
371
372
373size_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 identity_json: from_c(bytes: identity_keys), identity_json_length: identity_key_length
379 );
380}
381
382
383size_t olm_account_signature_length(
384 OlmAccount const * account
385) {
386 return b64_output_length(raw_length: from_c(account)->signature_length());
387}
388
389
390size_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 message: from_c(bytes: message), message_length,
403 signature: b64_output_pos(output: from_c(bytes: signature), raw_length), signature_length: raw_length
404 );
405 return b64_output(output: from_c(bytes: signature), raw_length);
406}
407
408
409size_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
416size_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 one_time_json: from_c(bytes: one_time_keys_json), one_time_json_length: one_time_key_json_length
422 );
423}
424
425
426size_t olm_account_mark_keys_as_published(
427 OlmAccount * account
428) {
429 return from_c(account)->mark_keys_as_published();
430}
431
432
433size_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
440size_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
448size_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 random: from_c(bytes: random), random_length
456 );
457 olm::unset(buffer: random, buffer_length: random_length);
458 return result;
459}
460
461
462size_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
469size_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 random: from_c(bytes: random), random_length
475 );
476 olm::unset(buffer: random, buffer_length: random_length);
477 return result;
478}
479
480
481size_t olm_account_fallback_key_length(
482 OlmAccount const * account
483) {
484 return from_c(account)->get_fallback_key_json_length();
485}
486
487
488size_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 fallback_json: from_c(bytes: fallback_key_json), fallback_json_length: fallback_key_json_length
494 );
495}
496
497
498size_t olm_account_unpublished_fallback_key_length(
499 OlmAccount const * account
500) {
501 return from_c(account)->get_unpublished_fallback_key_json_length();
502}
503
504
505size_t olm_account_unpublished_fallback_key(
506 OlmAccount * account,
507 void * fallback_key_json, size_t fallback_key_json_length
508) {
509 return from_c(account)->get_unpublished_fallback_key_json(
510 fallback_json: from_c(bytes: fallback_key_json), fallback_json_length: fallback_key_json_length
511 );
512}
513
514
515void olm_account_forget_old_fallback_key(
516 OlmAccount * account
517) {
518 return from_c(account)->forget_old_fallback_key();
519}
520
521
522size_t olm_create_outbound_session_random_length(
523 OlmSession const * session
524) {
525 return from_c(session)->new_outbound_session_random_length();
526}
527
528
529size_t olm_create_outbound_session(
530 OlmSession * session,
531 OlmAccount const * account,
532 void const * their_identity_key, size_t their_identity_key_length,
533 void const * their_one_time_key, size_t their_one_time_key_length,
534 void * random, size_t random_length
535) {
536 std::uint8_t const * id_key = from_c(bytes: their_identity_key);
537 std::uint8_t const * ot_key = from_c(bytes: their_one_time_key);
538 std::size_t id_key_length = their_identity_key_length;
539 std::size_t ot_key_length = their_one_time_key_length;
540
541 if (olm::decode_base64_length(input_length: id_key_length) != CURVE25519_KEY_LENGTH
542 || olm::decode_base64_length(input_length: ot_key_length) != CURVE25519_KEY_LENGTH
543 ) {
544 from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
545 return std::size_t(-1);
546 }
547 _olm_curve25519_public_key identity_key;
548 _olm_curve25519_public_key one_time_key;
549
550 olm::decode_base64(input: id_key, input_length: id_key_length, output: identity_key.public_key);
551 olm::decode_base64(input: ot_key, input_length: ot_key_length, output: one_time_key.public_key);
552
553 size_t result = from_c(session)->new_outbound_session(
554 local_account: *from_c(account), identity_key, one_time_key,
555 random: from_c(bytes: random), random_length
556 );
557 olm::unset(buffer: random, buffer_length: random_length);
558 return result;
559}
560
561
562size_t olm_create_inbound_session(
563 OlmSession * session,
564 OlmAccount * account,
565 void * one_time_key_message, size_t message_length
566) {
567 std::size_t raw_length = b64_input(
568 input: from_c(bytes: one_time_key_message), b64_length: message_length, last_error&: from_c(session)->last_error
569 );
570 if (raw_length == std::size_t(-1)) {
571 return std::size_t(-1);
572 }
573 return from_c(session)->new_inbound_session(
574 local_account&: *from_c(account), their_identity_key: nullptr, pre_key_message: from_c(bytes: one_time_key_message), message_length: raw_length
575 );
576}
577
578
579size_t olm_create_inbound_session_from(
580 OlmSession * session,
581 OlmAccount * account,
582 void const * their_identity_key, size_t their_identity_key_length,
583 void * one_time_key_message, size_t message_length
584) {
585 std::uint8_t const * id_key = from_c(bytes: their_identity_key);
586 std::size_t id_key_length = their_identity_key_length;
587
588 if (olm::decode_base64_length(input_length: id_key_length) != CURVE25519_KEY_LENGTH) {
589 from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
590 return std::size_t(-1);
591 }
592 _olm_curve25519_public_key identity_key;
593 olm::decode_base64(input: id_key, input_length: id_key_length, output: identity_key.public_key);
594
595 std::size_t raw_length = b64_input(
596 input: from_c(bytes: one_time_key_message), b64_length: message_length, last_error&: from_c(session)->last_error
597 );
598 if (raw_length == std::size_t(-1)) {
599 return std::size_t(-1);
600 }
601 return from_c(session)->new_inbound_session(
602 local_account&: *from_c(account), their_identity_key: &identity_key,
603 pre_key_message: from_c(bytes: one_time_key_message), message_length: raw_length
604 );
605}
606
607
608size_t olm_session_id_length(
609 OlmSession const * session
610) {
611 return b64_output_length(raw_length: from_c(session)->session_id_length());
612}
613
614size_t olm_session_id(
615 OlmSession * session,
616 void * id, size_t id_length
617) {
618 std::size_t raw_length = from_c(session)->session_id_length();
619 if (id_length < b64_output_length(raw_length)) {
620 from_c(session)->last_error =
621 OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
622 return std::size_t(-1);
623 }
624 std::size_t result = from_c(session)->session_id(
625 id: b64_output_pos(output: from_c(bytes: id), raw_length), id_length: raw_length
626 );
627 if (result == std::size_t(-1)) {
628 return result;
629 }
630 return b64_output(output: from_c(bytes: id), raw_length);
631}
632
633
634int olm_session_has_received_message(
635 OlmSession const * session
636) {
637 return from_c(session)->received_message;
638}
639
640void olm_session_describe(
641 OlmSession * session, char *buf, size_t buflen
642) {
643 from_c(session)->describe(buf, buflen);
644}
645
646size_t olm_matches_inbound_session(
647 OlmSession * session,
648 void * one_time_key_message, size_t message_length
649) {
650 std::size_t raw_length = b64_input(
651 input: from_c(bytes: one_time_key_message), b64_length: message_length, last_error&: from_c(session)->last_error
652 );
653 if (raw_length == std::size_t(-1)) {
654 return std::size_t(-1);
655 }
656 bool matches = from_c(session)->matches_inbound_session(
657 their_identity_key: nullptr, pre_key_message: from_c(bytes: one_time_key_message), message_length: raw_length
658 );
659 return matches ? 1 : 0;
660}
661
662
663size_t olm_matches_inbound_session_from(
664 OlmSession * session,
665 void const * their_identity_key, size_t their_identity_key_length,
666 void * one_time_key_message, size_t message_length
667) {
668 std::uint8_t const * id_key = from_c(bytes: their_identity_key);
669 std::size_t id_key_length = their_identity_key_length;
670
671 if (olm::decode_base64_length(input_length: id_key_length) != CURVE25519_KEY_LENGTH) {
672 from_c(session)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
673 return std::size_t(-1);
674 }
675 _olm_curve25519_public_key identity_key;
676 olm::decode_base64(input: id_key, input_length: id_key_length, output: identity_key.public_key);
677
678 std::size_t raw_length = b64_input(
679 input: from_c(bytes: one_time_key_message), b64_length: message_length, last_error&: from_c(session)->last_error
680 );
681 if (raw_length == std::size_t(-1)) {
682 return std::size_t(-1);
683 }
684 bool matches = from_c(session)->matches_inbound_session(
685 their_identity_key: &identity_key, pre_key_message: from_c(bytes: one_time_key_message), message_length: raw_length
686 );
687 return matches ? 1 : 0;
688}
689
690
691size_t olm_remove_one_time_keys(
692 OlmAccount * account,
693 OlmSession * session
694) {
695 size_t result = from_c(account)->remove_key(
696 public_key: from_c(session)->bob_one_time_key
697 );
698 if (result == std::size_t(-1)) {
699 from_c(account)->last_error = OlmErrorCode::OLM_BAD_MESSAGE_KEY_ID;
700 }
701 return result;
702}
703
704
705size_t olm_encrypt_message_type(
706 OlmSession const * session
707) {
708 return size_t(from_c(session)->encrypt_message_type());
709}
710
711
712size_t olm_encrypt_random_length(
713 OlmSession const * session
714) {
715 return from_c(session)->encrypt_random_length();
716}
717
718
719size_t olm_encrypt_message_length(
720 OlmSession const * session,
721 size_t plaintext_length
722) {
723 return b64_output_length(
724 raw_length: from_c(session)->encrypt_message_length(plaintext_length)
725 );
726}
727
728
729size_t olm_encrypt(
730 OlmSession * session,
731 void const * plaintext, size_t plaintext_length,
732 void * random, size_t random_length,
733 void * message, size_t message_length
734) {
735 std::size_t raw_length = from_c(session)->encrypt_message_length(
736 plaintext_length
737 );
738 if (message_length < b64_output_length(raw_length)) {
739 from_c(session)->last_error =
740 OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
741 return std::size_t(-1);
742 }
743 std::size_t result = from_c(session)->encrypt(
744 plaintext: from_c(bytes: plaintext), plaintext_length,
745 random: from_c(bytes: random), random_length,
746 message: b64_output_pos(output: from_c(bytes: message), raw_length), message_length: raw_length
747 );
748 olm::unset(buffer: random, buffer_length: random_length);
749 if (result == std::size_t(-1)) {
750 return result;
751 }
752 return b64_output(output: from_c(bytes: message), raw_length);
753}
754
755
756size_t olm_decrypt_max_plaintext_length(
757 OlmSession * session,
758 size_t message_type,
759 void * message, size_t message_length
760) {
761 std::size_t raw_length = b64_input(
762 input: from_c(bytes: message), b64_length: message_length, last_error&: from_c(session)->last_error
763 );
764 if (raw_length == std::size_t(-1)) {
765 return std::size_t(-1);
766 }
767 return from_c(session)->decrypt_max_plaintext_length(
768 message_type: olm::MessageType(message_type), message: from_c(bytes: message), message_length: raw_length
769 );
770}
771
772
773size_t olm_decrypt(
774 OlmSession * session,
775 size_t message_type,
776 void * message, size_t message_length,
777 void * plaintext, size_t max_plaintext_length
778) {
779 std::size_t raw_length = b64_input(
780 input: from_c(bytes: message), b64_length: message_length, last_error&: from_c(session)->last_error
781 );
782 if (raw_length == std::size_t(-1)) {
783 return std::size_t(-1);
784 }
785 return from_c(session)->decrypt(
786 message_type: olm::MessageType(message_type), message: from_c(bytes: message), message_length: raw_length,
787 plaintext: from_c(bytes: plaintext), max_plaintext_length
788 );
789}
790
791
792size_t olm_sha256_length(
793 OlmUtility const * utility
794) {
795 return b64_output_length(raw_length: from_c(utility)->sha256_length());
796}
797
798
799size_t olm_sha256(
800 OlmUtility * utility,
801 void const * input, size_t input_length,
802 void * output, size_t output_length
803) {
804 std::size_t raw_length = from_c(utility)->sha256_length();
805 if (output_length < b64_output_length(raw_length)) {
806 from_c(utility)->last_error =
807 OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
808 return std::size_t(-1);
809 }
810 std::size_t result = from_c(utility)->sha256(
811 input: from_c(bytes: input), input_length,
812 output: b64_output_pos(output: from_c(bytes: output), raw_length), output_length: raw_length
813 );
814 if (result == std::size_t(-1)) {
815 return result;
816 }
817 return b64_output(output: from_c(bytes: output), raw_length);
818}
819
820
821size_t olm_ed25519_verify(
822 OlmUtility * utility,
823 void const * key, size_t key_length,
824 void const * message, size_t message_length,
825 void * signature, size_t signature_length
826) {
827 if (olm::decode_base64_length(input_length: key_length) != CURVE25519_KEY_LENGTH) {
828 from_c(utility)->last_error = OlmErrorCode::OLM_INVALID_BASE64;
829 return std::size_t(-1);
830 }
831 _olm_ed25519_public_key verify_key;
832 olm::decode_base64(input: from_c(bytes: key), input_length: key_length, output: verify_key.public_key);
833 std::size_t raw_signature_length = b64_input(
834 input: from_c(bytes: signature), b64_length: signature_length, last_error&: from_c(utility)->last_error
835 );
836 if (raw_signature_length == std::size_t(-1)) {
837 return std::size_t(-1);
838 }
839 return from_c(utility)->ed25519_verify(
840 key: verify_key,
841 message: from_c(bytes: message), message_length,
842 signature: from_c(bytes: signature), signature_length: raw_signature_length
843 );
844}
845
846}
847