Compare commits

..

No commits in common. "master" and "dkasak/session-export-format" have entirely different histories.

50 changed files with 426 additions and 606 deletions

View file

@ -1,56 +1,3 @@
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>`_
===========================================================================

View file

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.4)
project(olm VERSION 3.2.16 LANGUAGES CXX C)
project(olm VERSION 3.2.11 LANGUAGES CXX C)
option(OLM_TESTS "Build tests" ON)
option(BUILD_SHARED_LIBS "Build as a shared library" ON)

View file

@ -8,6 +8,7 @@ RELEASE_OPTIMIZE_FLAGS ?= -O3
DEBUG_OPTIMIZE_FLAGS ?= -g -O0 -U_FORTIFY_SOURCE
JS_OPTIMIZE_FLAGS ?= -O3
FUZZER_OPTIMIZE_FLAGS ?= -O3
CC = gcc
EMCC = emcc
EMAR = emar
AR = ar
@ -30,7 +31,7 @@ JS_ASMJS_TARGET := javascript/olm_legacy.js
WASM_TARGET := $(BUILD_DIR)/wasm/libolm.a
JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json
JS_EXPORTED_RUNTIME_METHODS := [ALLOC_STACK,writeAsciiToMemory,intArrayFromString,UTF8ToString,stringToUTF8]
JS_EXPORTED_RUNTIME_METHODS := [ALLOC_STACK]
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 include/olm/error.h include/olm/olm_export.h
@ -93,7 +94,7 @@ LDFLAGS += -Wall -Werror
CFLAGS_NATIVE = -fPIC
CXXFLAGS_NATIVE = -fPIC
EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0 -s MODULARIZE=1 -Wno-error=closure
EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0 -s MODULARIZE=1
# 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

View file

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

View file

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

View file

@ -9,69 +9,6 @@ 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
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
To build olm as a shared library run:
@ -104,38 +41,22 @@ 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:
To build the JavaScript bindings, 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
Note that if you run emscripten in a docker container, 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
./gradlew clean assembleRelease
```
#### Objective-C
To build the Xcode workspace for Objective-C bindings, run:
```bash
@ -144,9 +65,7 @@ pod install
open OLMKit.xcworkspace
```
#### Python
To build the Python 3 bindings, first build olm as a library as above, and
To build the Python bindings, first build olm as a shared library as above, and
then run:
```bash
@ -154,6 +73,9 @@ 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``.
### Using make instead of cmake
**WARNING:** Using cmake is the preferred method for building the olm library;
@ -197,7 +119,7 @@ repository, some bindings are (in alphabetical order):
- [nim-olm](https://codeberg.org/BarrOff/nim-olm) (MIT) Nim bindings
- [olm-sys](https://gitlab.gnome.org/BrainBlasted/olm-sys) (Apache-2.0) Rust
bindings
- [Trixnity](https://gitlab.com/trixnity/trixnity) (Apache-2.0) Kotlin SDK for
- [Trixnity](https://gitlab.com/benkuly/trixnity) (AGPLv3) Kotlin SDK for
Matrix, including Olm bindings
Note that bindings may have a different license from libolm, and are *not*
@ -206,7 +128,7 @@ endorsed by the Matrix.org Foundation C.I.C.
## Release process
First: bump version numbers in ``common.mk``, ``CMakeLists.txt``,
``javascript/package.json``, ``python/pyproject.toml``, ``OLMKit.podspec``,
``javascript/package.json``, ``python/olm/__version__.py``, ``OLMKit.podspec``,
``Package.swift``, and ``android/gradle.properties``.
Also, ensure the changelog is up to date, and that everything is committed to

View file

@ -11,8 +11,8 @@
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_C_COMPILER x86_64-w64-mingw32-gcc)
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++)
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)
# here is the target environment located

View file

@ -26,7 +26,7 @@ org.gradle.configureondemand=false
# Ref: https://github.com/vanniktech/gradle-maven-publish-plugin
GROUP=org.matrix.android
POM_ARTIFACT_ID=olm
VERSION_NAME=3.2.16
VERSION_NAME=3.2.11
POM_PACKAGING=aar

View file

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

View file

@ -227,7 +227,7 @@ The Megolm session export format is thus as follows:
0 1 5 37 69 101 133 165 bytes
```
The version byte, ``V``, is ``"\x01"``.
The version byte, ``V``, is ``"\x02"``.
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

