Compare commits

...

184 commits

Author SHA1 Message Date
fd10167985
Fix listings and session print 2023-12-10 20:46:16 +01:00
cb3fe622ae
Fix 3ds build 2023-12-09 14:48:21 +01:00
Hubert Chathi
7e0c827703 release 3.2.16 2023-11-23 12:38:51 -05:00
Hubert Chathi
972faaadd5 use pypa/build instead of setup.py when building sdist 2023-11-21 21:25:55 -05:00
Hubert Chathi
807b252331 update Python versions in CI 2023-11-21 21:25:02 -05:00
parona' via Olm
bbdac4045d Fix breakage in setuptools-69.0.0 by cleaning up setup.py
Hello,

Setuptools 69.0.0 deprecated a bunch stuff leading to a nasty errors during install.

> File "/tmp/pip-build-env-w815o5v3/overlay/lib/python3.11/site-packages/setuptools/config/_apply_pyprojecttoml.py", line 183, in _license
>          _set_config(dist, "license", val["text"])
>                                       ~~~^^^^^^^^
> KeyError: 'text'
> [end of output]

__version__.py wasn't used anywhere except setup.py so removing and setting it all pyproject.toml is safe.

During this decided to move as much as I could out of setup.py, zip-safe has been obsolete for modern setuptools installation methods so dropped it.

From c0be008217350f03de7f856866a402d95b5db2a3 Mon Sep 17 00:00:00 2001
From: Alfred Wingate <parona@protonmail.com>
Date: Tue, 21 Nov 2023 15:13:35 +0200
Subject: [PATCH] Move metadata to project.toml

* Setuptools 69.0.0 deprecated a slew of old style configurations.

Signed-off-by: Alfred Wingate <parona@protonmail.com>
2023-11-21 16:07:46 -05:00
Hubert Chathi
4beb2487ce JS packages are now uploaded to npmjs.com rather than gitlab.matrix.org 2023-11-21 16:06:00 -05:00
Hubert Chathi
b54fa37fae add missing line from changelog 2023-11-21 16:05:27 -05:00
Hubert Chathi
66294cf7f6 release 3.2.15 2023-05-01 11:35:20 -04:00
Hubert Chathi
366520ebfd aha, it's lowercase 2023-04-27 19:53:44 -04:00
Hubert Chathi
d27f162316 attempt to fix js build 2023-04-27 19:48:16 -04:00
Hubert Chathi
4b69958c95 improve compatibility with Windows (though it still doesn't work) 2023-04-27 18:52:39 -04:00
Hubert Chathi
5cfe6c3dbd more packaging improvements 2023-04-27 17:19:53 -04:00
Hubert Chathi
bbdc12c569 Merge branch 'master' of https://gitlab.matrix.org/matrix-org/olm 2023-04-26 10:02:02 -04:00
Hubert Chathi
afb3d403e1 actually remove dependency on future 2023-04-26 10:00:34 -04:00
Hubert Chathi
418656ee9f make sure the headers are up to date when creating the sdist 2023-04-26 09:58:10 -04:00
Hubert Chathi
0d367baa5b add script for creating Python sdist 2023-04-25 18:47:37 -04:00
Hubert Chathi
8cbb60e476 improve Python packaging 2023-04-25 18:47:14 -04:00
Michael Telatynski
0880461134 Correct message_index type in return signature of InboundGroupSession::decrypt 2023-03-29 08:33:55 +00:00
Hubert Chathi
8f4b81b512 remove workaround for closure compiler that is now causing problems
was added in 5a60e543a5
2023-03-17 17:50:10 -04:00
Jon Ringer
ab4cbcd01a Enable darwin builds in Nix for olm
From 04f1249a66e75e91ef009ed04304cbc88dea798d Mon Sep 17 00:00:00 2001
From: Jonathan Ringer <jonringer117@gmail.com>
Date: Sun, 26 Feb 2023 15:14:23 -0800
Subject: [PATCH] Enable darwin builds in Nix

Move most packaging concerns into nix/overlay.nix. Alter packaging
to mostly align with nixpkgs best practices.

Signed-off-by: Jonathan Ringer <jonringer117@gmail.com>
2023-03-17 16:53:50 -04:00
Hubert Chathi
704b198f5a we are already living in the future, part 2 2023-01-19 13:46:34 -05:00
Hubert Chathi
0eb4550a8f we are already living in the future 2023-01-09 09:51:37 -05:00
Hubert Chathi
249acc9e0b fix tox config to work with newer version 2022-12-23 17:50:09 -05:00
Hubert Chathi
5efd38c990 release 3.2.14 2022-12-05 17:58:00 -05:00
Hubert Chathi
ad76fc1570 allow multiple arguments to be passed when linking Python library 2022-12-02 19:38:45 -05:00
Michael Telatynski
b5d68376b5 Improve Typescript typing 2022-12-01 18:36:00 +00:00
Hubert Chathi
dbd8a44fa2 add documentation for installation, and other doc improvements 2022-11-28 18:39:49 -05:00
Michael Telatynski
722f4df4aa Update javascript/index.d.ts 2022-11-18 16:09:55 +00:00
Hubert Chathi
6d767aaf29 release 3.2.13 2022-10-07 11:00:05 -04:00
Hubert Chathi
21e84095e6 pkgconfig improvements 2022-10-06 22:22:56 -04:00
Hubert Chathi
464e193dad update nix info 2022-10-06 15:26:39 -04:00
Brendan Abolivier
df2cfcb6d0 Python bindings: add py.typed to wheels 2022-10-06 17:59:11 +00:00
Hubert Chathi
ed94b56d16 fix compatibility with newer versions of emscripten 2022-10-06 13:14:38 -04:00
Hubert Chathi
f52d179c18 and update URL for Trixnity 2022-09-12 09:14:01 -04:00
Hubert Chathi
85c0be5fbc update license for Trixnity 2022-09-12 09:11:50 -04:00
Denis Kasak
203083cdd4 fix(megolm spec): Correct the version for the session export format.
It was mistakenly claimed to be 2 when it's supposed to be 1.
2022-09-01 14:58:16 +02:00
David Robertson
983e78dc53 Fix dead link to e2ee guide in the README 2022-06-22 16:47:15 +00:00
Hubert Chathi
92769cec71 release 3.2.12 2022-05-30 13:55:34 -04:00
Hubert Chathi
d18d12d379 minor documentation fixes 2022-05-30 13:55:10 -04:00
Denis Kasak
14c5ea70d4 Describe the session export format.
This is the Megolm session format used for `m.forwarded_room_key`, the
server-side room key backups and Megolm key file exports in the Matrix
specification and implementations.
2022-05-26 14:14:44 +02:00
Denis Kasak
ee1b0c8a9a Update megolm.md: Fix broken section link. 2022-05-26 10:43:28 +00:00
Hubert Chathi
84807125c0 allow memory to grow in wasm 2022-05-13 16:28:04 -04:00
Hubert Chathi
eb21951124 allow passing linker flag to link to standard C++ library 2022-05-13 16:23:58 -04:00
Hubert Chathi
39252b012b re-add olm-python3 rule that was accidentally removed 2022-05-13 16:21:54 -04:00
Brendan Abolivier
86a3d95855 Fix type hints on the PkDecryption class 2022-05-13 11:39:44 +01:00
Faye Duxovni
81f5c4a3cd Make sure checks actually run 2022-05-12 20:56:17 -04:00
Faye Duxovni
d0b2b8702f fix deprecated output attribute 2022-05-12 20:55:00 -04:00
Faye Duxovni
e000c33a58 don't try to harden unoptimized debug builds, it just causes errors 2022-05-12 20:55:00 -04:00
Faye Duxovni
43672251e4 ensure use of gcc/clang at stdenv level for checks 2022-05-12 19:42:47 -04:00
Hubert Chathi
e116efa752 Add check to nix flake: compile C library with gcc and clang 2022-05-12 17:05:22 -04:00
Faye Duxovni
a4a700739e ignore nix build result symlinks 2022-05-11 14:39:17 -04:00
Faye Duxovni
b8990d90f0 remove now-unused yarn, replace with nodejs 2022-05-11 14:35:37 -04:00
Faye Duxovni
99d635779c include version in derivation name 2022-05-11 14:29:53 -04:00
Faye Duxovni
b65ab350f0 let pinning of nixos-unstable commit happen in flake.lock rather than flake.nix 2022-05-11 14:15:37 -04:00
Faye Duxovni
c9e6bf9263 use npmlock2nix to provide node_modules 2022-05-11 13:59:33 -04:00
Faye Duxovni
727722d7a8 patch shebangs in build scripts 2022-05-11 13:07:57 -04:00
Hubert Chathi
8510b2f601 initial attempt at nix flake 2022-05-11 11:26:20 -04:00
Hubert Chathi
7bf6fb553e improve documentation for Python function 2022-05-02 12:12:31 -04:00
Hubert Chathi
1c7df35c5f exposed olm_sas_calculate_mac_fixed_base64 in the bindings 2022-04-21 21:45:19 -04:00
Hubert Chathi
2f23d99424 Release 3.2.11 2022-04-08 16:00:24 -04:00
ganfra
0a6a5a5caf Add public pickle/unpickle methods to java bindings 2022-04-08 14:28:24 +00:00
Valere
b5dfa28f3b code review 2022-04-08 13:16:37 +00:00
Valere
3c91c66ee2 Unpublished fallback key bindings + forget 2022-04-08 13:16:37 +00:00
Alex Baker
dcf5582f8a Add Java wrapper for olm_session_describe
Signed-off-by: Alex Baker <alex@beeper.com>
2022-02-25 10:19:11 -05:00
Hubert Chathi
9d66965962 add Trixnity to list of bindings 2022-02-17 10:08:01 -05:00
Hubert Chathi
dd1905454b fix doc building. Thanks to Jonas Smedegaard. 2022-01-14 11:08:58 -05:00
Benoit Marty
9908862979 release 3.2.10 2022-01-10 11:00:49 +01:00
Benoit Marty
7d0a69a099 Ensure the Android library includes the native olm libraries 2022-01-07 22:03:28 +01:00
Benoît Marty
2c6b9d5e3a Fix typo in the url 2022-01-07 18:55:53 +00:00
Hubert Chathi
0dde38bd4f release 3.2.9 2022-01-07 10:56:06 -05:00
Benoit Marty
b3478a526b Update POM_SCM_CONNECTION and POM_SCM_DEV_CONNECTION values 2022-01-07 00:13:43 +01:00
Benoit Marty
b11f555b01 Do not upload source and Javadoc
Only empty jars will be uploaded
2022-01-06 10:05:37 +01:00
Benoit Marty
23380ca331 Release the library on MavenCentral
Delete stuff added for Jitpack
2022-01-06 10:04:40 +01:00
Benoit Marty
1c3af112c8 Compile and target API 31 2022-01-05 16:28:04 +01:00
Benoit Marty
55c976d4f6 Use Java 11 source compat 2022-01-05 16:12:24 +01:00
Benoit Marty
db90ce6b62 Upgrade dependencies of test libraries 2022-01-05 16:12:13 +01:00
Benoit Marty
96407493d1 New notation for the different Int 2022-01-05 16:11:59 +01:00
Benoit Marty
9b2c116fbd Upgrade AGP from 4.2.3 to 7.0.4 2022-01-05 16:11:40 +01:00
Benoit Marty
cbc6886a37 Upgrade from gradle-7.0 to gradle-7.3.3 2022-01-05 16:10:31 +01:00
Benoit Marty
c172ab6236 Remove unnecessary file 2022-01-05 16:08:52 +01:00
Tulir Asokan
9946acac23 Add Python wrapper for olm_session_describe
Signed-off-by: Tulir Asokan <tulir@beeper.com>
2022-01-03 09:43:21 +00:00
Hubert Chathi
60122a2c2d switch to jasmine (instead of jasmine-node) for JavaScript tests 2021-12-22 13:51:47 -05:00
Hubert Chathi
8475061136 switch to doctest for unit testing
thanks to Nico Werner, who did most of the porting work
2021-12-22 13:45:33 -05:00
Hubert Chathi
e197cd76d6 some cleanup 2021-12-21 13:24:34 -05:00
Hubert Chathi
797183f27f release 3.2.8 2021-12-13 08:42:39 -05:00
Hubert Chathi
21dc11ecbf update location of Nim binding 2021-12-13 08:42:14 -05:00
Hubert Chathi
8519ce0269 clear out random arrays 2021-12-10 16:15:22 -05:00
Hubert Chathi
c23ce70fc6 improve handling of olm_session_describe when buffer is too short 2021-12-10 16:14:46 -05:00
Hubert Chathi
2dbeea2f1d release 3.2.7 2021-12-06 11:01:21 -05:00
Valere
e854c0f907 Quick fixes 2021-12-02 21:46:32 +00:00
valere
f647747d27 fallback key java bindings 2021-12-02 21:46:32 +00:00
Benjamin Kampmann
f6309f0281 Disable forced exports (introduced in 72b8bf53) for wasm. 2021-12-02 12:27:37 -05:00
Hubert Chathi
4b2f68d11e add missing word 2021-12-01 15:36:46 -05:00
Hubert Chathi
fb162258ab add function to TypeScript declaration 2021-12-01 14:34:41 -05:00
Hubert Chathi
ee76674f03 remove duplicate definition 2021-12-01 14:34:29 -05:00
Damir Jelić
701f9c765d python: Expose the method to forget the old fallback key 2021-11-24 20:06:24 +01:00
Damir Jelić
85a2f47088 python: Use the unpublished fallback key lenght when outputing fallback keys 2021-11-24 20:06:24 +01:00
Damir Jelić
8c62046392 python: Add support to generate fallback keys 2021-11-24 20:06:24 +01:00
Damir Jelić
845e7cb43b python: Remove Python 2 from the makefile 2021-11-24 20:06:24 +01:00
Hubert Chathi
69ca6cd5ca publish to gitlab.matrix.org Maven repository 2021-11-24 16:06:51 +00:00
Benjamin Kampmann
336e1d56a8 disable DEBUG symbols for emscripten build 2021-11-24 10:43:23 -05:00
Hubert Chathi
6f59e16b58 update function documentation 2021-11-23 22:35:10 +00:00
Denis Kasak
5e5e32fe83 fix typo 2021-11-23 22:35:10 +00:00
Hubert Chathi
631f050554 add a test for fallback keys, and clear memory when we forget the old fallback 2021-11-23 22:35:10 +00:00
Hubert Chathi
29e0287ef3 add function to forget the old fallback key 2021-11-23 22:35:10 +00:00
Hubert Chathi
c5eff859cb add JavaScript function for getting unpublished fallback key 2021-11-23 22:35:10 +00:00
Hubert Chathi
4127a84b3d add function for getting length of unpublished fallback keys
and fix a typo
2021-11-23 22:35:10 +00:00
Hubert Chathi
3b6ff327c0 keep testing logs 2021-11-23 22:35:10 +00:00
Hubert Chathi
b989db0117 track if fallback keys were published 2021-11-23 22:35:10 +00:00
Hubert Chathi
5039c0cc3a fix python build 2021-11-19 15:49:12 -05:00
Hubert Chathi
98b8e35a7c fix symbol exporting again 2021-11-19 15:28:43 -05:00
Denis Kasak
2430e9bb9a Add link to the Security Disclosure Policy to the README. 2021-11-19 10:17:37 +00:00
Hubert Chathi
609e7e8d40 make sure we have enough space for the encrypted and encoded version of the junk 2021-11-17 14:18:03 -05:00
Hubert Chathi
06b723db6e add note about telling olm how to find wasm file 2021-11-11 14:05:07 -05:00
Johannes Marbach
bce4f007b1 Use classic instead of semantic import
This replaces the semantic import for the Security framework with a
classic one. Semantic imports are currently not compatible with Kotlin
Multiplatform Mobile projects which makes OLMKit (and consequently
the iOS Matrix SDK) unusable in KMM.

Fixes: https://github.com/matrix-org/olm/issues/67
Signed-off-by: Johannes Marbach <n0-0ne@mailbox.org>
2021-11-08 15:15:46 -05:00
Hubert Chathi
0e7c0a5613 recommend using cmake more strongly 2021-11-02 16:16:07 -04:00
Hubert Chathi
201f139523 also install olm_export.h when using make 2021-11-02 12:49:52 -04:00
Hubert Chathi
03c5523aac fix typo 2021-09-29 18:33:30 -04:00
Hubert Chathi
8656f1463c release 3.2.6 2021-09-16 17:16:56 -04:00
Hubert Chathi
c81dfd0718 fix Python build 2021-09-16 17:06:45 -04:00
Hubert Chathi
4fb723cad3 install the export header too 2021-09-16 15:09:42 -04:00
Hubert Chathi
72b8bf5334 use visibility annotation rather than version file with CMake 2021-09-16 13:45:10 -04:00
Hubert Chathi
904e80b75f release 3.2.5 2021-09-15 19:15:58 -04:00
Onuray Sahin
06407aa08d Generate and retrieve fallback key functions added. 2021-09-14 22:19:13 +00:00
Hubert Chathi
6a63a5bfa9 use full path to externs.js because it's failing to find it 2021-09-14 18:18:26 -04:00
Hubert Chathi
e1aa1b3277 add jOlm binding 2021-08-25 21:50:33 -04:00
Stefan Ceriu
91a619b745 Added ObjC fallbackKey support and updated tests. 2021-08-18 16:44:34 +03:00
Stefan Ceriu
8ddb72cfed Updated podfile and added Xcode schemes for both iOS and macOS. 2021-08-18 16:40:32 +03:00
Hubert Chathi
6c552dd7eb use the right size in the tests 2021-08-09 16:21:13 -04:00
Hubert Chathi
d84c1af882 East const for consistency 2021-08-06 17:36:01 -04:00
Hubert Chathi
4d6c3ba8d1 make account const in create_outbound_session 2021-08-06 17:29:56 -04:00
Denis Kasak
b70e0b06df Differentiate between malformed pickle objects and trailing junk data.
Adds the OLM_PICKLE_EXTRA_DATA error code. We fail with this code when
the pickle object looks right except for some unexpected trailing bytes
which we didn't process.
2021-07-31 01:27:43 +00:00
Denis Kasak
d704f4bd3c Fail when an unpickle succeeds but has extra junk data at the end.
Also adds tests to ensure this is working.
2021-07-31 01:27:43 +00:00
Denis Kasak
131f7cfd71 Fix off-by-one comparison error when unpickling uint32_t. 2021-07-31 01:27:43 +00:00
Denis Kasak
bdd73c5c32 Fix unpickling error handling. 2021-07-31 01:27:43 +00:00
Denis Kasak
34974551ab unpickle_account: Add error checking to the harness. 2021-07-31 01:27:43 +00:00
Denis Kasak
0a8bbde361 Support building a "disarmed" target via the OLM_FUZZING macro.
Like other crypto libs, libolm contains many obstacles which a fuzzer is
unlikely to be able to surmount but which are not important for the end
goal of fuzzing. The easiest and most robust way around this is to remove
these obstacles conditionally when building the fuzzer binaries.

This commit adds a preprocessor macro OLM_FUZZING which can be used to
conditionally disables problematic bits of code during compile-time for
easier fuzzing.

Currently the only thing it disables is the encryption/decryption and
base64 encoding/decoding when processing pickled Megolm keys. This
allows the fuzzers to fuzz the unpickling functionality directly without
inadvertently fuzzing the base64 encoder and encryption (which should be
fuzzed separately).

The macro is set in the Makefile *only* when building fuzzer binaries.
2021-07-13 13:51:16 +02:00
Denis Kasak
b38e282f3a fuzzing: Add script for starting fuzzers on a given harness. 2021-07-13 13:49:18 +02:00
Denis Kasak
ceed90922a fuzzing: Add readme. 2021-07-13 13:49:18 +02:00
Denis Kasak
4d14750c38 Move fuzzers under fuzzing/ dir. 2021-07-13 13:49:18 +02:00
Denis Kasak
e06ac20558 Add unpickle_megolm_outbound fuzzer. Enable C harness support. 2021-07-13 11:13:15 +00:00
Denis Kasak
811e56a0f0 Add lib_exports.sh for printing list of exported functions.
Prints the list of exported functions from a built library object.
Useful for sanity checking.
2021-07-13 10:50:27 +02:00
Denis Kasak
583f8b761b Add some more files to .gitignore
- `compile_commands.json`: clang compilation database
- `.ccls-cache`: Cache directory for the ccls language server
- `.clang-format`: clang formatting description
2021-07-12 16:58:11 +02:00
Denis Kasak
84dbba8e1c Makefile: Remove debugging flag from the release target. 2021-07-12 16:50:34 +02:00
Denis Kasak
a44fc368f2 Makefile: Fix passing optimization flag to fuzzing builds. 2021-07-12 16:50:06 +02:00
Denis Kasak
93352b55e7 fuzz_group_decrypt: Enable AFL++ persistent mode. 2021-07-12 15:48:27 +02:00
Denis Kasak
7dd4c77c19 Add .editorconfig.
See https://editorconfig.org/ for more information.
2021-07-08 14:28:40 +00:00
Denis Kasak
4901435a0e Improve cleanup in fuzzing harnesses 2021-07-08 14:23:55 +00:00
Johannes Hayeß
254a4a5619 Fix building of tests with MSVC
Hi,

currently tests don't build with MSVC, because the Base64 test tries to initialize multiple arrays with a length value that was derived from a non-const context. I have fixed this by using vectors instead.

Sincerely

Johannes Hayeß

From 2d76972a862f0aa04b5011537bef71a49aa82a03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Johannes=20Haye=C3=9F?= <jhaye@mailbox.org>
Date: Sun, 27 Jun 2021 17:46:24 +0200
Subject: [PATCH] Fix compiling with MSVC
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Previously attempts to initialize arrays with non-const value. This
seemingly works on GCC/clang due to their static code analysis, but
fails with MSVC. This switches to dynamic memory allocation with
std::vector, to solve the problem.

Signed-off-by: Johannes Hayeß <jhaye@mailbox.org>
2021-06-29 13:14:05 -04:00
Hubert Chathi
abf8f97491 fix JavaScript build 2021-06-18 13:12:11 -04:00
Hubert Chathi
0f7c13334f install error.h when using make too 2021-06-17 15:26:46 -04:00
Hubert Chathi
2aad86ea84 fix Python build 2021-06-17 11:56:08 -04:00
Denis Kasak
9a8b421903 Update dart-olm URL. 2021-06-17 16:20:48 +02:00
Hubert Chathi
37c8e14e53 make functions const where possible 2021-06-16 23:22:25 -04:00
Hubert Chathi
7263c4221b add functions to get the error codes rather than error strings 2021-06-16 22:40:14 -04:00
Hubert Chathi
60be1ca55f add support file for cross-compiling Windows library 2021-06-16 15:28:30 -04:00
Hubert Chathi
1b7973626e only export olm functions to avoid colliding with other libraries 2021-06-16 15:05:19 -04:00
Hubert Chathi
d47c2a92b8 make new pickle/unpickle function 2021-06-09 14:59:31 +00:00
Hubert Chathi
4803f4192d make (de)serialize methods public in OlmAccount 2021-06-09 14:59:31 +00:00
Hubert Chathi
3612ac7ae7 add missing dependency in Makefile for javascript/olm_prefix.js 2021-06-08 14:57:05 -04:00
Denis Kasak
b90f9ee7d3 Fix typo in docstring (repeated word). 2021-06-04 22:24:15 +00:00
Denis Kasak
6ed8d687e8 Document olm_create_inbound_session_from properly.
The old docstring was the same as olm_create_inbound_session and didn't
explain the difference between them.
2021-06-04 22:24:15 +00:00
Denis Kasak
3e6592e445 Compile ASAN and MSAN versions of fuzzer harnesses too. 2021-06-02 14:02:19 +02:00
Denis Kasak
56df2613f3 Switch to afl-clang-fast(++).
This type of instrumentation is much faster (several times over) and
supports much more features than afl-gcc/afl-g++, though it requires
a LLVM/clang installation.
2021-06-02 14:02:19 +02:00
Hubert Chathi
64afab9364 prepare for release 2021-06-01 13:44:45 -04:00
Benoit Marty
995def932e Fix issue with Jitpack build 2021-05-28 18:12:50 +02:00
Hubert Chathi
d856c441b6 use Python 3 2021-05-24 10:32:57 -04:00
Hubert Chathi
22bc1155ed prepare for release 2021-05-24 10:29:24 -04:00
Hubert Chathi
891a5f22c8 fix path 2021-05-24 10:27:28 -04:00
Denis Kasak
ccc0d122ee olm_pk_decrypt: Ensure inputs are of correct length. 2021-05-24 15:50:14 +02:00
Denis Kasak
2f35e0bc61 olm_sas_set_their_key: Fail early on invalid base64. 2021-05-24 15:50:14 +02:00
Denis Kasak
e82f2601b0 Fail decoding base64 of invalid length.
olm::decode_base64 now returns the length of the raw decoded data on
success. When given input with an invalid base64 length, it fails early
(before decoding any input) and returns -1.

This also makes the C function _olm_decode_base64 an actual binding of
olm::decode_base64 instead of a wrapper with slightly different
behaviour.
2021-05-24 15:50:14 +02:00
Denis Kasak
a5efc08ef3 olm: Also initialize all fields when decoding Olm messages.
As a precaution.
2021-05-11 13:32:23 +02:00
Denis Kasak
c325db02fc megolm: Fix use of uninitialized value in group message decoding.
_olm_decode_group_message should initialize all fields of the results
struct before returning. This is because its caller
_decrypt_max_plaintext_length relies on it having initialized these
fields.

Luckily, this only allows one to subvert the version check in
_decrypt_max_plaintext_length, but not the following check that the
ciphertext field is non-null because that field *is* initialized.
2021-05-11 13:23:19 +02:00
Denis Kasak
0a7b6da9a0 Slightly refactor/comment the harness for clarity. 2021-05-10 21:04:44 +00:00
Denis Kasak
8d1cfd207a Fix a fuzzing harness double free when input is of size 0.
Consider the case when the input is size 0. In this case, `count` and
`buffer_pos` will be 0 as well. The `realloc` call in the `count == 0`
branch will then effectively become a free.

However, `realloc` can sometimes return `NULL` when a 0 is passed for
the size. The current code assumes that this only happens on a memory
allocation error and breaks out of the loop. This then becomes a double
free because the buffer is freed a second time, causing an abort.

The intent of the `realloc` is probably to downsize the buffer to fit
the data exactly in order to make incorrect memory access more obvious.
This commit skips this downsizing if the size of the input data is 0.
2021-05-10 21:04:44 +00:00
Arun Babu Neelicattu
15f65283c7 make: Replace deprecated emcc configuration
EXTRA_EXPORTED_RUNTIME_METHODS is deprecated. Replace with
EXPORTED_RUNTIME_METHODS.
2021-05-10 20:40:42 +00:00
Arun Babu Neelicattu
0684eb4564 ci: add initial build pipeline 2021-05-10 20:40:42 +00:00
Arun Babu Neelicattu
b0a05976ea python: remove tox basepython configuration 2021-05-10 20:40:42 +00:00
Hubert Chathi
18ad6cb067 Merge branch 'fix-ncc-audit-url' into 'master'
Fix URL to the NCC Group audit.

See merge request matrix-org/olm!22
2021-05-04 21:58:35 +00:00
Hubert Chathi
d7c3971f9a update release instructions 2021-05-04 17:54:05 -04:00
Denis Kasak
c95677611c Fix URL to the NCC Group audit.
The original URL is now redirecting to a generic listing page and there
are no links to the actual Olm audit paper there.
2021-05-04 15:09:29 +02:00
Lukas Lihotzki
7f53dedca6 Declare olm_sas_calculate_mac_fixed_base64 in header
Signed-off-by: Lukas Lihotzki <lukas@lihotzki.de>
2021-04-27 16:18:33 -04:00
437 changed files with 45313 additions and 1604 deletions

14
.editorconfig Normal file
View file

@ -0,0 +1,14 @@
root = true
[*]
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
[*.{c,cpp,h,hh,py,ts,js,java,m}]
indent_style = space
indent_size = 4
[Makefile]
indent_style = tab

10
.gitignore vendored
View file

@ -9,6 +9,13 @@
/python/dist /python/dist
/javascript/checksums.txt /javascript/checksums.txt
/javascript/checksums.txt.asc /javascript/checksums.txt.asc
/javascript/olm_prefix.js
/compile_commands.json
/.clang-format
.ccls-cache/
/python/.eggs
/python/install-temp
/result
# Xcode # Xcode
build/ build/
@ -31,3 +38,6 @@ xcuserdata/
*.dSYM *.dSYM
Pods/ Pods/
*.xcworkspace *.xcworkspace
# JetBrains tools
.idea/

51
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,51 @@
default:
image: registry.fedoraproject.org/fedora-minimal:latest
stages:
- build
- test
- trigger
build:lib:
stage: build
tags:
- docker
script:
- microdnf --assumeyes --nodocs install cmake gcc gcc-c++
- cmake . -Bbuild
- cmake --build build
artifacts:
paths:
- build/
test:lib:
stage: test
tags:
- docker
needs:
- build:lib
script:
- microdnf --assumeyes --nodocs install cmake
- pushd build/tests
- ctest .
artifacts:
paths:
- build/tests/Testing/Temporary/
trigger:android:
stage: trigger
trigger:
strategy: depend
include: android/.gitlab-ci.yml
trigger:javascript:
stage: trigger
trigger:
strategy: depend
include: javascript/.gitlab-ci.yml
trigger:python:
stage: trigger
trigger:
strategy: depend
include: python/.gitlab-ci.yml

View file

@ -1,3 +1,135 @@
Changes in `3.2.16 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.16>`_
===========================================================================
This release includes the following changes since 3.2.15:
* Fix and modernize the Python packaging (thanks to Alfred Wingate)
Changes in `3.2.15 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.15>`_
===========================================================================
This release includes the following changes since 3.2.14:
* Improvements to Python packaging
* No longer depend on ``future`` since Python 2 is no longer supported.
* Improve compatibility with tox 4.
* Add support for making standalone sdist.
* Improvements to Nix flake (Thanks to Jon Ringer)
* Improve structure.
* Enable Darwin builds.
* Typescript type fix.
Changes in `3.2.14 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.14>`_
===========================================================================
This release includes the following changes since 3.2.13:
* TypeScript type improvements.
* Improvements to Python packaging
* Documentation improvements.
Changes in `3.2.13 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.13>`_
===========================================================================
This release includes the following changes since 3.2.12:
* Fix compilation with newer versions of emscripten.
* The npm package is compiled with emscripten 3.1.17 to fix compatibility with
node 18.
* Add py.typed to Python wheels.
* Some documentation fixes and updates.
* Improve the pkgconfig file.
Changes in `3.2.12 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.12>`_
===========================================================================
This release includes the following changes since 3.2.11:
* Expose olm_sas_calculate_mac_fixed_base64 in the bindings.
* Allow memory to grow in wasm. Thanks to benkuly for the suggestion.
* Fix Python type hints.
* Some Python build fixes.
* Initial work on a Nix flake for building and testing.
Changes in `3.2.11 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.11>`_
===========================================================================
This release includes the following changes since 3.2.10:
* Fix building documentation. Thanks to Jonas Smedegaard. The documents
written in Markdown are now converted to HTML using Pandoc.
* Add methods for getting unpublished fallback key in Objective-C binding.
* Add public pickle/unpickle methods to Java binding.
* Add wrapper for olm_session_describe to Java binding. Thanks to Alex Baker.
Changes in `3.2.10 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.10>`_
===========================================================================
This release includes no change since 3.2.9, but is created to be able to
publish again the Android library on MavenCentral.
Changes in `3.2.9 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.9>`_
=========================================================================
This release includes the following changes since 3.2.8:
* Switch C++ tests to use doctest. Thanks to Nicolas Werner.
* Switch JavaScript tests to use jasmine instead of deprecated jasmine-node.
* Add session describe function to Python binding. Thanks to Tulir Asokan.
Changes in `3.2.8 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.8>`_
=========================================================================
This release includes the following changes since 3.2.7:
* Improve handling of olm_session_describe when the buffer is too small.
* Ensure random arrays are blanked in JavaScript bindings.
Changes in `3.2.7 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.7>`_
=========================================================================
This release includes the following changes since 3.2.6:
* Fix installation with the Makefile.
* Fix exporting again, so we only export olm symbols.
* Fix WASM build. Thanks to Benjamin Kampmann.
* Add more functions for fallback keys.
Changes in `3.2.6 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.6>`_
=========================================================================
This release includes the following changes since 3.2.5:
* Fix building on various platforms when using CMake. Building from the
Makefile still assumes that it is using gcc.
Changes in `3.2.5 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.5>`_
=========================================================================
This release includes the following changes since 3.2.4:
* Add functions for getting error codes rather than error strings. Thanks to
Nicolas Werner for the suggestion.
* Only export olm symbols. Thanks to Mohammed Sadiq for the suggestion.
* Improve error handling in unpickle functions.
* Add support for fallback keys to the Objective-C and Android bindings.
Changes in `3.2.4 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.4>`_
=========================================================================
This release includes the following changes since 3.2.3:
* Android build fixes.
Changes in `3.2.3 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.3>`_
=========================================================================
This release includes the following changes since 3.2.2:
* Add some checks for invalid input and ensure all fields are initialized.
* Include LibreJS license tags. Thanks to Johannes Marbach for the suggestion.
* Support for Swift Package Manager. Thanks to Johannes Marbach.
Changes in `3.2.2 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.2>`_ Changes in `3.2.2 <https://gitlab.matrix.org/matrix-org/olm/tags/3.2.2>`_
========================================================================= =========================================================================
@ -45,11 +177,13 @@ Changes in `3.1.5 <https://gitlab.matrix.org/matrix-org/olm/tags/3.1.5>`_
This release includes the following changes since 3.1.4: This release includes the following changes since 3.1.4:
* Build improvements: * Build improvements:
* Fix CMake handling when installing in a non-standard location. Thanks to * Fix CMake handling when installing in a non-standard location. Thanks to
Alexey Rusakov. Alexey Rusakov.
* Add support in the Makefile for creating a WASM-ready archive. Thanks to * Add support in the Makefile for creating a WASM-ready archive. Thanks to
stoically. stoically.
* Improve support for LLVM is Makefile. Thanks to caywin25 for reporting. * Improve support for LLVM is Makefile. Thanks to caywin25 for reporting.
* Add a TypeScript definition file. * Add a TypeScript definition file.
* Some documentation and example fixes. * Some documentation and example fixes.
* Add list of bindings to the README. * Add list of bindings to the README.

View file

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.4) cmake_minimum_required(VERSION 3.4)
project(olm VERSION 3.2.2 LANGUAGES CXX C) project(olm VERSION 3.2.16 LANGUAGES CXX C)
option(OLM_TESTS "Build tests" ON) option(OLM_TESTS "Build tests" ON)
option(BUILD_SHARED_LIBS "Build as a shared library" ON) option(BUILD_SHARED_LIBS "Build as a shared library" ON)
@ -21,6 +21,10 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release) set(CMAKE_BUILD_TYPE Release)
endif() endif()
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
set(CMAKE_VISIBILITY_INLINES_HIDDEN 1)
add_library(olm add_library(olm
src/account.cpp src/account.cpp
src/base64.cpp src/base64.cpp
@ -48,6 +52,11 @@ add_library(olm
lib/curve25519-donna/curve25519-donna.c) lib/curve25519-donna/curve25519-donna.c)
add_library(Olm::Olm ALIAS olm) add_library(Olm::Olm ALIAS olm)
# restrict the exported symbols
include(GenerateExportHeader)
generate_export_header(olm
EXPORT_FILE_NAME ${CMAKE_CURRENT_SOURCE_DIR}/include/olm/olm_export.h)
target_include_directories(olm target_include_directories(olm
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
@ -84,10 +93,12 @@ install(TARGETS olm
set_target_properties(olm PROPERTIES EXPORT_NAME Olm) set_target_properties(olm PROPERTIES EXPORT_NAME Olm)
install(FILES install(FILES
${CMAKE_CURRENT_SOURCE_DIR}/include/olm/olm.h ${CMAKE_CURRENT_SOURCE_DIR}/include/olm/olm.h
${CMAKE_CURRENT_SOURCE_DIR}/include/olm/olm_export.h
${CMAKE_CURRENT_SOURCE_DIR}/include/olm/outbound_group_session.h ${CMAKE_CURRENT_SOURCE_DIR}/include/olm/outbound_group_session.h
${CMAKE_CURRENT_SOURCE_DIR}/include/olm/inbound_group_session.h ${CMAKE_CURRENT_SOURCE_DIR}/include/olm/inbound_group_session.h
${CMAKE_CURRENT_SOURCE_DIR}/include/olm/pk.h ${CMAKE_CURRENT_SOURCE_DIR}/include/olm/pk.h
${CMAKE_CURRENT_SOURCE_DIR}/include/olm/sas.h ${CMAKE_CURRENT_SOURCE_DIR}/include/olm/sas.h
${CMAKE_CURRENT_SOURCE_DIR}/include/olm/error.h
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/olm) DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/olm)
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)

139
Makefile
View file

@ -4,15 +4,12 @@ include common.mk
VERSION := $(MAJOR).$(MINOR).$(PATCH) VERSION := $(MAJOR).$(MINOR).$(PATCH)
PREFIX ?= /usr/local PREFIX ?= /usr/local
BUILD_DIR := build BUILD_DIR := build
RELEASE_OPTIMIZE_FLAGS ?= -g -O3 RELEASE_OPTIMIZE_FLAGS ?= -O3
DEBUG_OPTIMIZE_FLAGS ?= -g -O0 DEBUG_OPTIMIZE_FLAGS ?= -g -O0 -U_FORTIFY_SOURCE
JS_OPTIMIZE_FLAGS ?= -O3 JS_OPTIMIZE_FLAGS ?= -O3
FUZZING_OPTIMIZE_FLAGS ?= -O3 FUZZER_OPTIMIZE_FLAGS ?= -O3
CC = gcc
EMCC = emcc EMCC = emcc
EMAR = emar EMAR = emar
AFL_CC = afl-gcc
AFL_CXX = afl-g++
AR = ar AR = ar
UNAME := $(shell uname) UNAME := $(shell uname)
@ -33,24 +30,29 @@ JS_ASMJS_TARGET := javascript/olm_legacy.js
WASM_TARGET := $(BUILD_DIR)/wasm/libolm.a WASM_TARGET := $(BUILD_DIR)/wasm/libolm.a
JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json
JS_EXTRA_EXPORTED_RUNTIME_METHODS := [ALLOC_STACK] JS_EXPORTED_RUNTIME_METHODS := [ALLOC_STACK,writeAsciiToMemory,intArrayFromString,UTF8ToString,stringToUTF8]
JS_EXTERNS := javascript/externs.js JS_EXTERNS := javascript/externs.js
PUBLIC_HEADERS := include/olm/olm.h include/olm/outbound_group_session.h include/olm/inbound_group_session.h include/olm/pk.h include/olm/sas.h PUBLIC_HEADERS := include/olm/olm.h include/olm/outbound_group_session.h include/olm/inbound_group_session.h include/olm/pk.h include/olm/sas.h include/olm/error.h include/olm/olm_export.h
SOURCES := $(wildcard src/*.cpp) $(wildcard src/*.c) \ SOURCES := $(wildcard src/*.cpp) $(wildcard src/*.c) \
lib/crypto-algorithms/sha256.c \ lib/crypto-algorithms/sha256.c \
lib/crypto-algorithms/aes.c \ lib/crypto-algorithms/aes.c \
lib/curve25519-donna/curve25519-donna.c lib/curve25519-donna/curve25519-donna.c
FUZZER_SOURCES := $(wildcard fuzzers/fuzz_*.cpp) $(wildcard fuzzers/fuzz_*.c) FUZZER_SOURCES := $(wildcard fuzzing/fuzzers/fuzz_*.cpp) $(wildcard fuzzing/fuzzers/fuzz_*.c)
TEST_SOURCES := $(wildcard tests/test_*.cpp) $(wildcard tests/test_*.c) TEST_SOURCES := $(wildcard tests/test_*.cpp) $(wildcard tests/test_*.c)
OBJECTS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES))) OBJECTS := $(patsubst %.c,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))
RELEASE_OBJECTS := $(addprefix $(BUILD_DIR)/release/,$(OBJECTS)) RELEASE_OBJECTS := $(addprefix $(BUILD_DIR)/release/,$(OBJECTS))
DEBUG_OBJECTS := $(addprefix $(BUILD_DIR)/debug/,$(OBJECTS)) DEBUG_OBJECTS := $(addprefix $(BUILD_DIR)/debug/,$(OBJECTS))
FUZZER_OBJECTS := $(addprefix $(BUILD_DIR)/fuzzers/objects/,$(OBJECTS)) FUZZER_OBJECTS := $(addprefix $(BUILD_DIR)/fuzzers/objects/,$(OBJECTS))
FUZZER_BINARIES := $(addprefix $(BUILD_DIR)/,$(basename $(FUZZER_SOURCES))) FUZZER_ASAN_OBJECTS := $(addprefix $(BUILD_DIR)/fuzzers/objects/,$(addprefix asan_,$(OBJECTS)))
FUZZER_MSAN_OBJECTS := $(addprefix $(BUILD_DIR)/fuzzers/objects/,$(addprefix msan_,$(OBJECTS)))
FUZZER_DEBUG_OBJECTS := $(addprefix $(BUILD_DIR)/fuzzers/objects/,$(addprefix debug_,$(OBJECTS)))
FUZZER_BINARIES := $(addprefix $(BUILD_DIR)/fuzzers/,$(basename $(notdir $(FUZZER_SOURCES))))
FUZZER_ASAN_BINARIES := $(addsuffix _asan,$(FUZZER_BINARIES))
FUZZER_MSAN_BINARIES := $(addsuffix _msan,$(FUZZER_BINARIES))
FUZZER_DEBUG_BINARIES := $(patsubst $(BUILD_DIR)/fuzzers/fuzz_%,$(BUILD_DIR)/fuzzers/debug_%,$(FUZZER_BINARIES)) FUZZER_DEBUG_BINARIES := $(patsubst $(BUILD_DIR)/fuzzers/fuzz_%,$(BUILD_DIR)/fuzzers/debug_%,$(FUZZER_BINARIES))
TEST_BINARIES := $(patsubst tests/%,$(BUILD_DIR)/tests/%,$(basename $(TEST_SOURCES))) TEST_BINARIES := $(patsubst tests/%,$(BUILD_DIR)/tests/%,$(basename $(TEST_SOURCES)))
JS_OBJECTS := $(addprefix $(BUILD_DIR)/javascript/,$(OBJECTS)) JS_OBJECTS := $(addprefix $(BUILD_DIR)/javascript/,$(OBJECTS))
@ -91,7 +93,7 @@ LDFLAGS += -Wall -Werror
CFLAGS_NATIVE = -fPIC CFLAGS_NATIVE = -fPIC
CXXFLAGS_NATIVE = -fPIC CXXFLAGS_NATIVE = -fPIC
EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0 -s MODULARIZE=1 EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0 -s MODULARIZE=1 -Wno-error=closure
# Olm generally doesn't need a lot of memory to encrypt / decrypt its usual # Olm generally doesn't need a lot of memory to encrypt / decrypt its usual
# payloads (ie. Matrix messages), but we do need about 128K of heap to encrypt # payloads (ie. Matrix messages), but we do need about 128K of heap to encrypt
@ -101,18 +103,29 @@ EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0
# (This can't be changed by the app with wasm since it's baked into the wasm). # (This can't be changed by the app with wasm since it's baked into the wasm).
# (emscripten also mandates at least 16MB of memory for asm.js now, so # (emscripten also mandates at least 16MB of memory for asm.js now, so
# we don't use this for the legacy build.) # we don't use this for the legacy build.)
EMCCFLAGS_WASM += -s TOTAL_STACK=65536 -s TOTAL_MEMORY=262144 EMCCFLAGS_WASM += -s TOTAL_STACK=65536 -s TOTAL_MEMORY=262144 -s ALLOW_MEMORY_GROWTH
EMCCFLAGS_ASMJS += -s WASM=0 EMCCFLAGS_ASMJS += -s WASM=0
EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c -DNDEBUG -DOLM_STATIC_DEFINE=1
EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c -DNDEBUG -DOLM_STATIC_DEFINE=1
EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS) EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS)
AFL_CC = afl-clang-fast
AFL_CXX = afl-clang-fast++
AFL.c = $(AFL_CC) $(CFLAGS) $(CPPFLAGS) -c AFL.c = $(AFL_CC) $(CFLAGS) $(CPPFLAGS) -c
AFL.cc = $(AFL_CXX) $(CXXFLAGS) $(CPPFLAGS) -c AFL.cc = $(AFL_CXX) $(CXXFLAGS) $(CPPFLAGS) -c
AFL_LINK.c = $(AFL_CC) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS) AFL_LINK.c = $(AFL_CC) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS)
AFL_LINK.cc = $(AFL_CXX) $(LDFLAGS) $(CXXFLAGS) $(CPPFLAGS) AFL_LINK.cc = $(AFL_CXX) $(LDFLAGS) $(CXXFLAGS) $(CPPFLAGS)
AFL_ASAN.c = AFL_USE_ASAN=1 $(AFL_CC) -m32 $(CFLAGS) $(CPPFLAGS) -c
AFL_ASAN.cc = AFL_USE_ASAN=1 $(AFL_CXX) -m32 $(CXXFLAGS) $(CPPFLAGS) -c
AFL_LINK_ASAN.c = AFL_USE_ASAN=1 $(AFL_CC) -m32 $(LDFLAGS) $(CFLAGS) $(CPPFLAGS)
AFL_LINK_ASAN.cc = AFL_USE_ASAN=1 $(AFL_CXX) -m32 $(LDFLAGS) $(CXXFLAGS) $(CPPFLAGS)
AFL_MSAN.c = AFL_USE_MSAN=1 $(AFL_CC) $(CFLAGS) $(CPPFLAGS) -c
AFL_MSAN.cc = AFL_USE_MSAN=1 $(AFL_CXX) $(CXXFLAGS) $(CPPFLAGS) -c
AFL_LINK_MSAN.c = AFL_USE_MSAN=1 $(AFL_CC) $(LDFLAGS) $(CFLAGS) $(CPPFLAGS)
AFL_LINK_MSAN.cc = AFL_USE_MSAN=1 $(AFL_CXX) $(LDFLAGS) $(CXXFLAGS) $(CPPFLAGS)
# generate .d files when compiling # generate .d files when compiling
CPPFLAGS += -MMD CPPFLAGS += -MMD
@ -130,12 +143,23 @@ $(DEBUG_TARGET): LDFLAGS += $(DEBUG_OPTIMIZE_FLAGS)
$(TEST_BINARIES): CPPFLAGS += -Itests/include $(TEST_BINARIES): CPPFLAGS += -Itests/include
$(TEST_BINARIES): LDFLAGS += $(DEBUG_OPTIMIZE_FLAGS) -L$(BUILD_DIR) $(TEST_BINARIES): LDFLAGS += $(DEBUG_OPTIMIZE_FLAGS) -L$(BUILD_DIR)
$(FUZZER_OBJECTS): CFLAGS += $(FUZZER_OPTIMIZE_FLAGS) $(FUZZER_OBJECTS): CFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -D OLM_FUZZING=1
$(FUZZER_OBJECTS): CXXFLAGS += $(FUZZER_OPTIMIZE_FLAGS) $(FUZZER_OBJECTS): CXXFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -D OLM_FUZZING=1
$(FUZZER_BINARIES): CPPFLAGS += -Ifuzzers/include $(FUZZER_DEBUG_OBJECTS): CFLAGS += $(DEBUG_OPTIMIZE_FLAGS) $(CFLAGS_NATIVE) -D OLM_FUZZING=1
$(FUZZER_BINARIES): LDFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -L$(BUILD_DIR) $(FUZZER_DEBUG_OBJECTS): CXXFLAGS += $(DEBUG_OPTIMIZE_FLAGS) $(CXXFLAGS_NATIVE) -D OLM_FUZZING=1
$(FUZZER_DEBUG_BINARIES): CPPFLAGS += -Ifuzzers/include $(FUZZER_ASAN_OBJECTS): CFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -D OLM_FUZZING=1
$(FUZZER_DEBUG_BINARIES): LDFLAGS += $(DEBUG_OPTIMIZE_FLAGS) $(FUZZER_ASAN_OBJECTS): CXXFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -D OLM_FUZZING=1
$(FUZZER_MSAN_OBJECTS): CFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -D OLM_FUZZING=1
$(FUZZER_MSAN_OBJECTS): CXXFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -D OLM_FUZZING=1
$(FUZZER_BINARIES): CPPFLAGS += -Ifuzzing/fuzzers/include
$(FUZZER_BINARIES): LDFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -L$(BUILD_DIR) -lstdc++
$(FUZZER_ASAN_BINARIES): CPPFLAGS += -Ifuzzing/fuzzers/include
$(FUZZER_ASAN_BINARIES): LDFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -L$(BUILD_DIR) -lstdc++
$(FUZZER_MSAN_BINARIES): CPPFLAGS += -Ifuzzing/fuzzers/include
$(FUZZER_MSAN_BINARIES): LDFLAGS += $(FUZZER_OPTIMIZE_FLAGS) -L$(BUILD_DIR) -lstdc++
$(FUZZER_DEBUG_BINARIES): CPPFLAGS += -Ifuzzing/fuzzers/include
$(FUZZER_DEBUG_BINARIES): LDFLAGS += $(DEBUG_OPTIMIZE_FLAGS) -lstdc++
$(JS_OBJECTS): CFLAGS += $(JS_OPTIMIZE_FLAGS) $(JS_OBJECTS): CFLAGS += $(JS_OPTIMIZE_FLAGS)
$(JS_OBJECTS): CXXFLAGS += $(JS_OPTIMIZE_FLAGS) $(JS_OBJECTS): CXXFLAGS += $(JS_OPTIMIZE_FLAGS)
@ -161,6 +185,12 @@ lib: $(RELEASE_TARGET)
.PHONY: lib .PHONY: lib
$(RELEASE_TARGET): $(RELEASE_OBJECTS) $(RELEASE_TARGET): $(RELEASE_OBJECTS)
@echo
@echo '****************************************************************************'
@echo '* WARNING: Building olm with make is deprecated. Please use cmake instead. *'
@echo '****************************************************************************'
@echo
$(CXX) $(LDFLAGS) --shared -fPIC \ $(CXX) $(LDFLAGS) --shared -fPIC \
$(OLM_LDFLAGS) \ $(OLM_LDFLAGS) \
$(OUTPUT_OPTION) $(RELEASE_OBJECTS) $(OUTPUT_OPTION) $(RELEASE_OBJECTS)
@ -191,32 +221,32 @@ wasm: $(WASM_TARGET)
$(WASM_TARGET): $(WASM_OBJECTS) $(WASM_TARGET): $(WASM_OBJECTS)
$(EMAR) rcs $@ $^ $(EMAR) rcs $@ $^
javascript/olm_prefix.js: javascript/olm_prefix.js.in Makefile javascript/olm_prefix.js: javascript/olm_prefix.js.in Makefile common.mk
sed s/@VERSION@/$(VERSION)/ javascript/olm_prefix.js.in > $@ sed s/@VERSION@/$(VERSION)/ javascript/olm_prefix.js.in > $@
# Note that the output file we give to emcc determines the name of the # Note that the output file we give to emcc determines the name of the
# wasm file baked into the js, hence messing around outputting to olm.js # wasm file baked into the js, hence messing around outputting to olm.js
# and then renaming it. # and then renaming it.
$(JS_WASM_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) $(JS_PREFIX) $(JS_SUFFIX) $(JS_WASM_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) $(JS_PREFIX) $(JS_SUFFIX)
EMCC_CLOSURE_ARGS="--externs $(JS_EXTERNS)" $(EMCC_LINK) \ EMCC_CLOSURE_ARGS="--externs $(CURDIR)/$(JS_EXTERNS)" $(EMCC_LINK) \
$(EMCCFLAGS_WASM) \ $(EMCCFLAGS_WASM) \
$(foreach f,$(JS_PRE),--pre-js $(f)) \ $(foreach f,$(JS_PRE),--pre-js $(f)) \
$(foreach f,$(JS_POST),--post-js $(f)) \ $(foreach f,$(JS_POST),--post-js $(f)) \
$(foreach f,$(JS_PREFIX),--extern-pre-js $(f)) \ $(foreach f,$(JS_PREFIX),--extern-pre-js $(f)) \
$(foreach f,$(JS_SUFFIX),--extern-post-js $(f)) \ $(foreach f,$(JS_SUFFIX),--extern-post-js $(f)) \
-s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \ -s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \
-s "EXTRA_EXPORTED_RUNTIME_METHODS=$(JS_EXTRA_EXPORTED_RUNTIME_METHODS)" \ -s "EXPORTED_RUNTIME_METHODS=$(JS_EXPORTED_RUNTIME_METHODS)" \
-o $@ $(JS_OBJECTS) -o $@ $(JS_OBJECTS)
$(JS_ASMJS_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) $(JS_PREFIX) $(JS_SUFFIX) $(JS_ASMJS_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) $(JS_PREFIX) $(JS_SUFFIX)
EMCC_CLOSURE_ARGS="--externs $(JS_EXTERNS)" $(EMCC_LINK) \ EMCC_CLOSURE_ARGS="--externs $(CURDIR)/$(JS_EXTERNS)" $(EMCC_LINK) \
$(EMCCFLAGS_ASMJS) \ $(EMCCFLAGS_ASMJS) \
$(foreach f,$(JS_PRE),--pre-js $(f)) \ $(foreach f,$(JS_PRE),--pre-js $(f)) \
$(foreach f,$(JS_POST),--post-js $(f)) \ $(foreach f,$(JS_POST),--post-js $(f)) \
$(foreach f,$(JS_PREFIX),--extern-pre-js $(f)) \ $(foreach f,$(JS_PREFIX),--extern-pre-js $(f)) \
$(foreach f,$(JS_SUFFIX),--extern-post-js $(f)) \ $(foreach f,$(JS_SUFFIX),--extern-post-js $(f)) \
-s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \ -s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \
-s "EXTRA_EXPORTED_RUNTIME_METHODS=$(JS_EXTRA_EXPORTED_RUNTIME_METHODS)" \ -s "EXPORTED_RUNTIME_METHODS=$(JS_EXPORTED_RUNTIME_METHODS)" \
-o $@ $(JS_OBJECTS) -o $@ $(JS_OBJECTS)
build_tests: $(TEST_BINARIES) build_tests: $(TEST_BINARIES)
@ -233,7 +263,7 @@ test_mem: build_tests
valgrind -q --leak-check=yes --exit-on-first-error=yes --error-exitcode=1 $$i || exit $$?; \ valgrind -q --leak-check=yes --exit-on-first-error=yes --error-exitcode=1 $$i || exit $$?; \
done done
fuzzers: $(FUZZER_BINARIES) $(FUZZER_DEBUG_BINARIES) fuzzers: $(FUZZER_BINARIES) $(FUZZER_ASAN_BINARIES) $(FUZZER_MSAN_BINARIES) $(FUZZER_DEBUG_BINARIES)
.PHONY: fuzzers .PHONY: fuzzers
$(JS_EXPORTED_FUNCTIONS): $(PUBLIC_HEADERS) $(JS_EXPORTED_FUNCTIONS): $(PUBLIC_HEADERS)
@ -318,21 +348,61 @@ $(BUILD_DIR)/fuzzers/objects/%.o: %.cpp
$(call mkdir,$(dir $@)) $(call mkdir,$(dir $@))
$(AFL.cc) $(OUTPUT_OPTION) $< $(AFL.cc) $(OUTPUT_OPTION) $<
$(BUILD_DIR)/fuzzers/fuzz_%: fuzzers/fuzz_%.c $(FUZZER_OBJECTS) $(BUILD_DIR)/fuzzers/objects/asan_%.o: %.c
$(call mkdir,$(dir $@))
$(AFL_ASAN.c) $(OUTPUT_OPTION) $<
$(BUILD_DIR)/fuzzers/objects/asan_%.o: %.cpp
$(call mkdir,$(dir $@))
$(AFL_ASAN.cc) $(OUTPUT_OPTION) $<
$(BUILD_DIR)/fuzzers/objects/msan_%.o: %.c
$(call mkdir,$(dir $@))
$(AFL_MSAN.c) $(OUTPUT_OPTION) $<
$(BUILD_DIR)/fuzzers/objects/msan_%.o: %.cpp
$(call mkdir,$(dir $@))
$(AFL_MSAN.cc) $(OUTPUT_OPTION) $<
$(BUILD_DIR)/fuzzers/objects/debug_%.o: %.c
$(call mkdir,$(dir $@))
$(COMPILE.c) $(OUTPUT_OPTION) $<
$(BUILD_DIR)/fuzzers/objects/debug_%.o: %.cpp
$(call mkdir,$(dir $@))
$(COMPILE.cc) $(OUTPUT_OPTION) $<
$(BUILD_DIR)/fuzzers/fuzz_%: fuzzing/fuzzers/fuzz_%.c $(FUZZER_OBJECTS)
$(AFL_LINK.c) -o $@ $< $(FUZZER_OBJECTS) $(LOADLIBES) $(LDLIBS) $(AFL_LINK.c) -o $@ $< $(FUZZER_OBJECTS) $(LOADLIBES) $(LDLIBS)
$(BUILD_DIR)/fuzzers/fuzz_%: fuzzers/fuzz_%.cpp $(FUZZER_OBJECTS) $(BUILD_DIR)/fuzzers/fuzz_%: fuzzing/fuzzers/fuzz_%.cpp $(FUZZER_OBJECTS)
$(AFL_LINK.cc) -o $@ $< $(FUZZER_OBJECTS) $(LOADLIBES) $(LDLIBS) $(AFL_LINK.cc) -o $@ $< $(FUZZER_OBJECTS) $(LOADLIBES) $(LDLIBS)
$(BUILD_DIR)/fuzzers/debug_%: fuzzers/fuzz_%.c $(DEBUG_OBJECTS) $(BUILD_DIR)/fuzzers/debug_%: fuzzing/fuzzers/fuzz_%.c $(FUZZER_DEBUG_OBJECTS)
$(LINK.c) -o $@ $< $(DEBUG_OBJECTS) $(LOADLIBES) $(LDLIBS) $(LINK.c) -o $@ $< $(FUZZER_DEBUG_OBJECTS) $(LOADLIBES) $(LDLIBS)
$(BUILD_DIR)/fuzzers/debug_%: fuzzers/fuzz_%.cpp $(DEBUG_OBJECTS) $(BUILD_DIR)/fuzzers/debug_%: fuzzing/fuzzers/fuzz_%.cpp $(FUZZER_DEBUG_OBJECTS)
$(LINK.cc) -o $@ $< $(DEBUG_OBJECTS) $(LOADLIBES) $(LDLIBS) $(LINK.cc) -o $@ $< $(FUZZER_DEBUG_OBJECTS) $(LOADLIBES) $(LDLIBS)
$(BUILD_DIR)/fuzzers/fuzz_%_asan: fuzzing/fuzzers/fuzz_%.c $(FUZZER_ASAN_OBJECTS)
$(AFL_LINK_ASAN.c) -o $@ $< $(FUZZER_ASAN_OBJECTS) $(LOADLIBES) $(LDLIBS)
$(BUILD_DIR)/fuzzers/fuzz_%_asan: fuzzing/fuzzers/fuzz_%.cpp $(FUZZER_ASAN_OBJECTS)
$(AFL_LINK_ASAN.cc) -o $@ $< $(FUZZER_ASAN_OBJECTS) $(LOADLIBES) $(LDLIBS)
$(BUILD_DIR)/fuzzers/fuzz_%_msan: fuzzing/fuzzers/fuzz_%.c $(FUZZER_MSAN_OBJECTS)
$(AFL_LINK_MSAN.c) -o $@ $< $(FUZZER_MSAN_OBJECTS) $(LOADLIBES) $(LDLIBS)
$(BUILD_DIR)/fuzzers/fuzz_%_msan: fuzzing/fuzzers/fuzz_%.cpp $(FUZZER_MSAN_OBJECTS)
$(AFL_LINK_MSAN.cc) -o $@ $< $(FUZZER_MSAN_OBJECTS) $(LOADLIBES) $(LDLIBS)
%.html: %.rst %.html: %.rst
rst2html $< $@ rst2html $< $@
%.html: %.md
pandoc --from markdown --to html5 --standalone --lua-filter gitlab-math.lua --katex -o $@ $<
### dependencies ### dependencies
-include $(RELEASE_OBJECTS:.o=.d) -include $(RELEASE_OBJECTS:.o=.d)
@ -340,5 +410,10 @@ $(BUILD_DIR)/fuzzers/debug_%: fuzzers/fuzz_%.cpp $(DEBUG_OBJECTS)
-include $(JS_OBJECTS:.o=.d) -include $(JS_OBJECTS:.o=.d)
-include $(TEST_BINARIES:=.d) -include $(TEST_BINARIES:=.d)
-include $(FUZZER_OBJECTS:.o=.d) -include $(FUZZER_OBJECTS:.o=.d)
-include $(FUZZER_DEBUG_OBJECTS:.o=.d)
-include $(FUZZER_ASAN_OBJECTS:.o=.d)
-include $(FUZZER_MSAN_OBJECTS:.o=.d)
-include $(FUZZER_BINARIES:=.d) -include $(FUZZER_BINARIES:=.d)
-include $(FUZZER_ASAN_BINARIES:=.d)
-include $(FUZZER_MSAN_BINARIES:=.d)
-include $(FUZZER_DEBUG_BINARIES:=.d) -include $(FUZZER_DEBUG_BINARIES:=.d)

View file

@ -3,7 +3,7 @@ Pod::Spec.new do |s|
# The libolm version # The libolm version
MAJOR = 3 MAJOR = 3
MINOR = 2 MINOR = 2
PATCH = 2 PATCH = 16
s.name = "OLMKit" s.name = "OLMKit"
s.version = "#{MAJOR}.#{MINOR}.#{PATCH}" s.version = "#{MAJOR}.#{MINOR}.#{PATCH}"

View file

@ -2,7 +2,7 @@
import PackageDescription import PackageDescription
let major = 3, minor = 2, patch = 2 let major = 3, minor = 2, patch = 16
let package = Package( let package = Package(
name: "Olm", name: "Olm",

243
README.md
View file

@ -9,85 +9,92 @@ The specification of the Olm ratchet can be found in [docs/olm.md](docs/olm.md).
This library also includes an implementation of the Megolm cryptographic This library also includes an implementation of the Megolm cryptographic
ratchet, as specified in [docs/megolm.md](docs/megolm.md). ratchet, as specified in [docs/megolm.md](docs/megolm.md).
## Installing
### Linux and other Unix-like systems
Your distribution may have pre-compiled packages available. If not, or if you
need a newer version, you will need to compile from source. See the "Building"
section below for more details.
### macOS
The easiest way to install on macOS is via Homebrew. If you do not have
Homebrew installed, follow the instructions at https://brew.sh/ to install it.
You can then install libolm by running
```bash
brew install libolm
```
If you also need the Python packages, you can run
```bash
pip3 install python-olm --global-option="build_ext" --global-option="--include-dirs="`brew --prefix libolm`"/include" --global-option="--library-dirs="`brew --prefix libolm`"/lib"
```
Note that this will install an older version of the Python bindings, which may
be missing some functions. If you need the latest version, you will need to
build from source.
### Windows
You will need to build from source. See the "Building" section below for more
details.
### Bindings
#### JavaScript
You can use pre-built npm packages, available at
<https://gitlab.matrix.org/matrix-org/olm/-/packages?type=npm>.
#### Python
A Python source package and pre-built packages for certain architectures from
<https://pypi.org/project/python-olm/>. If a pre-built package is not
available for your architecture, you will need:
- cmake (recommended) or GNU make
- a C/C++ compiler
to build the source package.
You can then run `pip install python-olm`.
Currently, we try to provide packages for all supported versions of Python on
x86-64, i686, and aarch64, but we cannot guarantee that packages for all
versions will be available on all architectures.
#### Android
Pre-built Android bindings are available at
<https://gitlab.matrix.org/matrix-org/olm/-/packages?type=Maven>.
## Building ## Building
To build olm as a shared library run either: To build olm as a shared library run:
```bash ```bash
cmake . -Bbuild cmake . -Bbuild
cmake --build build cmake --build build
``` ```
or: To run the tests, run:
```bash
make
```
Using cmake is the preferred method for building the shared library; the
Makefile may be removed in the future.
To run the tests when using cmake, run:
```bash ```bash
cd build/tests cd build/tests
ctest . ctest .
``` ```
To run the tests when using make, run:
```bash To build olm as a static library (which still needs libstdc++ dynamically) run:
make test
```
To build the JavaScript bindings, install emscripten from http://kripken.github.io/emscripten-site/ and then run:
```bash
make js
```
Note that if you run emscripten in a docker container, you need to pass through
the EMCC_CLOSURE_ARGS environment variable.
To build the android project for Android bindings, run:
```bash
cd android
./gradlew clean assembleRelease
```
To build the Xcode workspace for Objective-C bindings, run:
```bash
cd xcode
pod install
open OLMKit.xcworkspace
```
To build the Python bindings, first build olm as a shared library as above, and
then run:
```bash
cd python
make
```
to make both the Python 2 and Python 3 bindings. To make only one version, use
``make olm-python2`` or ``make olm-python3`` instead of just ``make``.
To build olm as a static library (which still needs libstdc++ dynamically) run
either:
```bash ```bash
cmake . -Bbuild -DBUILD_SHARED_LIBS=NO cmake . -Bbuild -DBUILD_SHARED_LIBS=NO
cmake --build build cmake --build build
``` ```
or
```bash
make static
```
The library can also be used as a dependency with CMake using: The library can also be used as a dependency with CMake using:
```cmake ```cmake
@ -95,6 +102,83 @@ find_package(Olm::Olm REQUIRED)
target_link_libraries(my_exe Olm::Olm) target_link_libraries(my_exe Olm::Olm)
``` ```
### Bindings
#### JavaScript
The recommended way to build the JavaScript bindings is using
[Nix](https://nixos.org/). With Nix, you can run
```bash
nix build .\#javascript
```
to build the bindings.
If you do not have Nix you can, install emscripten from https://emscripten.org/
and then run:
```bash
make js
```
Emscripten can also be run via Docker, in which case, you need to pass through
the EMCC_CLOSURE_ARGS environment variable.
#### Android
To build the android project for Android bindings, run:
```bash
cd android
./gradlew clean build
```
#### Objective-C
To build the Xcode workspace for Objective-C bindings, run:
```bash
cd xcode
pod install
open OLMKit.xcworkspace
```
#### Python
To build the Python 3 bindings, first build olm as a library as above, and
then run:
```bash
cd python
make
```
### Using make instead of cmake
**WARNING:** Using cmake is the preferred method for building the olm library;
the Makefile may be removed in the future or have functionality removed. In
addition, the Makefile may make certain assumptions about your system and is
not as well tested.
To build olm as a dynamic library, run:
```bash
make
```
To run the tests, run:
```bash
make test
```
To build olm as a static library, run:
```bash
make static
```
## Bindings ## Bindings
libolm can be used in different environments using bindings. In addition to the libolm can be used in different environments using bindings. In addition to the
@ -102,16 +186,19 @@ JavaScript, Python, Java (Android), and Objective-C bindings included in this
repository, some bindings are (in alphabetical order): repository, some bindings are (in alphabetical order):
- [cl-megolm](https://github.com/K1D77A/cl-megolm) (MIT) Common Lisp bindings - [cl-megolm](https://github.com/K1D77A/cl-megolm) (MIT) Common Lisp bindings
- [dart-olm](https://gitlab.com/famedly/libraries/dart-olm) (AGPLv3) Dart bindings - [dart-olm](https://gitlab.com/famedly/company/frontend/libraries/dart-olm) (AGPLv3) Dart bindings
- [Dhole/go-olm](https://github.com/Dhole/go-olm) (Apache-2.0) Go bindings - [Dhole/go-olm](https://github.com/Dhole/go-olm) (Apache-2.0) Go bindings
- [jOlm](https://github.com/brevilo/jolm) (Apache-2.0) Java bindings
- [libQtOlm](https://gitlab.com/b0/libqtolm/) (GPLv3) Qt bindings - [libQtOlm](https://gitlab.com/b0/libqtolm/) (GPLv3) Qt bindings
- [matrix-kt](https://github.com/Dominaezzz/matrix-kt) (Apache-2.0) Kotlin - [matrix-kt](https://github.com/Dominaezzz/matrix-kt) (Apache-2.0) Kotlin
library for Matrix, including Olm methods library for Matrix, including Olm methods
- [maunium.net/go/mautrix/crypto/olm](https://github.com/tulir/mautrix-go/tree/master/crypto/olm) - [maunium.net/go/mautrix/crypto/olm](https://github.com/tulir/mautrix-go/tree/master/crypto/olm)
(Apache-2.0) fork of Dhole/go-olm (Apache-2.0) fork of Dhole/go-olm
- [nim-olm](https://gitea.com/BarrOff/nim-olm) (MIT) Nim bindings - [nim-olm](https://codeberg.org/BarrOff/nim-olm) (MIT) Nim bindings
- [olm-sys](https://gitlab.gnome.org/BrainBlasted/olm-sys) (Apache-2.0) Rust - [olm-sys](https://gitlab.gnome.org/BrainBlasted/olm-sys) (Apache-2.0) Rust
bindings bindings
- [Trixnity](https://gitlab.com/trixnity/trixnity) (Apache-2.0) Kotlin SDK for
Matrix, including Olm bindings
Note that bindings may have a different license from libolm, and are *not* Note that bindings may have a different license from libolm, and are *not*
endorsed by the Matrix.org Foundation C.I.C. endorsed by the Matrix.org Foundation C.I.C.
@ -119,8 +206,8 @@ endorsed by the Matrix.org Foundation C.I.C.
## Release process ## Release process
First: bump version numbers in ``common.mk``, ``CMakeLists.txt``, First: bump version numbers in ``common.mk``, ``CMakeLists.txt``,
``javascript/package.json``, ``python/olm/__version__.py``, ``OLMKit.podspec``, ``Package.swift``, ``javascript/package.json``, ``python/pyproject.toml``, ``OLMKit.podspec``,
and ``android/olm-sdk/java/org/matrix/olm/OlmManager.java`` in function ``getVersion()```. ``Package.swift``, and ``android/gradle.properties``.
Also, ensure the changelog is up to date, and that everything is committed to Also, ensure the changelog is up to date, and that everything is committed to
git. git.
@ -136,11 +223,13 @@ make test
# build and test JS wrapper # build and test JS wrapper
make js make js
(cd javascript && npm run test && npm pack javascript) (cd javascript && \
npm run test && \
sha256sum olm.js olm_legacy.js olm.wasm > checksums.txt && \
gpg -b -a -u F75FDC22C1DE8453 checksums.txt && \
npm publish)
VERSION=x.y.z VERSION=x.y.z
gpg -b -a -u F75FDC22C1DE8453 javascript/olm-$VERSION.tgz
scp javascript/olm-$VERSION.tgz packages@ares.matrix.org:packages/npm/olm/
git tag $VERSION -s git tag $VERSION -s
git push --tags git push --tags
@ -153,6 +242,20 @@ pod trunk push OLMKit.podspec --use-libraries --allow-warnings
pod search OLMKit pod search OLMKit
``` ```
Python and JavaScript packages are published to the registry at
<https://gitlab.matrix.org/matrix-org/olm/-/packages>. The GitLab
documentation contains instructions on how to set up twine (Python) and npm
(JavaScript) to upload to the registry.
To publish the Android library to MavenCentral (you will need some secrets), in the /android folder:
- Run the command `./gradlew clean build publish --no-daemon --no-parallel --stacktrace`. The generated AAR must be approx 500 kb.
- Connect to https://s01.oss.sonatype.org
- Click on Staging Repositories and check the the files have been uploaded
- Click on close
- Wait (check Activity tab until step "Repository closed" is displayed)
- Click on release. The staging repository will disappear
- Check that the release is available in https://repo1.maven.org/maven2/org/matrix/android/olm-sdk/ (it can take a few minutes)
## Design ## Design
Olm is designed to be easy port to different platforms and to be easy Olm is designed to be easy port to different platforms and to be easy
@ -201,12 +304,16 @@ Please see [CONTRIBUTING.md](CONTRIBUTING.md) when making contributions to the l
Olm 1.3.0 was independently assessed by NCC Group's Cryptography Services Olm 1.3.0 was independently assessed by NCC Group's Cryptography Services
Practive in September 2016 to check for security issues: you can read all Practive in September 2016 to check for security issues: you can read all
about it at about it at
https://www.nccgroup.trust/us/our-research/matrix-olm-cryptographic-review/ https://www.nccgroup.com/globalassets/our-research/us/public-reports/2016/november/ncc_group_olm_cryptogrpahic_review_2016_11_01.pdf
and https://matrix.org/blog/2016/11/21/matrixs-olm-end-to-end-encryption-security-assessment-released-and-implemented-cross-platform-on-riot-at-last/ and https://matrix.org/blog/2016/11/21/matrixs-olm-end-to-end-encryption-security-assessment-released-and-implemented-cross-platform-on-riot-at-last/
## Security issues
If you think you found a security issue in libolm, any of its bindings or the Olm/Megolm protocols, please follow our [Security Disclosure Policy](https://matrix.org/security-disclosure-policy/) to report.
## Bug reports ## Bug reports
Please file bug reports at https://github.com/matrix-org/olm/issues For non-sensitive bugs, please file bug reports at https://github.com/matrix-org/olm/issues.
## What's an olm? ## What's an olm?

29
Windows64.cmake Normal file
View file

@ -0,0 +1,29 @@
# Cross-compile for Windows (64-bit) using Mingw-w64
# Build using:
# cmake . -Bbuild -DCMAKE_TOOLCHAIN_FILE=Windows64.cmake
# cmake --build build
# from @ticho:cyberdi.sk
# https://paste.debian.net/1201338/
# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Windows)
# which compilers to use for C and C++
SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix)
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix)
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
# here is the target environment located
SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# static-link against the standard libraries
set(CMAKE_CXX_STANDARD_LIBRARIES "-static-libgcc -static-libstdc++")

BIN
android/.DS_Store vendored

Binary file not shown.

46
android/.gitlab-ci.yml Normal file
View file

@ -0,0 +1,46 @@
# TODO: consider replacing this with a smaller image
image: docker.io/inovex/gitlab-ci-android
stages:
- build
- test
variables:
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
before_script:
- export GRADLE_USER_HOME=$(pwd)/.gradle
- export ANDROID_HOME=${ANDROID_SDK_HOME}
- echo "sdk.dir=${ANDROID_SDK_HOME}" > ./android/local.properties
- echo "ndk.dir=${ANDROID_NDK_HOME}" >> ./android/local.properties
- cp -R $ANDROID_SDK_ROOT/licenses ./android/.
- chmod +x ./android/gradlew
cache:
key: ${CI_PROJECT_ID}
paths:
- android/.gradle/
build:android:aar:
stage: build
tags:
- docker
script:
- pushd android
- ./gradlew clean assembleRelease
artifacts:
expire_in: 1 weeks
paths:
- android/olm-sdk/build/outputs/aar/*.aar
- android/local.properties
test:android:aar:
stage: test
tags:
- docker
script:
- pushd android
- ./gradlew assembleAndroidTest
# TODO: Add emulator to run tests
needs:
- build:android:aar

View file

@ -5,20 +5,16 @@ OlmLibSdk exposes an android wrapper to libolm.
Installation Installation
------------ ------------
Create a libs directory in your project directory
Copy the olm-sdk.aar into it.
In your build.gradle file, add in the android section:: Android Olm library is released on MavenCentral.
repositories { Add this dependency to your project:
flatDir {
dir 'libs'
}
}
Add in the dependencies category:: ```groovy
implementation "org.matrix.android:olm:3.2.8"
```
compile(name: 'olm-sdk', ext: 'aar') Latest version: ![Latest version](https://img.shields.io/maven-central/v/org.matrix.android/olm)
Development Development
----------- -----------

View file

@ -6,8 +6,10 @@ buildscript {
google() google()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.1.3' // Release notes of Android Gradle Plugin (AGP):
// https://developer.android.com/studio/releases/gradle-plugin
classpath 'com.android.tools.build:gradle:7.0.4'
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.18.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
} }
@ -18,6 +20,17 @@ allprojects {
mavenCentral() mavenCentral()
google() google()
} }
plugins.withId("com.vanniktech.maven.publish.base") {
group = project.getProperties().getOrDefault("GROUP", "0.0.0")
version = project.getProperties().getOrDefault("VERSION_NAME", "name")
mavenPublishing {
publishToMavenCentral("S01")
pomFromGradleProperties()
signAllPublications()
}
}
} }
task clean(type: Delete) { task clean(type: Delete) {

View file

@ -21,3 +21,29 @@
android.useAndroidX=true android.useAndroidX=true
org.gradle.configureondemand=false org.gradle.configureondemand=false
# Maven publication
# Ref: https://github.com/vanniktech/gradle-maven-publish-plugin
GROUP=org.matrix.android
POM_ARTIFACT_ID=olm
VERSION_NAME=3.2.16
POM_PACKAGING=aar
POM_NAME=Olm Android wrapper
POM_DESCRIPTION=An Android wrapper to libolm.
POM_INCEPTION_YEAR=2021
POM_URL=https://gitlab.matrix.org/matrix-org/olm
POM_LICENSE_NAME=The Apache Software License, Version 2.0
POM_LICENCE_URL=https://www.apache.org/licenses/LICENSE-2.0.txt
POM_LICENCE_DIST=repo
POM_SCM_URL=https://gitlab.matrix.org/matrix-org/olm
POM_SCM_CONNECTION=scm:git:https://gitlab.matrix.org/matrix-org/olm.git
POM_SCM_DEV_CONNECTION=scm:git:ssh://git@gitlab.int.matrix.org:matrix-org/olm.git
POM_DEVELOPER_ID=matrixdev
POM_DEVELOPER_NAME=matrixdev
POM_DEVELOPER_URL=https://gitlab.matrix.org/matrix-org
POM_DEVELOPER_EMAIL=android@element.io

View file

@ -1,7 +1,6 @@
#Thu Oct 13 09:38:01 CEST 2016
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip distributionSha256Sum=c9490e938b221daf0094982288e4038deed954a3f12fb54cbf270ddf4e37d879
distributionSha256Sum=81003f83b0056d20eedf48cddd4f52a9813163d4ba185bcf8abd34b8eeea4cbd distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View file

@ -1,19 +1,26 @@
import org.apache.tools.ant.taskdefs.condition.Os import org.apache.tools.ant.taskdefs.condition.Os
import com.vanniktech.maven.publish.AndroidLibrary
import com.vanniktech.maven.publish.JavadocJar
apply plugin: 'com.android.library' apply plugin: 'com.android.library'
apply plugin: "com.vanniktech.maven.publish.base"
android { android {
compileSdkVersion 30 compileSdk 31
defaultConfig { defaultConfig {
minSdkVersion 14 minSdk 14
targetSdkVersion 30 targetSdk 31
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildConfigField "String", "OLM_VERSION", "\"${project.getProperties().getOrDefault("VERSION_NAME", "0.0.0")}\""
// The following argument makes the Android Test Orchestrator run its // The following argument makes the Android Test Orchestrator run its
// "pm clear" command after each test invocation. This command ensures // "pm clear" command after each test invocation. This command ensures
// that the app's state is completely cleared between tests. // that the app's state is completely cleared between tests.
testInstrumentationRunnerArguments clearPackageData: 'true' testInstrumentationRunnerArguments clearPackageData: 'true'
buildConfigField "String", "OLM_VERSION", "\"${project.getProperties().getOrDefault("VERSION_NAME", "0.0.0")}\""
} }
buildTypes { buildTypes {
debug { debug {
@ -73,6 +80,27 @@ android {
compileTask.dependsOn buildJavaDoc compileTask.dependsOn buildJavaDoc
} }
task androidJavadocs(type: Javadoc) {
source = android.sourceSets.main.java.srcDirs
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
android.libraryVariants.all { variant ->
if (variant.name == 'release') {
owner.classpath += variant.javaCompileProvider.get().classpath
}
}
exclude '**/R.html', '**/R.*.html', '**/index.html'
}
task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) {
archiveClassifier.set('javadoc')
from androidJavadocs.destinationDir
}
task androidSourcesJar(type: Jar) {
archiveClassifier.set('sources')
from android.sourceSets.main.java.srcDirs
}
clean.dependsOn cleanNative clean.dependsOn cleanNative
@ -84,6 +112,11 @@ android {
} }
} }
} }
compileOptions {
sourceCompatibility JavaVersion.VERSION_11
targetCompatibility JavaVersion.VERSION_11
}
} }
def getNdkFolder() { def getNdkFolder() {
@ -123,8 +156,12 @@ dependencies {
testImplementation 'junit:junit:4.13.2' testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'junit:junit:4.13.2' androidTestImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test:core:1.3.0' androidTestImplementation 'androidx.test:core:1.4.0'
androidTestImplementation 'androidx.test:runner:1.3.0' androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.3.0' androidTestImplementation 'androidx.test:rules:1.4.0'
androidTestImplementation 'androidx.test.ext:junit:1.1.2' androidTestImplementation 'androidx.test.ext:junit:1.1.3'
}
mavenPublishing {
configure(new AndroidLibrary(new JavadocJar.Empty(), false))
} }

View file

@ -488,4 +488,19 @@ public class OlmAccountTest {
fail(e.getMessage()); fail(e.getMessage());
} }
} }
@Test
public void test18GenerateFallbackKey() {
try {
OlmAccount account1 = new OlmAccount();
account1.generateFallbackKey();
Map<String, Map<String, String>> fallbackKeyMap = account1.fallbackKey();
assertNotNull(fallbackKeyMap);
assertEquals(1, fallbackKeyMap.size());
} catch (OlmException e) {
fail(e.getMessage());
}
}
} }

View file

@ -1011,4 +1011,75 @@ public class OlmSessionTest {
assertTrue(bobSession.isReleased()); assertTrue(bobSession.isReleased());
} }
@Test
public void test07AliceBobSessionDescribe() {
// creates alice & bob accounts
OlmAccount aliceAccount = null;
OlmAccount bobAccount = null;
try {
aliceAccount = new OlmAccount();
bobAccount = new OlmAccount();
} catch (OlmException e) {
fail(e.getMessage());
}
// test accounts creation
assertTrue(0 != bobAccount.getOlmAccountId());
assertTrue(0 != aliceAccount.getOlmAccountId());
// CREATE ALICE SESSION
OlmSession aliceSession = null;
try {
aliceSession = new OlmSession();
} catch (OlmException e) {
fail("Exception Msg=" + e.getMessage());
}
assertTrue(0 != aliceSession.getOlmSessionId());
// CREATE ALICE SESSION
OlmSession bobSession = null;
try {
bobSession = new OlmSession();
} catch (OlmException e) {
e.printStackTrace();
fail(e.getMessage());
}
assertTrue(0 != bobSession.getOlmSessionId());
String aliceSessionDescribe = null;
try {
aliceSessionDescribe = aliceSession.sessionDescribe();
} catch (Exception e) {
fail(e.getMessage());
}
assertNotNull(aliceSessionDescribe);
String bobSessionDescribe = null;
try {
bobSessionDescribe = bobSession.sessionDescribe();
} catch (Exception e) {
fail(e.getMessage());
}
assertNotNull(bobSessionDescribe);
// must be the same for both ends of the conversation
assertEquals(aliceSessionDescribe, bobSessionDescribe);
assertEquals(
"sender chain index: 0 receiver chain indices: skipped message keys:",
aliceSessionDescribe
);
aliceAccount.releaseAccount();
bobAccount.releaseAccount();
assertTrue(aliceAccount.isReleased());
assertTrue(bobAccount.isReleased());
bobSession.releaseSession();
aliceSession.releaseSession();
assertTrue(bobSession.isReleased());
assertTrue(aliceSession.isReleased());
}
} }

View file

@ -114,11 +114,11 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable {
/** /**
* Return the identity keys (identity and fingerprint keys) in a dictionary.<br> * Return the identity keys (identity and fingerprint keys) in a dictionary.<br>
* Public API for {@link #identityKeysJni()}.<br> * Public API for {@link #identityKeysJni()}.<br>
* Ex:<tt> * Ex:<code>
* { * {
* "curve25519":"Vam++zZPMqDQM6ANKpO/uAl5ViJSHxV9hd+b0/fwRAg", * "curve25519":"Vam++zZPMqDQM6ANKpO/uAl5ViJSHxV9hd+b0/fwRAg",
* "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I" * "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I"
* }</tt> * }</code>
* @return identity keys dictionary if operation succeeds, null otherwise * @return identity keys dictionary if operation succeeds, null otherwise
* @exception OlmException the failure reason * @exception OlmException the failure reason
*/ */
@ -195,14 +195,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable {
/** /**
* Return the "one time keys" in a dictionary.<br> * Return the "one time keys" in a dictionary.<br>
* The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}<br> * The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}<br>
* Ex:<tt> * Ex:<code>
* { "curve25519": * { "curve25519":
* { * {
* "AAAABQ":"qefVZd8qvjOpsFzoKSAdfUnJVkIreyxWFlipCHjSQQg", * "AAAABQ":"qefVZd8qvjOpsFzoKSAdfUnJVkIreyxWFlipCHjSQQg",
* "AAAABA":"/X8szMU+p+lsTnr56wKjaLgjTMQQkCk8EIWEAilZtQ8", * "AAAABA":"/X8szMU+p+lsTnr56wKjaLgjTMQQkCk8EIWEAilZtQ8",
* "AAAAAw":"qxNxxFHzevFntaaPdT0fhhO7tc7pco4+xB/5VRG81hA", * "AAAAAw":"qxNxxFHzevFntaaPdT0fhhO7tc7pco4+xB/5VRG81hA",
* } * }
* }</tt><br> * }</code><br>
* Public API for {@link #oneTimeKeysJni()}.<br> * Public API for {@link #oneTimeKeysJni()}.<br>
* Note: these keys are to be published on the server. * Note: these keys are to be published on the server.
* @return one time keys in string dictionary. * @return one time keys in string dictionary.
@ -234,7 +234,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable {
/** /**
* Get the public parts of the unpublished "one time keys" for the account.<br> * Get the public parts of the unpublished "one time keys" for the account.<br>
* The returned data is a JSON-formatted object with the single property * The returned data is a JSON-formatted object with the single property
* <tt>curve25519</tt>, which is itself an object mapping key id to * <code>curve25519</code>, which is itself an object mapping key id to
* base64-encoded Curve25519 key.<br> * base64-encoded Curve25519 key.<br>
* @return byte array containing the one time keys or throw an exception if it fails * @return byte array containing the one time keys or throw an exception if it fails
*/ */
@ -417,4 +417,99 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable {
* @return the deserialized account * @return the deserialized account
**/ **/
private native long deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); private native long deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer);
/**
* Return a pickled account as a bytes buffer.<br>
* The account is serialized and encrypted with aKey.
* In case of failure, an error human readable
* description is provide in aErrorMsg.
* @param aKey encryption key
* @param aErrorMsg error message description
* @return the pickled account as bytes buffer
*/
public byte[] pickle(byte[] aKey, StringBuffer aErrorMsg) {
return serialize(aKey, aErrorMsg);
}
/**
* Loads an account from a pickled bytes buffer.<br>
* See {@link #serialize(byte[], StringBuffer)}
* @param aSerializedData bytes buffer
* @param aKey key used to encrypted
* @exception Exception the exception
*/
public void unpickle(byte[] aSerializedData, byte[] aKey) throws Exception {
deserialize(aSerializedData, aKey);
}
/**
* Generates a new fallback key.
* @throws OlmException exception with a reason.
*/
public void generateFallbackKey() throws OlmException {
try {
generateFallbackKeyJni();
} catch (Exception e) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_GENERATE_FALLBACK_KEY, e.getMessage());
}
}
private native void generateFallbackKeyJni();
/**
* Return the "fallback key" in a dictionary.<br>
* Ex:<code>
* { "curve25519":
* {
* "AAAABQ":"qefVZd8qvjOpsFzoKSAdfUnJVkIreyxWFlipCHjSQQg"
* }
* }</code><br>
* Public API for {@link #fallbackKeyJni()}.<br>
* Note: the key is to be published on the server.
* @return fallback key in string dictionary.
* @exception OlmException the failure reason
*/
public Map<String, Map<String, String>> fallbackKey() throws OlmException {
JSONObject fallbackKeyJsonObj = null;
byte[] fallbackKeyBuffer;
try {
fallbackKeyBuffer = fallbackKeyJni();
} catch (Exception e) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_FALLBACK_KEY, e.getMessage());
}
if( null != fallbackKeyBuffer) {
try {
fallbackKeyJsonObj = new JSONObject(new String(fallbackKeyBuffer, "UTF-8"));
} catch (Exception e) {
Log.e(LOG_TAG, "## fallbackKey(): Exception - Msg=" + e.getMessage());
}
} else {
Log.e(LOG_TAG, "## fallbackKey(): Failure - identityKeysJni()=null");
}
return OlmUtility.toStringMapMap(fallbackKeyJsonObj);
}
private native byte[] fallbackKeyJni();
/**
* Forget about the old fallback key.
*
* This should be called once you are reasonably certain that you will not
* receive any more messages that use the old fallback key (e.g. 5 minutes
* after the new fallback key has been published).
* @throws OlmException the failure reason
**/
public void forgetFallbackKey() throws OlmException {
try {
forgetFallbackKeyJni();
} catch (Exception e) {
throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_FORGET_FALLBACK_KEY, e.getMessage());
}
}
private native void forgetFallbackKeyJni();
} }

View file

@ -35,6 +35,9 @@ public class OlmException extends IOException {
public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 105; public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 105;
public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 106; public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 106;
public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 107; public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 107;
public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_FALLBACK_KEY = 108;
public static final int EXCEPTION_CODE_ACCOUNT_FALLBACK_KEY = 109;
public static final int EXCEPTION_CODE_ACCOUNT_FORGET_FALLBACK_KEY = 110;
public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 200; public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 200;
public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 201; public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 201;
@ -57,6 +60,7 @@ public class OlmException extends IOException {
public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 404; public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 404;
public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405; public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405;
public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406; public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406;
public static final int EXCEPTION_CODE_SESSION_SESSION_DESCRIBE = 407;
public static final int EXCEPTION_CODE_UTILITY_CREATION = 500; public static final int EXCEPTION_CODE_UTILITY_CREATION = 500;
public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 501; public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 501;

View file

@ -369,4 +369,29 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
* @return the deserialized session * @return the deserialized session
**/ **/
private native long deserializeJni(byte[] aSerializedData, byte[] aKey); private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
/**
* Return a pickled inbound group session as a bytes buffer.<br>
* The session is serialized and encrypted with aKey.
* In case of failure, an error human readable
* description is provide in aErrorMsg.
* @param aKey encryption key
* @param aErrorMsg error message description
* @return the pickled inbound group session as bytes buffer
*/
public byte[] pickle(byte[] aKey, StringBuffer aErrorMsg) {
return serialize(aKey, aErrorMsg);
}
/**
* Loads an inbound group session from a pickled bytes buffer.<br>
* See {@link #serialize(byte[], StringBuffer)}
* @param aSerializedData bytes buffer
* @param aKey key used to encrypted
* @exception Exception the exception
*/
public void unpickle(byte[] aSerializedData, byte[] aKey) throws Exception {
deserialize(aSerializedData, aKey);
}
} }

View file

@ -46,7 +46,7 @@ public class OlmManager {
* @return the library version * @return the library version
*/ */
public String getVersion() { public String getVersion() {
return "3.2.2"; return BuildConfig.OLM_VERSION;
} }
/** /**

View file

@ -293,4 +293,28 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser
**/ **/
private native long deserializeJni(byte[] aSerializedData, byte[] aKey); private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
/**
* Return a pickled outbound group session as a bytes buffer.<br>
* The session is serialized and encrypted with aKey.
* In case of failure, an error human readable
* description is provide in aErrorMsg.
* @param aKey encryption key
* @param aErrorMsg error message description
* @return the pickled outbound group session as bytes buffer
*/
public byte[] pickle(byte[] aKey, StringBuffer aErrorMsg) {
return serialize(aKey, aErrorMsg);
}
/**
* Loads an outbound group session from a pickled bytes buffer.<br>
* See {@link #serialize(byte[], StringBuffer)}
* @param aSerializedData bytes buffer
* @param aKey key used to encrypted
* @exception Exception the exception
*/
public void unpickle(byte[] aSerializedData, byte[] aKey) throws Exception {
deserialize(aSerializedData, aKey);
}
} }

View file

@ -106,6 +106,16 @@ public class OlmSAS {
return null; return null;
} }
public String calculateMacFixedBase64(String message, String info) throws OlmException {
try {
byte[] bytes = calculateMacFixedBase64Jni(message.getBytes("UTF-8"), info.getBytes("UTF-8"));
if (bytes != null) return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new OlmException(OlmException.EXCEPTION_CODE_SAS_ERROR, e.getMessage());
}
return null;
}
public String calculateMacLongKdf(String message, String info) throws OlmException { public String calculateMacLongKdf(String message, String info) throws OlmException {
try { try {
byte[] bytes = calculateMacLongKdfJni(message.getBytes("UTF-8"), info.getBytes("UTF-8")); byte[] bytes = calculateMacLongKdfJni(message.getBytes("UTF-8"), info.getBytes("UTF-8"));
@ -140,6 +150,8 @@ public class OlmSAS {
private native byte[] calculateMacJni(byte[] message, byte[] info); private native byte[] calculateMacJni(byte[] message, byte[] info);
private native byte[] calculateMacFixedBase64Jni(byte[] message, byte[] info);
private native byte[] calculateMacLongKdfJni(byte[] message, byte[] info); private native byte[] calculateMacLongKdfJni(byte[] message, byte[] info);
/** /**

View file

@ -223,6 +223,23 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
*/ */
private native byte[] getSessionIdentifierJni(); private native byte[] getSessionIdentifierJni();
public String sessionDescribe() throws OlmException {
try {
byte[] buffer = olmSessionDescribeJni();
if (null != buffer) {
return new String(buffer, "UTF-8");
}
} catch (Exception e) {
Log.e(LOG_TAG, "## sessionDescribe(): " + e.getMessage());
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SESSION_DESCRIBE, e.getMessage());
}
return null;
}
private native byte[] olmSessionDescribeJni();
/** /**
* Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.<br> * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.<br>
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY).
@ -448,5 +465,30 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
* @return the deserialized session * @return the deserialized session
**/ **/
private native long deserializeJni(byte[] aSerializedData, byte[] aKey); private native long deserializeJni(byte[] aSerializedData, byte[] aKey);
/**
* Return a pickled session as a bytes buffer.<br>
* The session is serialized and encrypted with aKey.
* In case of failure, an error human readable
* description is provide in aErrorMsg.
* @param aKey encryption key
* @param aErrorMsg error message description
* @return the pickled session as bytes buffer
*/
public byte[] pickle(byte[] aKey, StringBuffer aErrorMsg) {
return serialize(aKey, aErrorMsg);
}
/**
* Loads a session from a pickled bytes buffer.<br>
* See {@link #serialize(byte[], StringBuffer)}
* @param aSerializedData bytes buffer
* @param aKey key used to encrypted
* @exception Exception the exception
*/
public void unpickle(byte[] aSerializedData, byte[] aKey) throws Exception {
deserialize(aSerializedData, aKey);
}
} }

View file

@ -442,6 +442,161 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env,
} }
} }
/**
* Generate "fallback key".
* An exception is thrown if the operation fails.
**/
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateFallbackKeyJni)(JNIEnv *env, jobject thiz)
{
const char* errorMessage = NULL;
OlmAccount *accountPtr = getAccountInstanceId(env, thiz);
if (!accountPtr)
{
LOGE("## generateFallbackKeyJni(): failure - invalid Account ptr");
errorMessage = "invalid Account ptr";
}
else
{
// keys memory allocation
size_t randomLength = olm_account_generate_fallback_key_random_length(accountPtr);
LOGD("## generateFallbackKeyJni(): randomLength=%lu", static_cast<long unsigned int>(randomLength));
uint8_t *randomBufferPtr = NULL;
if ((0 != randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength))
{
LOGE("## generateFallbackKeyJni(): failure - random buffer init");
errorMessage = "random buffer init";
}
else
{
LOGD("## generateFallbackKeyJni(): accountPtr =%p", accountPtr);
// retrieve key pairs in keysBytesPtr
size_t result = olm_account_generate_fallback_key(accountPtr, (void*)randomBufferPtr, randomLength);
if (result == olm_error())
{
errorMessage = olm_account_last_error(accountPtr);
LOGE("## generateFallbackKeyJni(): failure - error generating fallback keys Msg=%s", errorMessage);
}
else
{
LOGD("## generateFallbackKeyJni(): success - result=%lu", static_cast<long unsigned int>(result));
}
}
if (randomBufferPtr)
{
memset(randomBufferPtr, 0, randomLength);
free(randomBufferPtr);
}
}
if (errorMessage)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
}
}
/**
* Get "fallback key".<br>
* Return the public parts of the unpublished "fallback key" for the account
* @return a valid byte array if operation succeed, null otherwise
**/
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(fallbackKeyJni)(JNIEnv *env, jobject thiz)
{
const char* errorMessage = NULL;
jbyteArray byteArrayRetValue = NULL;
OlmAccount* accountPtr = getAccountInstanceId(env, thiz);
LOGD("## fallbackKeyJni(): IN");
if (!accountPtr)
{
LOGE("## fallbackKeyJni(): failure - invalid Account ptr");
errorMessage = "invalid Account ptr";
}
else
{
// keys memory allocation
size_t keysLength = olm_account_unpublished_fallback_key_length(accountPtr);
uint8_t *keysBytesPtr = (uint8_t *)malloc(keysLength*sizeof(uint8_t));
if (!keysBytesPtr)
{
LOGE("## fallbackKeyJni(): failure - fallback key OOM");
errorMessage = "fallback key OOM";
}
else
{
// retrieve key pairs in keysBytesPtr
size_t keysResult = olm_account_unpublished_fallback_key(accountPtr, keysBytesPtr, keysLength);
if (keysResult == olm_error()) {
LOGE("## fallbackKeyJni(): failure - error getting fallback key Msg=%s",(const char *)olm_account_last_error(accountPtr));
errorMessage = (const char *)olm_account_last_error(accountPtr);
}
else
{
// allocate the byte array to be returned to java
byteArrayRetValue = env->NewByteArray(keysLength);
if (!byteArrayRetValue)
{
LOGE("## fallbackKeyJni(): failure - return byte array OOM");
errorMessage = "return byte array OOM";
}
else
{
env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, keysLength, (const jbyte*)keysBytesPtr);
LOGD("## fallbackKeyJni(): success");
}
}
free(keysBytesPtr);
}
}
if (errorMessage)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
}
return byteArrayRetValue;
}
/**
* Forget about the old fallback key.
*
* This should be called once you are reasonably certain that you will not
* receive any more messages that use the old fallback key (e.g. 5 minutes
* after the new fallback key has been published).
**/
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(forgetFallbackKeyJni)(JNIEnv *env, jobject thiz)
{
const char* errorMessage = NULL;
OlmAccount *accountPtr = getAccountInstanceId(env, thiz);
if (!accountPtr)
{
LOGE("## forgetFallbackKeyJni(): failure - invalid Account ptr");
errorMessage = "invalid Account ptr";
}
else
{
olm_account_forget_old_fallback_key(accountPtr);
}
if (errorMessage)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
}
}
/** /**
* Sign a message with the ed25519 key (fingerprint) for this account.<br> * Sign a message with the ed25519 key (fingerprint) for this account.<br>
* The signed message is returned by the function. * The signed message is returned by the function.

View file

@ -42,6 +42,11 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId);
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz);
// fallback keys
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateFallbackKeyJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(fallbackKeyJni)(JNIEnv *env, jobject thiz);
JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(forgetFallbackKeyJni)(JNIEnv *env, jobject thiz);
// signing // signing
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage);

View file

@ -309,6 +309,86 @@ JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz
return returnValue; return returnValue;
} }
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacFixedBase64Jni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) {
LOGD("## calculateMacFixedBase64Jni(): IN");
const char* errorMessage = NULL;
jbyteArray returnValue = 0;
OlmSAS* sasPtr = getOlmSasInstanceId(env, thiz);
jbyte *messagePtr = NULL;
jboolean messageWasCopied = JNI_FALSE;
jbyte *infoPtr = NULL;
jboolean infoWasCopied = JNI_FALSE;
if (!sasPtr)
{
LOGE("## calculateMacFixedBase64Jni(): failure - invalid SAS ptr=NULL");
errorMessage = "invalid SAS ptr=NULL";
} else if(!messageBuffer) {
LOGE("## calculateMacFixedBase64Jni(): failure - invalid message");
errorMessage = "invalid info";
}
else if (!(messagePtr = env->GetByteArrayElements(messageBuffer, &messageWasCopied)))
{
LOGE(" ## calculateMacFixedBase64Jni(): failure - message JNI allocation OOM");
errorMessage = "message JNI allocation OOM";
}
else if (!(infoPtr = env->GetByteArrayElements(infoBuffer, &infoWasCopied)))
{
LOGE(" ## calculateMacFixedBase64Jni(): failure - info JNI allocation OOM");
errorMessage = "info JNI allocation OOM";
} else {
size_t infoLength = (size_t)env->GetArrayLength(infoBuffer);
size_t messageLength = (size_t)env->GetArrayLength(messageBuffer);
size_t macLength = olm_sas_mac_length(sasPtr);
void *macPtr = malloc(macLength*sizeof(uint8_t));
size_t result = olm_sas_calculate_mac_fixed_base64(sasPtr,messagePtr,messageLength,infoPtr,infoLength,macPtr,macLength);
if (result == olm_error())
{
errorMessage = (const char *)olm_sas_last_error(sasPtr);
LOGE("## calculateMacFixedBase64Jni(): failure - error calculating SAS mac Msg=%s", errorMessage);
}
else
{
returnValue = env->NewByteArray(macLength);
env->SetByteArrayRegion(returnValue, 0 , macLength, (jbyte*)macPtr);
}
if (macPtr) {
free(macPtr);
}
}
// free alloc
if (infoPtr)
{
if (infoWasCopied)
{
memset(infoPtr, 0, (size_t)env->GetArrayLength(infoBuffer));
}
env->ReleaseByteArrayElements(infoBuffer, infoPtr, JNI_ABORT);
}
if (messagePtr)
{
if (messageWasCopied)
{
memset(messagePtr, 0, (size_t)env->GetArrayLength(messageBuffer));
}
env->ReleaseByteArrayElements(messageBuffer, messagePtr, JNI_ABORT);
}
if (errorMessage)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
}
return returnValue;
}
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) { JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz,jbyteArray messageBuffer,jbyteArray infoBuffer) {
LOGD("## calculateMacLongKdfJni(): IN"); LOGD("## calculateMacLongKdfJni(): IN");
const char* errorMessage = NULL; const char* errorMessage = NULL;

View file

@ -32,6 +32,7 @@ JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(getPubKeyJni)(JNIEnv *env, jobject thiz);
JNIEXPORT void OLM_SAS_FUNC_DEF(setTheirPubKey)(JNIEnv *env, jobject thiz,jbyteArray pubKey); JNIEXPORT void OLM_SAS_FUNC_DEF(setTheirPubKey)(JNIEnv *env, jobject thiz,jbyteArray pubKey);
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(generateShortCodeJni)(JNIEnv *env, jobject thiz, jbyteArray infoStringBytes, jint byteNb); JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(generateShortCodeJni)(JNIEnv *env, jobject thiz, jbyteArray infoStringBytes, jint byteNb);
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer); JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacFixedBase64Jni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer); JNIEXPORT jbyteArray OLM_SAS_FUNC_DEF(calculateMacLongKdfJni)(JNIEnv *env, jobject thiz, jbyteArray messageBuffer, jbyteArray infoBuffer);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -798,6 +798,58 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env,
return returnValue; return returnValue;
} }
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(olmSessionDescribeJni(JNIEnv *env, jobject thiz))
{
const char* errorMessage = NULL;
jbyteArray returnValue = 0;
LOGD("## olmSessionDescribeJni(): IN ");
OlmSession *sessionPtr = getSessionInstanceId(env, thiz);
if (!sessionPtr)
{
LOGE("## olmSessionDescribeJni(): failure - invalid Session ptr=NULL");
errorMessage = "invalid Session ptr=NULL";
}
else
{
int maxLength = 600;
char* describePtr = NULL;
describePtr = (char*) malloc(maxLength * sizeof *describePtr);
if (!describePtr)
{
LOGE("## olmSessionDescribeJni(): failure - describe allocation OOM");
errorMessage = "describe allocation OOM";
}
else
{
olm_session_describe(sessionPtr, describePtr, maxLength);
int length = strlen(describePtr);
if (length == 0)
{
LOGE("## olmSessionDescribeJni(): failure - get session describe");
}
else
{
LOGD("## olmSessionDescribeJni(): success - describe=%.*s", (char*)describePtr);
returnValue = env->NewByteArray(length);
env->SetByteArrayRegion(returnValue, 0, length, (jbyte*)describePtr);
}
free(describePtr);
}
}
if (errorMessage)
{
env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage);
}
return returnValue;
}
/** /**
* Serialize and encrypt session instance.<br> * Serialize and encrypt session instance.<br>
* An exception is thrown if the operation fails. * An exception is thrown if the operation fails.

View file

@ -47,6 +47,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg);
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(olmSessionDescribeJni)(JNIEnv *env, jobject thiz);
// serialization // serialization
JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey);

View file

@ -1,4 +1,4 @@
MAJOR := 3 MAJOR := 3
MINOR := 2 MINOR := 2
PATCH := 2 PATCH := 16

View file

@ -109,7 +109,7 @@ discriminate between sessions.
### Sharing session data ### Sharing session data
To allow other participants in the conversation to decrypt messages, the To allow other participants in the conversation to decrypt messages, the
session data is formatted as described in [Session-sharing format](#Session-sharing-format). It is then session data is formatted as described in [Session-sharing format](#session-sharing-format). It is then
shared with other participants in the conversation via a secure peer-to-peer shared with other participants in the conversation via a secure peer-to-peer
channel (such as that provided by [Olm][]). channel (such as that provided by [Olm][]).
@ -182,9 +182,13 @@ but the decision of which ratchet states to cache is left to the application.
## Data exchange formats ## Data exchange formats
### Session-sharing format ### Session sharing format
The Megolm key-sharing format is as follows: This format is used for the initial sharing of a Megolm session with other
group participants who need to be able to read messages encrypted by this
session.
The session sharing format is as follows:
``` ```
+---+----+--------+--------+--------+--------+------+-----------+ +---+----+--------+--------+--------+--------+------+-----------+
@ -202,6 +206,33 @@ part of the Ed25519 keypair $`K`$.
The data is then signed using the Ed25519 keypair, and the 64-byte signature is The data is then signed using the Ed25519 keypair, and the 64-byte signature is
appended. appended.
### Session export format
Once the session is initially shared with the group participants, each
participant needs to retain a copy of the session if they want to maintain
their ability to decrypt messages encrypted with that session.
For forward-secrecy purposes, a participant may choose to store a ratcheted
version of the session. But since the ratchet index is covered by the
signature, this would invalidate the signature. So we define a similar format,
called the *session export format*, which is identical to the [session sharing
format](#session-sharing-format) except for dropping the signature.
The Megolm session export format is thus as follows:
```
+---+----+--------+--------+--------+--------+------+
| V | i | R(i,0) | R(i,1) | R(i,2) | R(i,3) | Kpub |
+---+----+--------+--------+--------+--------+------+
0 1 5 37 69 101 133 165 bytes
```
The version byte, ``V``, is ``"\x01"``.
This is followed by the ratchet index, $`i`$, which is encoded as a
big-endian 32-bit integer; the ratchet values $`R_{i,j}`$; and the public
part of the Ed25519 keypair $`K`$.
### Message format ### Message format
Megolm messages consist of a one byte version, followed by a variable length Megolm messages consist of a one byte version, followed by a variable length

View file

@ -1,10 +1,10 @@
#!/usr/bin/env python #!/usr/bin/env python3
import sys import sys
import re import re
import json import json
expr = re.compile(r"(olm_[^( ]*)\(") expr = re.compile(r"(_*olm_[^( ]*)\(")
exports = {'_free', '_malloc'} exports = {'_free', '_malloc'}

60
flake.lock Normal file
View file

@ -0,0 +1,60 @@
{
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1664871473,
"narHash": "sha256-1LzbW6G6Uz8akWiOdlIi435GAm1ct5jF5tovw/9to0o=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b7a6fde153d9470afdb6aa1da51c4117f03b84ed",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"npmlock2nix": {
"flake": false,
"locked": {
"lastModified": 1654775747,
"narHash": "sha256-9pXHDpIjmsK5390wmpGHu9aA4QOPpegPBvThHeBlef4=",
"owner": "nix-community",
"repo": "npmlock2nix",
"rev": "5c4f247688fc91d665df65f71c81e0726621aaa8",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "npmlock2nix",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs",
"npmlock2nix": "npmlock2nix"
}
}
},
"root": "root",
"version": 7
}

40
flake.nix Normal file
View file

@ -0,0 +1,40 @@
{
description = "An implementation of the Double Ratchet cryptographic ratchet";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
# We can't use the current stable release because of
# https://github.com/emscripten-core/emscripten/issues/16913
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.npmlock2nix = {
url = "github:nix-community/npmlock2nix";
flake = false;
};
outputs = { self, nixpkgs, flake-utils, npmlock2nix }:
let
localOverlay = import ./nix/overlay.nix;
pkgsForSystem = system: import nixpkgs {
inherit system;
overlays = [
(final: prev: {
npmlock2nix = final.callPackage npmlock2nix {};
node_modules = final.npmlock2nix.node_modules { src = ./javascript; };
})
localOverlay
];
};
in (
# some systems cause issues, e.g. i686-linux is unsupported by gradle,
# which causes "nix flake check" to fail. Investigate more later, but for
# now, we will just allow x86_64-linux
flake-utils.lib.eachSystem [ "x86_64-linux" "x86_64-darwin" "aarch64-darwin" ] (system: rec {
legacyPackages = pkgsForSystem system;
checks = {
inherit (legacyPackages) olm-gcc-cmake olm-clang-cmake olm-gcc-make;
};
packages = {
javascript = legacyPackages.olm-javascript;
};
}
));
}

View file

@ -1,73 +0,0 @@
#include "olm/olm.hh"
#include "fuzzing.hh"
int main(int argc, const char *argv[]) {
size_t ignored;
if (argc <= 2) {
const char * message = "Usage: decrypt <pickle_key> <group_session>\n";
ignored = write(STDERR_FILENO, message, strlen(message));
exit(3);
}
const char * key = argv[1];
size_t key_length = strlen(key);
int session_fd = check_errno(
"Error opening session file", open(argv[2], O_RDONLY)
);
uint8_t *session_buffer;
ssize_t session_length = check_errno(
"Error reading session file", read_file(session_fd, &session_buffer)
);
int message_fd = STDIN_FILENO;
uint8_t * message_buffer;
ssize_t message_length = check_errno(
"Error reading message file", read_file(message_fd, &message_buffer)
);
uint8_t * tmp_buffer = (uint8_t *) malloc(message_length);
memcpy(tmp_buffer, message_buffer, message_length);
uint8_t session_memory[olm_inbound_group_session_size()];
OlmInboundGroupSession * session = olm_inbound_group_session(session_memory);
check_error(
olm_inbound_group_session_last_error,
session,
"Error unpickling session",
olm_unpickle_inbound_group_session(
session, key, key_length, session_buffer, session_length
)
);
size_t max_length = check_error(
olm_inbound_group_session_last_error,
session,
"Error getting plaintext length",
olm_group_decrypt_max_plaintext_length(
session, tmp_buffer, message_length
)
);
uint8_t plaintext[max_length];
uint32_t ratchet_index;
size_t length = check_error(
olm_inbound_group_session_last_error,
session,
"Error decrypting message",
olm_group_decrypt(
session,
message_buffer, message_length,
plaintext, max_length, &ratchet_index
)
);
ignored = write(STDOUT_FILENO, plaintext, length);
ignored = write(STDOUT_FILENO, "\n", 1);
return ignored;
}

View file

@ -1,14 +0,0 @@
#include "olm/account.hh"
#include "fuzzing.hh"
int main(int argc, const char *argv[]) {
int pickle_fd = STDIN_FILENO;
uint8_t * pickle_buffer;
ssize_t pickle_length = check_errno(
"Error reading pickle file", read_file(pickle_fd, &pickle_buffer)
);
olm::Account * account = new olm::Account;
unpickle(pickle_buffer, pickle_buffer + pickle_length, *account);
free(pickle_buffer);
delete account;
}

10
fuzzing/README.md Normal file
View file

@ -0,0 +1,10 @@
# Directory structure
- `fuzzers/`: Sources for the fuzzing harnesses.
- `corpora/`: Contains the fuzzing corpora and assorted tools. The corpora are
filed under a directory with the same name as the fuzzing harness. Each of
those directories also contains the following:
- `in/`: Contains the actual corpus test cases.
- `tools/`: Any tools useful for that particular harness. A good example
would be a binary which generates seed test cases.

View file

@ -11,4 +11,6 @@ int main(int argc, const char *argv[]) {
decode_message(*reader, message_buffer, message_length, 8); decode_message(*reader, message_buffer, message_length, 8);
free(message_buffer); free(message_buffer);
delete reader; delete reader;
return EXIT_SUCCESS;
} }

View file

@ -3,11 +3,10 @@
#include "fuzzing.hh" #include "fuzzing.hh"
int main(int argc, const char *argv[]) { int main(int argc, const char *argv[]) {
size_t ignored;
if (argc <= 3) { if (argc <= 3) {
const char * message = "Usage: decrypt: <session_key> <session_file>" const char * message = "Usage: decrypt: <session_key> <session_file>"
" <message_type>\n"; " <message_type>\n";
ignored = write(STDERR_FILENO, message, strlen(message)); (void)write(STDERR_FILENO, message, strlen(message));
exit(3); exit(3);
} }
@ -59,7 +58,12 @@ int main(int argc, const char *argv[]) {
) )
); );
ignored = write(STDOUT_FILENO, plaintext, length); (void)write(STDOUT_FILENO, plaintext, length);
ignored = write(STDOUT_FILENO, "\n", 1); (void)write(STDOUT_FILENO, "\n", 1);
return ignored;
free(session_buffer);
free(message_buffer);
free(tmp_buffer);
return EXIT_SUCCESS;
} }

View file

@ -0,0 +1,102 @@
#include "olm/olm.hh"
#include "fuzzing.hh"
#ifndef __AFL_FUZZ_TESTCASE_LEN
ssize_t fuzz_len;
#define __AFL_FUZZ_TESTCASE_LEN fuzz_len
unsigned char fuzz_buf[1024000];
#define __AFL_FUZZ_TESTCASE_BUF fuzz_buf
#define __AFL_FUZZ_INIT() void sync(void);
#define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0)
#define __AFL_INIT() sync()
#endif
__AFL_FUZZ_INIT();
int main(int argc, const char *argv[]) {
if (argc <= 2) {
const char * message = "Usage: decrypt <pickle_key> <group_session>\n";
(void)write(STDERR_FILENO, message, strlen(message));
exit(3);
}
const char * key = argv[1];
size_t key_length = strlen(key);
int session_fd = check_errno(
"Error opening session file", open(argv[2], O_RDONLY)
);
uint8_t *session_buffer;
ssize_t session_length = check_errno(
"Error reading session file", read_file(session_fd, &session_buffer)
);
uint8_t session_memory[olm_inbound_group_session_size()];
OlmInboundGroupSession * session = olm_inbound_group_session(session_memory);
check_error(
olm_inbound_group_session_last_error,
session,
"Error unpickling session",
olm_unpickle_inbound_group_session(
session, key, key_length, session_buffer, session_length
)
);
#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
#endif
size_t test_case_buf_len = 1024;
uint8_t * message_buffer = (uint8_t *) malloc(test_case_buf_len);
uint8_t * tmp_buffer = (uint8_t *) malloc(test_case_buf_len);
while (__AFL_LOOP(10000)) {
size_t message_length = __AFL_FUZZ_TESTCASE_LEN;
if (message_length > test_case_buf_len) {
message_buffer = (uint8_t *)realloc(message_buffer, message_length);
tmp_buffer = (uint8_t *)realloc(tmp_buffer, message_length);
if (!message_buffer || !tmp_buffer) return 1;
}
memcpy(message_buffer, __AFL_FUZZ_TESTCASE_BUF, message_length);
memcpy(tmp_buffer, message_buffer, message_length);
size_t max_length = check_error(
olm_inbound_group_session_last_error,
session,
"Error getting plaintext length",
olm_group_decrypt_max_plaintext_length(
session, tmp_buffer, message_length
)
);
uint8_t plaintext[max_length];
uint32_t ratchet_index;
size_t length = check_error(
olm_inbound_group_session_last_error,
session,
"Error decrypting message",
olm_group_decrypt(
session,
message_buffer, message_length,
plaintext, max_length, &ratchet_index
)
);
(void)write(STDOUT_FILENO, plaintext, length);
(void)write(STDOUT_FILENO, "\n", 1);
}
free(session_buffer);
free(message_buffer);
free(tmp_buffer);
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,41 @@
#include "fuzzing.hh"
#include "olm/account.hh"
#include "olm/olm.h"
size_t fuzz_unpickle_account(
OlmAccount * account, void * pickled, size_t pickled_length
) {
olm::Account & object = *reinterpret_cast<olm::Account *>(account);
std::uint8_t * const pos = reinterpret_cast<std::uint8_t *>(pickled);
std::uint8_t * const end = pos + pickled_length;
if (!unpickle(pos, end, object)) {
if (object.last_error == OlmErrorCode::OLM_SUCCESS) {
object.last_error = OlmErrorCode::OLM_CORRUPTED_PICKLE;
}
return std::size_t(-1);
}
return pickled_length;
}
int main(int argc, const char * argv[]) {
int pickle_fd = STDIN_FILENO;
uint8_t * pickle_buffer;
ssize_t pickle_length = check_errno(
"Error reading pickle file", read_file(pickle_fd, &pickle_buffer));
void * account_buf = malloc(olm_account_size());
if (!account_buf) {
return 3;
}
OlmAccount * account = olm_account(account_buf);
check_error(olm_account_last_error, account, "Error unpickling account",
fuzz_unpickle_account(account, pickle_buffer, pickle_length));
free(pickle_buffer);
free(account);
return EXIT_SUCCESS;
}

View file

@ -0,0 +1,28 @@
#include <olm/outbound_group_session.h>
#include "fuzzing.h"
int main(int argc, const char *argv[]) {
if (argc != 1) {
printf("Usage: %s <input_file\n", argv[0]);
exit(3);
}
void *session_buffer = malloc(olm_outbound_group_session_size());
OlmOutboundGroupSession *session = olm_outbound_group_session(session_buffer);
int pickle_fd = STDIN_FILENO;
uint8_t *pickle_buffer;
ssize_t pickle_length = check_errno("Error reading message file",
read_file(pickle_fd, &pickle_buffer));
check_outbound_group_session(
session, "Error unpickling outbound group session",
olm_unpickle_outbound_group_session(session, "", 0, pickle_buffer,
pickle_length));
free(session_buffer);
free(pickle_buffer);
return EXIT_SUCCESS;
}

View file

@ -11,4 +11,6 @@ int main(int argc, const char *argv[]) {
unpickle(pickle_buffer, pickle_buffer + pickle_length, *session); unpickle(pickle_buffer, pickle_buffer + pickle_length, *session);
free(pickle_buffer); free(pickle_buffer);
delete session; delete session;
return EXIT_SUCCESS;
} }

View file

@ -0,0 +1,101 @@
#include "olm/olm.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stddef.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define OLM_FUZZING 1
ssize_t read_file(
int fd,
uint8_t **buffer
) {
size_t buffer_size = 1;
size_t buffer_pos = 0;
uint8_t * current_buffer = (uint8_t *) malloc(buffer_size);
if (!current_buffer) return -1;
while (1) {
ssize_t count = read(
fd, current_buffer + buffer_pos, buffer_size - buffer_pos
);
if (count < 0) break; // A read error happened, so just fail immediately.
if (count == 0) {
// Nothing more left to read. We downsize the buffer to fit the
// data exactly, unless no data was read at all, in which case we
// skip the downsizing.
if (buffer_pos != 0) {
current_buffer = (uint8_t *) realloc(current_buffer, buffer_pos);
if (!current_buffer) break;
}
// The read was successful so we return the allocated buffer.
*buffer = current_buffer;
return buffer_pos;
}
buffer_pos += count;
// We've reached capacity, so enlarge the buffer.
if (buffer_pos == buffer_size) {
buffer_size *= 2;
uint8_t * new_buffer = (uint8_t *) realloc(current_buffer, buffer_size);
if (!new_buffer) break;
current_buffer = new_buffer;
}
}
free(current_buffer);
return -1;
}
ssize_t check_errno(
const char * message,
ssize_t value
) {
if (value == (ssize_t)-1) {
perror(message);
exit(1);
}
return value;
}
size_t check_error(
const char * message,
const char * olm_message,
size_t value
) {
if (value == olm_error()) {
(void)write(STDERR_FILENO, message, strlen(message));
(void)write(STDERR_FILENO, ": ", 2);
(void)write(STDERR_FILENO, olm_message, strlen(olm_message));
(void)write(STDERR_FILENO, "\n", 1);
exit(2);
}
return value;
}
size_t check_session(
OlmSession * session,
const char * message,
size_t value
) {
return check_error(message, olm_session_last_error(session), value);
}
size_t check_outbound_group_session(
OlmOutboundGroupSession * session,
const char * message,
size_t value
) {
return check_error(message, olm_outbound_group_session_last_error(session), value);
}

View file

@ -15,28 +15,43 @@ ssize_t read_file(
uint8_t **buffer uint8_t **buffer
) { ) {
size_t buffer_size = 4096; size_t buffer_size = 4096;
uint8_t * current_buffer = (uint8_t *) malloc(buffer_size);
if (current_buffer == NULL) return -1;
size_t buffer_pos = 0; size_t buffer_pos = 0;
uint8_t * current_buffer = (uint8_t *) malloc(buffer_size);
if (!current_buffer) return -1;
while (1) { while (1) {
ssize_t count = read( ssize_t count = read(
fd, current_buffer + buffer_pos, buffer_size - buffer_pos fd, current_buffer + buffer_pos, buffer_size - buffer_pos
); );
if (count < 0) break;
if (count < 0) break; // A read error happened, so just fail immediately.
if (count == 0) { if (count == 0) {
uint8_t * return_buffer = (uint8_t *) realloc(current_buffer, buffer_pos); // Nothing more left to read. We downsize the buffer to fit the
if (return_buffer == NULL) break; // data exactly, unless no data was read at all, in which case we
*buffer = return_buffer; // skip the downsizing.
if (buffer_pos != 0) {
current_buffer = (uint8_t *) realloc(current_buffer, buffer_pos);
if (!current_buffer) break;
}
// The read was successful so we return the allocated buffer.
*buffer = current_buffer;
return buffer_pos; return buffer_pos;
} }
buffer_pos += count; buffer_pos += count;
// We've reached capacity, so enlarge the buffer.
if (buffer_pos == buffer_size) { if (buffer_pos == buffer_size) {
buffer_size *= 2; buffer_size *= 2;
uint8_t * new_buffer = (uint8_t *) realloc(current_buffer, buffer_size); uint8_t * new_buffer = (uint8_t *) realloc(current_buffer, buffer_size);
if (new_buffer == NULL) break; if (!new_buffer) break;
current_buffer = new_buffer; current_buffer = new_buffer;
} }
} }
free(current_buffer); free(current_buffer);
return -1; return -1;
} }
@ -62,13 +77,12 @@ size_t check_error(
) { ) {
if (value == olm_error()) { if (value == olm_error()) {
const char * olm_message = f(object); const char * olm_message = f(object);
ssize_t ignored; (void)write(STDERR_FILENO, message, strlen(message));
ignored = write(STDERR_FILENO, message, strlen(message)); (void)write(STDERR_FILENO, ": ", 2);
ignored = write(STDERR_FILENO, ": ", 2); (void)write(STDERR_FILENO, olm_message, strlen(olm_message));
ignored = write(STDERR_FILENO, olm_message, strlen(olm_message)); (void)write(STDERR_FILENO, "\n", 1);
ignored = write(STDERR_FILENO, "\n", 1);
exit(2); exit(2);
return ignored;
} }
return value; return value;
} }

118
fuzzing/start_fuzzers.sh Executable file
View file

@ -0,0 +1,118 @@
#!/usr/bin/bash
# Needs to be started in tmux.
script_dir() {
dirname "$(readlink -f "$0")"
}
fuzzer_dir() {
printf '%s/fuzzers\n' "$(script_dir)"
}
fuzzer_list() {
find "$(fuzzer_dir)" -maxdepth 1 -type f \( -name '*.cpp' -or -name '*.c' \) -printf '%P\n' \
| while read -r fuzzer; do
fuzzer="${fuzzer#fuzz_}"
printf '%s\n' "${fuzzer%.c*}"
done
}
usage() {
printf '%s: HARNESS FUZZER\n\n' "$(basename "$0")"
printf ' HARNESS ∈ {\n'
# We want word-splitting here so that each fuzzer ends up as a separate
# argument.
# shellcheck disable=SC2046
printf '%30s,\n' $(fuzzer_list | tr '\n' ' ')
printf ' }\n'
printf ' FUZZER ∈ {afl, afl++}\n'
}
if [[ $# -ne 2 ]]; then
usage
exit 1
fi
case "$2" in
afl++)
export AFL_PATH=/home/dkasak/code/projects/afl/afl++
export AFL_AUTORESUME=1
AFL_ARGS_FUZZER0="-D"
AFL_ARGS_FUZZER1="-L 0"
AFL_ARGS_FUZZER2="-p rare"
AFL_ARGS_FUZZER3="-p fast"
AFL_ARGS_FUZZER4="-p exploit"
AFL_ARGS_FUZZER5="-p explore"
;;
afl)
export AFL_PATH=/usr/bin
;;
*)
printf 'Unknown fuzzer: %s\n' "$2"
exit 1
;;
esac
export AFL=$AFL_PATH/afl-fuzz
export AFL_TMPDIR=/tmp
case "$1" in
group_decrypt)
FUZZER_ARG1="fuzzing/$1/pickled-inbound-group-session.txt"
;;
decrypt)
FUZZER_ARG1="fuzzing/$1/pickled-session.txt"
FUZZER_ARG2="1"
;;
decode_message)
;;
unpickle_session)
;;
unpickle_account)
;;
unpickle_account_test)
;;
unpickle_megolm_outbound)
;;
*)
printf 'Unknown harness: %s\n' "$1"
exit 1
;;
esac
cd "$(script_dir)" || exit 1
# Fuzzer args are deliberately not quoted below so that word-splitting happens.
# This is used so that they expand into nothing in cases where they are missing
# or to expand into multiple arguments from a string definition.
# shellcheck disable=SC2086
tmux new-window -d -n "M" -- \
"$AFL" -i "corpora/$1/in" -o "corpora/$1/out" -M i0 "$AFL_ARGS_FUZZER0" \
-- "../build/fuzzers/fuzz_$1" $FUZZER_ARG1 $FUZZER_ARG2
# shellcheck disable=SC2086
tmux new-window -d -n "S1" -- \
"$AFL" -i "corpora/$1/in" -o "corpora/$1/out" -S i1 "$AFL_ARGS_FUZZER1" \
-- "../build/fuzzers/fuzz_$1" $FUZZER_ARG1 $FUZZER_ARG2
# shellcheck disable=SC2086
tmux new-window -d -n "S2" -- \
"$AFL" -i "corpora/$1/in" -o "corpora/$1/out" -S i2 $AFL_ARGS_FUZZER2 \
-- "../build/fuzzers/fuzz_$1" $FUZZER_ARG1 $FUZZER_ARG2
# shellcheck disable=SC2086
tmux new-window -d -n "S3" -- \
"$AFL" -i "corpora/$1/in" -o "corpora/$1/out" -S i3 $AFL_ARGS_FUZZER3 \
-- "../build/fuzzers/fuzz_$1" $FUZZER_ARG1 $FUZZER_ARG2
# shellcheck disable=SC2086
tmux new-window -d -n "S4" -- \
"$AFL" -i "corpora/$1/in" -o "corpora/$1/out" -S i4 $AFL_ARGS_FUZZER4 \
-- "../build/fuzzers/fuzz_$1_asan" $FUZZER_ARG1 $FUZZER_ARG2
# shellcheck disable=SC2086
tmux new-window -d -n "S5" -- \
"$AFL" -i "corpora/$1/in" -o "corpora/$1/out" -S i5 $AFL_ARGS_FUZZER5 \
-- "../build/fuzzers/fuzz_$1" $FUZZER_ARG1 $FUZZER_ARG2

17
gitlab-math.lua Normal file
View file

@ -0,0 +1,17 @@
function Math(el)
if el.mathtype == "InlineMath" then
if el.text:sub(1,1) == '`' and el.text:sub(#el.text) == '`' then
local text = el.text:sub(2,#el.text-1)
return pandoc.Math(el.mathtype, text)
else
local cont = pandoc.read(el.text)
return { pandoc.Str("$") } .. cont.blocks[1].content .. { pandoc.Str("$") }
end
end
end
function CodeBlock(el)
if el.classes[1] == "math" then
return pandoc.Para({ pandoc.Math("DisplayMath", el.text) })
end
end

View file

@ -43,13 +43,14 @@ struct Account {
Account(); Account();
IdentityKeys identity_keys; IdentityKeys identity_keys;
List<OneTimeKey, MAX_ONE_TIME_KEYS> one_time_keys; List<OneTimeKey, MAX_ONE_TIME_KEYS> one_time_keys;
std::uint8_t num_fallback_keys;
OneTimeKey current_fallback_key; OneTimeKey current_fallback_key;
OneTimeKey prev_fallback_key; OneTimeKey prev_fallback_key;
std::uint32_t next_one_time_key_id; std::uint32_t next_one_time_key_id;
OlmErrorCode last_error; OlmErrorCode last_error;
/** Number of random bytes needed to create a new account */ /** Number of random bytes needed to create a new account */
std::size_t new_account_random_length(); std::size_t new_account_random_length() const;
/** Create a new account. Returns std::size_t(-1) on error. If the number of /** Create a new account. Returns std::size_t(-1) on error. If the number of
* random bytes is too small then last_error will be NOT_ENOUGH_RANDOM */ * random bytes is too small then last_error will be NOT_ENOUGH_RANDOM */
@ -58,7 +59,7 @@ struct Account {
); );
/** Number of bytes needed to output the identity keys for this account */ /** Number of bytes needed to output the identity keys for this account */
std::size_t get_identity_json_length(); std::size_t get_identity_json_length() const;
/** Output the identity keys for this account as JSON in the following /** Output the identity keys for this account as JSON in the following
* format: * format:
@ -77,7 +78,7 @@ struct Account {
/** /**
* The length of an ed25519 signature in bytes. * The length of an ed25519 signature in bytes.
*/ */
std::size_t signature_length(); std::size_t signature_length() const;
/** /**
* Signs a message with the ed25519 key for this account. * Signs a message with the ed25519 key for this account.
@ -88,7 +89,7 @@ struct Account {
); );
/** Number of bytes needed to output the one time keys for this account */ /** Number of bytes needed to output the one time keys for this account */
std::size_t get_one_time_keys_json_length(); std::size_t get_one_time_keys_json_length() const;
/** Output the one time keys that haven't been published yet as JSON: /** Output the one time keys that haven't been published yet as JSON:
* *
@ -106,18 +107,20 @@ struct Account {
std::uint8_t * one_time_json, std::size_t one_time_json_length std::uint8_t * one_time_json, std::size_t one_time_json_length
); );
/** Mark the current list of one_time_keys as being published. They /** Mark the current list of one_time_keys and the current fallback key as
* will no longer be returned by get_one_time_keys_json_length(). */ * being published. The current one time keys will no longer be returned by
* get_one_time_keys_json() and the current fallback key will no longer be
* returned by get_unpublished_fallback_key_json(). */
std::size_t mark_keys_as_published(); std::size_t mark_keys_as_published();
/** The largest number of one time keys this account can store. */ /** The largest number of one time keys this account can store. */
std::size_t max_number_of_one_time_keys(); std::size_t max_number_of_one_time_keys() const;
/** The number of random bytes needed to generate a given number of new one /** The number of random bytes needed to generate a given number of new one
* time keys. */ * time keys. */
std::size_t generate_one_time_keys_random_length( std::size_t generate_one_time_keys_random_length(
std::size_t number_of_keys std::size_t number_of_keys
); ) const;
/** Generates a number of new one time keys. If the total number of keys /** Generates a number of new one time keys. If the total number of keys
* stored by this account exceeds max_number_of_one_time_keys() then the * stored by this account exceeds max_number_of_one_time_keys() then the
@ -129,7 +132,7 @@ struct Account {
); );
/** The number of random bytes needed to generate a fallback key. */ /** The number of random bytes needed to generate a fallback key. */
std::size_t generate_fallback_key_random_length(); std::size_t generate_fallback_key_random_length() const;
/** Generates a new fallback key. Returns std::size_t(-1) on error. If the /** Generates a new fallback key. Returns std::size_t(-1) on error. If the
* number of random bytes is too small then last_error will be * number of random bytes is too small then last_error will be
@ -138,8 +141,17 @@ struct Account {
std::uint8_t const * random, std::size_t random_length std::uint8_t const * random, std::size_t random_length
); );
/** Number of bytes needed to output the one time keys for this account */ /** Number of bytes needed to output the fallback keys for this account */
std::size_t get_fallback_key_json_length(); std::size_t get_fallback_key_json_length() const;
/** Deprecated: use get_unpublished_fallback_key_json instead */
std::size_t get_fallback_key_json(
std::uint8_t * fallback_json, std::size_t fallback_json_length
);
/** Number of bytes needed to output the unpublished fallback keys for this
* account */
std::size_t get_unpublished_fallback_key_json_length() const;
/** Output the fallback key as JSON: /** Output the fallback key as JSON:
* *
@ -150,13 +162,18 @@ struct Account {
* ] * ]
* } * }
* *
* if there is a fallback key and it has not been published yet.
*
* Returns the size of the JSON written or std::size_t(-1) on error. * Returns the size of the JSON written or std::size_t(-1) on error.
* If the buffer is too small last_error will be OUTPUT_BUFFER_TOO_SMALL. * If the buffer is too small last_error will be OUTPUT_BUFFER_TOO_SMALL.
*/ */
std::size_t get_fallback_key_json( std::size_t get_unpublished_fallback_key_json(
std::uint8_t * fallback_json, std::size_t fallback_json_length std::uint8_t * fallback_json, std::size_t fallback_json_length
); );
/** Forget about the old fallback key */
void forget_old_fallback_key();
/** Lookup a one time key with the given public key */ /** Lookup a one time key with the given public key */
OneTimeKey const * lookup_key( OneTimeKey const * lookup_key(
_olm_curve25519_public_key const & public_key _olm_curve25519_public_key const & public_key

View file

@ -22,6 +22,10 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -30,7 +34,7 @@ extern "C" {
/** /**
* The number of bytes of unpadded base64 needed to encode a length of input. * The number of bytes of unpadded base64 needed to encode a length of input.
*/ */
size_t _olm_encode_base64_length( OLM_EXPORT size_t _olm_encode_base64_length(
size_t input_length size_t input_length
); );
@ -42,7 +46,7 @@ size_t _olm_encode_base64_length(
* *
* Returns number of bytes encoded * Returns number of bytes encoded
*/ */
size_t _olm_encode_base64( OLM_EXPORT size_t _olm_encode_base64(
uint8_t const * input, size_t input_length, uint8_t const * input, size_t input_length,
uint8_t * output uint8_t * output
); );
@ -51,7 +55,7 @@ size_t _olm_encode_base64(
* The number of bytes of raw data a length of unpadded base64 will encode to. * The number of bytes of raw data a length of unpadded base64 will encode to.
* Returns size_t(-1) if the length is not a valid length for base64. * Returns size_t(-1) if the length is not a valid length for base64.
*/ */
size_t _olm_decode_base64_length( OLM_EXPORT size_t _olm_decode_base64_length(
size_t input_length size_t input_length
); );
@ -63,7 +67,7 @@ size_t _olm_decode_base64_length(
* *
* Returns number of bytes decoded * Returns number of bytes decoded
*/ */
size_t _olm_decode_base64( OLM_EXPORT size_t _olm_decode_base64(
uint8_t const * input, size_t input_length, uint8_t const * input, size_t input_length,
uint8_t * output uint8_t * output
); );

View file

@ -18,12 +18,16 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
namespace olm { namespace olm {
/** /**
* The number of bytes of unpadded base64 needed to encode a length of input. * The number of bytes of unpadded base64 needed to encode a length of input.
*/ */
std::size_t encode_base64_length( OLM_EXPORT std::size_t encode_base64_length(
std::size_t input_length std::size_t input_length
); );
@ -33,7 +37,7 @@ std::size_t encode_base64_length(
* The input can overlap with the last three quarters of the output buffer. * The input can overlap with the last three quarters of the output buffer.
* That is, the input pointer may be output + output_length - input_length. * That is, the input pointer may be output + output_length - input_length.
*/ */
std::uint8_t * encode_base64( OLM_EXPORT std::uint8_t * encode_base64(
std::uint8_t const * input, std::size_t input_length, std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output std::uint8_t * output
); );
@ -42,7 +46,7 @@ std::uint8_t * encode_base64(
* The number of bytes of raw data a length of unpadded base64 will encode to. * The number of bytes of raw data a length of unpadded base64 will encode to.
* Returns std::size_t(-1) if the length is not a valid length for base64. * Returns std::size_t(-1) if the length is not a valid length for base64.
*/ */
std::size_t decode_base64_length( OLM_EXPORT std::size_t decode_base64_length(
std::size_t input_length std::size_t input_length
); );
@ -51,8 +55,12 @@ std::size_t decode_base64_length(
* Writes decode_base64_length(input_length) bytes to the output buffer. * Writes decode_base64_length(input_length) bytes to the output buffer.
* The output can overlap with the first three quarters of the input buffer. * The output can overlap with the first three quarters of the input buffer.
* That is, the input pointers and output pointer may be the same. * That is, the input pointers and output pointer may be the same.
*
* Returns the number of bytes of raw data the base64 input decoded to. If the
* input length supplied is not a valid length for base64, returns
* std::size_t(-1) and does not decode.
*/ */
std::uint8_t const * decode_base64( OLM_EXPORT std::size_t decode_base64(
std::uint8_t const * input, std::size_t input_length, std::uint8_t const * input, std::size_t input_length,
std::uint8_t * output std::uint8_t * output
); );

View file

@ -19,6 +19,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -111,7 +115,7 @@ struct _olm_cipher_aes_sha_256 {
size_t kdf_info_length; size_t kdf_info_length;
}; };
extern const struct _olm_cipher_ops _olm_cipher_aes_sha_256_ops; OLM_EXPORT extern const struct _olm_cipher_ops _olm_cipher_aes_sha_256_ops;
/** /**
* get an initializer for an instance of struct _olm_cipher_aes_sha_256. * get an initializer for an instance of struct _olm_cipher_aes_sha_256.

View file

@ -20,6 +20,10 @@
#ifndef OLM_CRYPTO_H_ #ifndef OLM_CRYPTO_H_
#define OLM_CRYPTO_H_ #define OLM_CRYPTO_H_
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
@ -94,13 +98,13 @@ struct _olm_ed25519_key_pair {
/** The length of output the aes_encrypt_cbc function will write */ /** The length of output the aes_encrypt_cbc function will write */
size_t _olm_crypto_aes_encrypt_cbc_length( OLM_EXPORT size_t _olm_crypto_aes_encrypt_cbc_length(
size_t input_length size_t input_length
); );
/** Encrypts the input using AES256 in CBC mode with PKCS#7 padding. /** Encrypts the input using AES256 in CBC mode with PKCS#7 padding.
* The output buffer must be big enough to hold the output including padding */ * The output buffer must be big enough to hold the output including padding */
void _olm_crypto_aes_encrypt_cbc( OLM_EXPORT void _olm_crypto_aes_encrypt_cbc(
const struct _olm_aes256_key *key, const struct _olm_aes256_key *key,
const struct _olm_aes256_iv *iv, const struct _olm_aes256_iv *iv,
const uint8_t *input, size_t input_length, const uint8_t *input, size_t input_length,
@ -111,7 +115,7 @@ void _olm_crypto_aes_encrypt_cbc(
* least the same size as the input buffer. Returns the length of the plaintext * least the same size as the input buffer. Returns the length of the plaintext
* without padding on success or std::size_t(-1) if the padding is invalid. * without padding on success or std::size_t(-1) if the padding is invalid.
*/ */
size_t _olm_crypto_aes_decrypt_cbc( OLM_EXPORT size_t _olm_crypto_aes_decrypt_cbc(
const struct _olm_aes256_key *key, const struct _olm_aes256_key *key,
const struct _olm_aes256_iv *iv, const struct _olm_aes256_iv *iv,
uint8_t const * input, size_t input_length, uint8_t const * input, size_t input_length,
@ -121,7 +125,7 @@ size_t _olm_crypto_aes_decrypt_cbc(
/** Computes SHA-256 of the input. The output buffer must be a least /** Computes SHA-256 of the input. The output buffer must be a least
* SHA256_OUTPUT_LENGTH (32) bytes long. */ * SHA256_OUTPUT_LENGTH (32) bytes long. */
void _olm_crypto_sha256( OLM_EXPORT void _olm_crypto_sha256(
uint8_t const * input, size_t input_length, uint8_t const * input, size_t input_length,
uint8_t * output uint8_t * output
); );
@ -130,7 +134,7 @@ void _olm_crypto_sha256(
* http://tools.ietf.org/html/rfc2104 * http://tools.ietf.org/html/rfc2104
* Computes HMAC-SHA-256 of the input for the key. The output buffer must * Computes HMAC-SHA-256 of the input for the key. The output buffer must
* be at least SHA256_OUTPUT_LENGTH (32) bytes long. */ * be at least SHA256_OUTPUT_LENGTH (32) bytes long. */
void _olm_crypto_hmac_sha256( OLM_EXPORT void _olm_crypto_hmac_sha256(
uint8_t const * key, size_t key_length, uint8_t const * key, size_t key_length,
uint8_t const * input, size_t input_length, uint8_t const * input, size_t input_length,
uint8_t * output uint8_t * output
@ -140,7 +144,7 @@ void _olm_crypto_hmac_sha256(
/** HMAC-based Key Derivation Function (HKDF) /** HMAC-based Key Derivation Function (HKDF)
* https://tools.ietf.org/html/rfc5869 * https://tools.ietf.org/html/rfc5869
* Derives key material from the input bytes. */ * Derives key material from the input bytes. */
void _olm_crypto_hkdf_sha256( OLM_EXPORT void _olm_crypto_hkdf_sha256(
uint8_t const * input, size_t input_length, uint8_t const * input, size_t input_length,
uint8_t const * info, size_t info_length, uint8_t const * info, size_t info_length,
uint8_t const * salt, size_t salt_length, uint8_t const * salt, size_t salt_length,
@ -151,7 +155,7 @@ void _olm_crypto_hkdf_sha256(
/** Generate a curve25519 key pair /** Generate a curve25519 key pair
* random_32_bytes should be CURVE25519_RANDOM_LENGTH (32) bytes long. * random_32_bytes should be CURVE25519_RANDOM_LENGTH (32) bytes long.
*/ */
void _olm_crypto_curve25519_generate_key( OLM_EXPORT void _olm_crypto_curve25519_generate_key(
uint8_t const * random_32_bytes, uint8_t const * random_32_bytes,
struct _olm_curve25519_key_pair *output struct _olm_curve25519_key_pair *output
); );
@ -160,7 +164,7 @@ void _olm_crypto_curve25519_generate_key(
/** Create a shared secret using our private key and their public key. /** Create a shared secret using our private key and their public key.
* The output buffer must be at least CURVE25519_SHARED_SECRET_LENGTH (32) bytes long. * The output buffer must be at least CURVE25519_SHARED_SECRET_LENGTH (32) bytes long.
*/ */
void _olm_crypto_curve25519_shared_secret( OLM_EXPORT void _olm_crypto_curve25519_shared_secret(
const struct _olm_curve25519_key_pair *our_key, const struct _olm_curve25519_key_pair *our_key,
const struct _olm_curve25519_public_key *their_key, const struct _olm_curve25519_public_key *their_key,
uint8_t * output uint8_t * output
@ -169,7 +173,7 @@ void _olm_crypto_curve25519_shared_secret(
/** Generate an ed25519 key pair /** Generate an ed25519 key pair
* random_32_bytes should be ED25519_RANDOM_LENGTH (32) bytes long. * random_32_bytes should be ED25519_RANDOM_LENGTH (32) bytes long.
*/ */
void _olm_crypto_ed25519_generate_key( OLM_EXPORT void _olm_crypto_ed25519_generate_key(
uint8_t const * random_bytes, uint8_t const * random_bytes,
struct _olm_ed25519_key_pair *output struct _olm_ed25519_key_pair *output
); );
@ -178,7 +182,7 @@ void _olm_crypto_ed25519_generate_key(
* *
* The output buffer must be at least ED25519_SIGNATURE_LENGTH (64) bytes * The output buffer must be at least ED25519_SIGNATURE_LENGTH (64) bytes
* long. */ * long. */
void _olm_crypto_ed25519_sign( OLM_EXPORT void _olm_crypto_ed25519_sign(
const struct _olm_ed25519_key_pair *our_key, const struct _olm_ed25519_key_pair *our_key,
const uint8_t * message, size_t message_length, const uint8_t * message, size_t message_length,
uint8_t * output uint8_t * output
@ -187,7 +191,7 @@ void _olm_crypto_ed25519_sign(
/** Verify an ed25519 signature /** Verify an ed25519 signature
* The signature input buffer must be ED25519_SIGNATURE_LENGTH (64) bytes long. * The signature input buffer must be ED25519_SIGNATURE_LENGTH (64) bytes long.
* Returns non-zero if the signature is valid. */ * Returns non-zero if the signature is valid. */
int _olm_crypto_ed25519_verify( OLM_EXPORT int _olm_crypto_ed25519_verify(
const struct _olm_ed25519_public_key *their_key, const struct _olm_ed25519_public_key *their_key,
const uint8_t * message, size_t message_length, const uint8_t * message, size_t message_length,
const uint8_t * signature const uint8_t * signature

View file

@ -15,6 +15,8 @@
#ifndef OLM_ERROR_H_ #ifndef OLM_ERROR_H_
#define OLM_ERROR_H_ #define OLM_ERROR_H_
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -58,12 +60,18 @@ enum OlmErrorCode {
*/ */
OLM_SAS_THEIR_KEY_NOT_SET = 16, OLM_SAS_THEIR_KEY_NOT_SET = 16,
/**
* The pickled object was successfully decoded, but the unpickling still failed
* because it had some extraneous junk data at the end.
*/
OLM_PICKLE_EXTRA_DATA = 17,
/* remember to update the list of string constants in error.c when updating /* remember to update the list of string constants in error.c when updating
* this list. */ * this list. */
}; };
/** get a string representation of the given error code. */ /** get a string representation of the given error code. */
const char * _olm_error_to_string(enum OlmErrorCode error); OLM_EXPORT const char * _olm_error_to_string(enum OlmErrorCode error);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View file

@ -18,6 +18,10 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "olm/error.h"
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -25,31 +29,38 @@ extern "C" {
typedef struct OlmInboundGroupSession OlmInboundGroupSession; typedef struct OlmInboundGroupSession OlmInboundGroupSession;
/** get the size of an inbound group session, in bytes. */ /** get the size of an inbound group session, in bytes. */
size_t olm_inbound_group_session_size(void); OLM_EXPORT size_t olm_inbound_group_session_size(void);
/** /**
* Initialise an inbound group session object using the supplied memory * Initialise an inbound group session object using the supplied memory
* The supplied memory should be at least olm_inbound_group_session_size() * The supplied memory should be at least olm_inbound_group_session_size()
* bytes. * bytes.
*/ */
OlmInboundGroupSession * olm_inbound_group_session( OLM_EXPORT OlmInboundGroupSession * olm_inbound_group_session(
void *memory void *memory
); );
/** /**
* A null terminated string describing the most recent error to happen to a * A null terminated string describing the most recent error to happen to a
* group session */ * group session */
const char *olm_inbound_group_session_last_error( OLM_EXPORT const char *olm_inbound_group_session_last_error(
const OlmInboundGroupSession *session
);
/**
* An error code describing the most recent error to happen to a group
* session */
OLM_EXPORT enum OlmErrorCode olm_inbound_group_session_last_error_code(
const OlmInboundGroupSession *session const OlmInboundGroupSession *session
); );
/** Clears the memory used to back this group session */ /** Clears the memory used to back this group session */
size_t olm_clear_inbound_group_session( OLM_EXPORT size_t olm_clear_inbound_group_session(
OlmInboundGroupSession *session OlmInboundGroupSession *session
); );
/** Returns the number of bytes needed to store an inbound group session */ /** Returns the number of bytes needed to store an inbound group session */
size_t olm_pickle_inbound_group_session_length( OLM_EXPORT size_t olm_pickle_inbound_group_session_length(
const OlmInboundGroupSession *session const OlmInboundGroupSession *session
); );
@ -61,7 +72,7 @@ size_t olm_pickle_inbound_group_session_length(
* is smaller than olm_pickle_inbound_group_session_length() then * is smaller than olm_pickle_inbound_group_session_length() then
* olm_inbound_group_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" * olm_inbound_group_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL"
*/ */
size_t olm_pickle_inbound_group_session( OLM_EXPORT size_t olm_pickle_inbound_group_session(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
@ -77,7 +88,7 @@ size_t olm_pickle_inbound_group_session(
* olm_inbound_group_session_last_error() will be "INVALID_BASE64". The input * olm_inbound_group_session_last_error() will be "INVALID_BASE64". The input
* pickled buffer is destroyed * pickled buffer is destroyed
*/ */
size_t olm_unpickle_inbound_group_session( OLM_EXPORT size_t olm_unpickle_inbound_group_session(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
@ -94,7 +105,7 @@ size_t olm_unpickle_inbound_group_session(
* * OLM_INVALID_BASE64 if the session_key is not valid base64 * * OLM_INVALID_BASE64 if the session_key is not valid base64
* * OLM_BAD_SESSION_KEY if the session_key is invalid * * OLM_BAD_SESSION_KEY if the session_key is invalid
*/ */
size_t olm_init_inbound_group_session( OLM_EXPORT size_t olm_init_inbound_group_session(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
/* base64-encoded keys */ /* base64-encoded keys */
uint8_t const * session_key, size_t session_key_length uint8_t const * session_key, size_t session_key_length
@ -109,7 +120,7 @@ size_t olm_init_inbound_group_session(
* * OLM_INVALID_BASE64 if the session_key is not valid base64 * * OLM_INVALID_BASE64 if the session_key is not valid base64
* * OLM_BAD_SESSION_KEY if the session_key is invalid * * OLM_BAD_SESSION_KEY if the session_key is invalid
*/ */
size_t olm_import_inbound_group_session( OLM_EXPORT size_t olm_import_inbound_group_session(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
/* base64-encoded keys; note that it will be overwritten with the base64-decoded /* base64-encoded keys; note that it will be overwritten with the base64-decoded
data. */ data. */
@ -126,7 +137,7 @@ size_t olm_import_inbound_group_session(
* *
* Returns olm_error() on failure. * Returns olm_error() on failure.
*/ */
size_t olm_group_decrypt_max_plaintext_length( OLM_EXPORT size_t olm_group_decrypt_max_plaintext_length(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
uint8_t * message, size_t message_length uint8_t * message, size_t message_length
); );
@ -150,7 +161,7 @@ size_t olm_group_decrypt_max_plaintext_length(
* message's index (ie, it was sent before the session key was shared with * message's index (ie, it was sent before the session key was shared with
* us) * us)
*/ */
size_t olm_group_decrypt( OLM_EXPORT size_t olm_group_decrypt(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
/* input; note that it will be overwritten with the base64-decoded /* input; note that it will be overwritten with the base64-decoded
@ -166,7 +177,7 @@ size_t olm_group_decrypt(
/** /**
* Get the number of bytes returned by olm_inbound_group_session_id() * Get the number of bytes returned by olm_inbound_group_session_id()
*/ */
size_t olm_inbound_group_session_id_length( OLM_EXPORT size_t olm_inbound_group_session_id_length(
const OlmInboundGroupSession *session const OlmInboundGroupSession *session
); );
@ -178,7 +189,7 @@ size_t olm_inbound_group_session_id_length(
* last_error will be OUTPUT_BUFFER_TOO_SMALL if the id buffer was too * last_error will be OUTPUT_BUFFER_TOO_SMALL if the id buffer was too
* small. * small.
*/ */
size_t olm_inbound_group_session_id( OLM_EXPORT size_t olm_inbound_group_session_id(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
uint8_t * id, size_t id_length uint8_t * id, size_t id_length
); );
@ -186,7 +197,7 @@ size_t olm_inbound_group_session_id(
/** /**
* Get the first message index we know how to decrypt. * Get the first message index we know how to decrypt.
*/ */
uint32_t olm_inbound_group_session_first_known_index( OLM_EXPORT uint32_t olm_inbound_group_session_first_known_index(
const OlmInboundGroupSession *session const OlmInboundGroupSession *session
); );
@ -199,14 +210,14 @@ uint32_t olm_inbound_group_session_first_known_index(
* *
* This is mainly intended for the unit tests, currently. * This is mainly intended for the unit tests, currently.
*/ */
int olm_inbound_group_session_is_verified( OLM_EXPORT int olm_inbound_group_session_is_verified(
const OlmInboundGroupSession *session const OlmInboundGroupSession *session
); );
/** /**
* Get the number of bytes returned by olm_export_inbound_group_session() * Get the number of bytes returned by olm_export_inbound_group_session()
*/ */
size_t olm_export_inbound_group_session_length( OLM_EXPORT size_t olm_export_inbound_group_session_length(
const OlmInboundGroupSession *session const OlmInboundGroupSession *session
); );
@ -222,7 +233,7 @@ size_t olm_export_inbound_group_session_length(
* given index (ie, it was sent before the session key was shared with * given index (ie, it was sent before the session key was shared with
* us) * us)
*/ */
size_t olm_export_inbound_group_session( OLM_EXPORT size_t olm_export_inbound_group_session(
OlmInboundGroupSession *session, OlmInboundGroupSession *session,
uint8_t * key, size_t key_length, uint32_t message_index uint8_t * key, size_t key_length, uint32_t message_index
); );

View file

@ -99,9 +99,9 @@ public:
return *this; return *this;
} }
T * this_pos = _data; T * this_pos = _data;
T * const other_pos = other._data; const T * other_pos = other._data;
while (other_pos != other._end) { while (other_pos != other._end) {
*this_pos = *other; *this_pos = *other_pos;
++this_pos; ++this_pos;
++other_pos; ++other_pos;
} }

View file

@ -23,6 +23,10 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -59,25 +63,25 @@ extern const struct _olm_cipher *megolm_cipher;
* initialize the megolm ratchet. random_data should be at least * initialize the megolm ratchet. random_data should be at least
* MEGOLM_RATCHET_LENGTH bytes of randomness. * MEGOLM_RATCHET_LENGTH bytes of randomness.
*/ */
void megolm_init(Megolm *megolm, uint8_t const *random_data, uint32_t counter); OLM_EXPORT void megolm_init(Megolm *megolm, uint8_t const *random_data, uint32_t counter);
/** Returns the number of bytes needed to store a megolm */ /** Returns the number of bytes needed to store a megolm */
size_t megolm_pickle_length(const Megolm *megolm); OLM_EXPORT size_t megolm_pickle_length(const Megolm *megolm);
/** /**
* Pickle the megolm. Returns a pointer to the next free space in the buffer. * Pickle the megolm. Returns a pointer to the next free space in the buffer.
*/ */
uint8_t * megolm_pickle(const Megolm *megolm, uint8_t *pos); OLM_EXPORT uint8_t * megolm_pickle(const Megolm *megolm, uint8_t *pos);
/** /**
* Unpickle the megolm. Returns a pointer to the next item in the buffer. * Unpickle the megolm. Returns a pointer to the next item in the buffer.
*/ */
const uint8_t * megolm_unpickle(Megolm *megolm, const uint8_t *pos, OLM_EXPORT const uint8_t * megolm_unpickle(Megolm *megolm, const uint8_t *pos,
const uint8_t *end); const uint8_t *end);
/** advance the ratchet by one step */ /** advance the ratchet by one step */
void megolm_advance(Megolm *megolm); OLM_EXPORT void megolm_advance(Megolm *megolm);
/** /**
* get the key data in the ratchet. The returned data is * get the key data in the ratchet. The returned data is
@ -86,7 +90,7 @@ void megolm_advance(Megolm *megolm);
#define megolm_get_data(megolm) ((const uint8_t *)((megolm)->data)) #define megolm_get_data(megolm) ((const uint8_t *)((megolm)->data))
/** advance the ratchet to a given count */ /** advance the ratchet to a given count */
void megolm_advance_to(Megolm *megolm, uint32_t advance_to); OLM_EXPORT void megolm_advance_to(Megolm *megolm, uint32_t advance_to);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View file

@ -27,6 +27,10 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -34,7 +38,7 @@ extern "C" {
/** /**
* The length of the buffer needed to hold a group message. * The length of the buffer needed to hold a group message.
*/ */
size_t _olm_encode_group_message_length( OLM_EXPORT size_t _olm_encode_group_message_length(
uint32_t chain_index, uint32_t chain_index,
size_t ciphertext_length, size_t ciphertext_length,
size_t mac_length, size_t mac_length,
@ -55,7 +59,7 @@ size_t _olm_encode_group_message_length(
* *
* Returns the size of the message, up to the MAC. * Returns the size of the message, up to the MAC.
*/ */
size_t _olm_encode_group_message( OLM_EXPORT size_t _olm_encode_group_message(
uint8_t version, uint8_t version,
uint32_t message_index, uint32_t message_index,
size_t ciphertext_length, size_t ciphertext_length,
@ -76,7 +80,7 @@ struct _OlmDecodeGroupMessageResults {
/** /**
* Reads the message headers from the input buffer. * Reads the message headers from the input buffer.
*/ */
void _olm_decode_group_message( OLM_EXPORT void _olm_decode_group_message(
const uint8_t *input, size_t input_length, const uint8_t *input, size_t input_length,
size_t mac_length, size_t signature_length, size_t mac_length, size_t signature_length,

View file

@ -27,13 +27,16 @@
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
namespace olm { namespace olm {
/** /**
* The length of the buffer needed to hold a message. * The length of the buffer needed to hold a message.
*/ */
std::size_t encode_message_length( OLM_EXPORT std::size_t encode_message_length(
std::uint32_t counter, std::uint32_t counter,
std::size_t ratchet_key_length, std::size_t ratchet_key_length,
std::size_t ciphertext_length, std::size_t ciphertext_length,
@ -61,7 +64,7 @@ struct MessageReader {
* Writes the message headers into the output buffer. * Writes the message headers into the output buffer.
* Populates the writer struct with pointers into the output buffer. * Populates the writer struct with pointers into the output buffer.
*/ */
void encode_message( OLM_EXPORT void encode_message(
MessageWriter & writer, MessageWriter & writer,
std::uint8_t version, std::uint8_t version,
std::uint32_t counter, std::uint32_t counter,
@ -75,7 +78,7 @@ void encode_message(
* Reads the message headers from the input buffer. * Reads the message headers from the input buffer.
* Populates the reader struct with pointers into the input buffer. * Populates the reader struct with pointers into the input buffer.
*/ */
void decode_message( OLM_EXPORT void decode_message(
MessageReader & reader, MessageReader & reader,
std::uint8_t const * input, std::size_t input_length, std::uint8_t const * input, std::size_t input_length,
std::size_t mac_length std::size_t mac_length

View file

@ -19,9 +19,12 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "olm/error.h"
#include "olm/inbound_group_session.h" #include "olm/inbound_group_session.h"
#include "olm/outbound_group_session.h" #include "olm/outbound_group_session.h"
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -36,79 +39,94 @@ typedef struct OlmUtility OlmUtility;
/** Get the version number of the library. /** Get the version number of the library.
* Arguments will be updated if non-null. * Arguments will be updated if non-null.
*/ */
void olm_get_library_version(uint8_t *major, uint8_t *minor, uint8_t *patch); OLM_EXPORT void olm_get_library_version(uint8_t *major, uint8_t *minor, uint8_t *patch);
/** The size of an account object in bytes */ /** The size of an account object in bytes */
size_t olm_account_size(void); OLM_EXPORT size_t olm_account_size(void);
/** The size of a session object in bytes */ /** The size of a session object in bytes */
size_t olm_session_size(void); OLM_EXPORT size_t olm_session_size(void);
/** The size of a utility object in bytes */ /** The size of a utility object in bytes */
size_t olm_utility_size(void); OLM_EXPORT size_t olm_utility_size(void);
/** Initialise an account object using the supplied memory /** Initialise an account object using the supplied memory
* The supplied memory must be at least olm_account_size() bytes */ * The supplied memory must be at least olm_account_size() bytes */
OlmAccount * olm_account( OLM_EXPORT OlmAccount * olm_account(
void * memory void * memory
); );
/** Initialise a session object using the supplied memory /** Initialise a session object using the supplied memory
* The supplied memory must be at least olm_session_size() bytes */ * The supplied memory must be at least olm_session_size() bytes */
OlmSession * olm_session( OLM_EXPORT OlmSession * olm_session(
void * memory void * memory
); );
/** Initialise a utility object using the supplied memory /** Initialise a utility object using the supplied memory
* The supplied memory must be at least olm_utility_size() bytes */ * The supplied memory must be at least olm_utility_size() bytes */
OlmUtility * olm_utility( OLM_EXPORT OlmUtility * olm_utility(
void * memory void * memory
); );
/** The value that olm will return from a function if there was an error */ /** The value that olm will return from a function if there was an error */
size_t olm_error(void); OLM_EXPORT size_t olm_error(void);
/** A null terminated string describing the most recent error to happen to an /** A null terminated string describing the most recent error to happen to an
* account */ * account */
const char * olm_account_last_error( OLM_EXPORT const char * olm_account_last_error(
OlmAccount * account OlmAccount const * account
);
/** An error code describing the most recent error to happen to an account */
OLM_EXPORT enum OlmErrorCode olm_account_last_error_code(
OlmAccount const * account
); );
/** A null terminated string describing the most recent error to happen to a /** A null terminated string describing the most recent error to happen to a
* session */ * session */
const char * olm_session_last_error( OLM_EXPORT const char * olm_session_last_error(
OlmSession * session OlmSession const * session
);
/** An error code describing the most recent error to happen to a session */
OLM_EXPORT enum OlmErrorCode olm_session_last_error_code(
OlmSession const * session
); );
/** A null terminated string describing the most recent error to happen to a /** A null terminated string describing the most recent error to happen to a
* utility */ * utility */
const char * olm_utility_last_error( OLM_EXPORT const char * olm_utility_last_error(
OlmUtility * utility OlmUtility const * utility
);
/** An error code describing the most recent error to happen to a utility */
OLM_EXPORT enum OlmErrorCode olm_utility_last_error_code(
OlmUtility const * utility
); );
/** Clears the memory used to back this account */ /** Clears the memory used to back this account */
size_t olm_clear_account( OLM_EXPORT size_t olm_clear_account(
OlmAccount * account OlmAccount * account
); );
/** Clears the memory used to back this session */ /** Clears the memory used to back this session */
size_t olm_clear_session( OLM_EXPORT size_t olm_clear_session(
OlmSession * session OlmSession * session
); );
/** Clears the memory used to back this utility */ /** Clears the memory used to back this utility */
size_t olm_clear_utility( OLM_EXPORT size_t olm_clear_utility(
OlmUtility * utility OlmUtility * utility
); );
/** Returns the number of bytes needed to store an account */ /** Returns the number of bytes needed to store an account */
size_t olm_pickle_account_length( OLM_EXPORT size_t olm_pickle_account_length(
OlmAccount * account OlmAccount const * account
); );
/** Returns the number of bytes needed to store a session */ /** Returns the number of bytes needed to store a session */
size_t olm_pickle_session_length( OLM_EXPORT size_t olm_pickle_session_length(
OlmSession * session OlmSession const * session
); );
/** Stores an account as a base64 string. Encrypts the account using the /** Stores an account as a base64 string. Encrypts the account using the
@ -116,7 +134,7 @@ size_t olm_pickle_session_length(
* Returns olm_error() on failure. If the pickle output buffer * Returns olm_error() on failure. If the pickle output buffer
* is smaller than olm_pickle_account_length() then * is smaller than olm_pickle_account_length() then
* olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
size_t olm_pickle_account( OLM_EXPORT size_t olm_pickle_account(
OlmAccount * account, OlmAccount * account,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
@ -127,7 +145,7 @@ size_t olm_pickle_account(
* Returns olm_error() on failure. If the pickle output buffer * Returns olm_error() on failure. If the pickle output buffer
* is smaller than olm_pickle_session_length() then * is smaller than olm_pickle_session_length() then
* olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
size_t olm_pickle_session( OLM_EXPORT size_t olm_pickle_session(
OlmSession * session, OlmSession * session,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
@ -139,7 +157,7 @@ size_t olm_pickle_session(
* will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
* olm_account_last_error() will be "INVALID_BASE64". The input pickled * olm_account_last_error() will be "INVALID_BASE64". The input pickled
* buffer is destroyed */ * buffer is destroyed */
size_t olm_unpickle_account( OLM_EXPORT size_t olm_unpickle_account(
OlmAccount * account, OlmAccount * account,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
@ -151,57 +169,57 @@ size_t olm_unpickle_account(
* will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
* olm_session_last_error() will be "INVALID_BASE64". The input pickled * olm_session_last_error() will be "INVALID_BASE64". The input pickled
* buffer is destroyed */ * buffer is destroyed */
size_t olm_unpickle_session( OLM_EXPORT size_t olm_unpickle_session(
OlmSession * session, OlmSession * session,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
); );
/** The number of random bytes needed to create an account.*/ /** The number of random bytes needed to create an account.*/
size_t olm_create_account_random_length( OLM_EXPORT size_t olm_create_account_random_length(
OlmAccount * account OlmAccount const * account
); );
/** Creates a new account. Returns olm_error() on failure. If there weren't /** Creates a new account. Returns olm_error() on failure. If there weren't
* enough random bytes then olm_account_last_error() will be * enough random bytes then olm_account_last_error() will be
* "NOT_ENOUGH_RANDOM" */ * "NOT_ENOUGH_RANDOM" */
size_t olm_create_account( OLM_EXPORT size_t olm_create_account(
OlmAccount * account, OlmAccount * account,
void * random, size_t random_length void * random, size_t random_length
); );
/** The size of the output buffer needed to hold the identity keys */ /** The size of the output buffer needed to hold the identity keys */
size_t olm_account_identity_keys_length( OLM_EXPORT size_t olm_account_identity_keys_length(
OlmAccount * account OlmAccount const * account
); );
/** Writes the public parts of the identity keys for the account into the /** Writes the public parts of the identity keys for the account into the
* identity_keys output buffer. Returns olm_error() on failure. If the * identity_keys output buffer. Returns olm_error() on failure. If the
* identity_keys buffer was too small then olm_account_last_error() will be * identity_keys buffer was too small then olm_account_last_error() will be
* "OUTPUT_BUFFER_TOO_SMALL". */ * "OUTPUT_BUFFER_TOO_SMALL". */
size_t olm_account_identity_keys( OLM_EXPORT size_t olm_account_identity_keys(
OlmAccount * account, OlmAccount * account,
void * identity_keys, size_t identity_key_length void * identity_keys, size_t identity_key_length
); );
/** The length of an ed25519 signature encoded as base64. */ /** The length of an ed25519 signature encoded as base64. */
size_t olm_account_signature_length( OLM_EXPORT size_t olm_account_signature_length(
OlmAccount * account OlmAccount const * account
); );
/** Signs a message with the ed25519 key for this account. Returns olm_error() /** Signs a message with the ed25519 key for this account. Returns olm_error()
* on failure. If the signature buffer was too small then * on failure. If the signature buffer was too small then
* olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ * olm_account_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
size_t olm_account_sign( OLM_EXPORT size_t olm_account_sign(
OlmAccount * account, OlmAccount * account,
void const * message, size_t message_length, void const * message, size_t message_length,
void * signature, size_t signature_length void * signature, size_t signature_length
); );
/** The size of the output buffer needed to hold the one time keys */ /** The size of the output buffer needed to hold the one time keys */
size_t olm_account_one_time_keys_length( OLM_EXPORT size_t olm_account_one_time_keys_length(
OlmAccount * account OlmAccount const * account
); );
/** Writes the public parts of the unpublished one time keys for the account /** Writes the public parts of the unpublished one time keys for the account
@ -222,25 +240,31 @@ size_t olm_account_one_time_keys_length(
* <p> * <p>
* If the one_time_keys buffer was too small then olm_account_last_error() * If the one_time_keys buffer was too small then olm_account_last_error()
* will be "OUTPUT_BUFFER_TOO_SMALL". */ * will be "OUTPUT_BUFFER_TOO_SMALL". */
size_t olm_account_one_time_keys( OLM_EXPORT size_t olm_account_one_time_keys(
OlmAccount * account, OlmAccount * account,
void * one_time_keys, size_t one_time_keys_length void * one_time_keys, size_t one_time_keys_length
); );
/** Marks the current set of one time keys as being published. */ /** Marks the current set of one time keys and fallback key as being published
size_t olm_account_mark_keys_as_published( * Once marked as published, the one time keys will no longer be returned by
* olm_account_one_time_keys(), and the fallback key will no longer be returned
* by olm_account_unpublished_fallback_key().
*
* Returns the number of one-time keys that were marked as published. Note that
* this count does not include the fallback key. */
OLM_EXPORT size_t olm_account_mark_keys_as_published(
OlmAccount * account OlmAccount * account
); );
/** The largest number of one time keys this account can store. */ /** The largest number of one time keys this account can store. */
size_t olm_account_max_number_of_one_time_keys( OLM_EXPORT size_t olm_account_max_number_of_one_time_keys(
OlmAccount * account OlmAccount const * account
); );
/** The number of random bytes needed to generate a given number of new one /** The number of random bytes needed to generate a given number of new one
* time keys. */ * time keys. */
size_t olm_account_generate_one_time_keys_random_length( OLM_EXPORT size_t olm_account_generate_one_time_keys_random_length(
OlmAccount * account, OlmAccount const * account,
size_t number_of_keys size_t number_of_keys
); );
@ -248,40 +272,63 @@ size_t olm_account_generate_one_time_keys_random_length(
* by this account exceeds max_number_of_one_time_keys() then the old keys are * by this account exceeds max_number_of_one_time_keys() then the old keys are
* discarded. Returns olm_error() on error. If the number of random bytes is * discarded. Returns olm_error() on error. If the number of random bytes is
* too small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */ * too small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */
size_t olm_account_generate_one_time_keys( OLM_EXPORT size_t olm_account_generate_one_time_keys(
OlmAccount * account, OlmAccount * account,
size_t number_of_keys, size_t number_of_keys,
void * random, size_t random_length void * random, size_t random_length
); );
/** The number of random bytes needed to generate a fallback key. */ /** The number of random bytes needed to generate a fallback key. */
size_t olm_account_generate_fallback_key_random_length( OLM_EXPORT size_t olm_account_generate_fallback_key_random_length(
OlmAccount * account OlmAccount const * account
); );
/** Generates a new fallback key. Only one previous fallback key is /** Generates a new fallback key. Only one previous fallback key is
* stored. Returns olm_error() on error. If the number of random bytes is too * stored. Returns olm_error() on error. If the number of random bytes is too
* small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */ * small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */
size_t olm_account_generate_fallback_key( OLM_EXPORT size_t olm_account_generate_fallback_key(
OlmAccount * account, OlmAccount * account,
void * random, size_t random_length void * random, size_t random_length
); );
/** The number of bytes needed to hold the fallback key as returned by /** The number of bytes needed to hold the fallback key as returned by
* olm_account_fallback_key. */ * olm_account_fallback_key. */
size_t olm_account_fallback_key_length( OLM_EXPORT size_t olm_account_fallback_key_length(
OlmAccount * account OlmAccount const * account
); );
size_t olm_account_fallback_key( /** Deprecated: use olm_account_unpublished_fallback_key instead */
OLM_EXPORT size_t olm_account_fallback_key(
OlmAccount * account, OlmAccount * account,
void * fallback_key, size_t fallback_key_size void * fallback_key, size_t fallback_key_size
); );
/** The number of bytes needed to hold the unpublished fallback key as returned
* by olm_account_unpublished fallback_key. */
OLM_EXPORT size_t olm_account_unpublished_fallback_key_length(
OlmAccount const * account
);
/** Returns the fallback key (if present, and if unpublished) into the
* fallback_key buffer */
OLM_EXPORT size_t olm_account_unpublished_fallback_key(
OlmAccount * account,
void * fallback_key, size_t fallback_key_size
);
/** Forget about the old fallback key. This should be called once you are
* reasonably certain that you will not receive any more messages that use
* the old fallback key (e.g. 5 minutes after the new fallback key has been
* published).
*/
OLM_EXPORT void olm_account_forget_old_fallback_key(
OlmAccount * account
);
/** The number of random bytes needed to create an outbound session */ /** The number of random bytes needed to create an outbound session */
size_t olm_create_outbound_session_random_length( OLM_EXPORT size_t olm_create_outbound_session_random_length(
OlmSession * session OlmSession const * session
); );
/** Creates a new out-bound session for sending messages to a given identity_key /** Creates a new out-bound session for sending messages to a given identity_key
@ -289,9 +336,9 @@ size_t olm_create_outbound_session_random_length(
* decoded as base64 then olm_session_last_error() will be "INVALID_BASE64" * decoded as base64 then olm_session_last_error() will be "INVALID_BASE64"
* If there weren't enough random bytes then olm_session_last_error() will * If there weren't enough random bytes then olm_session_last_error() will
* be "NOT_ENOUGH_RANDOM". */ * be "NOT_ENOUGH_RANDOM". */
size_t olm_create_outbound_session( OLM_EXPORT size_t olm_create_outbound_session(
OlmSession * session, OlmSession * session,
OlmAccount * account, OlmAccount const * account,
void const * their_identity_key, size_t their_identity_key_length, 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 const * their_one_time_key, size_t their_one_time_key_length,
void * random, size_t random_length void * random, size_t random_length
@ -302,24 +349,19 @@ size_t olm_create_outbound_session(
* couldn't be decoded then olm_session_last_error will be "INVALID_BASE64". * couldn't be decoded then olm_session_last_error will be "INVALID_BASE64".
* If the message was for an unsupported protocol version then * If the message was for an unsupported protocol version then
* olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message * olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
* couldn't be decoded then then olm_session_last_error() will be * couldn't be decoded then olm_session_last_error() will be
* "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time * "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time
* key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */ * key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */
size_t olm_create_inbound_session( OLM_EXPORT size_t olm_create_inbound_session(
OlmSession * session, OlmSession * session,
OlmAccount * account, OlmAccount * account,
void * one_time_key_message, size_t message_length void * one_time_key_message, size_t message_length
); );
/** Create a new in-bound session for sending/receiving messages from an /** Same as olm_create_inbound_session, but ensures that the identity key
* incoming PRE_KEY message. Returns olm_error() on failure. If the base64 * in the pre-key message matches the expected identity key, supplied via the
* couldn't be decoded then olm_session_last_error will be "INVALID_BASE64". * `their_identity_key` parameter. Fails early if there is no match. */
* If the message was for an unsupported protocol version then OLM_EXPORT size_t olm_create_inbound_session_from(
* olm_session_last_error() will be "BAD_MESSAGE_VERSION". If the message
* couldn't be decoded then then olm_session_last_error() will be
* "BAD_MESSAGE_FORMAT". If the message refers to an unknown one time
* key then olm_session_last_error() will be "BAD_MESSAGE_KEY_ID". */
size_t olm_create_inbound_session_from(
OlmSession * session, OlmSession * session,
OlmAccount * account, OlmAccount * account,
void const * their_identity_key, size_t their_identity_key_length, void const * their_identity_key, size_t their_identity_key_length,
@ -327,27 +369,30 @@ size_t olm_create_inbound_session_from(
); );
/** The length of the buffer needed to return the id for this session. */ /** The length of the buffer needed to return the id for this session. */
size_t olm_session_id_length( OLM_EXPORT size_t olm_session_id_length(
OlmSession * session OlmSession const * session
); );
/** An identifier for this session. Will be the same for both ends of the /** An identifier for this session. Will be the same for both ends of the
* conversation. If the id buffer is too small then olm_session_last_error() * conversation. If the id buffer is too small then olm_session_last_error()
* will be "OUTPUT_BUFFER_TOO_SMALL". */ * will be "OUTPUT_BUFFER_TOO_SMALL". */
size_t olm_session_id( OLM_EXPORT size_t olm_session_id(
OlmSession * session, OlmSession * session,
void * id, size_t id_length void * id, size_t id_length
); );
int olm_session_has_received_message( OLM_EXPORT int olm_session_has_received_message(
OlmSession *session OlmSession const *session
); );
/** /**
* Write a null-terminated string describing the internal state of an olm * Write a null-terminated string describing the internal state of an olm
* session to the buffer provided for debugging and logging purposes. * session to the buffer provided for debugging and logging purposes. If the
* buffer is not large enough to hold the entire string, it will be truncated
* and will end with "...". A buffer length of 600 will be enough to hold any
* output.
*/ */
void olm_session_describe(OlmSession * session, char *buf, size_t buflen); OLM_EXPORT void olm_session_describe(OlmSession * session, char *buf, size_t buflen);
/** Checks if the PRE_KEY message is for this in-bound session. This can happen /** Checks if the PRE_KEY message is for this in-bound session. This can happen
* if multiple messages are sent to this account before this account sends a * if multiple messages are sent to this account before this account sends a
@ -358,7 +403,7 @@ void olm_session_describe(OlmSession * session, char *buf, size_t buflen);
* unsupported protocol version then olm_session_last_error() will be * unsupported protocol version then olm_session_last_error() will be
* "BAD_MESSAGE_VERSION". If the message couldn't be decoded then then * "BAD_MESSAGE_VERSION". If the message couldn't be decoded then then
* olm_session_last_error() will be "BAD_MESSAGE_FORMAT". */ * olm_session_last_error() will be "BAD_MESSAGE_FORMAT". */
size_t olm_matches_inbound_session( OLM_EXPORT size_t olm_matches_inbound_session(
OlmSession * session, OlmSession * session,
void * one_time_key_message, size_t message_length void * one_time_key_message, size_t message_length
); );
@ -372,7 +417,7 @@ size_t olm_matches_inbound_session(
* unsupported protocol version then olm_session_last_error() will be * unsupported protocol version then olm_session_last_error() will be
* "BAD_MESSAGE_VERSION". If the message couldn't be decoded then then * "BAD_MESSAGE_VERSION". If the message couldn't be decoded then then
* olm_session_last_error() will be "BAD_MESSAGE_FORMAT". */ * olm_session_last_error() will be "BAD_MESSAGE_FORMAT". */
size_t olm_matches_inbound_session_from( OLM_EXPORT size_t olm_matches_inbound_session_from(
OlmSession * session, OlmSession * session,
void const * their_identity_key, size_t their_identity_key_length, void const * their_identity_key, size_t their_identity_key_length,
void * one_time_key_message, size_t message_length void * one_time_key_message, size_t message_length
@ -381,7 +426,7 @@ size_t olm_matches_inbound_session_from(
/** Removes the one time keys that the session used from the account. Returns /** Removes the one time keys that the session used from the account. Returns
* olm_error() on failure. If the account doesn't have any matching one time * olm_error() on failure. If the account doesn't have any matching one time
* keys then olm_account_last_error() will be "BAD_MESSAGE_KEY_ID". */ * keys then olm_account_last_error() will be "BAD_MESSAGE_KEY_ID". */
size_t olm_remove_one_time_keys( OLM_EXPORT size_t olm_remove_one_time_keys(
OlmAccount * account, OlmAccount * account,
OlmSession * session OlmSession * session
); );
@ -390,19 +435,19 @@ size_t olm_remove_one_time_keys(
* OLM_MESSAGE_TYPE_PRE_KEY if the message will be a PRE_KEY message. * OLM_MESSAGE_TYPE_PRE_KEY if the message will be a PRE_KEY message.
* Returns OLM_MESSAGE_TYPE_MESSAGE if the message will be a normal message. * Returns OLM_MESSAGE_TYPE_MESSAGE if the message will be a normal message.
* Returns olm_error on failure. */ * Returns olm_error on failure. */
size_t olm_encrypt_message_type( OLM_EXPORT size_t olm_encrypt_message_type(
OlmSession * session OlmSession const * session
); );
/** The number of random bytes needed to encrypt the next message. */ /** The number of random bytes needed to encrypt the next message. */
size_t olm_encrypt_random_length( OLM_EXPORT size_t olm_encrypt_random_length(
OlmSession * session OlmSession const * session
); );
/** The size of the next message in bytes for the given number of plain-text /** The size of the next message in bytes for the given number of plain-text
* bytes. */ * bytes. */
size_t olm_encrypt_message_length( OLM_EXPORT size_t olm_encrypt_message_length(
OlmSession * session, OlmSession const * session,
size_t plaintext_length size_t plaintext_length
); );
@ -412,7 +457,7 @@ size_t olm_encrypt_message_length(
* olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If there * olm_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If there
* weren't enough random bytes then olm_session_last_error() will be * weren't enough random bytes then olm_session_last_error() will be
* "NOT_ENOUGH_RANDOM". */ * "NOT_ENOUGH_RANDOM". */
size_t olm_encrypt( OLM_EXPORT size_t olm_encrypt(
OlmSession * session, OlmSession * session,
void const * plaintext, size_t plaintext_length, void const * plaintext, size_t plaintext_length,
void * random, size_t random_length, void * random, size_t random_length,
@ -427,7 +472,7 @@ size_t olm_encrypt(
* protocol then olm_session_last_error() will be "BAD_MESSAGE_VERSION". * protocol then olm_session_last_error() will be "BAD_MESSAGE_VERSION".
* If the message couldn't be decoded then olm_session_last_error() will be * If the message couldn't be decoded then olm_session_last_error() will be
* "BAD_MESSAGE_FORMAT". */ * "BAD_MESSAGE_FORMAT". */
size_t olm_decrypt_max_plaintext_length( OLM_EXPORT size_t olm_decrypt_max_plaintext_length(
OlmSession * session, OlmSession * session,
size_t message_type, size_t message_type,
void * message, size_t message_length void * message, size_t message_length
@ -444,7 +489,7 @@ size_t olm_decrypt_max_plaintext_length(
* olm_session_last_error() will be BAD_MESSAGE_FORMAT". * olm_session_last_error() will be BAD_MESSAGE_FORMAT".
* If the MAC on the message was invalid then olm_session_last_error() will * If the MAC on the message was invalid then olm_session_last_error() will
* be "BAD_MESSAGE_MAC". */ * be "BAD_MESSAGE_MAC". */
size_t olm_decrypt( OLM_EXPORT size_t olm_decrypt(
OlmSession * session, OlmSession * session,
size_t message_type, size_t message_type,
void * message, size_t message_length, void * message, size_t message_length,
@ -452,14 +497,14 @@ size_t olm_decrypt(
); );
/** The length of the buffer needed to hold the SHA-256 hash. */ /** The length of the buffer needed to hold the SHA-256 hash. */
size_t olm_sha256_length( OLM_EXPORT size_t olm_sha256_length(
OlmUtility * utility OlmUtility const * utility
); );
/** Calculates the SHA-256 hash of the input and encodes it as base64. If the /** Calculates the SHA-256 hash of the input and encodes it as base64. If the
* output buffer is smaller than olm_sha256_length() then * output buffer is smaller than olm_sha256_length() then
* olm_utility_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */ * olm_utility_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */
size_t olm_sha256( OLM_EXPORT size_t olm_sha256(
OlmUtility * utility, OlmUtility * utility,
void const * input, size_t input_length, void const * input, size_t input_length,
void * output, size_t output_length void * output, size_t output_length
@ -468,7 +513,7 @@ size_t olm_sha256(
/** Verify an ed25519 signature. If the key was too small then /** Verify an ed25519 signature. If the key was too small then
* olm_utility_last_error() will be "INVALID_BASE64". If the signature was invalid * olm_utility_last_error() will be "INVALID_BASE64". If the signature was invalid
* then olm_utility_last_error() will be "BAD_MESSAGE_MAC". */ * then olm_utility_last_error() will be "BAD_MESSAGE_MAC". */
size_t olm_ed25519_verify( OLM_EXPORT size_t olm_ed25519_verify(
OlmUtility * utility, OlmUtility * utility,
void const * key, size_t key_length, void const * key, size_t key_length,
void const * message, size_t message_length, void const * message, size_t message_length,

42
include/olm/olm_export.h Normal file
View file

@ -0,0 +1,42 @@
#ifndef OLM_EXPORT_H
#define OLM_EXPORT_H
#ifdef OLM_STATIC_DEFINE
# define OLM_EXPORT
# define OLM_NO_EXPORT
#else
# ifndef OLM_EXPORT
# ifdef olm_EXPORTS
/* We are building this library */
# define OLM_EXPORT
# else
/* We are using this library */
# define OLM_EXPORT
# endif
# endif
# ifndef OLM_NO_EXPORT
# define OLM_NO_EXPORT
# endif
#endif
#ifndef OLM_DEPRECATED
# define OLM_DEPRECATED __attribute__ ((__deprecated__))
#endif
#ifndef OLM_DEPRECATED_EXPORT
# define OLM_DEPRECATED_EXPORT OLM_EXPORT OLM_DEPRECATED
#endif
#ifndef OLM_DEPRECATED_NO_EXPORT
# define OLM_DEPRECATED_NO_EXPORT OLM_NO_EXPORT OLM_DEPRECATED
#endif
#if 0 /* DEFINE_NO_DEPRECATED */
# ifndef OLM_NO_DEPRECATED
# define OLM_NO_DEPRECATED
# endif
#endif
#endif /* OLM_EXPORT_H */

View file

@ -18,6 +18,10 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "olm/error.h"
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -25,31 +29,38 @@ extern "C" {
typedef struct OlmOutboundGroupSession OlmOutboundGroupSession; typedef struct OlmOutboundGroupSession OlmOutboundGroupSession;
/** get the size of an outbound group session, in bytes. */ /** get the size of an outbound group session, in bytes. */
size_t olm_outbound_group_session_size(void); OLM_EXPORT size_t olm_outbound_group_session_size(void);
/** /**
* Initialise an outbound group session object using the supplied memory * Initialise an outbound group session object using the supplied memory
* The supplied memory should be at least olm_outbound_group_session_size() * The supplied memory should be at least olm_outbound_group_session_size()
* bytes. * bytes.
*/ */
OlmOutboundGroupSession * olm_outbound_group_session( OLM_EXPORT OlmOutboundGroupSession * olm_outbound_group_session(
void *memory void *memory
); );
/** /**
* A null terminated string describing the most recent error to happen to a * A null terminated string describing the most recent error to happen to a
* group session */ * group session */
const char *olm_outbound_group_session_last_error( OLM_EXPORT const char *olm_outbound_group_session_last_error(
const OlmOutboundGroupSession *session
);
/**
* An error code describing the most recent error to happen to a group
* session */
OLM_EXPORT enum OlmErrorCode olm_outbound_group_session_last_error_code(
const OlmOutboundGroupSession *session const OlmOutboundGroupSession *session
); );
/** Clears the memory used to back this group session */ /** Clears the memory used to back this group session */
size_t olm_clear_outbound_group_session( OLM_EXPORT size_t olm_clear_outbound_group_session(
OlmOutboundGroupSession *session OlmOutboundGroupSession *session
); );
/** Returns the number of bytes needed to store an outbound group session */ /** Returns the number of bytes needed to store an outbound group session */
size_t olm_pickle_outbound_group_session_length( OLM_EXPORT size_t olm_pickle_outbound_group_session_length(
const OlmOutboundGroupSession *session const OlmOutboundGroupSession *session
); );
@ -61,7 +72,7 @@ size_t olm_pickle_outbound_group_session_length(
* is smaller than olm_pickle_outbound_group_session_length() then * is smaller than olm_pickle_outbound_group_session_length() then
* olm_outbound_group_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" * olm_outbound_group_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL"
*/ */
size_t olm_pickle_outbound_group_session( OLM_EXPORT size_t olm_pickle_outbound_group_session(
OlmOutboundGroupSession *session, OlmOutboundGroupSession *session,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
@ -77,7 +88,7 @@ size_t olm_pickle_outbound_group_session(
* olm_outbound_group_session_last_error() will be "INVALID_BASE64". The input * olm_outbound_group_session_last_error() will be "INVALID_BASE64". The input
* pickled buffer is destroyed * pickled buffer is destroyed
*/ */
size_t olm_unpickle_outbound_group_session( OLM_EXPORT size_t olm_unpickle_outbound_group_session(
OlmOutboundGroupSession *session, OlmOutboundGroupSession *session,
void const * key, size_t key_length, void const * key, size_t key_length,
void * pickled, size_t pickled_length void * pickled, size_t pickled_length
@ -85,7 +96,7 @@ size_t olm_unpickle_outbound_group_session(
/** The number of random bytes needed to create an outbound group session */ /** The number of random bytes needed to create an outbound group session */
size_t olm_init_outbound_group_session_random_length( OLM_EXPORT size_t olm_init_outbound_group_session_random_length(
const OlmOutboundGroupSession *session const OlmOutboundGroupSession *session
); );
@ -94,7 +105,7 @@ size_t olm_init_outbound_group_session_random_length(
* failure last_error will be set with an error code. The last_error will be * failure last_error will be set with an error code. The last_error will be
* NOT_ENOUGH_RANDOM if the number of random bytes was too small. * NOT_ENOUGH_RANDOM if the number of random bytes was too small.
*/ */
size_t olm_init_outbound_group_session( OLM_EXPORT size_t olm_init_outbound_group_session(
OlmOutboundGroupSession *session, OlmOutboundGroupSession *session,
uint8_t *random, size_t random_length uint8_t *random, size_t random_length
); );
@ -102,7 +113,7 @@ size_t olm_init_outbound_group_session(
/** /**
* The number of bytes that will be created by encrypting a message * The number of bytes that will be created by encrypting a message
*/ */
size_t olm_group_encrypt_message_length( OLM_EXPORT size_t olm_group_encrypt_message_length(
OlmOutboundGroupSession *session, OlmOutboundGroupSession *session,
size_t plaintext_length size_t plaintext_length
); );
@ -113,7 +124,7 @@ size_t olm_group_encrypt_message_length(
* error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the output * error code. The last_error will be OUTPUT_BUFFER_TOO_SMALL if the output
* buffer is too small. * buffer is too small.
*/ */
size_t olm_group_encrypt( OLM_EXPORT size_t olm_group_encrypt(
OlmOutboundGroupSession *session, OlmOutboundGroupSession *session,
uint8_t const * plaintext, size_t plaintext_length, uint8_t const * plaintext, size_t plaintext_length,
uint8_t * message, size_t message_length uint8_t * message, size_t message_length
@ -123,7 +134,7 @@ size_t olm_group_encrypt(
/** /**
* Get the number of bytes returned by olm_outbound_group_session_id() * Get the number of bytes returned by olm_outbound_group_session_id()
*/ */
size_t olm_outbound_group_session_id_length( OLM_EXPORT size_t olm_outbound_group_session_id_length(
const OlmOutboundGroupSession *session const OlmOutboundGroupSession *session
); );
@ -135,7 +146,7 @@ size_t olm_outbound_group_session_id_length(
* last_error will be OUTPUT_BUFFER_TOO_SMALL if the id buffer was too * last_error will be OUTPUT_BUFFER_TOO_SMALL if the id buffer was too
* small. * small.
*/ */
size_t olm_outbound_group_session_id( OLM_EXPORT size_t olm_outbound_group_session_id(
OlmOutboundGroupSession *session, OlmOutboundGroupSession *session,
uint8_t * id, size_t id_length uint8_t * id, size_t id_length
); );
@ -146,14 +157,14 @@ size_t olm_outbound_group_session_id(
* Each message is sent with an increasing index; this returns the index for * Each message is sent with an increasing index; this returns the index for
* the next message. * the next message.
*/ */
uint32_t olm_outbound_group_session_message_index( OLM_EXPORT uint32_t olm_outbound_group_session_message_index(
OlmOutboundGroupSession *session OlmOutboundGroupSession *session
); );
/** /**
* Get the number of bytes returned by olm_outbound_group_session_key() * Get the number of bytes returned by olm_outbound_group_session_key()
*/ */
size_t olm_outbound_group_session_key_length( OLM_EXPORT size_t olm_outbound_group_session_key_length(
const OlmOutboundGroupSession *session const OlmOutboundGroupSession *session
); );
@ -167,7 +178,7 @@ size_t olm_outbound_group_session_key_length(
* failure. On failure last_error will be set with an error code. The * failure. On failure last_error will be set with an error code. The
* last_error will be OUTPUT_BUFFER_TOO_SMALL if the buffer was too small. * last_error will be OUTPUT_BUFFER_TOO_SMALL if the buffer was too small.
*/ */
size_t olm_outbound_group_session_key( OLM_EXPORT size_t olm_outbound_group_session_key(
OlmOutboundGroupSession *session, OlmOutboundGroupSession *session,
uint8_t * key, size_t key_length uint8_t * key, size_t key_length
); );

View file

@ -15,8 +15,25 @@
#ifndef OLM_PICKLE_H_ #ifndef OLM_PICKLE_H_
#define OLM_PICKLE_H_ #define OLM_PICKLE_H_
#include <stddef.h>
#include <stdint.h> #include <stdint.h>
/* Convenience macro for checking the return value of internal unpickling
* functions and returning early on failure. */
#ifndef UNPICKLE_OK
#define UNPICKLE_OK(x) do { if (!(x)) return NULL; } while(0)
#endif
/* Convenience macro for failing on corrupted pickles from public
* API unpickling functions. */
#define FAIL_ON_CORRUPTED_PICKLE(pos, session) \
do { \
if (!pos) { \
session->last_error = OLM_CORRUPTED_PICKLE; \
return (size_t)-1; \
} \
} while(0)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -59,7 +76,7 @@ uint8_t * _olm_pickle_ed25519_public_key(
); );
/** Unpickle the ed25519 public key. Returns a pointer to the next item in the /** Unpickle the ed25519 public key. Returns a pointer to the next item in the
* buffer. */ * buffer on success, NULL on error. */
const uint8_t * _olm_unpickle_ed25519_public_key( const uint8_t * _olm_unpickle_ed25519_public_key(
const uint8_t *pos, const uint8_t *end, const uint8_t *pos, const uint8_t *end,
struct _olm_ed25519_public_key * value struct _olm_ed25519_public_key * value
@ -77,7 +94,7 @@ uint8_t * _olm_pickle_ed25519_key_pair(
); );
/** Unpickle the ed25519 key pair. Returns a pointer to the next item in the /** Unpickle the ed25519 key pair. Returns a pointer to the next item in the
* buffer. */ * buffer on success, NULL on error. */
const uint8_t * _olm_unpickle_ed25519_key_pair( const uint8_t * _olm_unpickle_ed25519_key_pair(
const uint8_t *pos, const uint8_t *end, const uint8_t *pos, const uint8_t *end,
struct _olm_ed25519_key_pair * value struct _olm_ed25519_key_pair * value

View file

@ -21,6 +21,12 @@
#include <cstring> #include <cstring>
#include <cstdint> #include <cstdint>
/* Convenience macro for checking the return value of internal unpickling
* functions and returning early on failure. */
#ifndef UNPICKLE_OK
#define UNPICKLE_OK(x) do { if (!(x)) return nullptr; } while(0)
#endif
namespace olm { namespace olm {
inline std::size_t pickle_length( inline std::size_t pickle_length(
@ -40,6 +46,23 @@ std::uint8_t const * unpickle(
); );
inline std::size_t pickle_length(
const std::uint8_t & value
) {
return 1;
}
std::uint8_t * pickle(
std::uint8_t * pos,
std::uint8_t value
);
std::uint8_t const * unpickle(
std::uint8_t const * pos, std::uint8_t const * end,
std::uint8_t & value
);
inline std::size_t pickle_length( inline std::size_t pickle_length(
const bool & value const bool & value
) { ) {
@ -88,11 +111,21 @@ std::uint8_t const * unpickle(
olm::List<T, max_size> & list olm::List<T, max_size> & list
) { ) {
std::uint32_t size; std::uint32_t size;
pos = unpickle(pos, end, size); pos = unpickle(pos, end, size);
if (!pos) {
return nullptr;
}
while (size-- && pos != end) { while (size-- && pos != end) {
T * value = list.insert(list.end()); T * value = list.insert(list.end());
pos = unpickle(pos, end, *value); pos = unpickle(pos, end, *value);
if (!pos) {
return nullptr;
} }
}
return pos; return pos;
} }

View file

@ -23,6 +23,10 @@
#include "olm/error.h" #include "olm/error.h"
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -31,7 +35,7 @@ extern "C" {
/** /**
* Get the number of bytes needed to encode a pickle of the length given * Get the number of bytes needed to encode a pickle of the length given
*/ */
size_t _olm_enc_output_length(size_t raw_length); OLM_EXPORT size_t _olm_enc_output_length(size_t raw_length);
/** /**
* Get the point in the output buffer that the raw pickle should be written to. * Get the point in the output buffer that the raw pickle should be written to.
@ -41,7 +45,7 @@ size_t _olm_enc_output_length(size_t raw_length);
* base-64 encoding would otherwise overwrite the end of the input before it * base-64 encoding would otherwise overwrite the end of the input before it
* was encoded.) * was encoded.)
*/ */
uint8_t *_olm_enc_output_pos(uint8_t * output, size_t raw_length); OLM_EXPORT uint8_t *_olm_enc_output_pos(uint8_t * output, size_t raw_length);
/** /**
* Encrypt and encode the given pickle in-situ. * Encrypt and encode the given pickle in-situ.
@ -51,7 +55,7 @@ size_t _olm_enc_output_length(size_t raw_length);
* *
* Returns the number of bytes in the encoded pickle. * Returns the number of bytes in the encoded pickle.
*/ */
size_t _olm_enc_output( OLM_EXPORT size_t _olm_enc_output(
uint8_t const * key, size_t key_length, uint8_t const * key, size_t key_length,
uint8_t *pickle, size_t raw_length uint8_t *pickle, size_t raw_length
); );
@ -62,7 +66,7 @@ size_t _olm_enc_output(
* Returns the number of bytes in the decoded pickle, or olm_error() on error, * Returns the number of bytes in the decoded pickle, or olm_error() on error,
* in which case *last_error will be updated, if last_error is non-NULL. * in which case *last_error will be updated, if last_error is non-NULL.
*/ */
size_t _olm_enc_input( OLM_EXPORT size_t _olm_enc_input(
uint8_t const * key, size_t key_length, uint8_t const * key, size_t key_length,
uint8_t * input, size_t b64_length, uint8_t * input, size_t b64_length,
enum OlmErrorCode * last_error enum OlmErrorCode * last_error

View file

@ -19,6 +19,10 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "olm/error.h"
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -26,49 +30,55 @@ extern "C" {
typedef struct OlmPkEncryption OlmPkEncryption; typedef struct OlmPkEncryption OlmPkEncryption;
/* The size of an encryption object in bytes */ /* The size of an encryption object in bytes */
size_t olm_pk_encryption_size(void); OLM_EXPORT size_t olm_pk_encryption_size(void);
/** Initialise an encryption object using the supplied memory /** Initialise an encryption object using the supplied memory
* The supplied memory must be at least olm_pk_encryption_size() bytes */ * The supplied memory must be at least olm_pk_encryption_size() bytes */
OlmPkEncryption *olm_pk_encryption( OLM_EXPORT OlmPkEncryption *olm_pk_encryption(
void * memory void * memory
); );
/** A null terminated string describing the most recent error to happen to an /** A null terminated string describing the most recent error to happen to an
* encryption object */ * encryption object */
const char * olm_pk_encryption_last_error( OLM_EXPORT const char * olm_pk_encryption_last_error(
OlmPkEncryption * encryption const OlmPkEncryption * encryption
);
/** An error code describing the most recent error to happen to an encryption
* object */
OLM_EXPORT enum OlmErrorCode olm_pk_encryption_last_error_code(
const OlmPkEncryption * encryption
); );
/** Clears the memory used to back this encryption object */ /** Clears the memory used to back this encryption object */
size_t olm_clear_pk_encryption( OLM_EXPORT size_t olm_clear_pk_encryption(
OlmPkEncryption *encryption OlmPkEncryption *encryption
); );
/** Set the recipient's public key for encrypting to */ /** Set the recipient's public key for encrypting to */
size_t olm_pk_encryption_set_recipient_key( OLM_EXPORT size_t olm_pk_encryption_set_recipient_key(
OlmPkEncryption *encryption, OlmPkEncryption *encryption,
void const *public_key, size_t public_key_length void const *public_key, size_t public_key_length
); );
/** Get the length of the ciphertext that will correspond to a plaintext of the /** Get the length of the ciphertext that will correspond to a plaintext of the
* given length. */ * given length. */
size_t olm_pk_ciphertext_length( OLM_EXPORT size_t olm_pk_ciphertext_length(
OlmPkEncryption *encryption, const OlmPkEncryption *encryption,
size_t plaintext_length size_t plaintext_length
); );
/** Get the length of the message authentication code. */ /** Get the length of the message authentication code. */
size_t olm_pk_mac_length( OLM_EXPORT size_t olm_pk_mac_length(
OlmPkEncryption *encryption const OlmPkEncryption *encryption
); );
/** Get the length of a public or ephemeral key */ /** Get the length of a public or ephemeral key */
size_t olm_pk_key_length(void); OLM_EXPORT size_t olm_pk_key_length(void);
/** The number of random bytes needed to encrypt a message. */ /** The number of random bytes needed to encrypt a message. */
size_t olm_pk_encrypt_random_length( OLM_EXPORT size_t olm_pk_encrypt_random_length(
OlmPkEncryption *encryption const OlmPkEncryption *encryption
); );
/** Encrypt a plaintext for the recipient set using /** Encrypt a plaintext for the recipient set using
@ -81,7 +91,7 @@ size_t olm_pk_encrypt_random_length(
* ephemeral_key buffers were too small then olm_pk_encryption_last_error() * ephemeral_key buffers were too small then olm_pk_encryption_last_error()
* will be "OUTPUT_BUFFER_TOO_SMALL". If there weren't enough random bytes then * will be "OUTPUT_BUFFER_TOO_SMALL". If there weren't enough random bytes then
* olm_pk_encryption_last_error() will be "OLM_INPUT_BUFFER_TOO_SMALL". */ * olm_pk_encryption_last_error() will be "OLM_INPUT_BUFFER_TOO_SMALL". */
size_t olm_pk_encrypt( OLM_EXPORT size_t olm_pk_encrypt(
OlmPkEncryption *encryption, OlmPkEncryption *encryption,
void const * plaintext, size_t plaintext_length, void const * plaintext, size_t plaintext_length,
void * ciphertext, size_t ciphertext_length, void * ciphertext, size_t ciphertext_length,
@ -93,32 +103,38 @@ size_t olm_pk_encrypt(
typedef struct OlmPkDecryption OlmPkDecryption; typedef struct OlmPkDecryption OlmPkDecryption;
/* The size of a decryption object in bytes */ /* The size of a decryption object in bytes */
size_t olm_pk_decryption_size(void); OLM_EXPORT size_t olm_pk_decryption_size(void);
/** Initialise a decryption object using the supplied memory /** Initialise a decryption object using the supplied memory
* The supplied memory must be at least olm_pk_decryption_size() bytes */ * The supplied memory must be at least olm_pk_decryption_size() bytes */
OlmPkDecryption *olm_pk_decryption( OLM_EXPORT OlmPkDecryption *olm_pk_decryption(
void * memory void * memory
); );
/** A null terminated string describing the most recent error to happen to a /** A null terminated string describing the most recent error to happen to a
* decription object */ * decription object */
const char * olm_pk_decryption_last_error( OLM_EXPORT const char * olm_pk_decryption_last_error(
OlmPkDecryption * decryption const OlmPkDecryption * decryption
);
/** An error code describing the most recent error to happen to a decription
* object */
OLM_EXPORT enum OlmErrorCode olm_pk_decryption_last_error_code(
const OlmPkDecryption * decryption
); );
/** Clears the memory used to back this decryption object */ /** Clears the memory used to back this decryption object */
size_t olm_clear_pk_decryption( OLM_EXPORT size_t olm_clear_pk_decryption(
OlmPkDecryption *decryption OlmPkDecryption *decryption
); );
/** Get the number of bytes required to store an olm private key /** Get the number of bytes required to store an olm private key
*/ */
size_t olm_pk_private_key_length(void); OLM_EXPORT size_t olm_pk_private_key_length(void);
/** DEPRECATED: Use olm_pk_private_key_length() /** DEPRECATED: Use olm_pk_private_key_length()
*/ */
size_t olm_pk_generate_key_random_length(void); OLM_EXPORT size_t olm_pk_generate_key_random_length(void);
/** Initialise the key from the private part of a key as returned by /** Initialise the key from the private part of a key as returned by
* olm_pk_get_private_key(). The associated public key will be written to the * olm_pk_get_private_key(). The associated public key will be written to the
@ -130,7 +146,7 @@ size_t olm_pk_generate_key_random_length(void);
* Note that the pubkey is a base64 encoded string, but the private key is * Note that the pubkey is a base64 encoded string, but the private key is
* an unencoded byte array * an unencoded byte array
*/ */
size_t olm_pk_key_from_private( OLM_EXPORT size_t olm_pk_key_from_private(
OlmPkDecryption * decryption, OlmPkDecryption * decryption,
void * pubkey, size_t pubkey_length, void * pubkey, size_t pubkey_length,
const void * privkey, size_t privkey_length const void * privkey, size_t privkey_length
@ -138,15 +154,15 @@ size_t olm_pk_key_from_private(
/** DEPRECATED: Use olm_pk_key_from_private /** DEPRECATED: Use olm_pk_key_from_private
*/ */
size_t olm_pk_generate_key( OLM_EXPORT size_t olm_pk_generate_key(
OlmPkDecryption * decryption, OlmPkDecryption * decryption,
void * pubkey, size_t pubkey_length, void * pubkey, size_t pubkey_length,
const void * privkey, size_t privkey_length const void * privkey, size_t privkey_length
); );
/** Returns the number of bytes needed to store a decryption object. */ /** Returns the number of bytes needed to store a decryption object. */
size_t olm_pickle_pk_decryption_length( OLM_EXPORT size_t olm_pickle_pk_decryption_length(
OlmPkDecryption * decryption const OlmPkDecryption * decryption
); );
/** Stores decryption object as a base64 string. Encrypts the object using the /** Stores decryption object as a base64 string. Encrypts the object using the
@ -154,7 +170,7 @@ size_t olm_pickle_pk_decryption_length(
* Returns olm_error() on failure. If the pickle output buffer * Returns olm_error() on failure. If the pickle output buffer
* is smaller than olm_pickle_pk_decryption_length() then * is smaller than olm_pickle_pk_decryption_length() then
* olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */ * olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL" */
size_t olm_pickle_pk_decryption( OLM_EXPORT size_t olm_pickle_pk_decryption(
OlmPkDecryption * decryption, OlmPkDecryption * decryption,
void const * key, size_t key_length, void const * key, size_t key_length,
void *pickled, size_t pickled_length void *pickled, size_t pickled_length
@ -167,7 +183,7 @@ size_t olm_pickle_pk_decryption(
* will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then * will be "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
* olm_pk_decryption_last_error() will be "INVALID_BASE64". The input pickled * olm_pk_decryption_last_error() will be "INVALID_BASE64". The input pickled
* buffer is destroyed */ * buffer is destroyed */
size_t olm_unpickle_pk_decryption( OLM_EXPORT size_t olm_unpickle_pk_decryption(
OlmPkDecryption * decryption, OlmPkDecryption * decryption,
void const * key, size_t key_length, void const * key, size_t key_length,
void *pickled, size_t pickled_length, void *pickled, size_t pickled_length,
@ -176,8 +192,8 @@ size_t olm_unpickle_pk_decryption(
/** Get the length of the plaintext that will correspond to a ciphertext of the /** Get the length of the plaintext that will correspond to a ciphertext of the
* given length. */ * given length. */
size_t olm_pk_max_plaintext_length( OLM_EXPORT size_t olm_pk_max_plaintext_length(
OlmPkDecryption * decryption, const OlmPkDecryption * decryption,
size_t ciphertext_length size_t ciphertext_length
); );
@ -186,7 +202,7 @@ size_t olm_pk_max_plaintext_length(
* arguments. Returns the length of the plaintext on success. Returns * arguments. Returns the length of the plaintext on success. Returns
* olm_error() on failure. If the plaintext buffer is too small then * olm_error() on failure. If the plaintext buffer is too small then
* olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */ * olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */
size_t olm_pk_decrypt( OLM_EXPORT size_t olm_pk_decrypt(
OlmPkDecryption * decryption, OlmPkDecryption * decryption,
void const * ephemeral_key, size_t ephemeral_key_length, void const * ephemeral_key, size_t ephemeral_key_length,
void const * mac, size_t mac_length, void const * mac, size_t mac_length,
@ -202,7 +218,7 @@ size_t olm_pk_decrypt(
* and olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". * and olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
* Returns the number of bytes written. * Returns the number of bytes written.
*/ */
size_t olm_pk_get_private_key( OLM_EXPORT size_t olm_pk_get_private_key(
OlmPkDecryption * decryption, OlmPkDecryption * decryption,
void *private_key, size_t private_key_length void *private_key, size_t private_key_length
); );
@ -210,22 +226,28 @@ size_t olm_pk_get_private_key(
typedef struct OlmPkSigning OlmPkSigning; typedef struct OlmPkSigning OlmPkSigning;
/* The size of a signing object in bytes */ /* The size of a signing object in bytes */
size_t olm_pk_signing_size(void); OLM_EXPORT size_t olm_pk_signing_size(void);
/** Initialise a signing object using the supplied memory /** Initialise a signing object using the supplied memory
* The supplied memory must be at least olm_pk_signing_size() bytes */ * The supplied memory must be at least olm_pk_signing_size() bytes */
OlmPkSigning *olm_pk_signing( OLM_EXPORT OlmPkSigning *olm_pk_signing(
void * memory void * memory
); );
/** A null terminated string describing the most recent error to happen to a /** A null terminated string describing the most recent error to happen to a
* signing object */ * signing object */
const char * olm_pk_signing_last_error( OLM_EXPORT const char * olm_pk_signing_last_error(
OlmPkSigning * sign const OlmPkSigning * sign
);
/** A null terminated string describing the most recent error to happen to a
* signing object */
OLM_EXPORT enum OlmErrorCode olm_pk_signing_last_error_code(
const OlmPkSigning * sign
); );
/** Clears the memory used to back this signing object */ /** Clears the memory used to back this signing object */
size_t olm_clear_pk_signing( OLM_EXPORT size_t olm_clear_pk_signing(
OlmPkSigning *sign OlmPkSigning *sign
); );
@ -237,7 +259,7 @@ size_t olm_clear_pk_signing(
* buffer is too small then olm_pk_signing_last_error() will be * buffer is too small then olm_pk_signing_last_error() will be
* "INPUT_BUFFER_TOO_SMALL". * "INPUT_BUFFER_TOO_SMALL".
*/ */
size_t olm_pk_signing_key_from_seed( OLM_EXPORT size_t olm_pk_signing_key_from_seed(
OlmPkSigning * sign, OlmPkSigning * sign,
void * pubkey, size_t pubkey_length, void * pubkey, size_t pubkey_length,
const void * seed, size_t seed_length const void * seed, size_t seed_length
@ -246,24 +268,24 @@ size_t olm_pk_signing_key_from_seed(
/** /**
* The size required for the seed for initialising a signing object. * The size required for the seed for initialising a signing object.
*/ */
size_t olm_pk_signing_seed_length(void); OLM_EXPORT size_t olm_pk_signing_seed_length(void);
/** /**
* The size of the public key of a signing object. * The size of the public key of a signing object.
*/ */
size_t olm_pk_signing_public_key_length(void); OLM_EXPORT size_t olm_pk_signing_public_key_length(void);
/** /**
* The size of a signature created by a signing object. * The size of a signature created by a signing object.
*/ */
size_t olm_pk_signature_length(void); OLM_EXPORT size_t olm_pk_signature_length(void);
/** /**
* Sign a message. The signature will be written to the signature * Sign a message. The signature will be written to the signature
* buffer. Returns olm_error() on failure. If the signature buffer is too * buffer. Returns olm_error() on failure. If the signature buffer is too
* small, olm_pk_signing_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". * small, olm_pk_signing_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
*/ */
size_t olm_pk_sign( OLM_EXPORT size_t olm_pk_sign(
OlmPkSigning *sign, OlmPkSigning *sign,
uint8_t const * message, size_t message_length, uint8_t const * message, size_t message_length,
uint8_t * signature, size_t signature_length uint8_t * signature, size_t signature_length

View file

@ -19,6 +19,10 @@
#include "olm/list.hh" #include "olm/list.hh"
#include "olm/error.h" #include "olm/error.h"
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
struct _olm_cipher; struct _olm_cipher;
namespace olm { namespace olm {
@ -72,7 +76,7 @@ struct KdfInfo {
}; };
struct Ratchet { struct OLM_EXPORT Ratchet {
Ratchet( Ratchet(
KdfInfo const & kdf_info, KdfInfo const & kdf_info,
@ -124,12 +128,12 @@ struct Ratchet {
* a given message length. */ * a given message length. */
std::size_t encrypt_output_length( std::size_t encrypt_output_length(
std::size_t plaintext_length std::size_t plaintext_length
); ) const;
/** The number of bytes of random data the encrypt method will need to /** The number of bytes of random data the encrypt method will need to
* encrypt a message. This will be 32 bytes if the session needs to * encrypt a message. This will be 32 bytes if the session needs to
* generate a new ephemeral key, or will be 0 bytes otherwise.*/ * generate a new ephemeral key, or will be 0 bytes otherwise.*/
std::size_t encrypt_random_length(); std::size_t encrypt_random_length() const;
/** Encrypt some plain-text. Returns the length of the encrypted message /** Encrypt some plain-text. Returns the length of the encrypted message
* or std::size_t(-1) on failure. On failure last_error will be set with * or std::size_t(-1) on failure. On failure last_error will be set with

View file

@ -19,6 +19,10 @@
#include <stddef.h> #include <stddef.h>
#include "olm/error.h"
#include "olm/olm_export.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -33,27 +37,33 @@ typedef struct OlmSAS OlmSAS;
/** A null terminated string describing the most recent error to happen to an /** A null terminated string describing the most recent error to happen to an
* SAS object. */ * SAS object. */
const char * olm_sas_last_error( OLM_EXPORT const char * olm_sas_last_error(
OlmSAS * sas const OlmSAS * sas
);
/** An error code describing the most recent error to happen to an SAS
* object. */
OLM_EXPORT enum OlmErrorCode olm_sas_last_error_code(
const OlmSAS * sas
); );
/** The size of an SAS object in bytes. */ /** The size of an SAS object in bytes. */
size_t olm_sas_size(void); OLM_EXPORT size_t olm_sas_size(void);
/** Initialize an SAS object using the supplied memory. /** Initialize an SAS object using the supplied memory.
* The supplied memory must be at least `olm_sas_size()` bytes. */ * The supplied memory must be at least `olm_sas_size()` bytes. */
OlmSAS * olm_sas( OLM_EXPORT OlmSAS * olm_sas(
void * memory void * memory
); );
/** Clears the memory used to back an SAS object. */ /** Clears the memory used to back an SAS object. */
size_t olm_clear_sas( OLM_EXPORT size_t olm_clear_sas(
OlmSAS * sas OlmSAS * sas
); );
/** The number of random bytes needed to create an SAS object. */ /** The number of random bytes needed to create an SAS object. */
size_t olm_create_sas_random_length( OLM_EXPORT size_t olm_create_sas_random_length(
OlmSAS * sas const OlmSAS * sas
); );
/** Creates a new SAS object. /** Creates a new SAS object.
@ -67,13 +77,13 @@ size_t olm_create_sas_random_length(
* @return `olm_error()` on failure. If there weren't enough random bytes then * @return `olm_error()` on failure. If there weren't enough random bytes then
* `olm_sas_last_error()` will be `NOT_ENOUGH_RANDOM`. * `olm_sas_last_error()` will be `NOT_ENOUGH_RANDOM`.
*/ */
size_t olm_create_sas( OLM_EXPORT size_t olm_create_sas(
OlmSAS * sas, OlmSAS * sas,
void * random, size_t random_length void * random, size_t random_length
); );
/** The size of a public key in bytes. */ /** The size of a public key in bytes. */
size_t olm_sas_pubkey_length(OlmSAS * sas); OLM_EXPORT size_t olm_sas_pubkey_length(const OlmSAS * sas);
/** Get the public key for the SAS object. /** Get the public key for the SAS object.
* *
@ -85,7 +95,7 @@ size_t olm_sas_pubkey_length(OlmSAS * sas);
* @return `olm_error()` on failure. If the `pubkey` buffer is too small, then * @return `olm_error()` on failure. If the `pubkey` buffer is too small, then
* `olm_sas_last_error()` will be `OUTPUT_BUFFER_TOO_SMALL`. * `olm_sas_last_error()` will be `OUTPUT_BUFFER_TOO_SMALL`.
*/ */
size_t olm_sas_get_pubkey( OLM_EXPORT size_t olm_sas_get_pubkey(
OlmSAS * sas, OlmSAS * sas,
void * pubkey, size_t pubkey_length void * pubkey, size_t pubkey_length
); );
@ -100,7 +110,7 @@ size_t olm_sas_get_pubkey(
* @return `olm_error()` on failure. If the `their_key` buffer is too small, * @return `olm_error()` on failure. If the `their_key` buffer is too small,
* then `olm_sas_last_error()` will be `INPUT_BUFFER_TOO_SMALL`. * then `olm_sas_last_error()` will be `INPUT_BUFFER_TOO_SMALL`.
*/ */
size_t olm_sas_set_their_key( OLM_EXPORT size_t olm_sas_set_their_key(
OlmSAS *sas, OlmSAS *sas,
void * their_key, size_t their_key_length void * their_key, size_t their_key_length
); );
@ -110,8 +120,8 @@ size_t olm_sas_set_their_key(
* @param[in] sas the SAS object. * @param[in] sas the SAS object.
* *
*/ */
int olm_sas_is_their_key_set( OLM_EXPORT int olm_sas_is_their_key_set(
OlmSAS *sas const OlmSAS *sas
); );
/** Generate bytes to use for the short authentication string. /** Generate bytes to use for the short authentication string.
@ -127,7 +137,7 @@ int olm_sas_is_their_key_set(
* @return `olm_error()` on failure. If their key wasn't set then * @return `olm_error()` on failure. If their key wasn't set then
* `olm_sas_last_error()` will be `SAS_THEIR_KEY_NOT_SET`. * `olm_sas_last_error()` will be `SAS_THEIR_KEY_NOT_SET`.
*/ */
size_t olm_sas_generate_bytes( OLM_EXPORT size_t olm_sas_generate_bytes(
OlmSAS * sas, OlmSAS * sas,
const void * info, size_t info_length, const void * info, size_t info_length,
void * output, size_t output_length void * output, size_t output_length
@ -135,8 +145,8 @@ size_t olm_sas_generate_bytes(
/** The size of the message authentication code generated by /** The size of the message authentication code generated by
* olm_sas_calculate_mac()`. */ * olm_sas_calculate_mac()`. */
size_t olm_sas_mac_length( OLM_EXPORT size_t olm_sas_mac_length(
OlmSAS *sas const OlmSAS *sas
); );
/** Generate a message authentication code (MAC) based on the shared secret. /** Generate a message authentication code (MAC) based on the shared secret.
@ -154,7 +164,16 @@ size_t olm_sas_mac_length(
* @return `olm_error()` on failure. If the `mac` buffer is too small, then * @return `olm_error()` on failure. If the `mac` buffer is too small, then
* `olm_sas_last_error()` will be `OUTPUT_BUFFER_TOO_SMALL`. * `olm_sas_last_error()` will be `OUTPUT_BUFFER_TOO_SMALL`.
*/ */
size_t olm_sas_calculate_mac( OLM_EXPORT size_t olm_sas_calculate_mac(
OlmSAS * sas,
const void * input, size_t input_length,
const void * info, size_t info_length,
void * mac, size_t mac_length
);
// A version of the calculate mac function that produces base64 strings that are
// compatible with other base64 implementations.
OLM_EXPORT size_t olm_sas_calculate_mac_fixed_base64(
OlmSAS * sas, OlmSAS * sas,
const void * input, size_t input_length, const void * input, size_t input_length,
const void * info, size_t info_length, const void * info, size_t info_length,
@ -162,7 +181,7 @@ size_t olm_sas_calculate_mac(
); );
// for compatibility with an old version of Riot // for compatibility with an old version of Riot
size_t olm_sas_calculate_mac_long_kdf( OLM_EXPORT size_t olm_sas_calculate_mac_long_kdf(
OlmSAS * sas, OlmSAS * sas,
const void * input, size_t input_length, const void * input, size_t input_length,
const void * info, size_t info_length, const void * info, size_t info_length,

View file

@ -17,6 +17,10 @@
#include "olm/ratchet.hh" #include "olm/ratchet.hh"
// Note: exports in this file are only for unit tests. Nobody else should be
// using this externally
#include "olm/olm_export.h"
namespace olm { namespace olm {
struct Account; struct Account;
@ -26,7 +30,7 @@ enum struct MessageType {
MESSAGE = 1, MESSAGE = 1,
}; };
struct Session { struct OLM_EXPORT Session {
Session(); Session();
@ -41,7 +45,7 @@ struct Session {
/** The number of random bytes that are needed to create a new outbound /** The number of random bytes that are needed to create a new outbound
* session. This will be 64 bytes since two ephemeral keys are needed. */ * session. This will be 64 bytes since two ephemeral keys are needed. */
std::size_t new_outbound_session_random_length(); std::size_t new_outbound_session_random_length() const;
/** Start a new outbound session. Returns std::size_t(-1) on failure. On /** Start a new outbound session. Returns std::size_t(-1) on failure. On
* failure last_error will be set with an error code. The last_error will be * failure last_error will be set with an error code. The last_error will be
@ -64,7 +68,7 @@ struct Session {
); );
/** The number of bytes written by session_id() */ /** The number of bytes written by session_id() */
std::size_t session_id_length(); std::size_t session_id_length() const;
/** An identifier for this session. Generated by hashing the public keys /** An identifier for this session. Generated by hashing the public keys
* used to create the session. Returns the length of the session id on * used to create the session. Returns the length of the session id on
@ -84,21 +88,21 @@ struct Session {
bool matches_inbound_session( bool matches_inbound_session(
_olm_curve25519_public_key const * their_identity_key, _olm_curve25519_public_key const * their_identity_key,
std::uint8_t const * pre_key_message, std::size_t message_length std::uint8_t const * pre_key_message, std::size_t message_length
); ) const;
/** Whether the next message will be a pre-key message or a normal message. /** Whether the next message will be a pre-key message or a normal message.
* An outbound session will send pre-key messages until it receives a * An outbound session will send pre-key messages until it receives a
* message with a ratchet key. */ * message with a ratchet key. */
MessageType encrypt_message_type(); MessageType encrypt_message_type() const;
std::size_t encrypt_message_length( std::size_t encrypt_message_length(
std::size_t plaintext_length std::size_t plaintext_length
); ) const;
/** The number of bytes of random data the encrypt method will need to /** The number of bytes of random data the encrypt method will need to
* encrypt a message. This will be 32 bytes if the session needs to * encrypt a message. This will be 32 bytes if the session needs to
* generate a new ephemeral key, or will be 0 bytes otherwise. */ * generate a new ephemeral key, or will be 0 bytes otherwise. */
std::size_t encrypt_random_length(); std::size_t encrypt_random_length() const;
/** Encrypt some plain-text. Returns the length of the encrypted message /** Encrypt some plain-text. Returns the length of the encrypted message
* or std::size_t(-1) on failure. On failure last_error will be set with * or std::size_t(-1) on failure. On failure last_error will be set with
@ -153,7 +157,7 @@ std::uint8_t * pickle(
); );
std::uint8_t const * unpickle( OLM_EXPORT std::uint8_t const * unpickle(
std::uint8_t const * pos, std::uint8_t const * end, std::uint8_t const * pos, std::uint8_t const * end,
Session & value Session & value
); );

View file

@ -32,7 +32,7 @@ struct Utility {
OlmErrorCode last_error; OlmErrorCode last_error;
/** The length of a SHA-256 hash in bytes. */ /** The length of a SHA-256 hash in bytes. */
std::size_t sha256_length(); std::size_t sha256_length() const;
/** Compute a SHA-256 hash. Returns the length of the SHA-256 hash in bytes /** Compute a SHA-256 hash. Returns the length of the SHA-256 hash in bytes
* on success. Returns std::size_t(-1) on failure. On failure last_error * on success. Returns std::size_t(-1) on failure. On failure last_error

29
javascript/.gitlab-ci.yml Normal file
View file

@ -0,0 +1,29 @@
default:
image: docker.io/emscripten/emsdk:latest
stages:
- build
- test
build:js:
stage: build
script:
- ln -sf $(which python3) /usr/local/bin/python
- make js
artifacts:
paths:
- build/javascript
- javascript/olm.js
- javascript/olm.wasm
- javascript/olm_legacy.js
- javascript/index.d.ts
- javascript/exported_functions.json
test:js:
stage: test
needs:
- build:js
script:
- pushd javascript
- npm i
- npm run test

View file

@ -5,6 +5,11 @@ Note: before using any of the olm functions, you must call `Olm.init()`, and
wait for the promise to resolve, otherwise you will get errors like: wait for the promise to resolve, otherwise you will get errors like:
`Uncaught TypeError: Olm.Account is not a constructor` `Uncaught TypeError: Olm.Account is not a constructor`
If you get errors about failure to compile the wasm file, it is likely that Olm
is not locating the wasm file properly. You can tell Olm where the wasm file
is by passing a `locateFile` parameter to `Olm.init()`, for example:
`Olm.init({locateFile: () => pathToWasmFile})`.
Example: Example:
var alice = new Olm.Account(); var alice = new Olm.Account();

39
javascript/index.d.ts vendored
View file

@ -18,26 +18,28 @@ export as namespace Olm;
declare class Account { declare class Account {
constructor(); constructor();
free(); free(): void;
create(); create(): void;
identity_keys(): string; identity_keys(): string;
sign(message: string | Uint8Array): string; sign(message: string | Uint8Array): string;
one_time_keys(): string; one_time_keys(): string;
mark_keys_as_published(); mark_keys_as_published(): void;
max_number_of_one_time_keys(): number; max_number_of_one_time_keys(): number;
generate_one_time_keys(number_of_keys: number); generate_one_time_keys(number_of_keys: number): void;
remove_one_time_keys(session: Session); remove_one_time_keys(session: Session): void;
generate_fallback_key(); generate_fallback_key(): void;
fallback_key(): string; fallback_key(): string;
unpublished_fallback_key(): string;
forget_old_fallback_key(): void;
pickle(key: string | Uint8Array): string; pickle(key: string | Uint8Array): string;
unpickle(key: string | Uint8Array, pickle: string); unpickle(key: string | Uint8Array, pickle: string): void;
} }
declare class Session { declare class Session {
constructor(); constructor();
free(): void; free(): void;
pickle(key: string | Uint8Array): string; pickle(key: string | Uint8Array): string;
unpickle(key: string | Uint8Array, pickle: string); unpickle(key: string | Uint8Array, pickle: string): void;
create_outbound( create_outbound(
account: Account, their_identity_key: string, their_one_time_key: string, account: Account, their_identity_key: string, their_one_time_key: string,
): void; ): void;
@ -49,7 +51,10 @@ declare class Session {
has_received_message(): boolean; has_received_message(): boolean;
matches_inbound(one_time_key_message: string): boolean; matches_inbound(one_time_key_message: string): boolean;
matches_inbound_from(identity_key: string, one_time_key_message: string): boolean; matches_inbound_from(identity_key: string, one_time_key_message: string): boolean;
encrypt(plaintext: string): object; encrypt(plaintext: string): {
type: 0 | 1; // 0: PreKey, 1: Message
body: string;
};
decrypt(message_type: number, message: string): string; decrypt(message_type: number, message: string): string;
describe(): string; describe(): string;
} }
@ -65,10 +70,13 @@ declare class InboundGroupSession {
constructor(); constructor();
free(): void; free(): void;
pickle(key: string | Uint8Array): string; pickle(key: string | Uint8Array): string;
unpickle(key: string | Uint8Array, pickle: string); unpickle(key: string | Uint8Array, pickle: string): void;
create(session_key: string): string; create(session_key: string): string;
import_session(session_key: string): string; import_session(session_key: string): string;
decrypt(message: string): object; decrypt(message: string): {
message_index: number;
plaintext: string;
};
session_id(): string; session_id(): string;
first_known_index(): number; first_known_index(): number;
export_session(message_index: number): string; export_session(message_index: number): string;
@ -78,7 +86,7 @@ declare class OutboundGroupSession {
constructor(); constructor();
free(): void; free(): void;
pickle(key: string | Uint8Array): string; pickle(key: string | Uint8Array): string;
unpickle(key: string | Uint8Array, pickle: string); unpickle(key: string | Uint8Array, pickle: string): void;
create(): void; create(): void;
encrypt(plaintext: string): string; encrypt(plaintext: string): string;
session_id(): string; session_id(): string;
@ -90,7 +98,11 @@ declare class PkEncryption {
constructor(); constructor();
free(): void; free(): void;
set_recipient_key(key: string): void; set_recipient_key(key: string): void;
encrypt(plaintext: string): object; encrypt(plaintext: string): {
ciphertext: string;
mac: string;
ephemeral: string;
};
} }
declare class PkDecryption { declare class PkDecryption {
@ -119,6 +131,7 @@ declare class SAS {
set_their_key(their_key: string): void; set_their_key(their_key: string): void;
generate_bytes(info: string, length: number): Uint8Array; generate_bytes(info: string, length: number): Uint8Array;
calculate_mac(input: string, info: string): string; calculate_mac(input: string, info: string): string;
calculate_mac_fixed_base64(input: string, info: string): string;
calculate_mac_long_kdf(input: string, info: string): string; calculate_mac_long_kdf(input: string, info: string): string;
} }

View file

@ -1,3 +1,4 @@
/** @constructor */
function InboundGroupSession() { function InboundGroupSession() {
var size = Module['_olm_inbound_group_session_size'](); var size = Module['_olm_inbound_group_session_size']();
this.buf = malloc(size); this.buf = malloc(size);

View file

@ -1,3 +1,4 @@
/** @constructor */
function OutboundGroupSession() { function OutboundGroupSession() {
var size = Module['_olm_outbound_group_session_size'](); var size = Module['_olm_outbound_group_session_size']();
this.buf = malloc(size); this.buf = malloc(size);
@ -67,9 +68,14 @@ OutboundGroupSession.prototype['create'] = restore_stack(function() {
Module['_olm_init_outbound_group_session_random_length'] Module['_olm_init_outbound_group_session_random_length']
)(this.ptr); )(this.ptr);
var random = random_stack(random_length); var random = random_stack(random_length);
try {
outbound_group_session_method(Module['_olm_init_outbound_group_session'])( outbound_group_session_method(Module['_olm_init_outbound_group_session'])(
this.ptr, random, random_length this.ptr, random, random_length
); );
} finally {
// clear the random buffer
bzero(random, random_length);
}
}); });
OutboundGroupSession.prototype['encrypt'] = function(plaintext) { OutboundGroupSession.prototype['encrypt'] = function(plaintext) {

View file

@ -1,3 +1,4 @@
/** @constructor */
function PkEncryption() { function PkEncryption() {
var size = Module['_olm_pk_encryption_size'](); var size = Module['_olm_pk_encryption_size']();
this.buf = malloc(size); this.buf = malloc(size);
@ -98,6 +99,7 @@ PkEncryption.prototype['encrypt'] = restore_stack(function(
}); });
/** @constructor */
function PkDecryption() { function PkDecryption() {
var size = Module['_olm_pk_decryption_size'](); var size = Module['_olm_pk_decryption_size']();
this.buf = malloc(size); this.buf = malloc(size);
@ -273,6 +275,7 @@ PkDecryption.prototype['decrypt'] = restore_stack(function (
}) })
/** @constructor */
function PkSigning() { function PkSigning() {
var size = Module['_olm_pk_signing_size'](); var size = Module['_olm_pk_signing_size']();
this.buf = malloc(size); this.buf = malloc(size);

View file

@ -44,6 +44,7 @@ function bzero(ptr, n) {
} }
} }
/** @constructor */
function Account() { function Account() {
var size = Module['_olm_account_size'](); var size = Module['_olm_account_size']();
this.buf = malloc(size); this.buf = malloc(size);
@ -73,9 +74,14 @@ Account.prototype['create'] = restore_stack(function() {
Module['_olm_create_account_random_length'] Module['_olm_create_account_random_length']
)(this.ptr); )(this.ptr);
var random = random_stack(random_length); var random = random_stack(random_length);
try {
account_method(Module['_olm_create_account'])( account_method(Module['_olm_create_account'])(
this.ptr, random, random_length this.ptr, random, random_length
); );
} finally {
// clear the random buffer
bzero(random, random_length);
}
}); });
Account.prototype['identity_keys'] = restore_stack(function() { Account.prototype['identity_keys'] = restore_stack(function() {
@ -140,9 +146,14 @@ Account.prototype['generate_one_time_keys'] = restore_stack(function(
Module['_olm_account_generate_one_time_keys_random_length'] Module['_olm_account_generate_one_time_keys_random_length']
)(this.ptr, number_of_keys); )(this.ptr, number_of_keys);
var random = random_stack(random_length); var random = random_stack(random_length);
try {
account_method(Module['_olm_account_generate_one_time_keys'])( account_method(Module['_olm_account_generate_one_time_keys'])(
this.ptr, number_of_keys, random, random_length this.ptr, number_of_keys, random, random_length
); );
} finally {
// clear the random buffer
bzero(random, random_length);
}
}); });
Account.prototype['remove_one_time_keys'] = restore_stack(function(session) { Account.prototype['remove_one_time_keys'] = restore_stack(function(session) {
@ -156,9 +167,14 @@ Account.prototype['generate_fallback_key'] = restore_stack(function() {
Module['_olm_account_generate_fallback_key_random_length'] Module['_olm_account_generate_fallback_key_random_length']
)(this.ptr); )(this.ptr);
var random = random_stack(random_length); var random = random_stack(random_length);
try {
account_method(Module['_olm_account_generate_fallback_key'])( account_method(Module['_olm_account_generate_fallback_key'])(
this.ptr, random, random_length this.ptr, random, random_length
); );
} finally {
// clear the random buffer
bzero(random, random_length);
}
}); });
Account.prototype['fallback_key'] = restore_stack(function() { Account.prototype['fallback_key'] = restore_stack(function() {
@ -172,6 +188,23 @@ Account.prototype['fallback_key'] = restore_stack(function() {
return UTF8ToString(keys, keys_length); return UTF8ToString(keys, keys_length);
}); });
Account.prototype['unpublished_fallback_key'] = restore_stack(function() {
var keys_length = account_method(
Module['_olm_account_unpublished_fallback_key_length']
)(this.ptr);
var keys = stack(keys_length + NULL_BYTE_PADDING_LENGTH);
account_method(Module['_olm_account_unpublished_fallback_key'])(
this.ptr, keys, keys_length
);
return UTF8ToString(keys, keys_length);
});
Account.prototype['forget_old_fallback_key'] = restore_stack(function() {
account_method(Module['_olm_account_forget_old_fallback_key'])(
this.ptr
);
});
Account.prototype['pickle'] = restore_stack(function(key) { Account.prototype['pickle'] = restore_stack(function(key) {
var key_array = array_from_string(key); var key_array = array_from_string(key);
var pickle_length = account_method( var pickle_length = account_method(
@ -212,6 +245,7 @@ Account.prototype['unpickle'] = restore_stack(function(key, pickle) {
} }
}); });
/** @constructor */
function Session() { function Session() {
var size = Module['_olm_session_size'](); var size = Module['_olm_session_size']();
this.buf = malloc(size); this.buf = malloc(size);
@ -498,6 +532,7 @@ Session.prototype['describe'] = restore_stack(function() {
} }
}); });
/** @constructor */
function Utility() { function Utility() {
var size = Module['_olm_utility_size'](); var size = Module['_olm_utility_size']();
this.buf = malloc(size); this.buf = malloc(size);

View file

@ -14,7 +14,6 @@ if (typeof(window) !== 'undefined') {
var bytes = nodeCrypto['randomBytes'](buf.length); var bytes = nodeCrypto['randomBytes'](buf.length);
buf.set(bytes); buf.set(bytes);
}; };
process = global["process"];
} else { } else {
throw new Error("Cannot find global to attach library to"); throw new Error("Cannot find global to attach library to");
} }

View file

@ -1,3 +1,4 @@
/** @constructor */
function SAS() { function SAS() {
var size = Module['_olm_sas_size'](); var size = Module['_olm_sas_size']();
var random_length = Module['_olm_create_sas_random_length'](); var random_length = Module['_olm_create_sas_random_length']();
@ -82,6 +83,22 @@ SAS.prototype['calculate_mac'] = restore_stack(function(input, info) {
return UTF8ToString(mac_buffer, mac_length); return UTF8ToString(mac_buffer, mac_length);
}); });
SAS.prototype['calculate_mac_fixed_base64'] = restore_stack(function(input, info) {
var input_array = array_from_string(input);
var input_buffer = stack(input_array);
var info_array = array_from_string(info);
var info_buffer = stack(info_array);
var mac_length = sas_method(Module['_olm_sas_mac_length'])(this.ptr);
var mac_buffer = stack(mac_length + NULL_BYTE_PADDING_LENGTH);
sas_method(Module['_olm_sas_calculate_mac_fixed_base64'])(
this.ptr,
input_buffer, input_array.length,
info_buffer, info_array.length,
mac_buffer, mac_length
);
return UTF8ToString(mac_buffer, mac_length);
});
SAS.prototype['calculate_mac_long_kdf'] = restore_stack(function(input, info) { SAS.prototype['calculate_mac_long_kdf'] = restore_stack(function(input, info) {
var input_array = array_from_string(input); var input_array = array_from_string(input);
var input_buffer = stack(input_array); var input_buffer = stack(input_array);

241
javascript/package-lock.json generated Normal file
View file

@ -0,0 +1,241 @@
{
"name": "@matrix-org/olm",
"version": "3.2.11",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@matrix-org/olm",
"version": "3.2.11",
"license": "Apache-2.0",
"devDependencies": {
"jasmine": "^3.0.0"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"node_modules/glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"node_modules/jasmine": {
"version": "3.99.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.99.0.tgz",
"integrity": "sha512-YIThBuHzaIIcjxeuLmPD40SjxkEcc8i//sGMDKCgkRMVgIwRJf5qyExtlJpQeh7pkeoBSOe6lQEdg+/9uKg9mw==",
"dev": true,
"dependencies": {
"glob": "^7.1.6",
"jasmine-core": "~3.99.0"
},
"bin": {
"jasmine": "bin/jasmine.js"
}
},
"node_modules/jasmine-core": {
"version": "3.99.1",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz",
"integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==",
"dev": true
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"dependencies": {
"wrappy": "1"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
},
"dependencies": {
"balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"brace-expansion": {
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
"dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
"dev": true
},
"fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
"dev": true
},
"glob": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
"integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
"dev": true,
"requires": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.0.4",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
}
},
"inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
"dev": true,
"requires": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"dev": true
},
"jasmine": {
"version": "3.99.0",
"resolved": "https://registry.npmjs.org/jasmine/-/jasmine-3.99.0.tgz",
"integrity": "sha512-YIThBuHzaIIcjxeuLmPD40SjxkEcc8i//sGMDKCgkRMVgIwRJf5qyExtlJpQeh7pkeoBSOe6lQEdg+/9uKg9mw==",
"dev": true,
"requires": {
"glob": "^7.1.6",
"jasmine-core": "~3.99.0"
}
},
"jasmine-core": {
"version": "3.99.1",
"resolved": "https://registry.npmjs.org/jasmine-core/-/jasmine-core-3.99.1.tgz",
"integrity": "sha512-Hu1dmuoGcZ7AfyynN3LsfruwMbxMALMka+YtZeGoLuDEySVmVAPaonkNoBRIw/ectu8b9tVQCJNgp4a4knp+tg==",
"dev": true
},
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
},
"once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
"dev": true,
"requires": {
"wrappy": "1"
}
},
"path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
"dev": true
},
"wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
"dev": true
}
}
}

View file

@ -1,6 +1,6 @@
{ {
"name": "@matrix-org/olm", "name": "@matrix-org/olm",
"version": "3.2.2", "version": "3.2.16",
"description": "An implementation of the Double Ratchet cryptographic ratchet", "description": "An implementation of the Double Ratchet cryptographic ratchet",
"main": "olm.js", "main": "olm.js",
"files": [ "files": [
@ -14,7 +14,7 @@
], ],
"scripts": { "scripts": {
"build": "make -C .. js", "build": "make -C .. js",
"test": "jasmine-node test --verbose --junitreport --captureExceptions" "test": "jasmine --config=test/jasmine.json"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,9 +30,6 @@
}, },
"homepage": "https://gitlab.matrix.org/matrix-org/olm", "homepage": "https://gitlab.matrix.org/matrix-org/olm",
"devDependencies": { "devDependencies": {
"jasmine-node": "^1.14.5" "jasmine": "^3.0.0"
},
"publishConfig": {
"@matrix-org:registry":"https://gitlab.matrix.org/api/v4/projects/27/packages/npm/"
} }
} }

View file

@ -0,0 +1,6 @@
{
"spec_dir": "test",
"spec_files": [
"**/*.spec.js"
]
}

View file

@ -19,7 +19,7 @@ var Olm = require('../olm');
describe("sas", function() { describe("sas", function() {
var alice, bob; var alice, bob;
beforeEach(async function(done) { beforeEach(function(done) {
Olm.init().then(function() { Olm.init().then(function() {
alice = new Olm.SAS(); alice = new Olm.SAS();
bob = new Olm.SAS(); bob = new Olm.SAS();

View file

@ -11,13 +11,13 @@
/*************************** HEADER FILES ***************************/ /*************************** HEADER FILES ***************************/
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
/****************************** MACROS ******************************/ /****************************** MACROS ******************************/
#define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time #define AES_BLOCK_SIZE 16 // AES operates on 16 bytes at a time
/**************************** DATA TYPES ****************************/ /**************************** DATA TYPES ****************************/
typedef unsigned char BYTE; // 8-bit byte typedef uint8_t BYTE; // 8-bit byte
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines
/*********************** FUNCTION DECLARATIONS **********************/ /*********************** FUNCTION DECLARATIONS **********************/
/////////////////// ///////////////////

View file

@ -11,13 +11,14 @@
/*************************** HEADER FILES ***************************/ /*************************** HEADER FILES ***************************/
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
/****************************** MACROS ******************************/ /****************************** MACROS ******************************/
#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest
/**************************** DATA TYPES ****************************/ /**************************** DATA TYPES ****************************/
typedef unsigned char BYTE; // 8-bit byte typedef uint8_t BYTE; // 8-bit byte
typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines typedef uint32_t WORD; // 32-bit word, change to "long" for 16-bit machines
typedef struct { typedef struct {
BYTE data[64]; BYTE data[64];

82
lib/doctest/.clang-format Normal file
View file

@ -0,0 +1,82 @@
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
DisableFormat: false
Language: Cpp
Standard: Cpp11
IndentWidth: 4
TabWidth: 4
UseTab: Never
ColumnLimit: 100
ReflowComments: false
SortIncludes: false
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlinesLeft: false
AlignOperands: true
AlignTrailingComments: true
AlignAfterOpenBracket: true
DerivePointerAlignment: false
PointerAlignment: Left
IndentCaseLabels: true
ContinuationIndentWidth: 8
NamespaceIndentation: Inner
CompactNamespaces: true
FixNamespaceComments: true
AccessModifierOffset: -4
SpaceAfterControlStatementKeyword: false
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: Never
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesInContainerLiterals: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Cpp11BracedListStyle: true
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
BinPackArguments: true
BinPackParameters: true
AlwaysBreakAfterReturnType: None
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakTemplateDeclarations: true
BreakConstructorInitializersBeforeComma: true
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 8
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortFunctionsOnASingleLine: All
BreakBeforeBinaryOperators: false
BreakBeforeTernaryOperators: false
BreakStringLiterals: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterEnum: true
AfterNamespace: false
AfterStruct: true
AfterUnion: true
BeforeCatch: false
BeforeElse: false
IndentBraces: false
AfterFunction: false
AfterControlStatement: false
# penalties not thought of yet
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 60
PenaltyBreakString: 1000
PenaltyBreakFirstLessLess: 120
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000

12
lib/doctest/.editorconfig Normal file
View file

@ -0,0 +1,12 @@
root = true
[*]
charset = utf-8
trim_trailing_whitespace = true
end_of_line = lf
indent_style = space
indent_size = 4
insert_final_newline = true
[*.yml]
indent_size = 2

1
lib/doctest/.gitattributes vendored Normal file
View file

@ -0,0 +1 @@
* text=auto

4
lib/doctest/.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,4 @@
github: onqtam
patreon: onqtam
custom: https://www.paypal.me/onqtam/10

29
lib/doctest/.github/issue_template.md vendored Normal file
View file

@ -0,0 +1,29 @@
## Description
<!--
If your issue is a bugreport, this means describing what you did,
what did you want to happen and what actually did happen.
If your issue is a feature request, describe the feature and why do you
want it.
-->
### Steps to reproduce
<!--
This is only relevant for bug reports, but if you do have one,
please provide a minimal set of steps to reproduce the problem.
Usually this means providing a small and self-contained code using doctest
and specifying compiler flags/tools used if relevant.
-->
### Extra information
<!--
Fill in any extra information that might be important for your issue.
If your issue is a bugreport, definitely fill out at least the following.
-->
* doctest version: **v42.42.42**
* Operating System: **Joe's discount operating system**
* Compiler+version: **Hidden Dragon v1.2.3**

View file

@ -0,0 +1,26 @@
<!--
Make sure the PR is against the dev branch and not master which contains
the latest stable release. Also make sure to have read CONTRIBUTING.md.
Please do not submit pull requests changing the single-include `doctest.h`
file, it is generated from the 2 files in the doctest/parts/ folder.
-->
## Description
<!--
Describe the what and the why of your pull request. Remember that these two
are usually a bit different. As an example, if you have made various changes
to decrease the number of new strings allocated, that's what. The why probably
was that you have a large set of tests and found that this speeds them up.
-->
## GitHub Issues
<!--
If this PR was motivated by some existing issues, reference them here.
If it is a simple bug-fix, please also add a line like 'Closes #123'
to your commit message, so that it is automatically closed.
If it is not, don't, as it might take several iterations for a feature
to be done properly. If in doubt, leave it open and reference it in the
PR itself, so that maintainers can decide.
-->

View file

@ -0,0 +1,67 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '38 1 * * *'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'cpp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

490
lib/doctest/.github/workflows/main.yml vendored Normal file
View file

@ -0,0 +1,490 @@
name: CI
on: [push, pull_request]
jobs:
ci:
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
env:
CMAKE_GENERATOR: Ninja
ASAN_OPTIONS: strict_string_checks=true:detect_odr_violation=2:detect_stack_use_after_return=true:check_initialization_order=true:strict_init_order=true
TSAN_OPTIONS: force_seq_cst_atomics=1
CTEST_OUTPUT_ON_FAILURE: ON
CTEST_PARALLEL_LEVEL: 2
ACTIONS_ALLOW_UNSECURE_COMMANDS: true # because of the set-env calls
strategy:
fail-fast: false
matrix:
# Github Actions requires a single row to be added to the build matrix.
# See https://help.github.com/en/articles/workflow-syntax-for-github-actions.
name: [
ubuntu-18.04-gcc-4.8,
ubuntu-18.04-gcc-4.9,
ubuntu-18.04-gcc-5,
ubuntu-18.04-gcc-6,
ubuntu-18.04-gcc-7,
ubuntu-18.04-gcc-8,
ubuntu-18.04-gcc-9,
ubuntu-latest-gcc-10,
ubuntu-18.04-clang-3.5,
ubuntu-18.04-clang-3.6,
ubuntu-18.04-clang-3.7,
ubuntu-18.04-clang-3.8,
ubuntu-18.04-clang-3.9,
ubuntu-18.04-clang-4.0,
ubuntu-18.04-clang-5.0,
ubuntu-18.04-clang-6.0,
ubuntu-18.04-clang-7,
ubuntu-18.04-clang-8,
# ubuntu-latest-clang-9,
ubuntu-latest-clang-10,
# ubuntu-latest-clang-11,
windows-2016-cl,
windows-2016-clang-cl,
windows-2016-clang,
# windows-2016-gcc,
windows-2019-cl,
windows-2019-clang-cl,
windows-2019-clang,
# windows-2019-gcc,
macOS-latest-xcode-11.3,
]
include:
- name: ubuntu-18.04-gcc-4.8
os: ubuntu-18.04
compiler: gcc
version: "4.8"
- name: ubuntu-18.04-gcc-4.9
os: ubuntu-18.04
compiler: gcc
version: "4.9"
- name: ubuntu-18.04-gcc-5
os: ubuntu-18.04
compiler: gcc
version: "5"
- name: ubuntu-18.04-gcc-6
os: ubuntu-18.04
compiler: gcc
version: "6"
- name: ubuntu-18.04-gcc-7
os: ubuntu-18.04
compiler: gcc
version: "7"
- name: ubuntu-18.04-gcc-8
os: ubuntu-18.04
compiler: gcc
version: "8"
- name: ubuntu-18.04-gcc-9
os: ubuntu-18.04
compiler: gcc
version: "9"
- name: ubuntu-latest-gcc-10
os: ubuntu-latest
compiler: gcc
version: "10"
- name: ubuntu-18.04-clang-3.5
os: ubuntu-18.04
compiler: clang
version: "3.5"
- name: ubuntu-18.04-clang-3.6
os: ubuntu-18.04
compiler: clang
version: "3.6"
- name: ubuntu-18.04-clang-3.7
os: ubuntu-18.04
compiler: clang
version: "3.7"
- name: ubuntu-18.04-clang-3.8
os: ubuntu-18.04
compiler: clang
version: "3.8"
- name: ubuntu-18.04-clang-3.9
os: ubuntu-18.04
compiler: clang
version: "3.9"
- name: ubuntu-18.04-clang-4.0
os: ubuntu-18.04
compiler: clang
version: "4.0"
- name: ubuntu-18.04-clang-5.0
os: ubuntu-18.04
compiler: clang
version: "5.0"
- name: ubuntu-18.04-clang-6.0
os: ubuntu-18.04
compiler: clang
version: "6.0"
- name: ubuntu-18.04-clang-7
os: ubuntu-18.04
compiler: clang
version: "7"
- name: ubuntu-18.04-clang-8
os: ubuntu-18.04
compiler: clang
version: "8"
# fails like this: https://github.com/onqtam/doctest/runs/1562896476?check_suite_focus=true
# - name: ubuntu-latest-clang-9
# os: ubuntu-latest
# compiler: clang
# version: "9"
- name: ubuntu-latest-clang-10
os: ubuntu-latest
compiler: clang
version: "10"
# fails like this: https://github.com/onqtam/doctest/runs/1562896512?check_suite_focus=true
# - name: ubuntu-latest-clang-11
# os: ubuntu-latest
# compiler: clang
# version: "11"
- name: windows-2016-cl
os: windows-2016
compiler: cl
- name: windows-2016-clang-cl
os: windows-2016
compiler: clang-cl
- name: windows-2016-clang
os: windows-2016
compiler: clang
- name: windows-2019-cl
os: windows-2019
compiler: cl
# fails to install it...
# - name: windows-2016-gcc
# os: windows-2016
# compiler: gcc
- name: windows-2019-clang-cl
os: windows-2019
compiler: clang-cl
- name: windows-2019-clang
os: windows-2019
compiler: clang
# fails to install it...
# - name: windows-2019-gcc
# os: windows-2019
# compiler: gcc
- name: macOS-latest-xcode-11.3
os: macOS-10.15
compiler: xcode
version: "11.3"
steps:
- uses: actions/checkout@v1
- name: Install (Linux)
if: runner.os == 'Linux'
run: |
# CMake 3.15 allows specifying the generator using the CMAKE_GENERATOR
# environment variable.
curl -sSL https://github.com/Kitware/CMake/releases/download/v3.15.4/cmake-3.15.4-Linux-x86_64.tar.gz -o cmake.tar.gz
sudo tar xf cmake.tar.gz --strip 1 -C /usr/local
# Required for libc6-dbg:i386 and g++-multilib packages which are
# needed for x86 builds.
sudo dpkg --add-architecture i386
# clang-3.7 and earlier are not available in Bionic anymore so we get
# them from the Xenial repositories instead.
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial main"
sudo add-apt-repository "deb http://dk.archive.ubuntu.com/ubuntu/ xenial universe"
# LLVM 9 is not in Bionic's repositories so we add the official LLVM repository.
if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then
sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main"
fi
sudo apt-get update
# sudo apt-get install libopenmpi-dev
# sudo apt-get install openmpi-bin
# libc6-dbg:i386 is required for running valgrind on x86.
sudo apt-get install -y ninja-build valgrind libc6-dbg:i386
if [ "${{ matrix.compiler }}" = "gcc" ]; then
sudo apt-get install -y g++-${{ matrix.version }} g++-${{ matrix.version }}-multilib
echo "::set-env name=CC::gcc-${{ matrix.version }}"
echo "::set-env name=CXX::g++-${{ matrix.version }}"
else
sudo apt-get install -y clang-${{ matrix.version }} g++-multilib
echo "::set-env name=CC::clang-${{ matrix.version }}"
echo "::set-env name=CXX::clang++-${{ matrix.version }}"
fi
- name: Install (macOS)
if: runner.os == 'macOS'
run: |
brew install cmake ninja
if [ "${{ matrix.compiler }}" = "gcc" ]; then
brew install gcc@${{ matrix.version }}
echo "::set-env name=CC::gcc-${{ matrix.version }}"
echo "::set-env name=CXX::g++-${{ matrix.version }}"
else
ls -ls /Applications/
sudo xcode-select -switch /Applications/Xcode_${{ matrix.version }}.app
echo "::set-env name=CC::clang"
echo "::set-env name=CXX::clang++"
fi
- name: Install (Windows)
if: runner.os == 'Windows'
shell: powershell
run: |
Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh')
scoop install ninja --global
if ("${{ matrix.compiler }}".StartsWith("clang")) {
scoop install llvm --global
}
if ("${{ matrix.compiler }}" -eq "gcc") {
# Chocolatey GCC is broken on the windows-2019 image.
# See: https://github.com/DaanDeMeyer/doctest/runs/231595515
# See: https://github.community/t5/GitHub-Actions/Something-is-wrong-with-the-chocolatey-installed-version-of-gcc/td-p/32413
scoop install gcc --global
echo "::set-env name=CC::gcc"
echo "::set-env name=CXX::g++"
} elseif ("${{ matrix.compiler }}" -eq "clang") {
echo "::set-env name=CC::clang"
echo "::set-env name=CXX::clang++"
} else {
echo "::set-env name=CC::${{ matrix.compiler }}"
echo "::set-env name=CXX::${{ matrix.compiler }}"
}
# Scoop modifies the PATH so we make the modified PATH global.
echo "::set-env name=PATH::$env:PATH"
- name: Configure ASAN/UBSAN
if: runner.os == 'Linux' || runner.os == 'macOS'
run: |
# https://stackoverflow.com/a/37939589/11900641
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
# Disable sanitizers in configurations where we know they are buggy.
# TODO: Move these conditions to the if clause if Github Actions ever
# adds support for comparing versions.
# See: https://github.community/t5/GitHub-Actions/Allow-comparing-versions-in-if-conditions/m-p/33912#M1710
if [ "${{ runner.os }}" = "Linux" ] && \
[ "${{ matrix.compiler }}" = "gcc" ] && \
[ $(version ${{ matrix.version }}) -le $(version "5.0") ]; then
exit 0
fi
if [ "${{ runner.os }}" = "Linux" ] && \
[ "${{ matrix.compiler }}" = "clang" ] && \
[ $(version ${{ matrix.version }}) -le $(version "6.0") ]; then
exit 0
fi
if [ "${{ runner.os }}" = "macOS" ] && \
[ "${{ matrix.compiler }}" = "xcode" ] && \
[ $(version ${{ matrix.version }}) -le $(version "9.4.1") ]; then
exit 0
fi
if [ "${{ runner.os }}" = "macOS" ] && \
[ "${{ matrix.compiler }}" = "gcc" ]; then
exit 0
fi
ASAN_UBSAN_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
# Link statically against ASAN libraries because dynamically linking
# against ASAN libraries causes problems when using dlopen on Ubuntu.
# See: https://github.com/DaanDeMeyer/doctest/runs/249002713
if [ "${{ runner.os }}" = "Linux" ] && [ "${{ matrix.compiler }}" = "gcc" ]; then
ASAN_UBSAN_FLAGS="$ASAN_UBSAN_FLAGS -static-libasan"
fi
# Compiling in bash on Windows doesn't work and powershell doesn't
# exit on non-zero exit codes so we're forced to use cmd which means
# we don't have a cross platform way to access environment variables.
# To circumvent this, we put the sanitizer flags in an environment
# variable that is automatically picked up by CMake.
echo "::set-env name=CXXFLAGS::$ASAN_UBSAN_FLAGS"
- name: Configure TSAN
if: runner.os == 'Linux' || runner.os == 'macOS'
run: |
# https://stackoverflow.com/a/37939589/11900641
function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
if [ "${{ runner.os }}" = "Linux" ] && \
[ "${{ matrix.compiler }}" = "gcc" ] && \
[ $(version ${{ matrix.version }}) -le $(version "6.0") ]; then
exit 0
fi
if [ "${{ runner.os }}" = "Linux" ] && \
[ "${{ matrix.compiler }}" = "clang" ] && \
[ $(version ${{ matrix.version }}) -le $(version "3.9") ]; then
exit 0
fi
if [ "${{ runner.os }}" = "macOS" ] && \
[ "${{ matrix.compiler }}" = "gcc" ]; then
exit 0
fi
TSAN_FLAGS="-fsanitize=thread -pie -fPIE"
if [ "${{ runner.os }}" = "Linux" ] && [ "${{ matrix.compiler }}" = "gcc" ]; then
TSAN_FLAGS="$TSAN_FLAGS -static-libtsan"
fi
# The thread sanitizers build does not run on Windows so we can just
# use bash syntax to access the TSAN flags in the thread sanitizers
# build step.
echo "::set-env name=TSAN_FLAGS::$TSAN_FLAGS"
- name: Configure x64
if: runner.os == 'Windows'
run: .github\workflows\vsenv.bat -arch=x64 -host_arch=x64
- name: Build & Test Debug x64
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DDOCTEST_TEST_MODE=COMPARE
cmake --build build
cd build
ctest
- name: Build & Test Release x64
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DDOCTEST_TEST_MODE=COMPARE
cmake --build build
cd build
ctest
# Valgrind doesn't support the latest macOS versions.
# `-DCMAKE_CXX_FLAGS=""` overrides CXXFLAGS (disables sanitizers).
- name: Build & Test Debug x64 Valgrind
if: runner.os == 'Linux'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="" -DDOCTEST_TEST_MODE=VALGRIND
cmake --build build
cd build
ctest
- name: Build & Test Release x64 Valgrind
if: runner.os == 'Linux'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="" -DDOCTEST_TEST_MODE=VALGRIND
cmake --build build
cd build
ctest
- name: Build & Test Debug x64 Thread Sanitizers
if: runner.os == 'Linux' || runner.os == 'macOS'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="$TSAN_FLAGS" -DDOCTEST_TEST_MODE=COMPARE
cmake --build build
cd build
ctest
- name: Build & Test Debug x64 without RTTI
if: runner.os == 'Linux' || runner.os == 'macOS'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fno-rtti" -DDOCTEST_TEST_MODE=COMPARE
cmake --build build
cd build
ctest
- name: Build x64 Debug without exceptions
if: runner.os == 'Linux' || runner.os == 'macOS'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-fno-exceptions -DDOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS"
cmake --build build
# MinGW x86 tests fail on Windows: https://github.com/DaanDeMeyer/doctest/runs/240600881.
# MacOS doesn't support x86 from Xcode 10 onwards.
- name: Configure x86
shell: pwsh
if: (runner.os == 'Windows' && matrix.compiler != 'gcc') || runner.os == 'Linux'
run: |
if ("${{ runner.os }}" -eq "Windows") {
& .github\workflows\vsenv.bat -arch=x86 -host_arch=x64
}
if ("${{ matrix.compiler }}" -notcontains "cl") {
echo "::set-env name=CXXFLAGS::$env:CXXFLAGS -m32"
}
- name: Build & Test Debug x86
if: (runner.os == 'Windows' && matrix.compiler != 'gcc') || runner.os == 'Linux'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DDOCTEST_TEST_MODE=COMPARE
cmake --build build
cd build
ctest
- name: Build & Test Release x86
if: (runner.os == 'Windows' && matrix.compiler != 'gcc') || runner.os == 'Linux'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DDOCTEST_TEST_MODE=COMPARE
cmake --build build
cd build
ctest
- name: Build & Test Debug x86 Valgrind
if: runner.os == 'Linux'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="-m32" -DDOCTEST_TEST_MODE=VALGRIND
cmake --build build
cd build
ctest
- name: Build & Test Release x86 Valgrind
if: runner.os == 'Linux'
run: |
cmake -E remove_directory build
cmake -B build -S . -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="-m32" -DDOCTEST_TEST_MODE=VALGRIND
cmake --build build
cd build
ctest

17
lib/doctest/.github/workflows/vsenv.bat vendored Normal file
View file

@ -0,0 +1,17 @@
@echo off
SET VSWHERE="C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere"
:: See https://github.com/microsoft/vswhere/wiki/Find-VC
for /f "usebackq delims=*" %%i in (`%VSWHERE% -latest -property installationPath`) do (
call "%%i"\Common7\Tools\vsdevcmd.bat %*
)
:: Loop over all environment variables and make them global using set-env.
:: See: https://help.github.com/en/articles/development-tools-for-github-actions#set-an-environment-variable-set-env
:: See: https://stackoverflow.com/questions/39183272/loop-through-all-environmental-variables-and-take-actions-depending-on-prefix
setlocal
for /f "delims== tokens=1,2" %%a in ('set') do (
echo ::set-env name=%%a::%%b
)
endlocal

40
lib/doctest/.gitignore vendored Normal file
View file

@ -0,0 +1,40 @@
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
# Text garbage
*.ii
*.s
# My garbage :)
Win32/
x64/
doctest_with_main.dir/
scripts/bench/project/*
scripts/bench/catch*.hpp
scripts/bench/results.txt
build/
build-mingw/
*.pyc
*vscode*
.idea/
cmake-build-*/
bazel-*

413
lib/doctest/.travis.yml Normal file
View file

@ -0,0 +1,413 @@
# # this file is HEAVILY influenced by https://github.com/boostorg/hana/blob/master/.travis.yml
# dist: trusty
# language: c++
# notifications:
# email: false
# # gitter
# webhooks:
# urls: https://webhooks.gitter.im/e/10941dd1c67e5e967706
# on_success: change
# on_failure: always
# git:
# depth: 500
# # both apt and ccache make the builds slower...
# #cache:
# # - apt
# # - ccache
# env:
# global:
# # - USE_CCACHE=1
# # - CCACHE_SLOPPINESS=pch_defines,time_macros
# # - CCACHE_COMPRESS=1
# # - CCACHE_MAXSIZE=200M
# # - CCACHE_CPP2=1
# - CMAKE_OPTIONS_GLOBAL="-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
# addons:
# coverity_scan:
# # COVERITY_SCAN_TOKEN added as env var in travis project
# project:
# name: onqtam/doctest
# notification_email: vik.kirilov@gmail.com
# build_command: clang++ scripts/hello_world.cpp -I doctest
# branch_pattern: coverity_scan
# # these apt sources will be referenced later (by using *name)
# apt:
# sources: &apt_sources
# - ubuntu-toolchain-r-test
# - llvm-toolchain-trusty
# - llvm-toolchain-precise-3.7
# - llvm-toolchain-trusty-3.9
# - llvm-toolchain-trusty-4.0
# - llvm-toolchain-trusty-5.0
# - llvm-toolchain-trusty-6.0
# - llvm-toolchain-trusty-7
# - llvm-toolchain-trusty-8
# - llvm-toolchain-trusty-9
# - llvm-toolchain-trusty-10
# compiler: clang
# os: linux
# matrix:
# include:
# # coverage
# - env: COMPILER=g++ CODE_COVERAGE=true
# compiler: gcc
# addons:
# apt:
# packages: ["lcov"]
# # static code analysis
# - env: COMPILER=clang++-4.0 STATIC_CODE_ANALYSIS=true
# addons: &static_analysis
# apt:
# packages: ["clang-4.0", "clang-tidy-4.0", "cppcheck"]
# sources: *apt_sources
# # GCC 4.8
# - env: COMPILER=g++-4.8 HAS_ASAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
# compiler: gcc
# addons: &gcc48
# apt:
# packages: ["g++-4.8", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # GCC 4.9
# - env: COMPILER=g++-4.9 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
# compiler: gcc
# addons: &gcc49
# apt:
# packages: ["g++-4.9", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # GCC 5
# - env: COMPILER=g++-5 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
# compiler: gcc
# addons: &gcc5
# apt:
# packages: ["g++-5", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # GCC 6
# - env: COMPILER=g++-6 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
# compiler: gcc
# addons: &gcc6
# apt:
# packages: ["g++-6", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # GCC 7
# - env: COMPILER=g++-7 HAS_ASAN=true HAS_UBSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan" # TSAN broken for some time - seg faults
# compiler: gcc
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &gcc7
# apt:
# packages: ["g++-7", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # GCC 8
# - env: COMPILER=g++-8 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
# compiler: gcc
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &gcc8
# apt:
# packages: ["g++-8", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # GCC 9
# - env: COMPILER=g++-9 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
# compiler: gcc
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &gcc9
# apt:
# packages: ["g++-9", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # GCC 10
# - env: COMPILER=g++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
# compiler: gcc
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &gcc10
# apt:
# packages: ["g++-10", "valgrind", "libc6-dbg", "linux-libc-dev"]
# sources: *apt_sources
# # Clang 3.5
# - env: COMPILER=clang++-3.5 HAS_ASAN=true HAS_UBSAN=true # no HAS_TSAN - see errors: https://travis-ci.org/onqtam/doctest/builds/417926743
# addons: &clang35
# apt:
# packages: ["clang-3.5", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 3.6
# - env: COMPILER=clang++-3.6 HAS_ASAN=true HAS_UBSAN=true # no HAS_TSAN - see errors: https://travis-ci.org/onqtam/doctest/builds/417926743
# addons: &clang36
# apt:
# packages: ["clang-3.6", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 3.7
# - env: COMPILER=clang++-3.7
# addons: &clang37
# apt:
# packages: ["clang-3.7", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 3.8
# - env: COMPILER=clang++-3.8 HAS_ASAN=true HAS_UBSAN=true # no HAS_TSAN - see errors: https://travis-ci.org/onqtam/doctest/builds/417926743
# addons: &clang38
# apt:
# packages: ["clang-3.8", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 3.9
# - env: COMPILER=clang++-3.9 # no HAS_ASAN/HAS_UBSAN - see errors: https://travis-ci.org/onqtam/doctest/jobs/386263910
# addons: &clang39
# apt:
# packages: ["clang-3.9", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 4.0
# - env: COMPILER=clang++-4.0 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &clang40
# apt:
# packages: ["clang-4.0", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 5.0
# - env: COMPILER=clang++-5.0 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &clang50
# apt:
# packages: ["clang-5.0", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 6.0
# - env: COMPILER=clang++-6.0 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &clang60
# apt:
# packages: ["clang-6.0", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 7
# - env: COMPILER=clang++-7 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &clang7
# apt:
# packages: ["clang-7", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 8
# - env: COMPILER=clang++-8 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &clang8
# apt:
# packages: ["clang-8", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 9
# - env: COMPILER=clang++-9 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &clang9
# apt:
# packages: ["clang-9", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Clang 10
# - env: COMPILER=clang++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required # see this issue for more details: https://github.com/travis-ci/travis-ci/issues/9033
# addons: &clang9
# apt:
# packages: ["clang-10", "valgrind", "libc6-dbg", "g++-6"]
# sources: *apt_sources
# # Xcode 9.4 Clang
# - env: COMPILER=clang++ HAS_UBSAN=true HAS_TSAN=true # no HAS_ASAN - errors since using thread_local even in single-threaded cases - see errors: https://travis-ci.org/onqtam/doctest/builds/417181981
# osx_image: xcode9.4
# os: osx
# # Xcode 10.0 Clang
# - env: COMPILER=clang++ HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# osx_image: xcode10
# os: osx
# # Xcode 10.2 Clang
# - env: COMPILER=clang++ HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# osx_image: xcode10.2
# os: osx
# # Xcode 11.2 Clang
# - env: COMPILER=clang++ HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# osx_image: xcode11.2
# os: osx
# # OSX LLVM-GCC
# - env: COMPILER=g++ HAS_ASAN=true HAS_TSAN=true
# compiler: gcc
# osx_image: xcode10
# os: osx
# allow_failures:
# # static code analysis
# - env: COMPILER=clang++-4.0 STATIC_CODE_ANALYSIS=true
# # seems to not be present yet: https://travis-ci.org/github/onqtam/doctest/jobs/688097537
# # GCC 10
# - env: COMPILER=g++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true SANITIZER_CXX_FLAGS="-fuse-ld=gold -static-libasan" TSAN_CXX_FLAGS="-ltsan"
# compiler: gcc
# sudo: required
# # Clang 10
# - env: COMPILER=clang++-10 HAS_ASAN=true HAS_UBSAN=true HAS_TSAN=true
# sudo: required
# install:
# - if [[ "${CODE_COVERAGE}" == "true" ]]; then gem install coveralls-lcov ; fi
# ############################################################################
# # All the dependencies are installed in ${TRAVIS_BUILD_DIR}/deps/
# ############################################################################
# # Make a dir for all
# - DEPS_DIR="${TRAVIS_BUILD_DIR}/deps"
# - mkdir -p ${DEPS_DIR} && cd ${DEPS_DIR}
# # Install a recent CMake
# - |
# if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then
# CMAKE_URL="http://www.cmake.org/files/v3.7/cmake-3.7.2-Linux-x86_64.tar.gz"
# mkdir cmake && travis_retry wget --no-check-certificate --quiet -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
# export PATH=${DEPS_DIR}/cmake/bin:${PATH}
# fi
# # Install OCLint
# - |
# if [[ "${STATIC_CODE_ANALYSIS}" = "true" ]]; then
# OCLINT_URL="https://github.com/oclint/oclint/releases/download/v0.12/oclint-0.12-x86_64-linux-3.13.0-112-generic.tar.gz"
# mkdir oclint && travis_retry wget --no-check-certificate --quiet -O - ${OCLINT_URL} | tar --strip-components=1 -xz -C oclint
# export PATH=${DEPS_DIR}/oclint/bin:${PATH}
# fi
# # Go back to ${TRAVIS_BUILD_DIR}
# - cd ${TRAVIS_BUILD_DIR}
# ############################################################################
# # Install stuff with homebrew under OSX
# ############################################################################
# - |
# if [[ "${TRAVIS_OS_NAME}" == "osx" ]]; then
# brew update
# # brew install ccache
# # brew install valgrind
# # cmake
# if brew list -1 | grep -q "^cmake\$"; then
# brew outdated cmake || brew upgrade cmake
# else
# brew install cmake
# fi
# fi
# - export CXX="${COMPILER}"
# # - export CXX="ccache ${COMPILER}"
# # - ccache -s
# before_script:
# - ${CXX} --version
# script:
# # coverage
# - |
# if [[ "${CODE_COVERAGE}" = "true" ]]; then
# cmake ${CMAKE_OPTIONS_GLOBAL} ${CMAKE_OPTIONS} -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_CXX_FLAGS="-fprofile-arcs -ftest-coverage -std=c++0x" -DCMAKE_BUILD_TYPE=Debug . || exit 1
# make -k -j2 || exit 1
# ctest -j2 --output-on-failure || exit 1
# lcov -d . -c -o coverage.info # parse coverage data
# lcov -r coverage.info "/usr*" -o coverage.info # remove data for system headers
# lcov -r coverage.info "$(readlink -f examples)/*" -o coverage.info # remove data for .cpp files
# lcov -r coverage.info "$(readlink -f scripts)/*" -o coverage.info # remove data for .cpp files
# lcov -l coverage.info # just list a short summary of the results
# coveralls-lcov --repo-token=${COVERALLS_REPO_TOKEN} coverage.info # upload results
# # do not continue with other build configurations after that
# exit
# fi
# # static code analysis
# - |
# if [[ "${STATIC_CODE_ANALYSIS}" = "true" ]]; then
# # setup a test file "doctest.cpp" that is the header + a test case at the end
# echo "#define DOCTEST_CONFIG_IMPLEMENT_WITH_MAIN\n" >> doctest.cpp
# cat doctest/doctest.h >> doctest.cpp
# echo -e "TEST_CASE(\"\") {\n\tint a = 6;\n\tSUBCASE(\"\") a = 5;\n\tCAPTURE(a);\n\tCHECK(a == 6);\n}\n" >> doctest.cpp
# # cppcheck
# cppcheck doctest.cpp --enable=all --suppress=unmatchedSuppression --suppress=missingIncludeSystem --suppress=unusedFunction --suppress=functionConst --inline-suppr --platform=unix64 --inconclusive --std=posix --inconclusive -v --error-exitcode=1 --template "{file}({line}): {severity} ({id}): {message}"
# # oclint
# oclint doctest.cpp -disable-rule=ShortVariableName -disable-rule=LongLine -disable-rule=LongMethod -disable-rule=HighNcssMethod -disable-rule=LongVariableName -disable-rule=HighCyclomaticComplexity -disable-rule=HighNPathComplexity -disable-rule=UnusedLocalVariable -disable-rule=DoubleNegative -disable-rule=MultipleUnaryOperator -disable-rule=DeepNestedBlock || exit 1
# # clang-tidy
# cd scripts/playground
# cmake ${CMAKE_OPTIONS_GLOBAL} ${CMAKE_OPTIONS} -DCMAKE_CXX_COMPILER=${CXX} . || exit 1
# clang-tidy-4.0 -std=c++11 -p=. *.cpp -header-filter=.* -warnings-as-errors=* -checks='*,-misc-misplaced-widening-cast,-misc-macro-parentheses,-misc-definitions-in-headers,-misc-unused-parameters,-llvm-header-guard,-llvm-include-order,-google-readability-braces-around-statements,-google-runtime-references,-google-readability-todo,-google-build-using-namespace,-google-explicit-constructor,-cert-err58-cpp,-cppcoreguidelines-pro-type-vararg,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-cppcoreguidelines-special-member-functions,-cppcoreguidelines-pro-type-reinterpret-cast,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-type-member-init,-cppcoreguidelines-pro-type-union-access,-clang-analyzer-security.insecureAPI.strcpy,-modernize-loop-convert,-modernize-use-auto,-modernize-use-bool-literals,-readability-braces-around-statements,-readability-named-parameter,-readability-else-after-return,-readability-redundant-declaration,-readability-implicit-bool-cast,-clang-diagnostic-variadic-macros,-clang-diagnostic-c++11-compat' || exit 1
# # do not continue with other build configurations after that
# exit
# fi
# # initial run with options
# - cmake ${CMAKE_OPTIONS_GLOBAL} ${CMAKE_OPTIONS} -DCMAKE_CXX_COMPILER=${CXX} .
# # set the common CXX flags
# - export CXX_FLAGS="${CXX_FLAGS} -std=c++0x"
# # debug
# - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" .
# - make clean && make -k -j2
# - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then cmake -DDOCTEST_TEST_MODE=VALGRIND . && ctest -j2 --output-on-failure ; fi
# - cmake -DDOCTEST_TEST_MODE=COMPARE . && ctest -j2 --output-on-failure
# # release
# - cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS}" .
# - make clean && make -k -j2
# - if [[ "${TRAVIS_OS_NAME}" == "linux" ]]; then cmake -DDOCTEST_TEST_MODE=VALGRIND . && ctest -j2 --output-on-failure ; fi
# - cmake -DDOCTEST_TEST_MODE=COMPARE . && ctest -j2 --output-on-failure
# # sanitizers - again Debug/Release configs through address/undefined/thread sanitizers
# # on separate commands because when something fails I want to see which one exactly
# - cmake -DDOCTEST_TEST_MODE=NORMAL .
# - export ASAN_OPTIONS=verbosity=2:strict_string_checks=true:detect_odr_violation=2:detect_stack_use_after_return=true:check_initialization_order=true:strict_init_order=true
# - if [[ "${HAS_ASAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=address" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
# - if [[ "${HAS_ASAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=address" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
# - export UBSAN_OPTIONS=verbosity=2
# - if [[ "${HAS_UBSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=undefined" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
# - if [[ "${HAS_UBSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=undefined" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
# - export TSAN_OPTIONS=verbosity=2:force_seq_cst_atomics=1
# - if [[ "${HAS_TSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=thread -pie -fPIE ${TSAN_CXX_FLAGS}" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
# - if [[ "${HAS_TSAN}" = "true" ]]; then cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${SANITIZER_CXX_FLAGS} -g -fno-omit-frame-pointer -fsanitize=thread -pie -fPIE ${TSAN_CXX_FLAGS}" . && make clean && make -k -j2 && ctest -j2 --output-on-failure ; fi
# # test without rtti - just Debug
# - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -fno-rtti" .
# - make clean && make -k -j2
# - cmake -DDOCTEST_TEST_MODE=COMPARE . && ctest -j2 --output-on-failure
# # test only compilation without exceptions - just Debug
# - cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS="${CXX_FLAGS} -fno-exceptions -DDOCTEST_CONFIG_NO_EXCEPTIONS_BUT_WITH_ALL_ASSERTS" .
# - make clean && make -k -j2
# # - ccache -s
# #after_script:
# # - cat compile_commands.json

743
lib/doctest/CHANGELOG.md Normal file
View file

@ -0,0 +1,743 @@
# Change Log
## [2.4.7](https://github.com/doctest/doctest/tree/2.4.7) (2021-12-10)
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.6...2.4.7)
**Implemented enhancements:**
- Add a default Bazel BUILD file [\#433](https://github.com/doctest/doctest/issues/433)
**Fixed bugs:**
- Stack-buffer-overflow probably because char array is viewed as NULL terminated string [\#476](https://github.com/doctest/doctest/issues/476)
**Closed issues:**
- "C4834: discarding return value" with REQUIRE\_THROWS [\#549](https://github.com/doctest/doctest/issues/549)
- Xcode 11.3 is gone from macOS-latest \(=macOS-11\) [\#547](https://github.com/doctest/doctest/issues/547)
- is it possible to define dependency for CHECKs [\#545](https://github.com/doctest/doctest/issues/545)
- Output summary explanation [\#541](https://github.com/doctest/doctest/issues/541)
- compiler errors in doctest.h using cmake in CLion [\#540](https://github.com/doctest/doctest/issues/540)
- Fails to build in VS2013 because of constexpr [\#539](https://github.com/doctest/doctest/issues/539)
- -Wreserved-identifier warnings with Clang 13.0.0 [\#536](https://github.com/doctest/doctest/issues/536)
- Build fails with latest MSVC 2019 \(v16.11\) due to /WX [\#535](https://github.com/doctest/doctest/issues/535)
- VS 16.11 warning about unreferenced function with internal linkage [\#533](https://github.com/doctest/doctest/issues/533)
- Faq googletest mocking dead link [\#532](https://github.com/doctest/doctest/issues/532)
- FR: Documentation: FAQ: Add sectoin 'multiple files' [\#526](https://github.com/doctest/doctest/issues/526)
- CMAKE: doctest\_discover\_tests\(\) error when ADD\_LABELS is not specified [\#524](https://github.com/doctest/doctest/issues/524)
- Register tests based on test data available [\#521](https://github.com/doctest/doctest/issues/521)
- naming override in different testcase files [\#517](https://github.com/doctest/doctest/issues/517)
- Segmentation fault during the compilation without the copy elision optimization [\#515](https://github.com/doctest/doctest/issues/515)
- Compiler warnings on Xcode 12.5 [\#514](https://github.com/doctest/doctest/issues/514)
- Using filter `-sc` does not work properly? [\#513](https://github.com/doctest/doctest/issues/513)
- \[question\] Example of tests in production code & DLLs & shared libraries? [\#511](https://github.com/doctest/doctest/issues/511)
- Dumping fixture state to disk on error [\#509](https://github.com/doctest/doctest/issues/509)
- Macros construct reserved identifiers [\#507](https://github.com/doctest/doctest/issues/507)
- Running doctest on embedded ARM Cortex µCs [\#506](https://github.com/doctest/doctest/issues/506)
- Asserts Outside of Tests Example Does Not Link [\#504](https://github.com/doctest/doctest/issues/504)
- \[FEATURE REQUEST\] Quiet flag [\#503](https://github.com/doctest/doctest/issues/503)
- Compile error on Intel C++ Classic Compilers [\#502](https://github.com/doctest/doctest/issues/502)
- compiling doctest in 32-bit with \_\_stdcall calling convention fails [\#500](https://github.com/doctest/doctest/issues/500)
- Duplicate 'const' compilation error from TEST\_CASE\_CLASS macro [\#498](https://github.com/doctest/doctest/issues/498)
- Packed fields can't be accessed in 2.4.6 [\#495](https://github.com/doctest/doctest/issues/495)
- Dangling pointers with .str\(\).c\_str\(\) [\#494](https://github.com/doctest/doctest/issues/494)
- Automatic adding of TEST\_SUITE labels to discovered tests fails if ADD\_LABELS not set [\#489](https://github.com/doctest/doctest/issues/489)
- Adding a bunch of REQUIRE/CHECK utilities [\#487](https://github.com/doctest/doctest/issues/487)
- Warning C4114 in MSVC [\#485](https://github.com/doctest/doctest/issues/485)
- Own repository [\#410](https://github.com/doctest/doctest/issues/410)
- Linking problem with Clang 10 on Windows [\#362](https://github.com/doctest/doctest/issues/362)
- Add option not to print the intro text [\#342](https://github.com/doctest/doctest/issues/342)
- \[Feature\] Better integration with tools \(VS Code Test Adapter Extension\) [\#320](https://github.com/doctest/doctest/issues/320)
- vscode test explorer [\#303](https://github.com/doctest/doctest/issues/303)
- Want an option not to print any intro [\#245](https://github.com/doctest/doctest/issues/245)
- Add way to disable printing of intro [\#181](https://github.com/doctest/doctest/issues/181)
**Merged pull requests:**
- Make String::operator+ non-member [\#564](https://github.com/doctest/doctest/pull/564) ([Saalvage](https://github.com/Saalvage))
- Add -minimal flag [\#562](https://github.com/doctest/doctest/pull/562) ([Saalvage](https://github.com/Saalvage))
- Quiet flag [\#561](https://github.com/doctest/doctest/pull/561) ([Saalvage](https://github.com/Saalvage))
- Fix redefinition error while using double time DOCTEST\_ANONYMOUS\(DOCTEST\_CAPTURE\_\) [\#557](https://github.com/doctest/doctest/pull/557) ([isaevil](https://github.com/isaevil))
- Fix error: missing initializer for member doctest::detail::TestSuite [\#556](https://github.com/doctest/doctest/pull/556) ([isaevil](https://github.com/isaevil))
- Xcode 11.3 with macos 10.15 [\#548](https://github.com/doctest/doctest/pull/548) ([jsoref](https://github.com/jsoref))
- Spelling [\#546](https://github.com/doctest/doctest/pull/546) ([jsoref](https://github.com/jsoref))
- Fix build with -Wunused-but-set-variable [\#543](https://github.com/doctest/doctest/pull/543) ([jktjkt](https://github.com/jktjkt))
- build\(meson\): use `override\_dependency` if supported [\#538](https://github.com/doctest/doctest/pull/538) ([Tachi107](https://github.com/Tachi107))
- Fix google death test URL [\#528](https://github.com/doctest/doctest/pull/528) ([emrecil](https://github.com/emrecil))
- Fixing issue with doctestAddTests.cmake [\#527](https://github.com/doctest/doctest/pull/527) ([jharmer95](https://github.com/jharmer95))
- Replace gendered pronouns [\#525](https://github.com/doctest/doctest/pull/525) ([mletterle](https://github.com/mletterle))
- Fixed intel compiler parser bug. Should fix \#502 [\#523](https://github.com/doctest/doctest/pull/523) ([BerengerBerthoul](https://github.com/BerengerBerthoul))
- specifying working directory for execute\_process in doctest\_discover\_tests [\#518](https://github.com/doctest/doctest/pull/518) ([philbucher](https://github.com/philbucher))
- Fix the logic that depends on optional copy elision optimization [\#516](https://github.com/doctest/doctest/pull/516) ([ivankochin](https://github.com/ivankochin))
- Fix reserved identifiers [\#510](https://github.com/doctest/doctest/pull/510) ([ts826848](https://github.com/ts826848))
- Fix build with GCC 11 [\#505](https://github.com/doctest/doctest/pull/505) ([jktjkt](https://github.com/jktjkt))
- minor fixes in MPI docs [\#499](https://github.com/doctest/doctest/pull/499) ([philbucher](https://github.com/philbucher))
- Add a minimal bazel config [\#497](https://github.com/doctest/doctest/pull/497) ([elliottt](https://github.com/elliottt))
- Handle escaped commas in parsed arguments [\#493](https://github.com/doctest/doctest/pull/493) ([friendlyanon](https://github.com/friendlyanon))
- Fixes Issue 476 . When running executables with "-s" stringifyBinaryE… [\#491](https://github.com/doctest/doctest/pull/491) ([navinp0304](https://github.com/navinp0304))
- Set variable to 0 if not set [\#490](https://github.com/doctest/doctest/pull/490) ([shivupa](https://github.com/shivupa))
## [2.4.6](https://github.com/doctest/doctest/tree/2.4.6) (2021-03-22)
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.5...2.4.6)
**Fixed bugs:**
- REQUIRE does not compile when operator== in different namespace [\#443](https://github.com/doctest/doctest/issues/443)
- Using templated operator== inside TEST\_CASE changes deduced types of forwarding references [\#399](https://github.com/doctest/doctest/issues/399)
**Closed issues:**
- CMake doesn't link package [\#483](https://github.com/doctest/doctest/issues/483)
- Assertions are slow when running on Windows with a debugger attached [\#481](https://github.com/doctest/doctest/issues/481)
- Get list of registered test-case names [\#479](https://github.com/doctest/doctest/issues/479)
- Can't compile with glibc master \(future 2.34\): SIGSTKSZ is no longer a constant [\#473](https://github.com/doctest/doctest/issues/473)
- How to use Doctest with Github Actions [\#472](https://github.com/doctest/doctest/issues/472)
- Link error \(multiple definition...\) in simple project [\#470](https://github.com/doctest/doctest/issues/470)
- INFO does not compile when used like a function call [\#469](https://github.com/doctest/doctest/issues/469)
- std::uncaught\_exceptions is only available if compiling for macOS 10.12 or above [\#466](https://github.com/doctest/doctest/issues/466)
- Compile failure with WinRT on 2.4.5 [\#465](https://github.com/doctest/doctest/issues/465)
**Merged pull requests:**
- Improve speed with attached debugger \(Windows\) [\#482](https://github.com/doctest/doctest/pull/482) ([pgroke](https://github.com/pgroke))
- Convert to bool by casting, rather than double negation [\#480](https://github.com/doctest/doctest/pull/480) ([kitegi](https://github.com/kitegi))
- Fix compile error when targeting macOS version earlier and macOS 10.12 [\#478](https://github.com/doctest/doctest/pull/478) ([SamWindell](https://github.com/SamWindell))
- Fix MSVC linter warning about uninitialized TestSuite variables [\#471](https://github.com/doctest/doctest/pull/471) ([Reedbeta](https://github.com/Reedbeta))
- REQUIRE does not compile when operator== in different namespace \#443 . [\#468](https://github.com/doctest/doctest/pull/468) ([navinp0304](https://github.com/navinp0304))
- Automatically add TEST\_SUITE labels to discovered tests [\#464](https://github.com/doctest/doctest/pull/464) ([shivupa](https://github.com/shivupa))
## [2.4.5](https://github.com/doctest/doctest/tree/2.4.5) (2021-02-02)
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.4...2.4.5)
**Closed issues:**
- Stack buffer overflow in `String` constructor [\#460](https://github.com/doctest/doctest/issues/460)
- Suppress warnings from clang-tidy [\#459](https://github.com/doctest/doctest/issues/459)
- compilation issue in MSVC when defining DOCTEST\_THREAD\_LOCAL to static [\#458](https://github.com/doctest/doctest/issues/458)
- nvcc compiler warning; doctest.h\(4138\): warning : expression has no effect [\#454](https://github.com/doctest/doctest/issues/454)
- Use of std::atomic can slow down multithreaded tests [\#452](https://github.com/doctest/doctest/issues/452)
**Merged pull requests:**
- Fix compilation on case-sensitive filesystems [\#463](https://github.com/doctest/doctest/pull/463) ([jhasse](https://github.com/jhasse))
- Use function-like macros for prefixless macro names [\#462](https://github.com/doctest/doctest/pull/462) ([tbleher](https://github.com/tbleher))
- Implement a multi lane atomic for assertion counts [\#453](https://github.com/doctest/doctest/pull/453) ([martinus](https://github.com/martinus))
## [2.4.4](https://github.com/doctest/doctest/tree/2.4.4) (2020-12-25)
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.3...2.4.4)
**Closed issues:**
- 2.4.2: build fails [\#450](https://github.com/doctest/doctest/issues/450)
- combine the same tests for different build configurations from multiple shared objects without having symbol clashes [\#436](https://github.com/doctest/doctest/issues/436)
- Issue with GitHub Security Scanning: gmtime [\#423](https://github.com/doctest/doctest/issues/423)
## [2.4.3](https://github.com/doctest/doctest/tree/2.4.3) (2020-12-16)
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.2...2.4.3)
## [2.4.2](https://github.com/doctest/doctest/tree/2.4.2) (2020-12-15)
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.1...2.4.2)
**Closed issues:**
- DOCTEST\_CHECK\_THROWS\_WITH\_AS fails to work with dependant exception type [\#447](https://github.com/doctest/doctest/issues/447)
- MSVC warnings: narrowing conversion, signed/unsigned mismatch [\#446](https://github.com/doctest/doctest/issues/446)
- log contexts for failures in JUnit reporter [\#441](https://github.com/doctest/doctest/issues/441)
- MinGW "'mutex' in namespace 'std' does not name a type" error. [\#438](https://github.com/doctest/doctest/issues/438)
- Test runner thread initialization [\#435](https://github.com/doctest/doctest/issues/435)
- PLATFORM is misdetected on MacOSX Big Sur [\#415](https://github.com/doctest/doctest/issues/415)
- CHECK\_EQ with enum values [\#276](https://github.com/doctest/doctest/issues/276)
**Merged pull requests:**
- Squash MSVC warnings when including ntstatus.h [\#449](https://github.com/doctest/doctest/pull/449) ([nickhutchinson](https://github.com/nickhutchinson))
- Add MAIN\_PROJECT check for test option [\#445](https://github.com/doctest/doctest/pull/445) ([globberwops](https://github.com/globberwops))
- Suppress clang-analyzer-cplusplus.NewDeleteLeaks [\#444](https://github.com/doctest/doctest/pull/444) ([ncihnegn](https://github.com/ncihnegn))
- log contexts for failures in JUnit reporter [\#442](https://github.com/doctest/doctest/pull/442) ([runave](https://github.com/runave))
- Fix 32bit support on macOS [\#440](https://github.com/doctest/doctest/pull/440) ([AlexanderLanin](https://github.com/AlexanderLanin))
## [2.4.1](https://github.com/doctest/doctest/tree/2.4.1) (2020-11-04)
[Full Changelog](https://github.com/doctest/doctest/compare/2.4.0...2.4.1)
**Closed issues:**
- Avoid old C-style casts [\#424](https://github.com/doctest/doctest/issues/424)
- Segfault in unwind [\#422](https://github.com/doctest/doctest/issues/422)
- Inspect exception with gdb [\#421](https://github.com/doctest/doctest/issues/421)
- use-of-uninitialized-value [\#414](https://github.com/doctest/doctest/issues/414)
- Support unit tests with MPI [\#413](https://github.com/doctest/doctest/issues/413)
- Break into debugger support is missing for Linux [\#411](https://github.com/doctest/doctest/issues/411)
- What if built doctest as static library instead of header-only [\#408](https://github.com/doctest/doctest/issues/408)
- \[Question\] How to get test case name [\#407](https://github.com/doctest/doctest/issues/407)
- create extensions header for optional features requiring more std includes or newer C++ features [\#405](https://github.com/doctest/doctest/issues/405)
- tests/asserts summary lines are misaligned when counts exceed 999999 [\#402](https://github.com/doctest/doctest/issues/402)
- Call to 'ne' is ambiguous -- with solution [\#395](https://github.com/doctest/doctest/issues/395)
- Intermittent Segfaults [\#391](https://github.com/doctest/doctest/issues/391)
- Junit classname [\#390](https://github.com/doctest/doctest/issues/390)
- Add default printers for enums [\#121](https://github.com/doctest/doctest/issues/121)
**Merged pull requests:**
- Enum support \(fix for Issue \#121\) [\#429](https://github.com/doctest/doctest/pull/429) ([jkriegshauser](https://github.com/jkriegshauser))
- Support Clang 3.4 [\#428](https://github.com/doctest/doctest/pull/428) ([AlexanderLanin](https://github.com/AlexanderLanin))
- Silence remarks on old C-style casts [\#425](https://github.com/doctest/doctest/pull/425) ([UnePierre](https://github.com/UnePierre))
- Initial MPI unit tests implementation [\#418](https://github.com/doctest/doctest/pull/418) ([BerengerBerthoul](https://github.com/BerengerBerthoul))
- Add JUNIT\_OUTPUT\_DIR option to doctest\_discover\_tests [\#417](https://github.com/doctest/doctest/pull/417) ([Tradias](https://github.com/Tradias))
- Add option to build with std headers. [\#416](https://github.com/doctest/doctest/pull/416) ([avostrik](https://github.com/avostrik))
- Port Catch2 break into debugger for Linux. closes \#411 [\#412](https://github.com/doctest/doctest/pull/412) ([mikezackles](https://github.com/mikezackles))
- summary: align even large values \#402 [\#403](https://github.com/doctest/doctest/pull/403) ([dankamongmen](https://github.com/dankamongmen))
- Add breakpoint inline assembly for the Apple Silicon macOS. [\#400](https://github.com/doctest/doctest/pull/400) ([bruvzg](https://github.com/bruvzg))
- fix google's death test URI in roadmap [\#393](https://github.com/doctest/doctest/pull/393) ([ashutosh108](https://github.com/ashutosh108))
## [2.4.0](https://github.com/doctest/doctest/tree/2.4.0) (2020-06-27)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.8...2.4.0)
**Closed issues:**
- Count points based on the number of passed/failed cases? [\#386](https://github.com/doctest/doctest/issues/386)
- How to understand "\#data\_array" in std::string? [\#383](https://github.com/doctest/doctest/issues/383)
- crash: doctest with custom allocator [\#382](https://github.com/doctest/doctest/issues/382)
- Feature Request: format PRIVATE/PUBLIC/INTERFACE entries with constant indentation [\#378](https://github.com/doctest/doctest/issues/378)
- JUnit Reporter for Doctest [\#376](https://github.com/doctest/doctest/issues/376)
- Avoiding Feature Bloat [\#374](https://github.com/doctest/doctest/issues/374)
- StringMaker\<wchar\_t\> fail to compile with C++20 enabled \(GCC\) [\#357](https://github.com/doctest/doctest/issues/357)
- doctest\_discover\_tests and FetchContent\_Declare [\#351](https://github.com/doctest/doctest/issues/351)
- Junit reporter [\#318](https://github.com/doctest/doctest/issues/318)
**Merged pull requests:**
- Add a note that doctest can be installed through Homebrew [\#388](https://github.com/doctest/doctest/pull/388) ([cameronwhite](https://github.com/cameronwhite))
- provide alternative implementation of has\_insertion\_operator for C++20 [\#387](https://github.com/doctest/doctest/pull/387) ([lukaszgemborowski](https://github.com/lukaszgemborowski))
- Fix issue template to mention doctest [\#380](https://github.com/doctest/doctest/pull/380) ([nyanpasu64](https://github.com/nyanpasu64))
## [2.3.8](https://github.com/doctest/doctest/tree/2.3.8) (2020-05-17)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.7...2.3.8)
**Closed issues:**
- Scenario name can not be passed to -tc to execute single scenario [\#373](https://github.com/doctest/doctest/issues/373)
- Compile Error with CHECK\_NOTHROW when using 2 Template Arguments [\#372](https://github.com/doctest/doctest/issues/372)
- dll example won't compile [\#371](https://github.com/doctest/doctest/issues/371)
- Build error with MinGW \(Mingw-w64\) due to missing Windows.h \(with capital W\) [\#370](https://github.com/doctest/doctest/issues/370)
- How to override file\_line\_to\_stream? [\#369](https://github.com/doctest/doctest/issues/369)
- Memory sanitizer fails. [\#365](https://github.com/doctest/doctest/issues/365)
- Warning c6319 in Visual Studio [\#359](https://github.com/doctest/doctest/issues/359)
- Any option to show each test case's execute time? [\#358](https://github.com/doctest/doctest/issues/358)
- doctest in embedded [\#355](https://github.com/doctest/doctest/issues/355)
- Reloading a plugin with test cases leads to a segmentation fault [\#350](https://github.com/doctest/doctest/issues/350)
- Compiling with DOCTEST\_CONFIG\_COLORS\_ANSI fails on Windows [\#348](https://github.com/doctest/doctest/issues/348)
- Can I inherit ConsoleReporter? [\#344](https://github.com/doctest/doctest/issues/344)
- Noreturn and noexcept defines for Visual Studio 2013 support [\#327](https://github.com/doctest/doctest/issues/327)
- Data-driven testing -- print out the deepest DOCTEST\_SUBCASE [\#215](https://github.com/doctest/doctest/issues/215)
- Print the SUBCASE path when an assert fails in the TEST\_CASE body [\#125](https://github.com/doctest/doctest/issues/125)
**Merged pull requests:**
- fix: possible UB with nullptr increment [\#368](https://github.com/doctest/doctest/pull/368) ([oktonion](https://github.com/oktonion))
- Use CMake's CMP0077 policy if available [\#363](https://github.com/doctest/doctest/pull/363) ([thelink2012](https://github.com/thelink2012))
- Fix warning c6319 in Visual Studio 16.5 [\#361](https://github.com/doctest/doctest/pull/361) ([Cvelth](https://github.com/Cvelth))
## [2.3.7](https://github.com/doctest/doctest/tree/2.3.7) (2020-02-24)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.6...2.3.7)
**Closed issues:**
- Some of the GitHub CI builds are failing [\#334](https://github.com/doctest/doctest/issues/334)
- C++20 removed std::uncaught\_exception [\#333](https://github.com/doctest/doctest/issues/333)
- Doctest SEH handlers are called before \_\_except handlers [\#324](https://github.com/doctest/doctest/issues/324)
**Merged pull requests:**
- using std namespace where necessary and timer ticks fix [\#341](https://github.com/doctest/doctest/pull/341) ([oktonion](https://github.com/oktonion))
- fix std::uncaught\_exceptions [\#340](https://github.com/doctest/doctest/pull/340) ([cyyever](https://github.com/cyyever))
- Fix GitHub CI and add GitHub build badges [\#336](https://github.com/doctest/doctest/pull/336) ([claremacrae](https://github.com/claremacrae))
- http -\> https [\#331](https://github.com/doctest/doctest/pull/331) ([Coeur](https://github.com/Coeur))
- Switch to catching unhandled exceptions on Windows Closes \#324 [\#325](https://github.com/doctest/doctest/pull/325) ([jkriegshauser](https://github.com/jkriegshauser))
## [2.3.6](https://github.com/doctest/doctest/tree/2.3.6) (2019-12-16)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.5...2.3.6)
**Closed issues:**
- Link problem w/ BUILD=Release if MESSAGE\(\) with std::string/ostream-operator is used [\#316](https://github.com/doctest/doctest/issues/316)
- the FAQ about difference to Catch2 is missing tags [\#315](https://github.com/doctest/doctest/issues/315)
- include Windows.h in small caps to silence clang warnings [\#312](https://github.com/doctest/doctest/issues/312)
- Mistake in generator with lgtm error [\#311](https://github.com/doctest/doctest/issues/311)
- CMake: cannot install target doctest\_with\_main [\#310](https://github.com/doctest/doctest/issues/310)
- \[bug\] INFO\(\) and CAPTURE\(\) cannot compile using MSVC when used with DOCTEST\_CONFIG\_IMPLEMENTATION\_IN\_DLL [\#306](https://github.com/doctest/doctest/issues/306)
- Skip subcase [\#304](https://github.com/doctest/doctest/issues/304)
- Does some equivalent features from google test exist here? [\#300](https://github.com/doctest/doctest/issues/300)
- How to use doctest in dll only\(without main.cpp and .exe\) [\#299](https://github.com/doctest/doctest/issues/299)
- Warning: C26812: The enum type 'doctest::assertType::Enum' is unscoped. Prefer 'enum class' over 'enum' \(Enum.3\). [\#298](https://github.com/doctest/doctest/issues/298)
- test executable\_dll\_and\_plugin fails on Linux, GCC 8.1.0, -fsanitize=address [\#201](https://github.com/doctest/doctest/issues/201)
**Merged pull requests:**
- Fixed missing ostream include for MacOS when defining DOCTEST\_CONFIG\_… [\#314](https://github.com/doctest/doctest/pull/314) ([NKTomHaygarth](https://github.com/NKTomHaygarth))
- include windows.h in cmall caps to silence clang nonportable warnings [\#313](https://github.com/doctest/doctest/pull/313) ([suoniq](https://github.com/suoniq))
- Add .editorconfig file. [\#301](https://github.com/doctest/doctest/pull/301) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- Add Github Actions CI [\#285](https://github.com/doctest/doctest/pull/285) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
## [2.3.5](https://github.com/doctest/doctest/tree/2.3.5) (2019-09-22)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.4...2.3.5)
**Closed issues:**
- \[feature request\] Assertion macros for throwing exception of a specific type with message - \<LEVEL\>\_THROWS\_WITH\_AS\(expr, string, ex\_type\) [\#295](https://github.com/doctest/doctest/issues/295)
- CHECK\_THROWS\_AS of non-default constructor wants to call default constructor [\#293](https://github.com/doctest/doctest/issues/293)
- Typos and spelling errors in source, documentation and scripts [\#291](https://github.com/doctest/doctest/issues/291)
- Customize test names / variable substitution [\#284](https://github.com/doctest/doctest/issues/284)
- SUBCASE in function not behaving as expected [\#282](https://github.com/doctest/doctest/issues/282)
- SUPER\_FAST\_ASSERTS fails to compile CHECK\_MESSAGE [\#281](https://github.com/doctest/doctest/issues/281)
- CHECK\_MESSAGE no longer works with DOCTEST\_CONFIG\_SUPER\_FAST\_ASSERTS [\#280](https://github.com/doctest/doctest/issues/280)
- CAPTURE of structured binding element no longer works [\#279](https://github.com/doctest/doctest/issues/279)
- Reporter: `test\_case\_end` no longer fired after test case restart [\#278](https://github.com/doctest/doctest/issues/278)
- Add debug break override support [\#277](https://github.com/doctest/doctest/issues/277)
- Running tests from within Visual Studio in a static lib project [\#275](https://github.com/doctest/doctest/issues/275)
- Compile-time error when using a raw string literal inside of REQUIRE \(MSVC 2017\) [\#274](https://github.com/doctest/doctest/issues/274)
- Give example for having tests in production code [\#252](https://github.com/doctest/doctest/issues/252)
- Memory leaks just by including doctest.h [\#205](https://github.com/doctest/doctest/issues/205)
- Feature request: print subcase when an exception is thrown inside one [\#136](https://github.com/doctest/doctest/issues/136)
**Merged pull requests:**
- Fix typos and misspellings found by codespell. [\#292](https://github.com/doctest/doctest/pull/292) ([warmsocks](https://github.com/warmsocks))
- Document order by issue correctly [\#290](https://github.com/doctest/doctest/pull/290) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- Document that -order-by=file is compiler-dependent [\#289](https://github.com/doctest/doctest/pull/289) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- Add -order-by=name to filter\_2 test [\#288](https://github.com/doctest/doctest/pull/288) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- Add support for compiling with clang-cl [\#286](https://github.com/doctest/doctest/pull/286) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- No minimum version limitation of Meson [\#283](https://github.com/doctest/doctest/pull/283) ([ydm](https://github.com/ydm))
## [2.3.4](https://github.com/doctest/doctest/tree/2.3.4) (2019-08-12)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.3...2.3.4)
**Closed issues:**
- Remove INFO\(\) limitation for using only lvalues and no rvalues [\#269](https://github.com/doctest/doctest/issues/269)
- Compile error on MAC OS with AppleClang 8.0.0.8000042 [\#266](https://github.com/doctest/doctest/issues/266)
- Throwing exception in a mocked method [\#265](https://github.com/doctest/doctest/issues/265)
- Illegal syntax for decorators compiles and runs without warning, but has no effect [\#264](https://github.com/doctest/doctest/issues/264)
- Support conditional expressions in REQUIRE [\#262](https://github.com/doctest/doctest/issues/262)
- Register a listener\(reporter\) that always listens [\#257](https://github.com/doctest/doctest/issues/257)
- Memory sanitizer complaint [\#255](https://github.com/doctest/doctest/issues/255)
- Windows Clang GNU command line warnings [\#253](https://github.com/doctest/doctest/issues/253)
- The build writes into the source directory [\#249](https://github.com/doctest/doctest/issues/249)
- How to enable tests inside another exe [\#246](https://github.com/doctest/doctest/issues/246)
- Testing multiple headers. [\#244](https://github.com/doctest/doctest/issues/244)
- CMakeLists.txt: Needs CMAKE\_CXX\_STANDARD=11 [\#243](https://github.com/doctest/doctest/issues/243)
- \[bug\] Can't compile the tests because of mutex, that is declared in the doctest [\#242](https://github.com/doctest/doctest/issues/242)
**Merged pull requests:**
- Improve Listener docs [\#273](https://github.com/doctest/doctest/pull/273) ([claremacrae](https://github.com/claremacrae))
- Rework `INFO` lazy evaluation to use lambdas. [\#270](https://github.com/doctest/doctest/pull/270) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- Prevent compile errors with AppleClang compiler [\#268](https://github.com/doctest/doctest/pull/268) ([ClausKlein](https://github.com/ClausKlein))
- Revert "fix : including windows.h header cause error" [\#263](https://github.com/doctest/doctest/pull/263) ([onqtam](https://github.com/onqtam))
- Fix static analyzer URLs [\#259](https://github.com/doctest/doctest/pull/259) ([godbyk](https://github.com/godbyk))
- fix : including windows.h header cause error [\#258](https://github.com/doctest/doctest/pull/258) ([rinechran](https://github.com/rinechran))
- only look for C++ compiler with CMake [\#256](https://github.com/doctest/doctest/pull/256) ([zhihaoy](https://github.com/zhihaoy))
- Fix \#253 [\#254](https://github.com/doctest/doctest/pull/254) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- add alias target for doctest for use in build tree [\#247](https://github.com/doctest/doctest/pull/247) ([trondhe](https://github.com/trondhe))
## [2.3.3](https://github.com/doctest/doctest/tree/2.3.3) (2019-06-02)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.2...2.3.3)
**Closed issues:**
- Build fails with gcc9 because of -Wstrict-overflow=5 which is too high [\#241](https://github.com/doctest/doctest/issues/241)
- doctest given defined with short macro name [\#239](https://github.com/doctest/doctest/issues/239)
- Splitting templated test across different translation units [\#238](https://github.com/doctest/doctest/issues/238)
- Compile errors with iosfwd.h and Visual Studio 2019 Preview [\#183](https://github.com/doctest/doctest/issues/183)
- Add CMake test support as catch\_discover\_tests\(\) in Catch2 [\#171](https://github.com/doctest/doctest/issues/171)
**Merged pull requests:**
- fix \#239 - use long macro name [\#240](https://github.com/doctest/doctest/pull/240) ([m-bd](https://github.com/m-bd))
- Add doctest\_discover\_tests\(\) [\#236](https://github.com/doctest/doctest/pull/236) ([reddwarf69](https://github.com/reddwarf69))
- Ignore redundant-decls warning on MinGW [\#235](https://github.com/doctest/doctest/pull/235) ([AMS21](https://github.com/AMS21))
- Fixed meson build file dependency declaration [\#233](https://github.com/doctest/doctest/pull/233) ([jormundgand](https://github.com/jormundgand))
## [2.3.2](https://github.com/doctest/doctest/tree/2.3.2) (2019-05-06)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.1...2.3.2)
**Closed issues:**
- scripts/bench/run\_all.py : module 'urllib' has no attribute 'urlretrieve' [\#230](https://github.com/doctest/doctest/issues/230)
- wrong set of tests registered with TEST\_CASE\_TEMPLATE get executed [\#228](https://github.com/doctest/doctest/issues/228)
- Logging not Working for me [\#227](https://github.com/doctest/doctest/issues/227)
- Link test runner executable into dll? [\#226](https://github.com/doctest/doctest/issues/226)
- Linking issue for executables after including doctest in library [\#224](https://github.com/doctest/doctest/issues/224)
- Strange REQUIRE\_THROWS behaviour [\#223](https://github.com/doctest/doctest/issues/223)
- Windows clang-cl -Wunused-variable warning [\#221](https://github.com/doctest/doctest/issues/221)
- Update doctest 2.3.1 in bincrafters [\#220](https://github.com/doctest/doctest/issues/220)
- make install, on 64 bit, installs cmake files into lib instead of lib64 folder [\#218](https://github.com/doctest/doctest/issues/218)
- TSAN: data race related to hasLoggedCurrentTestStart [\#217](https://github.com/doctest/doctest/issues/217)
- REQUIRE\_THROWS\_AS does not support class constructors [\#216](https://github.com/doctest/doctest/issues/216)
- Build failure on clang 7.0.1 on Fedora 29 [\#214](https://github.com/doctest/doctest/issues/214)
- add example compatible with -\> https://github.com/report-ci/ [\#212](https://github.com/doctest/doctest/issues/212)
- No DOCTEST\_WITH\_TESTS? [\#211](https://github.com/doctest/doctest/issues/211)
**Merged pull requests:**
- Added meson file, to declare a dependency. [\#232](https://github.com/doctest/doctest/pull/232) ([jormundgand](https://github.com/jormundgand))
- Explicitly specify the doctest\_with\_main C++ standard in CMake. [\#231](https://github.com/doctest/doctest/pull/231) ([DaanDeMeyer](https://github.com/DaanDeMeyer))
- Remove architecture check from CMake package [\#225](https://github.com/doctest/doctest/pull/225) ([mmha](https://github.com/mmha))
- add default install prefix [\#219](https://github.com/doctest/doctest/pull/219) ([a4z](https://github.com/a4z))
- \[regression\] Workaround MSVC preprocessor issue triggered by REQUIRE\_THROWS [\#213](https://github.com/doctest/doctest/pull/213) ([zhihaoy](https://github.com/zhihaoy))
## [2.3.1](https://github.com/doctest/doctest/tree/2.3.1) (2019-03-24)
[Full Changelog](https://github.com/doctest/doctest/compare/2.3.0...2.3.1)
**Merged pull requests:**
- Add two very simple examples of using doctest with CMake [\#209](https://github.com/doctest/doctest/pull/209) ([pr0g](https://github.com/pr0g))
## [2.3.0](https://github.com/doctest/doctest/tree/2.3.0) (2019-03-23)
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.3...2.3.0)
**Closed issues:**
- Compilation with emscripten fails by default because of signal handling [\#207](https://github.com/doctest/doctest/issues/207)
- Compilation fails with cl.exe /Zc:wchar\_t- [\#206](https://github.com/doctest/doctest/issues/206)
- Parallel invocation of doctest's own testsuite via CTest fails [\#202](https://github.com/doctest/doctest/issues/202)
- Get the number of passed/failed tests in the code [\#200](https://github.com/doctest/doctest/issues/200)
- Tests alongside code with multiple executables [\#199](https://github.com/doctest/doctest/issues/199)
- Cppcheck 1.86 warnings [\#198](https://github.com/doctest/doctest/issues/198)
- Compiling as Dll maybe is wrong [\#196](https://github.com/doctest/doctest/issues/196)
- Forward-declaring identifiers in std:: is UB - consider including some of the cheaper C/C++ stdlib headers [\#194](https://github.com/doctest/doctest/issues/194)
- QtCreator + clang warning about operator \<\< precedence [\#191](https://github.com/doctest/doctest/issues/191)
- run test fixture from cli [\#190](https://github.com/doctest/doctest/issues/190)
- Installing doctest using cmake and make fails on Ubuntu 16.04 \(C++11 is not used\) [\#189](https://github.com/doctest/doctest/issues/189)
- c++17 requirement for testing private members [\#188](https://github.com/doctest/doctest/issues/188)
- \[feature request\] implement a user-extendable reporter system [\#138](https://github.com/doctest/doctest/issues/138)
- Same test runs multiple times when written in a header and included with different unnormalized paths [\#45](https://github.com/doctest/doctest/issues/45)
**Merged pull requests:**
- Fix unmatched bracket in DOCTEST\_TEST\_CASE\_CLASS [\#204](https://github.com/doctest/doctest/pull/204) ([patstew](https://github.com/patstew))
- Template apply [\#203](https://github.com/doctest/doctest/pull/203) ([zhihaoy](https://github.com/zhihaoy))
- No undefined behavior per C++ standard in detecting endianness. [\#195](https://github.com/doctest/doctest/pull/195) ([dimztimz](https://github.com/dimztimz))
- Fix propagating include directories of target doctest\_with\_main [\#193](https://github.com/doctest/doctest/pull/193) ([dimztimz](https://github.com/dimztimz))
- Move single header to a separate folder [\#187](https://github.com/doctest/doctest/pull/187) ([dimztimz](https://github.com/dimztimz))
- Fix Clang format to handle C++11 [\#186](https://github.com/doctest/doctest/pull/186) ([dimztimz](https://github.com/dimztimz))
- Rename doctest\_impl.h to doctest.cpp for less confusion. [\#185](https://github.com/doctest/doctest/pull/185) ([dimztimz](https://github.com/dimztimz))
## [2.2.3](https://github.com/doctest/doctest/tree/2.2.3) (2019-02-10)
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.2...2.2.3)
**Closed issues:**
- Calling convention needed on a few functions [\#182](https://github.com/doctest/doctest/issues/182)
- Terminal color is not reset when a test fails with some signal [\#122](https://github.com/doctest/doctest/issues/122)
## [2.2.2](https://github.com/doctest/doctest/tree/2.2.2) (2019-01-28)
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.1...2.2.2)
**Closed issues:**
- Add way to override getCurrentTicks\(\) implementation [\#178](https://github.com/doctest/doctest/issues/178)
- Wrap \<csignal\> include with ifdef [\#177](https://github.com/doctest/doctest/issues/177)
- How to stop doctest hijack unhandled exceptions? [\#176](https://github.com/doctest/doctest/issues/176)
- Change the include path of the `doctest` CMake interface target so users need to specify the folder as well [\#175](https://github.com/doctest/doctest/issues/175)
- Reduce scope of DebugOutputWindowReporter instance [\#174](https://github.com/doctest/doctest/issues/174)
- Can logging \(INFO\) be used in helper class outside of TEST\_CASE? [\#169](https://github.com/doctest/doctest/issues/169)
**Merged pull requests:**
- Change the include path in examples as \#175 [\#180](https://github.com/doctest/doctest/pull/180) ([ncihnegn](https://github.com/ncihnegn))
- Fix CMake include path \#175 [\#179](https://github.com/doctest/doctest/pull/179) ([ncihnegn](https://github.com/ncihnegn))
## [2.2.1](https://github.com/doctest/doctest/tree/2.2.1) (2019-01-15)
[Full Changelog](https://github.com/doctest/doctest/compare/2.2.0...2.2.1)
**Closed issues:**
- the `--no-throw` option shouldn't affect `\<LEVEL\>\_NOTHROW` asserts [\#173](https://github.com/doctest/doctest/issues/173)
- Make doctest work with XCode 6 and 7 \(no support for C++11 thread\_local\) [\#172](https://github.com/doctest/doctest/issues/172)
- Print vector content. [\#170](https://github.com/doctest/doctest/issues/170)
- Conan package [\#103](https://github.com/doctest/doctest/issues/103)
- \[feature request\] Thread-safety for asserts and logging facilities [\#4](https://github.com/doctest/doctest/issues/4)
## [2.2.0](https://github.com/doctest/doctest/tree/2.2.0) (2018-12-05)
[Full Changelog](https://github.com/doctest/doctest/compare/2.1.0...2.2.0)
**Closed issues:**
- remove the FAST\_ versions of the binary asserts \(not a breaking change!\) [\#167](https://github.com/doctest/doctest/issues/167)
- \[compile times\] make the DOCTEST\_CONFIG\_SUPER\_FAST\_ASSERTS identifier affect normal asserts too [\#166](https://github.com/doctest/doctest/issues/166)
## [2.1.0](https://github.com/doctest/doctest/tree/2.1.0) (2018-11-30)
[Full Changelog](https://github.com/doctest/doctest/compare/2.0.1...2.1.0)
**Closed issues:**
- doctest::String ctor with non-zero terminated string [\#165](https://github.com/doctest/doctest/issues/165)
- thread\_local is not supported on iOS 9.0 [\#164](https://github.com/doctest/doctest/issues/164)
- Compiler error on Android NDK r18 [\#163](https://github.com/doctest/doctest/issues/163)
- \[question\] One setup for multiple tests [\#160](https://github.com/doctest/doctest/issues/160)
- clang unwanted warning in user code [\#156](https://github.com/doctest/doctest/issues/156)
- Unsigned integer overflow in fileOrderComparator [\#151](https://github.com/doctest/doctest/issues/151)
- ThreadSanitizer: signal-unsafe call inside of a signal [\#147](https://github.com/doctest/doctest/issues/147)
- Feature request: check for exception string \(like Catch's CHECK\_THROWS\_WITH\) [\#97](https://github.com/doctest/doctest/issues/97)
**Merged pull requests:**
- Fixed build error under Android NDK [\#162](https://github.com/doctest/doctest/pull/162) ([tals](https://github.com/tals))
- Added clang-7 to travis build [\#161](https://github.com/doctest/doctest/pull/161) ([AMS21](https://github.com/AMS21))
- Remove clang-tidy warnings for static fields created by doctest [\#159](https://github.com/doctest/doctest/pull/159) ([rantasub](https://github.com/rantasub))
- Make it possible to change the command line options prefix [\#158](https://github.com/doctest/doctest/pull/158) ([tbleher](https://github.com/tbleher))
## [2.0.1](https://github.com/doctest/doctest/tree/2.0.1) (2018-10-24)
[Full Changelog](https://github.com/doctest/doctest/compare/2.0.0...2.0.1)
**Closed issues:**
- macro name collision with google log [\#157](https://github.com/doctest/doctest/issues/157)
- Add \#define to not run tests by default [\#152](https://github.com/doctest/doctest/issues/152)
- REQUIRE\_THROWS\_MESSAGE not checking message correctly [\#150](https://github.com/doctest/doctest/issues/150)
- Test case passes even though subcase failed [\#149](https://github.com/doctest/doctest/issues/149)
**Merged pull requests:**
- Correctly document when a main\(\) entry point will be created [\#155](https://github.com/doctest/doctest/pull/155) ([tbleher](https://github.com/tbleher))
- Correct format string for unsigned char [\#154](https://github.com/doctest/doctest/pull/154) ([tbleher](https://github.com/tbleher))
## [2.0.0](https://github.com/doctest/doctest/tree/2.0.0) (2018-08-23)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.9...2.0.0)
**Closed issues:**
- MSVC 2017 15.8.1, New Warnings as Errors [\#144](https://github.com/doctest/doctest/issues/144)
- Windows clang-cl -Wdeprecated-declarations warnings [\#143](https://github.com/doctest/doctest/issues/143)
- Logo Proposal for Doctest [\#141](https://github.com/doctest/doctest/issues/141)
- PCH Support [\#140](https://github.com/doctest/doctest/issues/140)
- improve compile times even further [\#139](https://github.com/doctest/doctest/issues/139)
- !!! BREAKING CHANGE !!! - Move to C++11 for next version of the library [\#137](https://github.com/doctest/doctest/issues/137)
- getCurrentTicks producing warning on MinGW [\#133](https://github.com/doctest/doctest/issues/133)
- \[enhancement\] Add support for "stand-alone assertions". [\#114](https://github.com/doctest/doctest/issues/114)
**Merged pull requests:**
- Suppress compiler warning on MinGW [\#134](https://github.com/doctest/doctest/pull/134) ([AMS21](https://github.com/AMS21))
## [1.2.9](https://github.com/doctest/doctest/tree/1.2.9) (2018-05-10)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.8...1.2.9)
**Closed issues:**
- GCC 8.0 std::uncaught\_exception\(\) is deprecated [\#130](https://github.com/doctest/doctest/issues/130)
- Signal stack size too small on Linux [\#129](https://github.com/doctest/doctest/issues/129)
- Support Intel Compiler [\#128](https://github.com/doctest/doctest/issues/128)
- Please add support for MSVC 2005 [\#127](https://github.com/doctest/doctest/issues/127)
- scan-build report "Dereference of null pointer" for function wildcmp [\#124](https://github.com/doctest/doctest/issues/124)
- !!! BREAKING CHANGE \(console output only\) !!! - Emulate the error/warning format emitted by native compiler gcc/clang/msvc when printing test failures in the log [\#123](https://github.com/doctest/doctest/issues/123)
- ARM builds: FTBFS on armhf - error: cast from 'const char\*' to 'const [\#118](https://github.com/doctest/doctest/issues/118)
**Merged pull requests:**
- Exclude Intel from GCC compiler check [\#132](https://github.com/doctest/doctest/pull/132) ([smcallis](https://github.com/smcallis))
- Fix deprecated-declarations warning with GCC-8.0 [\#131](https://github.com/doctest/doctest/pull/131) ([AMS21](https://github.com/AMS21))
## [1.2.8](https://github.com/doctest/doctest/tree/1.2.8) (2018-03-10)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.7...1.2.8)
**Closed issues:**
- ARM64 builds: templated\_test\_cases.cpp test fails [\#119](https://github.com/doctest/doctest/issues/119)
## [1.2.7](https://github.com/doctest/doctest/tree/1.2.7) (2018-02-06)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.6...1.2.7)
**Closed issues:**
- MSan has runtime error: unsigned integer overflow [\#116](https://github.com/doctest/doctest/issues/116)
- clang-tidy warning about cert-err58-cpp [\#115](https://github.com/doctest/doctest/issues/115)
- Linking errors [\#113](https://github.com/doctest/doctest/issues/113)
- inlining function defs [\#111](https://github.com/doctest/doctest/issues/111)
- Nullptr issue. [\#110](https://github.com/doctest/doctest/issues/110)
- MemorySanitizer: use-of-uninitialized-value [\#109](https://github.com/doctest/doctest/issues/109)
- Potential memory leak through scan-build [\#108](https://github.com/doctest/doctest/issues/108)
- Warnings raised to error with latest MSVC version [\#107](https://github.com/doctest/doctest/issues/107)
- New solution for tests in static libraries ! \(MSVC\) [\#106](https://github.com/doctest/doctest/issues/106)
- Command line flags do not work after code formatter/beautifier [\#104](https://github.com/doctest/doctest/issues/104)
- Cppcheck 1.81 warnings [\#102](https://github.com/doctest/doctest/issues/102)
**Merged pull requests:**
- Fix macros WIN32\_LEAN\_AND\_MEAN typo [\#112](https://github.com/doctest/doctest/pull/112) ([vladimirgamalyan](https://github.com/vladimirgamalyan))
- Correct DOCTEST\_NO\_INSTALL logic; do install unless it is set \(\#99\) [\#100](https://github.com/doctest/doctest/pull/100) ([onqtam](https://github.com/onqtam))
- Correct DOCTEST\_NO\_INSTALL logic; do install unless it is set [\#99](https://github.com/doctest/doctest/pull/99) ([OdyX](https://github.com/OdyX))
## [1.2.6](https://github.com/doctest/doctest/tree/1.2.6) (2017-10-29)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.5...1.2.6)
**Closed issues:**
- \[bug\] writing an exception translator in a header file results in it being registered multiple times which is suboptimal [\#98](https://github.com/doctest/doctest/issues/98)
- Warnings when using something more than /W4 for Visual Studio [\#95](https://github.com/doctest/doctest/issues/95)
**Merged pull requests:**
- Added an option to not install Doctest in the CMake scripts [\#96](https://github.com/doctest/doctest/pull/96) ([nm17](https://github.com/nm17))
- Adding a defensive check against a null pointer for the current test suite [\#94](https://github.com/doctest/doctest/pull/94) ([Lectem](https://github.com/Lectem))
- Remove incomplete copy ctor [\#93](https://github.com/doctest/doctest/pull/93) ([McMartin](https://github.com/McMartin))
## [1.2.5](https://github.com/doctest/doctest/tree/1.2.5) (2017-10-06)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.4...1.2.5)
**Closed issues:**
- Xcode 9 / clang - unknown warning group [\#92](https://github.com/doctest/doctest/issues/92)
## [1.2.4](https://github.com/doctest/doctest/tree/1.2.4) (2017-09-20)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.3...1.2.4)
**Closed issues:**
- \[bug\] test cases can end up in the wrong test suite [\#91](https://github.com/doctest/doctest/issues/91)
## [1.2.3](https://github.com/doctest/doctest/tree/1.2.3) (2017-09-11)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.2...1.2.3)
**Closed issues:**
- \[bug\] Defining a variable T inside a test with DOCTEST\_CONFIG\_DISABLE defined does not compile [\#90](https://github.com/doctest/doctest/issues/90)
- \[support\] Using `DOCTEST\_CONFIG\_NO\_SHORT\_MACRO\_NAMES` does not compile using g++ 6.3.0 [\#89](https://github.com/doctest/doctest/issues/89)
- \[question\] Why are SUBCASEs executed only once when within a function called multiple times? [\#88](https://github.com/doctest/doctest/issues/88)
## [1.2.2](https://github.com/doctest/doctest/tree/1.2.2) (2017-09-05)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.1...1.2.2)
**Closed issues:**
- \[question\] Differences between doctest and googletest \(gtest\) for uninitialised local variables in test cases [\#86](https://github.com/doctest/doctest/issues/86)
- !!! BREAKING CHANGE !!! - remove the custom implementation of std::is\_constructible and optionally use the \<type\_traits\> header because of infinite template recursion issues with GCC [\#85](https://github.com/doctest/doctest/issues/85)
- Static Analysis results of doctest [\#83](https://github.com/doctest/doctest/issues/83)
- !!! BREAKING CHANGE !!! - catch exceptions as const reference in \<LEVEL\>\_THROWS\_AS [\#81](https://github.com/doctest/doctest/issues/81)
- doctest implementation as static library [\#77](https://github.com/doctest/doctest/issues/77)
- Provide some easy way to compare structs containing float/doubles [\#73](https://github.com/doctest/doctest/issues/73)
**Merged pull requests:**
- Add support for templated scenarios [\#87](https://github.com/doctest/doctest/pull/87) ([Lectem](https://github.com/Lectem))
- Prefer if\(MSVC\) in CMakeLists.txt. [\#84](https://github.com/doctest/doctest/pull/84) ([martinmoene](https://github.com/martinmoene))
- catch throw\_as exception as const reference [\#82](https://github.com/doctest/doctest/pull/82) ([a4z](https://github.com/a4z))
- Added doctest\_with\_main static lib [\#78](https://github.com/doctest/doctest/pull/78) ([ymadzhunkov](https://github.com/ymadzhunkov))
## [1.2.1](https://github.com/doctest/doctest/tree/1.2.1) (2017-05-24)
[Full Changelog](https://github.com/doctest/doctest/compare/1.2.0...1.2.1)
**Closed issues:**
- Compile error under MSVC 2015/2017 if \<thread\> included in same file as "doctest.h" [\#72](https://github.com/doctest/doctest/issues/72)
**Merged pull requests:**
- docs: TEST\_CASE\_METHOD -\> TEST\_CASE\_FIXTURE [\#71](https://github.com/doctest/doctest/pull/71) ([akrzemi1](https://github.com/akrzemi1))
## [1.2.0](https://github.com/doctest/doctest/tree/1.2.0) (2017-05-15)
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.4...1.2.0)
**Closed issues:**
- Further improvements on compile time - disable inlining of functions used in asserts [\#70](https://github.com/doctest/doctest/issues/70)
- Improve runtime performance - lazy stringification, more inlining, no statics on the hot path, move semantics for classes such as doctest::String which are used by value, etc. [\#69](https://github.com/doctest/doctest/issues/69)
- Add option to show duration of test case execution and add a timeout\(seconds\) decorator - marking them as failed if they exceed it [\#68](https://github.com/doctest/doctest/issues/68)
- Add support for test case decorators - label, description, skip, may\_fail, should\_fail, expected\_failures, etc. [\#67](https://github.com/doctest/doctest/issues/67)
- Integrate static analysis into the CI builds [\#66](https://github.com/doctest/doctest/issues/66)
- Print the test suite name on test case failure [\#65](https://github.com/doctest/doctest/issues/65)
- Add signal handlers to handle crashes \(and use SEH under Windows\) - report which test case failed [\#63](https://github.com/doctest/doctest/issues/63)
- Add support to Approx for strong typedefs of double [\#62](https://github.com/doctest/doctest/issues/62)
- \[question\] Is there a way to always have 0 as the exit code regardless of test results? [\#59](https://github.com/doctest/doctest/issues/59)
- Add support for un-parenthesized expressions containing commas in asserts [\#58](https://github.com/doctest/doctest/issues/58)
- Add ability to filter subcases with filters [\#57](https://github.com/doctest/doctest/issues/57)
- Add option to query if code is being ran inside of a test - doctest::is\_running\_in\_test [\#56](https://github.com/doctest/doctest/issues/56)
- Ability for a binary \(executable / shared object\) to use the test runner implementation of another binary - with exported symbols - so tests end up in a single registry [\#55](https://github.com/doctest/doctest/issues/55)
- How to force the use of colors in the terminal? [\#54](https://github.com/doctest/doctest/issues/54)
- How can I mix production code with the Unit Tests? [\#53](https://github.com/doctest/doctest/issues/53)
- add \<= and \>= operators to Approx \(and also maybe \< and \>\) [\#52](https://github.com/doctest/doctest/issues/52)
- Add ability to capture variables from test scope [\#48](https://github.com/doctest/doctest/issues/48)
- !!! BREAKING CHANGE !!! - Make TEST\_SUITE work with blocks and add TEST\_SUITE\_BEGIN [\#41](https://github.com/doctest/doctest/issues/41)
- Add option to print which test suites/cases are run [\#39](https://github.com/doctest/doctest/issues/39)
- Add support for templated test cases - parameterized by type [\#38](https://github.com/doctest/doctest/issues/38)
- Add custom failure messages with lazy stringification [\#23](https://github.com/doctest/doctest/issues/23)
- Add an exception translation mechanism + the ability for users to extend it with custom exception types [\#12](https://github.com/doctest/doctest/issues/12)
- Add API for reporting failures [\#9](https://github.com/doctest/doctest/issues/9)
**Merged pull requests:**
- Update doctest to work with ARM DS5-compiler [\#64](https://github.com/doctest/doctest/pull/64) ([tomasnilefrost](https://github.com/tomasnilefrost))
## [1.1.4](https://github.com/doctest/doctest/tree/1.1.4) (2017-02-18)
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.3...1.1.4)
**Closed issues:**
- Add option --force-colors - for when a tty is not detected for stdout [\#51](https://github.com/doctest/doctest/issues/51)
- Issue with using lambdas in tests in gcc [\#49](https://github.com/doctest/doctest/issues/49)
- Add the include file to releases [\#47](https://github.com/doctest/doctest/issues/47)
**Merged pull requests:**
- Add translation of std::exception for exceptions that terminate a test case [\#46](https://github.com/doctest/doctest/pull/46) ([eliaskosunen](https://github.com/eliaskosunen))
## [1.1.3](https://github.com/doctest/doctest/tree/1.1.3) (2016-11-15)
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.2...1.1.3)
**Closed issues:**
- Exception handlers cause warnings when exceptions are disabled [\#44](https://github.com/doctest/doctest/issues/44)
## [1.1.2](https://github.com/doctest/doctest/tree/1.1.2) (2016-10-10)
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.1...1.1.2)
**Closed issues:**
- clang warnings when using C++11 or newer [\#42](https://github.com/doctest/doctest/issues/42)
- \[support\] identical names for test suites? [\#40](https://github.com/doctest/doctest/issues/40)
## [1.1.1](https://github.com/doctest/doctest/tree/1.1.1) (2016-09-22)
[Full Changelog](https://github.com/doctest/doctest/compare/1.1.0...1.1.1)
## [1.1.0](https://github.com/doctest/doctest/tree/1.1.0) (2016-09-21)
[Full Changelog](https://github.com/doctest/doctest/compare/1.0.0...1.1.0)
**Closed issues:**
- char\* comparison uses the contents, not the pointer [\#36](https://github.com/doctest/doctest/issues/36)
- add configuration preprocessor identifier for passing by value in assertions instead of by reference [\#35](https://github.com/doctest/doctest/issues/35)
- restrict expressions in assertion macros to binary comparisons at most with a static assert [\#34](https://github.com/doctest/doctest/issues/34)
- Add clearFilters\(\) to doctest::Context [\#33](https://github.com/doctest/doctest/issues/33)
- A way to refrain from polluting “\#define” space for users of tested code? [\#32](https://github.com/doctest/doctest/issues/32)
- drop VC++6 support [\#31](https://github.com/doctest/doctest/issues/31)
- False positive test [\#30](https://github.com/doctest/doctest/issues/30)
- Turn off coloring after tests are finished? [\#28](https://github.com/doctest/doctest/issues/28)
- C++11 nullptr [\#27](https://github.com/doctest/doctest/issues/27)
- Only one SUBCASE per line is executed [\#25](https://github.com/doctest/doctest/issues/25)
- creative formatting of chars [\#24](https://github.com/doctest/doctest/issues/24)
- DOCTEST\_BREAK\_INTO\_DEBUGGER undefined under OSX [\#22](https://github.com/doctest/doctest/issues/22)
- Tests inside a static library [\#21](https://github.com/doctest/doctest/issues/21)
- Add example how to remove doctest options from the command line for the program after the tests run [\#20](https://github.com/doctest/doctest/issues/20)
- Single-letter options active even without leading '-' \(dash\) [\#19](https://github.com/doctest/doctest/issues/19)
- pointer stringification not working for compilers different from MSVC [\#18](https://github.com/doctest/doctest/issues/18)
- Tests that accompany code run and produce output at default [\#17](https://github.com/doctest/doctest/issues/17)
- GCC 5.3.1 Compiler warning: sign compare [\#16](https://github.com/doctest/doctest/issues/16)
- Slower than Catch in realistic test cases [\#14](https://github.com/doctest/doctest/issues/14)
- Rename doctest::detail::Result res; in DOCTEST\_ASSERT\_IMPLEMENT [\#10](https://github.com/doctest/doctest/issues/10)
- No red when all tests pass [\#7](https://github.com/doctest/doctest/issues/7)
- UNIX line feedings on GitHub please [\#6](https://github.com/doctest/doctest/issues/6)
**Merged pull requests:**
- don't show green when tests fail [\#26](https://github.com/doctest/doctest/pull/26) ([ferkulat](https://github.com/ferkulat))
- Include "program code" in example [\#15](https://github.com/doctest/doctest/pull/15) ([martinmoene](https://github.com/martinmoene))
## [1.0.0](https://github.com/doctest/doctest/tree/1.0.0) (2016-05-22)
**Merged pull requests:**
- Reduce the header size for test users [\#3](https://github.com/doctest/doctest/pull/3) ([zah](https://github.com/zah))
- Add a Gitter chat badge to README.md [\#1](https://github.com/doctest/doctest/pull/1) ([gitter-badger](https://github.com/gitter-badger))
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*

Some files were not shown because too many files have changed in this diff Show more