View file

@ -2,11 +2,11 @@
"nodes": {
"flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"lastModified": 1649676176,
"narHash": "sha256-OWKJratjt2RW151VUlJPRALb7OU2S5s+f0vLj4o1bHM=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"rev": "a4b154ebbdc88c8498a5c7b01589addc9e9cb678",
"type": "github"
},
"original": {
@ -17,11 +17,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1664871473,
"narHash": "sha256-1LzbW6G6Uz8akWiOdlIi435GAm1ct5jF5tovw/9to0o=",
"lastModified": 1652172129,
"narHash": "sha256-8e2JMrswaKe02P8rYfvIMoc59pNuw6h/GYu8DBE1c+0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b7a6fde153d9470afdb6aa1da51c4117f03b84ed",
"rev": "f419dc5763c2b3c5580e396dea065b6d8b58ee27",
"type": "github"
},
"original": {
@ -34,11 +34,11 @@
"npmlock2nix": {
"flake": false,
"locked": {
"lastModified": 1654775747,
"narHash": "sha256-9pXHDpIjmsK5390wmpGHu9aA4QOPpegPBvThHeBlef4=",
"lastModified": 1648735462,
"narHash": "sha256-G22WBttdFoWp7E/YvGfePOc+W+ZsQGw+IwpFbAwJNeI=",
"owner": "nix-community",
"repo": "npmlock2nix",
"rev": "5c4f247688fc91d665df65f71c81e0726621aaa8",
"rev": "dd2897c3a6e404446704a63f40b9a29fa0acf752",
"type": "github"
},
"original": {

128
flake.nix
View file

@ -3,7 +3,7 @@
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
# https://github.com/emscripten-core/emscripten/issues/14995
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.npmlock2nix = {
url = "github:nix-community/npmlock2nix";
@ -11,30 +11,126 @@
};
outputs = { self, nixpkgs, flake-utils, npmlock2nix }:
(
# 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" ] (system:
let
localOverlay = import ./nix/overlay.nix;
pkgsForSystem = system: import nixpkgs {
pkgs = 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;
node_modules = pkgs.npmlock2nix.node_modules { src = ./javascript; };
in
rec {
checks.gcc-cmake = pkgs.gccStdenv.mkDerivation {
name = "olm";
buildInputs = [ pkgs.cmake ];
src = ./.;
buildPhase = ''
cmake . -Bbuild
cmake --build build
'';
doCheck = true;
checkPhase = ''
cd build/tests
ctest .
cd ../..
'';
};
packages = {
javascript = legacyPackages.olm-javascript;
checks.clang-cmake = pkgs.clangStdenv.mkDerivation {
name = "olm";
buildInputs = [ pkgs.cmake ];
src = ./.;
buildPhase = ''
cmake . -Bbuild
cmake --build build
'';
doCheck = true;
checkPhase = ''
cd build/tests
ctest .
cd ../..
'';
};
checks.gcc-make = pkgs.gccStdenv.mkDerivation {
name = "olm";
src = ./.;
buildPhase = ''
make
'';
doCheck = true;
checkPhase = ''
make test
'';
installPhase = ''
make install PREFIX=$out
'';
};
packages.javascript = pkgs.buildEmscriptenPackage {
pname = "olm";
inherit (builtins.fromJSON (builtins.readFile ./javascript/package.json)) version;
buildInputs = with pkgs; [ gnumake python3 nodejs ];
src = ./.;
postPatch = ''
patchShebangs .
'';
configurePhase = "";
buildPhase = ''
export EM_CACHE=$TMPDIR
make javascript/exported_functions.json
make js
'';
output = [ "out" ];
installPhase = ''
mkdir -p $out/javascript
cd javascript
echo sha256: > checksums.txt
sha256sum olm.js olm_legacy.js olm.wasm >> checksums.txt
echo sha512: >> checksums.txt
sha512sum olm.js olm_legacy.js olm.wasm >> checksums.txt
cp package.json olm.js olm.wasm olm_legacy.js index.d.ts README.md checksums.txt $out/javascript
cd ..
'';
checkPhase = ''
cd javascript
export HOME=$TMPDIR
ln -s ${node_modules}/node_modules ./node_modules
npm test
cd ..
'';
};
packages.default = packages.javascript;
}
));
)
);
}

View file

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

View file

@ -9,15 +9,15 @@
# ifndef OLM_EXPORT
# ifdef olm_EXPORTS
/* We are building this library */
# define OLM_EXPORT
# define OLM_EXPORT __attribute__((visibility("default")))
# else
/* We are using this library */
# define OLM_EXPORT
# define OLM_EXPORT __attribute__((visibility("default")))
# endif
# endif
# ifndef OLM_NO_EXPORT
# define OLM_NO_EXPORT
# define OLM_NO_EXPORT __attribute__((visibility("hidden")))
# endif
#endif

36
javascript/index.d.ts vendored
View file

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

View file

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

View file

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

View file

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

View file

@ -44,7 +44,6 @@ function bzero(ptr, n) {
}
}
/** @constructor */
function Account() {
var size = Module['_olm_account_size']();
this.buf = malloc(size);
@ -245,7 +244,6 @@ Account.prototype['unpickle'] = restore_stack(function(key, pickle) {
}
});
/** @constructor */
function Session() {
var size = Module['_olm_session_size']();
this.buf = malloc(size);
@ -532,7 +530,6 @@ Session.prototype['describe'] = restore_stack(function() {
}
});
/** @constructor */
function Utility() {
var size = Module['_olm_utility_size']();
this.buf = malloc(size);

View file

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

View file

@ -1,4 +1,3 @@
/** @constructor */
function SAS() {
var size = Module['_olm_sas_size']();
var random_length = Module['_olm_create_sas_random_length']();

View file

@ -1,6 +1,6 @@
{
"name": "@matrix-org/olm",
"version": "3.2.16",
"version": "3.2.11",
"description": "An implementation of the Double Ratchet cryptographic ratchet",
"main": "olm.js",
"files": [
@ -31,5 +31,8 @@
"homepage": "https://gitlab.matrix.org/matrix-org/olm",
"devDependencies": {
"jasmine": "^3.0.0"
},
"publishConfig": {
"@matrix-org:registry":"https://gitlab.matrix.org/api/v4/projects/27/packages/npm/"
}
}

View file

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

View file

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

View file

@ -4498,7 +4498,7 @@ namespace {
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = {};
sa.sa_handler = handleSignal; // NOLINT
sa.sa_flags = SS_ONSTACK;
sa.sa_flags = SA_ONSTACK;
for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
}

View file

@ -1684,7 +1684,7 @@ namespace {
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = {};
sa.sa_handler = handleSignal; // NOLINT
sa.sa_flags = SS_ONSTACK;
sa.sa_flags = SA_ONSTACK;
for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
}

View file

@ -1,76 +0,0 @@
final: prev: {
olm-gcc-cmake = prev.gccStdenv.mkDerivation {
name = "olm_gcc_cmake";
src = ./..;
nativeBuildInputs = [ prev.cmake ];
doCheck = true;
checkPhase = ''
(cd tests && ctest . -j $NIX_BUILD_CORES)
'';
};
olm-clang-cmake = prev.clangStdenv.mkDerivation {
name = "olm_clang_cmake";
src = ./..;
nativeBuildInputs = [ prev.cmake ];
doCheck = true;
checkPhase = ''
(cd tests && ctest . -j $NIX_BUILD_CORES)
'';
};
olm-gcc-make = prev.gccStdenv.mkDerivation {
name = "olm";
src = ./..;
doCheck = true;
makeFlags = [ "PREFIX=$out" ];
};
olm-javascript = final.buildEmscriptenPackage {
pname = "olm_javascript";
inherit (builtins.fromJSON (builtins.readFile ../javascript/package.json)) version;
src = ./..;
nativeBuildInputs = with prev; [ gnumake python3 nodejs ];
postPatch = ''
patchShebangs .
'';
configurePhase = false;
buildPhase = ''
export EM_CACHE=$TMPDIR
make javascript/exported_functions.json
make js
'';
installPhase = ''
mkdir -p $out/javascript
cd javascript
echo sha256: > checksums.txt
sha256sum olm.js olm_legacy.js olm.wasm >> checksums.txt
echo sha512: >> checksums.txt
sha512sum olm.js olm_legacy.js olm.wasm >> checksums.txt
cp package.json olm.js olm.wasm olm_legacy.js index.d.ts README.md checksums.txt $out/javascript
cd ..
'';
checkPhase = ''
cd javascript
export HOME=$TMPDIR
ln -s ${final.node_modules}/node_modules ./node_modules
npm test
cd ..
'';
};
}

View file

@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
Name: olm
Description: implementation of the Double Ratchet cryptographic ratchet in C++

View file

@ -34,7 +34,7 @@ test:python:
image: docker.io/python:$PYTHON_VERSIONS
parallel:
matrix:
- PYTHON_VERSIONS: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
- PYTHON_VERSIONS: [ "3.6", "3.7", "3.8", "3.9" ]
script:
- pip install tox
- make headers

View file

@ -1,3 +1,5 @@
include include/olm/*.h
include include/olm/olm.h
include include/olm/pk.h
include include/olm/sas.h
include Makefile
include olm_build.py

View file

@ -15,18 +15,6 @@ found [here][6].
The full API reference can be found [here][7].
# Installation instructions
To install from the source package, you will need:
- cmake (recommended) or GNU make
- a C/C++ compiler
You can then run `pip install python-olm`.
This should work in UNIX-like environments, including macOS, and may work in
other environments too, but is known to not work yet in Windows.
# Accounts
Accounts create and hold the central identity of the Olm protocol, they consist of a fingerprint and identity
@ -169,5 +157,5 @@ Pickling works the same way as for peer-to-peer Olm sessions.
[3]: https://cffi.readthedocs.io/en/latest/
[4]: https://git.matrix.org/git/olm/about/docs/olm.rst
[5]: https://git.matrix.org/git/olm/about/docs/megolm.rst
[6]: https://matrix.org/docs/guides/end-to-end-encryption-implementation-guide
[6]: https://matrix.org/docs/guides/e2e_implementation.html
[7]: https://poljar.github.io/python-olm/html/index.html

View file

@ -1,35 +0,0 @@
#!/bin/bash
set -e
DIR=$(mktemp -d)
SRC=$(pwd)
echo "Making headers"
make headers
cd $DIR
echo "Copying python module"
cp -a $SRC/* .
mkdir -p libolm
echo "Cleaning sources"
make clean > /dev/null
cp -a $SRC/include .
echo "Copying libolm sources"
for src in cmake CMakeLists.txt common.mk include lib Makefile olm.pc.in src tests; do
cp -a $SRC/../$src libolm
done
find libolm -name \*~ -delete
find libolm -name \#\*\# -delete
echo "Building"
patch -p1 < $SRC/packaging.diff
python3 -m build -s
echo "Copying result"
mkdir -p $SRC/dist
cp dist/* $SRC/dist
echo "Cleaning up"
cd $SRC
rm -rf $DIR

View file

@ -0,0 +1,9 @@
__title__ = "python-olm"
__description__ = ("python CFFI bindings for the olm "
"cryptographic ratchet library")
__url__ = "https://github.com/poljar/python-olm"
__version__ = "3.2.11"
__author__ = "Damir Jelić"
__author_email__ = "poljar@termina.org.uk"
__license__ = "Apache 2.0"
__copyright__ = "Copyright 2018-2019 Damir Jelić"

View file

@ -23,6 +23,7 @@
This is designed for avoiding __del__.
"""
from __future__ import print_function
import sys
import traceback

View file

@ -32,6 +32,8 @@ import json
from builtins import bytes, super
from typing import AnyStr, Dict, Optional, Type
from future.utils import bytes_to_native_str
# pylint: disable=no-name-in-module
from _libolm import ffi, lib # type: ignore
@ -91,7 +93,8 @@ class Account(object):
if ret != lib.olm_error():
return
last_error = ffi.string((lib.olm_account_last_error(self._account))).decode()
last_error = bytes_to_native_str(
ffi.string((lib.olm_account_last_error(self._account))))
raise OlmAccountError(last_error)
@ -206,7 +209,7 @@ class Account(object):
for i in range(0, len(bytes_message)):
bytes_message[i] = 0
return ffi.unpack(out_buffer, out_length).decode()
return bytes_to_native_str(ffi.unpack(out_buffer, out_length))
@property
def max_one_time_keys(self):

View file

@ -28,6 +28,8 @@ Examples:
from builtins import bytes, super
from typing import AnyStr, Optional, Tuple, Type
from future.utils import bytes_to_native_str
# pylint: disable=no-name-in-module
from _libolm import ffi, lib # type: ignore
@ -169,9 +171,8 @@ class InboundGroupSession(object):
if ret != lib.olm_error():
return
last_error = ffi.string(
lib.olm_inbound_group_session_last_error(self._session)
).decode()
last_error = bytes_to_native_str(ffi.string(
lib.olm_inbound_group_session_last_error(self._session)))
raise OlmGroupSessionError(last_error)
@ -251,7 +252,7 @@ class InboundGroupSession(object):
id_length
)
self._check_error(ret)
return ffi.unpack(id_buffer, id_length).decode()
return bytes_to_native_str(ffi.unpack(id_buffer, id_length))
@property
def first_known_index(self):
@ -289,7 +290,7 @@ class InboundGroupSession(object):
message_index
)
self._check_error(ret)
export_str = ffi.unpack(export_buffer, export_length).decode()
export_str = bytes_to_native_str(ffi.unpack(export_buffer, export_length))
# clear out copies of the key
lib.memset(export_buffer, 0, export_length)
@ -372,9 +373,9 @@ class OutboundGroupSession(object):
if ret != lib.olm_error():
return
last_error = ffi.string(
last_error = bytes_to_native_str(ffi.string(
lib.olm_outbound_group_session_last_error(self._session)
).decode()
))
raise OlmGroupSessionError(last_error)
@ -482,7 +483,7 @@ class OutboundGroupSession(object):
for i in range(0, len(byte_plaintext)):
byte_plaintext[i] = 0
return ffi.unpack(message_buffer, message_length).decode()
return bytes_to_native_str(ffi.unpack(message_buffer, message_length))
@property
def id(self):
@ -498,7 +499,7 @@ class OutboundGroupSession(object):
)
self._check_error(ret)
return ffi.unpack(id_buffer, id_length).decode()
return bytes_to_native_str(ffi.unpack(id_buffer, id_length))
@property
def message_index(self):
@ -528,4 +529,4 @@ class OutboundGroupSession(object):
)
self._check_error(ret)
return ffi.unpack(key_buffer, key_length).decode()
return bytes_to_native_str(ffi.unpack(key_buffer, key_length))

View file

@ -36,6 +36,8 @@ Examples:
from builtins import super
from typing import AnyStr, Type
from future.utils import bytes_to_native_str
from _libolm import ffi, lib # type: ignore
from ._compat import URANDOM, to_bytearray, to_unicode_str
@ -114,9 +116,8 @@ class PkEncryption(object):
if ret != lib.olm_error():
return
last_error = ffi.string(
lib.olm_pk_encryption_last_error(self._pk_encryption)
).decode()
last_error = bytes_to_native_str(
ffi.string(lib.olm_pk_encryption_last_error(self._pk_encryption)))
raise PkEncryptionError(last_error)
@ -165,9 +166,12 @@ class PkEncryption(object):
byte_plaintext[i] = 0
message = PkMessage(
ffi.unpack(ephemeral_key, ephemeral_key_size).decode(),
ffi.unpack(mac, mac_length).decode(),
ffi.unpack(ciphertext, ciphertext_length).decode(),
bytes_to_native_str(
ffi.unpack(ephemeral_key, ephemeral_key_size)),
bytes_to_native_str(
ffi.unpack(mac, mac_length)),
bytes_to_native_str(
ffi.unpack(ciphertext, ciphertext_length))
)
return message
@ -213,19 +217,18 @@ class PkDecryption(object):
random_buffer, random_length
)
self._check_error(ret)
self.public_key: str = ffi.unpack(
self.public_key: str = bytes_to_native_str(ffi.unpack(
key_buffer,
key_length
).decode()
))
def _check_error(self, ret):
# type: (int) -> None
if ret != lib.olm_error():
return
last_error = ffi.string(
lib.olm_pk_decryption_last_error(self._pk_decryption)
).decode()
last_error = bytes_to_native_str(
ffi.string(lib.olm_pk_decryption_last_error(self._pk_decryption)))
raise PkDecryptionError(last_error)
@ -303,10 +306,10 @@ class PkDecryption(object):
for i in range(0, len(byte_key)):
byte_key[i] = 0
obj.public_key = ffi.unpack(
obj.public_key = bytes_to_native_str(ffi.unpack(
pubkey_buffer,
pubkey_length
).decode()
))
return obj
@ -408,14 +411,17 @@ class PkSigning(object):
self._check_error(ret)
self.public_key = ffi.unpack(pubkey_buffer, pubkey_length).decode()
self.public_key = bytes_to_native_str(
ffi.unpack(pubkey_buffer, pubkey_length)
)
def _check_error(self, ret):
# type: (int) -> None
if ret != lib.olm_error():
return
last_error = ffi.string(lib.olm_pk_signing_last_error(self._pk_signing)).decode()
last_error = bytes_to_native_str(
ffi.string(lib.olm_pk_signing_last_error(self._pk_signing)))
raise PkSigningError(last_error)
@ -450,4 +456,6 @@ class PkSigning(object):
signature_buffer, signature_length)
self._check_error(ret)
return ffi.unpack(signature_buffer, signature_length).decode()
return bytes_to_native_str(
ffi.unpack(signature_buffer, signature_length)
)

View file

@ -34,6 +34,8 @@ from builtins import bytes
from functools import wraps
from typing import Optional
from future.utils import bytes_to_native_str
from _libolm import ffi, lib
from ._compat import URANDOM, to_bytearray, to_bytes
@ -90,7 +92,8 @@ class Sas(object):
if ret != lib.olm_error():
return
last_error = ffi.string((lib.olm_sas_last_error(self._sas))).decode()
last_error = bytes_to_native_str(
ffi.string((lib.olm_sas_last_error(self._sas))))
raise OlmSasError(last_error)
@ -112,7 +115,7 @@ class Sas(object):
lib.olm_sas_get_pubkey(self._sas, pubkey_buffer, pubkey_length)
)
return ffi.unpack(pubkey_buffer, pubkey_length).decode()
return bytes_to_native_str(ffi.unpack(pubkey_buffer, pubkey_length))
@property
def other_key_set(self):
@ -205,7 +208,7 @@ class Sas(object):
mac_length
)
)
return ffi.unpack(mac_buffer, mac_length).decode()
return bytes_to_native_str(ffi.unpack(mac_buffer, mac_length))
def calculate_mac_fixed_base64(self, message, extra_info):
# type: (str, str) -> str
@ -239,7 +242,7 @@ class Sas(object):
mac_length
)
)
return ffi.unpack(mac_buffer, mac_length).decode()
return bytes_to_native_str(ffi.unpack(mac_buffer, mac_length))
def calculate_mac_long_kdf(self, message, extra_info):
# type: (str, str) -> str
@ -273,4 +276,4 @@ class Sas(object):
mac_length
)
)
return ffi.unpack(mac_buffer, mac_length).decode()
return bytes_to_native_str(ffi.unpack(mac_buffer, mac_length))

View file

@ -35,6 +35,8 @@ Examples:
from builtins import bytes, super
from typing import AnyStr, Optional, Type
from future.utils import bytes_to_native_str
# pylint: disable=no-name-in-module
from _libolm import ffi, lib # type: ignore
@ -144,7 +146,8 @@ class Session(object):
if ret != lib.olm_error():
return
last_error = ffi.string(lib.olm_session_last_error(self._session)).decode()
last_error = bytes_to_native_str(
ffi.string(lib.olm_session_last_error(self._session)))
raise OlmSessionError(last_error)
@ -257,16 +260,16 @@ class Session(object):
if message_type == lib.OLM_MESSAGE_TYPE_PRE_KEY:
return OlmPreKeyMessage(
ffi.unpack(
bytes_to_native_str(ffi.unpack(
ciphertext_buffer,
ciphertext_length
).decode())
)))
elif message_type == lib.OLM_MESSAGE_TYPE_MESSAGE:
return OlmMessage(
ffi.unpack(
bytes_to_native_str(ffi.unpack(
ciphertext_buffer,
ciphertext_length
).decode())
)))
else: # pragma: no cover
raise ValueError("Unknown message type")
@ -337,7 +340,7 @@ class Session(object):
self._check_error(
lib.olm_session_id(self._session, id_buffer, id_length)
)
return ffi.unpack(id_buffer, id_length).decode()
return bytes_to_native_str(ffi.unpack(id_buffer, id_length))
def matches(self, message, identity_key=None):
# type: (OlmPreKeyMessage, Optional[AnyStr]) -> bool
@ -404,7 +407,7 @@ class Session(object):
lib.olm_session_describe(
self._session, describe_buffer, buffer_length
)
return ffi.string(describe_buffer).decode()
return bytes_to_native_str(ffi.string(describe_buffer))
class InboundSession(Session):

View file

@ -33,6 +33,8 @@ Examples:
# pylint: disable=redefined-builtin,unused-import
from typing import AnyStr, Type
from future.utils import bytes_to_native_str
# pylint: disable=no-name-in-module
from _libolm import ffi, lib # type: ignore
@ -121,7 +123,7 @@ class _Utility(object):
cls._check_error(ret, OlmHashError)
return ffi.unpack(hash, hash_length).decode()
return bytes_to_native_str(ffi.unpack(hash, hash_length))
def ed25519_verify(key, message, signature):

View file

@ -15,6 +15,8 @@
# CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
from __future__ import unicode_literals
import os
import subprocess
@ -26,10 +28,18 @@ PATH = os.path.dirname(__file__)
DEVELOP = os.environ.get("DEVELOP")
compile_args = ["-I../include"]
link_args = ["-L../build"]
if DEVELOP and DEVELOP.lower() in ["yes", "true", "1"]:
link_args.append('-Wl,-rpath=../build')
# If libolm is compiled statically, we may need to link to the C++ standard
# library dynamically. This flag allows passing the required linker flag to do
# so.
CXX_LIB = os.environ.get("CXX_LIB")
if CXX_LIB:
link_args.append(CXX_LIB)
headers_build = subprocess.Popen("make headers", shell=True)
headers_build.wait()
@ -43,10 +53,8 @@ ffibuilder.set_source(
#include <olm/sas.h>
""",
libraries=["olm"],
library_dirs=[os.path.join("..", "build")],
extra_compile_args=compile_args,
source_extension=".cpp", # we need to link the C++ standard library, so use a C++ extension
)
extra_link_args=link_args)
with open(os.path.join(PATH, "include/olm/error.h")) as f:
ffibuilder.cdef(f.read(), override=True)

View file

@ -1,56 +0,0 @@
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,3 +1,8 @@
include include/olm/*.h
-include Makefile
include olm_build.py
+include libolm/*
+include libolm/cmake/*
+include libolm/include/olm/*
+recursive-include libolm/lib *
+include libolm/src/*
+recursive-include libolm/tests *
--- a/olm_build.py
+++ b/olm_build.py
@@ -25,12 +25,29 @@
DEVELOP = os.environ.get("DEVELOP")
-compile_args = ["-I../include"]
+compile_args = ["-Ilibolm/include"]
if DEVELOP and DEVELOP.lower() in ["yes", "true", "1"]:
link_args.append('-Wl,-rpath=../build')
-headers_build = subprocess.Popen("make headers", shell=True)
-headers_build.wait()
+# Try to build with cmake first, fall back to GNU make
+try:
+ subprocess.run(
+ ["cmake", ".", "-Bbuild", "-DBUILD_SHARED_LIBS=NO"],
+ cwd="libolm", check=True,
+ )
+ subprocess.run(
+ ["cmake", "--build", "build"],
+ cwd="libolm", check=True,
+ )
+except FileNotFoundError:
+ try:
+ # try "gmake" first because some systems have a non-GNU make
+ # installed as "make"
+ subprocess.run(["gmake", "static"], cwd="libolm", check=True)
+ except FileNotFoundError:
+ # some systems have GNU make installed without the leading "g"
+ # so give that a try (though this may fail if it isn't GNU make)
+ subprocess.run(["make", "static"], cwd="libolm", check=True)
ffibuilder.set_source(
@@ -43,7 +60,7 @@
#include <olm/sas.h>
""",
libraries=["olm"],
- library_dirs=[os.path.join("..", "build")],
+ library_dirs=[os.path.join("libolm", "build")],
extra_compile_args=compile_args,
source_extension=".cpp", # we need to link the C++ standard library, so use a C++ extension
)

View file

@ -1,22 +0,0 @@
[build-system]
requires = ["setuptools", "cffi>=1.0.0"]
build-backend = "setuptools.build_meta"
[project]
name = "python-olm"
version = "3.2.16"
description = "python CFFI bindings for the olm cryptographic ratchet library"
authors = [{name = "Damir Jelić", email = "poljar@termina.org.uk"}]
license = {text = "Apache-2.0"}
readme = "README.md"
classifiers = [
"License :: OSI Approved :: Apache Software License",
"Topic :: Communications",
]
dependencies = ["cffi>=1.0.0"]
[project.urls]
homepage = "https://gitlab.matrix.org/matrix-org/olm/-/tree/master/python"
[tool.setuptools]
packages = [ "olm" ]

View file

@ -1,2 +1,3 @@
future
cffi
typing

View file

@ -3,3 +3,6 @@ testpaths = tests
flake8-ignore =
olm/*.py F401
tests/*.py W503
[coverage:run]
omit=olm/__version__.py

View file

@ -1,6 +1,31 @@
# -*- coding: utf-8 -*-
import os
from codecs import open
from setuptools import setup
here = os.path.abspath(os.path.dirname(__file__))
about = {}
with open(os.path.join(here, "olm", "__version__.py"), "r", "utf-8") as f:
exec(f.read(), about)
setup(
cffi_modules=["olm_build.py:ffibuilder"]
name=about["__title__"],
version=about["__version__"],
description=about["__description__"],
author=about["__author__"],
author_email=about["__author_email__"],
url=about["__url__"],
license=about["__license__"],
packages=["olm"],
setup_requires=["cffi>=1.0.0"],
cffi_modules=["olm_build.py:ffibuilder"],
install_requires=[
"cffi>=1.0.0",
"future",
"typing;python_version<'3.5'"
],
zip_safe=False
)

View file

@ -1,6 +1,8 @@
import base64
import hashlib
from future.utils import bytes_to_native_str
from olm import sha256
from olm._compat import to_bytes
@ -17,7 +19,7 @@ class TestClass(object):
hashlib.sha256(to_bytes(input1)).digest()
)
hashlib_hash = hashlib_hash[:-1].decode()
hashlib_hash = bytes_to_native_str(hashlib_hash[:-1])
assert first_hash != second_hash
assert hashlib_hash == first_hash

View file

@ -6,7 +6,7 @@ envlist = py27,py36,pypy,{py2,py3}-cov,coverage
deps = -rrequirements.txt
-rtest-requirements.txt
passenv = TOXENV,CI,TRAVIS,TRAVIS_*
passenv = TOXENV CI TRAVIS TRAVIS_*
commands = pytest --benchmark-disable
usedevelop = True

View file

@ -437,7 +437,7 @@ void olm::Session::describe(char *describe_buffer, size_t buflen) {
size = snprintf(
describe_buffer, remaining,
"sender chain index: %lu ", ratchet.sender_chain[0].chain_key.index
"sender chain index: %d ", ratchet.sender_chain[0].chain_key.index
);
CHECK_SIZE_AND_ADVANCE;
@ -447,7 +447,7 @@ void olm::Session::describe(char *describe_buffer, size_t buflen) {
for (size_t i = 0; i < ratchet.receiver_chains.size(); ++i) {
size = snprintf(
describe_buffer, remaining,
" %lu", ratchet.receiver_chains[i].chain_key.index
" %d", ratchet.receiver_chains[i].chain_key.index
);
CHECK_SIZE_AND_ADVANCE;
}
@ -458,7 +458,7 @@ void olm::Session::describe(char *describe_buffer, size_t buflen) {
for (size_t i = 0; i < ratchet.skipped_message_keys.size(); ++i) {
size = snprintf(
describe_buffer, remaining,
" %lu", ratchet.skipped_message_keys[i].message_key.index
" %d", ratchet.skipped_message_keys[i].message_key.index
);
CHECK_SIZE_AND_ADVANCE;
}

View file

@ -4498,7 +4498,7 @@ namespace {
sigaltstack(&sigStack, &oldSigStack);
struct sigaction sa = {};
sa.sa_handler = handleSignal; // NOLINT
sa.sa_flags = SS_ONSTACK;
sa.sa_flags = SA_ONSTACK;
for(std::size_t i = 0; i < DOCTEST_COUNTOF(signalDefs); ++i) {
sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
}