Merge branch 'master' into poljar
This commit is contained in:
commit
5cf074d337
33 changed files with 562 additions and 210 deletions
27
.circleci/config.yml
Normal file
27
.circleci/config.yml
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
version: 2
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
docker:
|
||||||
|
- image: trzeci/emscripten
|
||||||
|
|
||||||
|
working_directory: ~/repo
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: Native Compile
|
||||||
|
command: make
|
||||||
|
- run:
|
||||||
|
name: Native Tests
|
||||||
|
command: make test
|
||||||
|
- run:
|
||||||
|
name: JS Compile
|
||||||
|
command: make js
|
||||||
|
- run:
|
||||||
|
name: Install JS Deps
|
||||||
|
working_directory: ~/repo/javascript
|
||||||
|
command: npm install
|
||||||
|
- run:
|
||||||
|
name: JS Tests
|
||||||
|
working_directory: ~/repo/javascript
|
||||||
|
command: npm run test
|
|
@ -1,3 +1,15 @@
|
||||||
|
Changes in latest release
|
||||||
|
|
||||||
|
BREAKING CHANGE: Olm now uses WebAssembly which means it needs
|
||||||
|
to load the wasm file asynchronously, and therefore needs to be
|
||||||
|
started up asynchronously. The imported module now has an init()
|
||||||
|
method which returns a promise. The library cannot be used until
|
||||||
|
this promise resolves. It will reject if the library fails to start.
|
||||||
|
|
||||||
|
olm_pk_generate_key() and olm_pk_generate_key_random_length() have
|
||||||
|
been removed: to generate a random key, use olm_pk_key_from_private()
|
||||||
|
with random bytes as the private key.
|
||||||
|
|
||||||
Changes in `2.3.0 <http://matrix.org/git/olm/commit/?h=2.3.0>`_
|
Changes in `2.3.0 <http://matrix.org/git/olm/commit/?h=2.3.0>`_
|
||||||
|
|
||||||
This release includes the following changes since 2.2.2:
|
This release includes the following changes since 2.2.2:
|
||||||
|
|
99
Makefile
99
Makefile
|
@ -14,12 +14,25 @@ AFL_CC = afl-gcc
|
||||||
AFL_CXX = afl-g++
|
AFL_CXX = afl-g++
|
||||||
AR = ar
|
AR = ar
|
||||||
|
|
||||||
RELEASE_TARGET := $(BUILD_DIR)/libolm.so.$(VERSION)
|
UNAME := $(shell uname)
|
||||||
|
ifeq ($(UNAME),Darwin)
|
||||||
|
SO := dylib
|
||||||
|
OLM_LDFLAGS :=
|
||||||
|
else
|
||||||
|
SO := so
|
||||||
|
OLM_LDFLAGS := -Wl,-soname,libolm.so.$(MAJOR) \
|
||||||
|
-Wl,--version-script,version_script.ver
|
||||||
|
endif
|
||||||
|
|
||||||
|
RELEASE_TARGET := $(BUILD_DIR)/libolm.$(SO).$(VERSION)
|
||||||
STATIC_RELEASE_TARGET := $(BUILD_DIR)/libolm.a
|
STATIC_RELEASE_TARGET := $(BUILD_DIR)/libolm.a
|
||||||
DEBUG_TARGET := $(BUILD_DIR)/libolm_debug.so.$(VERSION)
|
DEBUG_TARGET := $(BUILD_DIR)/libolm_debug.$(SO).$(VERSION)
|
||||||
JS_TARGET := javascript/olm.js
|
JS_WASM_TARGET := javascript/olm.js
|
||||||
|
JS_ASMJS_TARGET := javascript/olm_legacy.js
|
||||||
|
|
||||||
JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json
|
JS_EXPORTED_FUNCTIONS := javascript/exported_functions.json
|
||||||
|
JS_EXTRA_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
|
PUBLIC_HEADERS := include/olm/olm.h include/olm/outbound_group_session.h include/olm/inbound_group_session.h include/olm/pk.h
|
||||||
|
|
||||||
|
@ -39,11 +52,22 @@ FUZZER_BINARIES := $(addprefix $(BUILD_DIR)/,$(basename $(FUZZER_SOURCES)))
|
||||||
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))
|
||||||
|
|
||||||
|
# pre & post are the js-pre/js-post options to emcc.
|
||||||
|
# They are injected inside the modularised code and
|
||||||
|
# processed by the optimiser.
|
||||||
JS_PRE := $(wildcard javascript/*pre.js)
|
JS_PRE := $(wildcard javascript/*pre.js)
|
||||||
JS_POST := javascript/olm_outbound_group_session.js \
|
JS_POST := javascript/olm_outbound_group_session.js \
|
||||||
javascript/olm_inbound_group_session.js \
|
javascript/olm_inbound_group_session.js \
|
||||||
javascript/olm_pk.js \
|
javascript/olm_pk.js \
|
||||||
javascript/olm_post.js
|
javascript/olm_post.js
|
||||||
|
|
||||||
|
# The prefix & suffix are just added onto the start & end
|
||||||
|
# of what comes out emcc, so are outside of the modularised
|
||||||
|
# code and not seen by the opimiser.
|
||||||
|
JS_PREFIX := javascript/olm_prefix.js
|
||||||
|
JS_SUFFIX := javascript/olm_suffix.js
|
||||||
|
|
||||||
DOCS := tracing/README.html \
|
DOCS := tracing/README.html \
|
||||||
docs/megolm.html \
|
docs/megolm.html \
|
||||||
docs/olm.html \
|
docs/olm.html \
|
||||||
|
@ -60,11 +84,23 @@ CFLAGS += -Wall -Werror -std=c99 -fPIC
|
||||||
CXXFLAGS += -Wall -Werror -std=c++11 -fPIC
|
CXXFLAGS += -Wall -Werror -std=c++11 -fPIC
|
||||||
LDFLAGS += -Wall -Werror
|
LDFLAGS += -Wall -Werror
|
||||||
|
|
||||||
EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0
|
EMCCFLAGS = --closure 1 --memory-init-file 0 -s NO_FILESYSTEM=1 -s INVOKE_RUN=0 -s MODULARIZE=1
|
||||||
# NO_BROWSER is kept for compatibility with emscripten 1.35.24, but is no
|
# NO_BROWSER is kept for compatibility with emscripten 1.35.24, but is no
|
||||||
# longer needed.
|
# longer needed.
|
||||||
EMCCFLAGS += -s NO_BROWSER=1
|
EMCCFLAGS += -s NO_BROWSER=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
|
||||||
|
# a 64K event (enough to store the ciphertext and the plaintext, bearing in
|
||||||
|
# mind that the plaintext can only be 48K because base64). We also have about
|
||||||
|
# 36K of statics. So let's have 256K of memory.
|
||||||
|
# (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
|
||||||
|
# we don't use this for the legacy build.)
|
||||||
|
EMCCFLAGS_WASM += -s TOTAL_STACK=65536 -s TOTAL_MEMORY=262144
|
||||||
|
|
||||||
|
EMCCFLAGS_ASMJS += -s WASM=0
|
||||||
|
|
||||||
EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c
|
EMCC.c = $(EMCC) $(CFLAGS) $(CPPFLAGS) -c
|
||||||
EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c
|
EMCC.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||||
EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS)
|
EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS)
|
||||||
|
@ -99,7 +135,8 @@ $(FUZZER_DEBUG_BINARIES): LDFLAGS += $(DEBUG_OPTIMIZE_FLAGS)
|
||||||
|
|
||||||
$(JS_OBJECTS): CFLAGS += $(JS_OPTIMIZE_FLAGS)
|
$(JS_OBJECTS): CFLAGS += $(JS_OPTIMIZE_FLAGS)
|
||||||
$(JS_OBJECTS): CXXFLAGS += $(JS_OPTIMIZE_FLAGS)
|
$(JS_OBJECTS): CXXFLAGS += $(JS_OPTIMIZE_FLAGS)
|
||||||
$(JS_TARGET): LDFLAGS += $(JS_OPTIMIZE_FLAGS)
|
$(JS_WASM_TARGET): LDFLAGS += $(JS_OPTIMIZE_FLAGS)
|
||||||
|
$(JS_ASMJS_TARGET): LDFLAGS += $(JS_OPTIMIZE_FLAGS)
|
||||||
|
|
||||||
### Fix to make mkdir work on windows and linux
|
### Fix to make mkdir work on windows and linux
|
||||||
ifeq ($(shell echo "check_quotes"),"check_quotes")
|
ifeq ($(shell echo "check_quotes"),"check_quotes")
|
||||||
|
@ -121,21 +158,19 @@ lib: $(RELEASE_TARGET)
|
||||||
|
|
||||||
$(RELEASE_TARGET): $(RELEASE_OBJECTS)
|
$(RELEASE_TARGET): $(RELEASE_OBJECTS)
|
||||||
$(CXX) $(LDFLAGS) --shared -fPIC \
|
$(CXX) $(LDFLAGS) --shared -fPIC \
|
||||||
-Wl,-soname,libolm.so.$(MAJOR) \
|
$(OLM_LDFLAGS) \
|
||||||
-Wl,--version-script,version_script.ver \
|
|
||||||
$(OUTPUT_OPTION) $(RELEASE_OBJECTS)
|
$(OUTPUT_OPTION) $(RELEASE_OBJECTS)
|
||||||
ln -sf libolm.so.$(VERSION) $(BUILD_DIR)/libolm.so.$(MAJOR)
|
ln -sf libolm.$(SO).$(VERSION) $(BUILD_DIR)/libolm.$(SO).$(MAJOR)
|
||||||
ln -sf libolm.so.$(VERSION) $(BUILD_DIR)/libolm.so
|
ln -sf libolm.$(SO).$(VERSION) $(BUILD_DIR)/libolm.$(SO)
|
||||||
|
|
||||||
debug: $(DEBUG_TARGET)
|
debug: $(DEBUG_TARGET)
|
||||||
.PHONY: debug
|
.PHONY: debug
|
||||||
|
|
||||||
$(DEBUG_TARGET): $(DEBUG_OBJECTS)
|
$(DEBUG_TARGET): $(DEBUG_OBJECTS)
|
||||||
$(CXX) $(LDFLAGS) --shared -fPIC \
|
$(CXX) $(LDFLAGS) --shared -fPIC \
|
||||||
-Wl,-soname,libolm_debug.so.$(MAJOR) \
|
$(OLM_LDFLAGS) \
|
||||||
-Wl,--version-script,version_script.ver \
|
|
||||||
$(OUTPUT_OPTION) $(DEBUG_OBJECTS)
|
$(OUTPUT_OPTION) $(DEBUG_OBJECTS)
|
||||||
ln -sf libolm_debug.so.$(VERSION) $(BUILD_DIR)/libolm_debug.so.$(MAJOR)
|
ln -sf libolm_debug.$(SO).$(VERSION) $(BUILD_DIR)/libolm_debug.$(SO).$(MAJOR)
|
||||||
|
|
||||||
static: $(STATIC_RELEASE_TARGET)
|
static: $(STATIC_RELEASE_TARGET)
|
||||||
.PHONY: static
|
.PHONY: static
|
||||||
|
@ -143,15 +178,35 @@ static: $(STATIC_RELEASE_TARGET)
|
||||||
$(STATIC_RELEASE_TARGET): $(RELEASE_OBJECTS)
|
$(STATIC_RELEASE_TARGET): $(RELEASE_OBJECTS)
|
||||||
$(AR) rcs $@ $^
|
$(AR) rcs $@ $^
|
||||||
|
|
||||||
js: $(JS_TARGET)
|
js: $(JS_WASM_TARGET) $(JS_ASMJS_TARGET)
|
||||||
.PHONY: js
|
.PHONY: js
|
||||||
|
|
||||||
$(JS_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS)
|
# Note that the output file we give to emcc determines the name of the
|
||||||
$(EMCC_LINK) \
|
# wasm file baked into the js, hence messing around outputting to olm.js
|
||||||
|
# and then renaming it.
|
||||||
|
$(JS_WASM_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) $(JS_PREFIX) $(JS_SUFFIX)
|
||||||
|
EMCC_CLOSURE_ARGS="--externs $(JS_EXTERNS)" $(EMCC_LINK) \
|
||||||
|
$(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)) \
|
||||||
-s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \
|
-s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \
|
||||||
|
-s "EXTRA_EXPORTED_RUNTIME_METHODS=$(JS_EXTRA_EXPORTED_RUNTIME_METHODS)" \
|
||||||
$(JS_OBJECTS) -o $@
|
$(JS_OBJECTS) -o $@
|
||||||
|
mv $@ javascript/olmtmp.js
|
||||||
|
cat $(JS_PREFIX) javascript/olmtmp.js $(JS_SUFFIX) > $@
|
||||||
|
rm javascript/olmtmp.js
|
||||||
|
|
||||||
|
$(JS_ASMJS_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS) $(JS_PREFIX) $(JS_SUFFIX)
|
||||||
|
EMCC_CLOSURE_ARGS="--externs $(JS_EXTERNS)" $(EMCC_LINK) \
|
||||||
|
$(EMCCFLAGS_ASMJS) \
|
||||||
|
$(foreach f,$(JS_PRE),--pre-js $(f)) \
|
||||||
|
$(foreach f,$(JS_POST),--post-js $(f)) \
|
||||||
|
-s "EXPORTED_FUNCTIONS=@$(JS_EXPORTED_FUNCTIONS)" \
|
||||||
|
-s "EXTRA_EXPORTED_RUNTIME_METHODS=$(JS_EXTRA_EXPORTED_RUNTIME_METHODS)" \
|
||||||
|
$(JS_OBJECTS) -o $@
|
||||||
|
mv $@ javascript/olmtmp.js
|
||||||
|
cat $(JS_PREFIX) javascript/olmtmp.js $(JS_SUFFIX) > $@
|
||||||
|
rm javascript/olmtmp.js
|
||||||
|
|
||||||
build_tests: $(TEST_BINARIES)
|
build_tests: $(TEST_BINARIES)
|
||||||
|
|
||||||
|
@ -165,7 +220,7 @@ fuzzers: $(FUZZER_BINARIES) $(FUZZER_DEBUG_BINARIES)
|
||||||
.PHONY: fuzzers
|
.PHONY: fuzzers
|
||||||
|
|
||||||
$(JS_EXPORTED_FUNCTIONS): $(PUBLIC_HEADERS)
|
$(JS_EXPORTED_FUNCTIONS): $(PUBLIC_HEADERS)
|
||||||
perl -MJSON -ne '$$f{"_$$1"}=1 if /(olm_[^( ]*)\(/; END { @f=sort keys %f; print encode_json \@f }' $^ > $@.tmp
|
./exports.py $^ > $@.tmp
|
||||||
mv $@.tmp $@
|
mv $@.tmp $@
|
||||||
|
|
||||||
all: test js lib debug doc
|
all: test js lib debug doc
|
||||||
|
@ -178,16 +233,16 @@ install-headers: $(PUBLIC_HEADERS)
|
||||||
|
|
||||||
install-debug: debug install-headers
|
install-debug: debug install-headers
|
||||||
test -d $(DESTDIR)$(PREFIX)/lib || $(call mkdir,$(DESTDIR)$(PREFIX)/lib)
|
test -d $(DESTDIR)$(PREFIX)/lib || $(call mkdir,$(DESTDIR)$(PREFIX)/lib)
|
||||||
install -Dm755 $(DEBUG_TARGET) $(DESTDIR)$(PREFIX)/lib/libolm_debug.so.$(VERSION)
|
install -Dm755 $(DEBUG_TARGET) $(DESTDIR)$(PREFIX)/lib/libolm_debug.$(SO).$(VERSION)
|
||||||
ln -s libolm_debug.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm_debug.so.$(MAJOR)
|
ln -s libolm_debug.$(SO).$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm_debug.$(SO).$(MAJOR)
|
||||||
ln -s libolm_debug.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm_debug.so
|
ln -s libolm_debug.$(SO).$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm_debug.$(SO)
|
||||||
.PHONY: install-debug
|
.PHONY: install-debug
|
||||||
|
|
||||||
install: lib install-headers
|
install: lib install-headers
|
||||||
test -d $(DESTDIR)$(PREFIX)/lib || $(call mkdir,$(DESTDIR)$(PREFIX)/lib)
|
test -d $(DESTDIR)$(PREFIX)/lib || $(call mkdir,$(DESTDIR)$(PREFIX)/lib)
|
||||||
install -Dm755 $(RELEASE_TARGET) $(DESTDIR)$(PREFIX)/lib/libolm.so.$(VERSION)
|
install -Dm755 $(RELEASE_TARGET) $(DESTDIR)$(PREFIX)/lib/libolm.$(SO).$(VERSION)
|
||||||
ln -s libolm.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm.so.$(MAJOR)
|
ln -s libolm.$(SO).$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm.$(SO).$(MAJOR)
|
||||||
ln -s libolm.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm.so
|
ln -s libolm.$(SO).$(VERSION) $(DESTDIR)$(PREFIX)/lib/libolm.$(SO)
|
||||||
.PHONY: install
|
.PHONY: install
|
||||||
|
|
||||||
clean:;
|
clean:;
|
||||||
|
|
|
@ -31,6 +31,9 @@ To build the javascript bindings, install emscripten from http://kripken.github.
|
||||||
|
|
||||||
make js
|
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:
|
To build the android project for Android bindings, run:
|
||||||
|
|
||||||
.. code:: bash
|
.. code:: bash
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to create an inbound <a href="http://matrix.org/docs/guides/e2e_implementation.html#handling-an-m-room-key-event">Megolm session</a>.<br>
|
* Class used to create an inbound <a href="http://matrix.org/docs/guides/e2e_implementation.html#handling-an-m-room-key-event">Megolm session</a>.<br>
|
||||||
* Counter part of the outbound group session {@link OlmOutboundGroupSession}, this class decrypts the messages sent by the outbound side.
|
* Counter part of the outbound group session {@link OlmOutboundGroupSession}, this class decrypts the messages sent by the outbound side.
|
||||||
|
@ -236,7 +238,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
|
||||||
* In case of error, null is returned and an error message description is provided in aErrorMsg.
|
* In case of error, null is returned and an error message description is provided in aErrorMsg.
|
||||||
* @param aEncryptedMsg the message to be decrypted
|
* @param aEncryptedMsg the message to be decrypted
|
||||||
* @return the decrypted message information
|
* @return the decrypted message information
|
||||||
* @exception OlmException teh failure reason
|
* @exception OlmException the failure reason
|
||||||
*/
|
*/
|
||||||
public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws OlmException {
|
public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws OlmException {
|
||||||
DecryptMessageResult result = new DecryptMessageResult();
|
DecryptMessageResult result = new DecryptMessageResult();
|
||||||
|
@ -246,6 +248,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
|
||||||
|
|
||||||
if (null != decryptedMessageBuffer) {
|
if (null != decryptedMessageBuffer) {
|
||||||
result.mDecryptedMessage = new String(decryptedMessageBuffer, "UTF-8");
|
result.mDecryptedMessage = new String(decryptedMessageBuffer, "UTF-8");
|
||||||
|
Arrays.fill(decryptedMessageBuffer, (byte) 0);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage());
|
Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage());
|
||||||
|
|
|
@ -26,6 +26,8 @@ import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class used to create an outbound a <a href="http://matrix.org/docs/guides/e2e_implementation.html#starting-a-megolm-session">Megolm session</a>.<br>
|
* Class used to create an outbound a <a href="http://matrix.org/docs/guides/e2e_implementation.html#starting-a-megolm-session">Megolm session</a>.<br>
|
||||||
* To send a first message in an encrypted room, the client should start a new outbound Megolm session.
|
* To send a first message in an encrypted room, the client should start a new outbound Megolm session.
|
||||||
|
@ -166,7 +168,9 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser
|
||||||
|
|
||||||
if (!TextUtils.isEmpty(aClearMsg)) {
|
if (!TextUtils.isEmpty(aClearMsg)) {
|
||||||
try {
|
try {
|
||||||
byte[] encryptedBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8"));
|
byte[] clearMsgBuffer = aClearMsg.getBytes("UTF-8");
|
||||||
|
byte[] encryptedBuffer = encryptMessageJni(clearMsgBuffer);
|
||||||
|
Arrays.fill(clearMsgBuffer, (byte) 0);
|
||||||
|
|
||||||
if (null != encryptedBuffer) {
|
if (null != encryptedBuffer) {
|
||||||
retValue = new String(encryptedBuffer , "UTF-8");
|
retValue = new String(encryptedBuffer , "UTF-8");
|
||||||
|
|
|
@ -18,6 +18,8 @@ package org.matrix.olm;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class OlmPkDecryption {
|
public class OlmPkDecryption {
|
||||||
private static final String LOG_TAG = "OlmPkDecryption";
|
private static final String LOG_TAG = "OlmPkDecryption";
|
||||||
|
|
||||||
|
@ -67,7 +69,10 @@ public class OlmPkDecryption {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new String(decryptJni(aMessage), "UTF-8");
|
byte[] plaintextBuffer = decryptJni(aMessage);
|
||||||
|
String plaintext = new String(plaintextBuffer, "UTF-8");
|
||||||
|
Arrays.fill(plaintextBuffer, (byte) 0);
|
||||||
|
return plaintext;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(LOG_TAG, "## pkDecrypt(): failed " + e.getMessage());
|
Log.e(LOG_TAG, "## pkDecrypt(): failed " + e.getMessage());
|
||||||
throw new OlmException(OlmException.EXCEPTION_CODE_PK_DECRYPTION_DECRYPT, e.getMessage());
|
throw new OlmException(OlmException.EXCEPTION_CODE_PK_DECRYPTION_DECRYPT, e.getMessage());
|
||||||
|
|
|
@ -18,6 +18,8 @@ package org.matrix.olm;
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class OlmPkEncryption {
|
public class OlmPkEncryption {
|
||||||
private static final String LOG_TAG = "OlmPkEncryption";
|
private static final String LOG_TAG = "OlmPkEncryption";
|
||||||
|
|
||||||
|
@ -72,7 +74,9 @@ public class OlmPkEncryption {
|
||||||
OlmPkMessage encryptedMsgRetValue = new OlmPkMessage();
|
OlmPkMessage encryptedMsgRetValue = new OlmPkMessage();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] ciphertextBuffer = encryptJni(aPlaintext.getBytes("UTF-8"), encryptedMsgRetValue);
|
byte[] plaintextBuffer = aPlaintext.getBytes("UTF-8");
|
||||||
|
byte[] ciphertextBuffer = encryptJni(plaintextBuffer, encryptedMsgRetValue);
|
||||||
|
Arrays.fill(plaintextBuffer, (byte) 0);
|
||||||
|
|
||||||
if (null != ciphertextBuffer) {
|
if (null != ciphertextBuffer) {
|
||||||
encryptedMsgRetValue.mCipherText = new String(ciphertextBuffer, "UTF-8");
|
encryptedMsgRetValue.mCipherText = new String(ciphertextBuffer, "UTF-8");
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.io.ObjectInputStream;
|
||||||
import java.io.ObjectOutputStream;
|
import java.io.ObjectOutputStream;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Session class used to create Olm sessions in conjunction with {@link OlmAccount} class.<br>
|
* Session class used to create Olm sessions in conjunction with {@link OlmAccount} class.<br>
|
||||||
* Olm session is used to encrypt data between devices, especially to create Olm group sessions (see {@link OlmOutboundGroupSession} and {@link OlmInboundGroupSession}).<br>
|
* Olm session is used to encrypt data between devices, especially to create Olm group sessions (see {@link OlmOutboundGroupSession} and {@link OlmInboundGroupSession}).<br>
|
||||||
|
@ -295,7 +297,9 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
|
||||||
OlmMessage encryptedMsgRetValue = new OlmMessage();
|
OlmMessage encryptedMsgRetValue = new OlmMessage();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
byte[] encryptedMessageBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue);
|
byte[] clearMsgBuffer = aClearMsg.getBytes("UTF-8");
|
||||||
|
byte[] encryptedMessageBuffer = encryptMessageJni(clearMsgBuffer, encryptedMsgRetValue);
|
||||||
|
Arrays.fill(clearMsgBuffer, (byte) 0);
|
||||||
|
|
||||||
if (null != encryptedMessageBuffer) {
|
if (null != encryptedMessageBuffer) {
|
||||||
encryptedMsgRetValue.mCipherText = new String(encryptedMessageBuffer, "UTF-8");
|
encryptedMsgRetValue.mCipherText = new String(encryptedMessageBuffer, "UTF-8");
|
||||||
|
@ -330,7 +334,10 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return new String(decryptMessageJni(aEncryptedMsg), "UTF-8");
|
byte[] plaintextBuffer = decryptMessageJni(aEncryptedMsg);
|
||||||
|
String plaintext = new String(plaintextBuffer, "UTF-8");
|
||||||
|
Arrays.fill(plaintextBuffer, (byte) 0);
|
||||||
|
return plaintext;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e(LOG_TAG, "## decryptMessage(): failed " + e.getMessage());
|
Log.e(LOG_TAG, "## decryptMessage(): failed " + e.getMessage());
|
||||||
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage());
|
throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage());
|
||||||
|
|
|
@ -297,6 +297,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE
|
||||||
|
|
||||||
OlmOutboundGroupSession *sessionPtr = NULL;
|
OlmOutboundGroupSession *sessionPtr = NULL;
|
||||||
jbyte* clearMsgPtr = NULL;
|
jbyte* clearMsgPtr = NULL;
|
||||||
|
jboolean clearMsgIsCopied = JNI_FALSE;
|
||||||
|
|
||||||
if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
|
if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
|
||||||
{
|
{
|
||||||
|
@ -308,7 +309,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE
|
||||||
LOGE(" ## encryptMessageJni(): failure - invalid clear message");
|
LOGE(" ## encryptMessageJni(): failure - invalid clear message");
|
||||||
errorMessage = "invalid clear message";
|
errorMessage = "invalid clear message";
|
||||||
}
|
}
|
||||||
else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, NULL)))
|
else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, &clearMsgIsCopied)))
|
||||||
{
|
{
|
||||||
LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM");
|
LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM");
|
||||||
errorMessage = "clear message JNI allocation OOM";
|
errorMessage = "clear message JNI allocation OOM";
|
||||||
|
@ -359,6 +360,10 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE
|
||||||
// free alloc
|
// free alloc
|
||||||
if (clearMsgPtr)
|
if (clearMsgPtr)
|
||||||
{
|
{
|
||||||
|
if (clearMsgIsCopied)
|
||||||
|
{
|
||||||
|
memset(clearMsgPtr, 0, (size_t)env->GetArrayLength(aClearMsgBuffer));
|
||||||
|
}
|
||||||
env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT);
|
env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,10 @@ OlmPkEncryption * initializePkEncryptionMemory()
|
||||||
{
|
{
|
||||||
// init encryption object
|
// init encryption object
|
||||||
encryptionPtr = olm_pk_encryption(encryptionPtr);
|
encryptionPtr = olm_pk_encryption(encryptionPtr);
|
||||||
LOGD("## initializePkEncryptionMemory(): success - OLM encryption size=%lu",static_cast<long unsigned int>(encryptionSize));
|
LOGD(
|
||||||
|
"## initializePkEncryptionMemory(): success - OLM encryption size=%lu",
|
||||||
|
static_cast<long unsigned int>(encryptionSize)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -53,7 +56,10 @@ JNIEXPORT jlong OLM_PK_ENCRYPTION_FUNC_DEF(createNewPkEncryptionJni)(JNIEnv *env
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGD("## createNewPkEncryptionJni(): success - OLM encryption created");
|
LOGD("## createNewPkEncryptionJni(): success - OLM encryption created");
|
||||||
LOGD("## createNewPkEncryptionJni(): encryptionPtr=%p (jlong)(intptr_t)encryptionPtr=%lld", encryptionPtr, (jlong)(intptr_t)encryptionPtr);
|
LOGD(
|
||||||
|
"## createNewPkEncryptionJni(): encryptionPtr=%p (jlong)(intptr_t)encryptionPtr=%lld",
|
||||||
|
encryptionPtr, (jlong)(intptr_t)encryptionPtr
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorMessage)
|
if (errorMessage)
|
||||||
|
@ -93,8 +99,9 @@ JNIEXPORT void OLM_PK_ENCRYPTION_FUNC_DEF(releasePkEncryptionJni)(JNIEnv *env, j
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT void OLM_PK_ENCRYPTION_FUNC_DEF(setRecipientKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer)
|
JNIEXPORT void OLM_PK_ENCRYPTION_FUNC_DEF(setRecipientKeyJni)(
|
||||||
{
|
JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer
|
||||||
|
) {
|
||||||
const char *errorMessage = NULL;
|
const char *errorMessage = NULL;
|
||||||
jbyte *keyPtr = NULL;
|
jbyte *keyPtr = NULL;
|
||||||
|
|
||||||
|
@ -116,10 +123,13 @@ JNIEXPORT void OLM_PK_ENCRYPTION_FUNC_DEF(setRecipientKeyJni)(JNIEnv *env, jobje
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(olm_pk_encryption_set_recipient_key(encryptionPtr, keyPtr, (size_t)env->GetArrayLength(aKeyBuffer)) == olm_error())
|
if (olm_pk_encryption_set_recipient_key(encryptionPtr, keyPtr, (size_t)env->GetArrayLength(aKeyBuffer)) == olm_error())
|
||||||
{
|
{
|
||||||
errorMessage = olm_pk_encryption_last_error(encryptionPtr);
|
errorMessage = olm_pk_encryption_last_error(encryptionPtr);
|
||||||
LOGE(" ## pkSetRecipientKeyJni(): failure - olm_pk_encryption_set_recipient_key Msg=%s", errorMessage);
|
LOGE(
|
||||||
|
" ## pkSetRecipientKeyJni(): failure - olm_pk_encryption_set_recipient_key Msg=%s",
|
||||||
|
errorMessage
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,11 +144,13 @@ JNIEXPORT void OLM_PK_ENCRYPTION_FUNC_DEF(setRecipientKeyJni)(JNIEnv *env, jobje
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(JNIEnv *env, jobject thiz, jbyteArray aPlaintextBuffer, jobject aEncryptedMsg)
|
JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(
|
||||||
{
|
JNIEnv *env, jobject thiz, jbyteArray aPlaintextBuffer, jobject aEncryptedMsg
|
||||||
|
) {
|
||||||
jbyteArray encryptedMsgRet = 0;
|
jbyteArray encryptedMsgRet = 0;
|
||||||
const char* errorMessage = NULL;
|
const char* errorMessage = NULL;
|
||||||
jbyte *plaintextPtr = NULL;
|
jbyte *plaintextPtr = NULL;
|
||||||
|
jboolean plaintextIsCopied = JNI_FALSE;
|
||||||
|
|
||||||
OlmPkEncryption *encryptionPtr = getPkEncryptionInstanceId(env, thiz);
|
OlmPkEncryption *encryptionPtr = getPkEncryptionInstanceId(env, thiz);
|
||||||
jclass encryptedMsgJClass = 0;
|
jclass encryptedMsgJClass = 0;
|
||||||
|
@ -154,15 +166,15 @@ JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(JNIEnv *env, jobject
|
||||||
LOGE(" ## pkEncryptJni(): failure - invalid clear message");
|
LOGE(" ## pkEncryptJni(): failure - invalid clear message");
|
||||||
errorMessage = "invalid clear message";
|
errorMessage = "invalid clear message";
|
||||||
}
|
}
|
||||||
else if (!(plaintextPtr = env->GetByteArrayElements(aPlaintextBuffer, 0)))
|
else if (!(plaintextPtr = env->GetByteArrayElements(aPlaintextBuffer, &plaintextIsCopied)))
|
||||||
{
|
{
|
||||||
LOGE(" ## pkEncryptJni(): failure - plaintext JNI allocation OOM");
|
LOGE(" ## pkEncryptJni(): failure - plaintext JNI allocation OOM");
|
||||||
errorMessage = "plaintext JNI allocation OOM";
|
errorMessage = "plaintext JNI allocation OOM";
|
||||||
}
|
}
|
||||||
else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg)))
|
else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg)))
|
||||||
{
|
{
|
||||||
LOGE(" ## pkEncryptJni(): failure - unable to get crypted message class");
|
LOGE(" ## pkEncryptJni(): failure - unable to get encrypted message class");
|
||||||
errorMessage = "unable to get crypted message class";
|
errorMessage = "unable to get encrypted message class";
|
||||||
}
|
}
|
||||||
else if (!(macFieldId = env->GetFieldID(encryptedMsgJClass, "mMac", "Ljava/lang/String;")))
|
else if (!(macFieldId = env->GetFieldID(encryptedMsgJClass, "mMac", "Ljava/lang/String;")))
|
||||||
{
|
{
|
||||||
|
@ -226,7 +238,9 @@ JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(JNIEnv *env, jobject
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
encryptedMsgRet = env->NewByteArray(ciphertextLength);
|
encryptedMsgRet = env->NewByteArray(ciphertextLength);
|
||||||
env->SetByteArrayRegion(encryptedMsgRet, 0, ciphertextLength, (jbyte*)ciphertextPtr);
|
env->SetByteArrayRegion(
|
||||||
|
encryptedMsgRet, 0, ciphertextLength, (jbyte*)ciphertextPtr
|
||||||
|
);
|
||||||
|
|
||||||
jstring macStr = env->NewStringUTF((char*)macPtr);
|
jstring macStr = env->NewStringUTF((char*)macPtr);
|
||||||
env->SetObjectField(aEncryptedMsg, macFieldId, macStr);
|
env->SetObjectField(aEncryptedMsg, macFieldId, macStr);
|
||||||
|
@ -256,6 +270,10 @@ JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(JNIEnv *env, jobject
|
||||||
|
|
||||||
if (plaintextPtr)
|
if (plaintextPtr)
|
||||||
{
|
{
|
||||||
|
if (plaintextIsCopied)
|
||||||
|
{
|
||||||
|
memset(plaintextPtr, 0, (size_t)env->GetArrayLength(aPlaintextBuffer));
|
||||||
|
}
|
||||||
env->ReleaseByteArrayElements(aPlaintextBuffer, plaintextPtr, JNI_ABORT);
|
env->ReleaseByteArrayElements(aPlaintextBuffer, plaintextPtr, JNI_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,7 +294,10 @@ OlmPkDecryption * initializePkDecryptionMemory()
|
||||||
{
|
{
|
||||||
// init decryption object
|
// init decryption object
|
||||||
decryptionPtr = olm_pk_decryption(decryptionPtr);
|
decryptionPtr = olm_pk_decryption(decryptionPtr);
|
||||||
LOGD("## initializePkDecryptionMemory(): success - OLM decryption size=%lu",static_cast<long unsigned int>(decryptionSize));
|
LOGD(
|
||||||
|
"## initializePkDecryptionMemory(): success - OLM decryption size=%lu",
|
||||||
|
static_cast<long unsigned int>(decryptionSize)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -300,7 +321,10 @@ JNIEXPORT jlong OLM_PK_DECRYPTION_FUNC_DEF(createNewPkDecryptionJni)(JNIEnv *env
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGD("## createNewPkDecryptionJni(): success - OLM decryption created");
|
LOGD("## createNewPkDecryptionJni(): success - OLM decryption created");
|
||||||
LOGD("## createNewPkDecryptionJni(): decryptionPtr=%p (jlong)(intptr_t)decryptionPtr=%lld", decryptionPtr, (jlong)(intptr_t)decryptionPtr);
|
LOGD(
|
||||||
|
"## createNewPkDecryptionJni(): decryptionPtr=%p (jlong)(intptr_t)decryptionPtr=%lld",
|
||||||
|
decryptionPtr, (jlong)(intptr_t)decryptionPtr
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errorMessage)
|
if (errorMessage)
|
||||||
|
@ -402,8 +426,9 @@ JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(generateKeyJni)(JNIEnv *env, job
|
||||||
return publicKeyRet;
|
return publicKeyRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(decryptJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg)
|
JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(decryptJni)(
|
||||||
{
|
JNIEnv *env, jobject thiz, jobject aEncryptedMsg
|
||||||
|
) {
|
||||||
const char* errorMessage = NULL;
|
const char* errorMessage = NULL;
|
||||||
OlmPkDecryption *decryptionPtr = getPkDecryptionInstanceId(env, thiz);
|
OlmPkDecryption *decryptionPtr = getPkDecryptionInstanceId(env, thiz);
|
||||||
|
|
||||||
|
@ -528,7 +553,10 @@ JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(decryptJni)(JNIEnv *env, jobject
|
||||||
{
|
{
|
||||||
decryptedMsgRet = env->NewByteArray(plaintextLength);
|
decryptedMsgRet = env->NewByteArray(plaintextLength);
|
||||||
env->SetByteArrayRegion(decryptedMsgRet, 0, plaintextLength, (jbyte*)plaintextPtr);
|
env->SetByteArrayRegion(decryptedMsgRet, 0, plaintextLength, (jbyte*)plaintextPtr);
|
||||||
LOGD("## pkDecryptJni(): success returnedLg=%lu OK", static_cast<long unsigned int>(plaintextLength));
|
LOGD(
|
||||||
|
"## pkDecryptJni(): success returnedLg=%lu OK",
|
||||||
|
static_cast<long unsigned int>(plaintextLength)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +566,7 @@ JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(decryptJni)(JNIEnv *env, jobject
|
||||||
}
|
}
|
||||||
if (plaintextPtr)
|
if (plaintextPtr)
|
||||||
{
|
{
|
||||||
|
memset(plaintextPtr, 0, maxPlaintextLength);
|
||||||
free(plaintextPtr);
|
free(plaintextPtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -472,6 +472,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
|
||||||
|
|
||||||
OlmSession *sessionPtr = getSessionInstanceId(env, thiz);
|
OlmSession *sessionPtr = getSessionInstanceId(env, thiz);
|
||||||
jbyte *clearMsgPtr = NULL;
|
jbyte *clearMsgPtr = NULL;
|
||||||
|
jboolean clearMsgIsCopied = JNI_FALSE;
|
||||||
jclass encryptedMsgJClass = 0;
|
jclass encryptedMsgJClass = 0;
|
||||||
jfieldID typeMsgFieldId;
|
jfieldID typeMsgFieldId;
|
||||||
|
|
||||||
|
@ -490,8 +491,9 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
|
||||||
else if (!aEncryptedMsg)
|
else if (!aEncryptedMsg)
|
||||||
{
|
{
|
||||||
LOGE("## encryptMessageJni(): failure - invalid encrypted message");
|
LOGE("## encryptMessageJni(): failure - invalid encrypted message");
|
||||||
|
errorMessage = "invalid encrypted message";
|
||||||
}
|
}
|
||||||
else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, 0)))
|
else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, &clearMsgIsCopied)))
|
||||||
{
|
{
|
||||||
LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM");
|
LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM");
|
||||||
errorMessage = "clear message JNI allocation OOM";
|
errorMessage = "clear message JNI allocation OOM";
|
||||||
|
@ -580,6 +582,10 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
|
||||||
// free alloc
|
// free alloc
|
||||||
if (clearMsgPtr)
|
if (clearMsgPtr)
|
||||||
{
|
{
|
||||||
|
if (clearMsgIsCopied)
|
||||||
|
{
|
||||||
|
memset(clearMsgPtr, 0, (size_t)env->GetArrayLength(aClearMsgBuffer));
|
||||||
|
}
|
||||||
env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT);
|
env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -702,6 +708,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec
|
||||||
|
|
||||||
LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast<long unsigned int>(plaintextLength));
|
LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast<long unsigned int>(plaintextLength));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(plainTextMsgPtr, 0, maxPlainTextLength);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,7 @@ info.
|
||||||
Advancing the chain key
|
Advancing the chain key
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Advancing a chain key takes the previous chain key, :math:`C_{i,j-i}`. The next
|
Advancing a chain key takes the previous chain key, :math:`C_{i,j-1}`. The next
|
||||||
chain key, :math:`C_{i,j}`, is the HMAC-SHA-256_ of ``"\x02"`` using the
|
chain key, :math:`C_{i,j}`, is the HMAC-SHA-256_ of ``"\x02"`` using the
|
||||||
previous chain key as the key.
|
previous chain key as the key.
|
||||||
|
|
||||||
|
@ -338,7 +338,7 @@ The Olm specification (this document) is hereby placed in the public domain.
|
||||||
Feedback
|
Feedback
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Can be sent to mark at matrix.org.
|
Can be sent to olm at matrix.org.
|
||||||
|
|
||||||
Acknowledgements
|
Acknowledgements
|
||||||
----------------
|
----------------
|
||||||
|
|
|
@ -113,6 +113,6 @@ This document is licensed under the `Apache License, Version 2.0
|
||||||
Feedback
|
Feedback
|
||||||
--------
|
--------
|
||||||
|
|
||||||
Questions and feedback can be sent to richard at matrix.org.
|
Questions and feedback can be sent to olm at matrix.org.
|
||||||
|
|
||||||
.. _`Ed25519`: http://ed25519.cr.yp.to/
|
.. _`Ed25519`: http://ed25519.cr.yp.to/
|
||||||
|
|
18
exports.py
Executable file
18
exports.py
Executable file
|
@ -0,0 +1,18 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
|
||||||
|
expr = re.compile(r"(olm_[^( ]*)\(")
|
||||||
|
|
||||||
|
exports = set()
|
||||||
|
|
||||||
|
for f in sys.argv[1:]:
|
||||||
|
with open(f) as fp:
|
||||||
|
for line in fp:
|
||||||
|
matches = expr.search(line)
|
||||||
|
if matches is not None:
|
||||||
|
exports.add('_%s' % (matches.group(1),))
|
||||||
|
|
||||||
|
json.dump(sorted(exports), sys.stdout)
|
|
@ -51,6 +51,13 @@ enum OlmErrorCode {
|
||||||
*/
|
*/
|
||||||
OLM_BAD_SIGNATURE = 14,
|
OLM_BAD_SIGNATURE = 14,
|
||||||
|
|
||||||
|
OLM_INPUT_BUFFER_TOO_SMALL = 15,
|
||||||
|
|
||||||
|
// Not an error code, just here to pad out the enum past 16 because
|
||||||
|
// otherwise the compiler warns about a redunant check. If you're
|
||||||
|
// adding an error code, replace this one!
|
||||||
|
OLM_ERROR_NOT_INVENTED_YET = 16,
|
||||||
|
|
||||||
/* 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. */
|
||||||
};
|
};
|
||||||
|
|
|
@ -72,11 +72,15 @@ size_t olm_pk_encrypt_random_length(
|
||||||
);
|
);
|
||||||
|
|
||||||
/** Encrypt a plaintext for the recipient set using
|
/** Encrypt a plaintext for the recipient set using
|
||||||
* olm_pk_encryption_set_recipient_key. Returns olm_error() on failure. If the
|
* olm_pk_encryption_set_recipient_key. Writes to the ciphertext, mac, and
|
||||||
* ciphertext, mac, or ephemeral_key buffers were too small then
|
* ephemeral_key buffers, whose values should be sent to the recipient. mac is
|
||||||
* olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". If there
|
* a Message Authentication Code to ensure that the data is received and
|
||||||
* weren't enough random bytes then olm_pk_encryption_last_error() will be
|
* decrypted properly. ephemeral_key is the public part of the ephemeral key
|
||||||
* "NOT_ENOUGH_RANDOM". */
|
* used (together with the recipient's key) to generate a symmetric encryption
|
||||||
|
* key. Returns olm_error() on failure. If the ciphertext, mac, or
|
||||||
|
* 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
|
||||||
|
* olm_pk_encryption_last_error() will be "OLM_INPUT_BUFFER_TOO_SMALL". */
|
||||||
size_t olm_pk_encrypt(
|
size_t olm_pk_encrypt(
|
||||||
OlmPkEncryption *encryption,
|
OlmPkEncryption *encryption,
|
||||||
void const * plaintext, size_t plaintext_length,
|
void const * plaintext, size_t plaintext_length,
|
||||||
|
@ -108,18 +112,36 @@ size_t olm_clear_pk_decryption(
|
||||||
OlmPkDecryption *decryption
|
OlmPkDecryption *decryption
|
||||||
);
|
);
|
||||||
|
|
||||||
/** The number of random bytes needed to generate a new key. */
|
/** Get the number of bytes required to store an olm private key
|
||||||
|
*/
|
||||||
|
size_t olm_pk_private_key_length();
|
||||||
|
|
||||||
|
/** DEPRECATED: Use olm_pk_private_key_length()
|
||||||
|
*/
|
||||||
size_t olm_pk_generate_key_random_length(void);
|
size_t olm_pk_generate_key_random_length(void);
|
||||||
|
|
||||||
/** Generate a new key to use for decrypting messages. The associated public
|
/** Initialise the key from the private part of a key as returned by
|
||||||
* key will be written to the pubkey buffer. Returns olm_error() on failure. If
|
* olm_pk_get_private_key(). The associated public key will be written to the
|
||||||
* the pubkey buffer is too small then olm_pk_decryption_last_error() will be
|
* pubkey buffer. Returns olm_error() on failure. If the pubkey buffer is too
|
||||||
* "OUTPUT_BUFFER_TOO_SMALL". If there weren't enough random bytes then
|
* small then olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
|
||||||
* olm_pk_decryption_last_error() will be "NOT_ENOUGH_RANDOM". */
|
* If the private key was not long enough then olm_pk_decryption_last_error()
|
||||||
|
* will be "OLM_INPUT_BUFFER_TOO_SMALL".
|
||||||
|
*
|
||||||
|
* Note that the pubkey is a base64 encoded string, but the private key is
|
||||||
|
* an unencoded byte array
|
||||||
|
*/
|
||||||
|
size_t olm_pk_key_from_private(
|
||||||
|
OlmPkDecryption * decryption,
|
||||||
|
void * pubkey, size_t pubkey_length,
|
||||||
|
void * privkey, size_t privkey_length
|
||||||
|
);
|
||||||
|
|
||||||
|
/** DEPRECATED: Use olm_pk_key_from_private
|
||||||
|
*/
|
||||||
size_t olm_pk_generate_key(
|
size_t olm_pk_generate_key(
|
||||||
OlmPkDecryption * decryption,
|
OlmPkDecryption * decryption,
|
||||||
void * pubkey, size_t pubkey_length,
|
void * pubkey, size_t pubkey_length,
|
||||||
void * random, size_t random_length
|
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. */
|
||||||
|
@ -159,18 +181,32 @@ size_t olm_pk_max_plaintext_length(
|
||||||
size_t ciphertext_length
|
size_t ciphertext_length
|
||||||
);
|
);
|
||||||
|
|
||||||
/** Decrypt a ciphertext. The input ciphertext buffer is destroyed. Returns
|
/** Decrypt a ciphertext. The input ciphertext buffer is destroyed. See the
|
||||||
* the length of the plaintext on success. Returns olm_error() on failure. If
|
* olm_pk_encrypt function for descriptions of the ephemeral_key and mac
|
||||||
* the plaintext buffer is too small then olm_pk_encryption_last_error() will
|
* arguments. Returns the length of the plaintext on success. Returns
|
||||||
* be "OUTPUT_BUFFER_TOO_SMALL". */
|
* olm_error() on failure. If the plaintext buffer is too small then
|
||||||
|
* olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL". */
|
||||||
size_t olm_pk_decrypt(
|
size_t olm_pk_decrypt(
|
||||||
OlmPkDecryption * decrytion,
|
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,
|
||||||
void * ciphertext, size_t ciphertext_length,
|
void * ciphertext, size_t ciphertext_length,
|
||||||
void * plaintext, size_t max_plaintext_length
|
void * plaintext, size_t max_plaintext_length
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the private key for an OlmDecryption object as an unencoded byte array
|
||||||
|
* private_key must be a pointer to a buffer of at least
|
||||||
|
* olm_pk_private_key_length() bytes and this length must be passed in
|
||||||
|
* private_key_length. If the given buffer is too small, returns olm_error()
|
||||||
|
* and olm_pk_encryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
|
||||||
|
* Returns the number of bytes written.
|
||||||
|
*/
|
||||||
|
size_t olm_pk_get_private_key(
|
||||||
|
OlmPkDecryption * decryption,
|
||||||
|
void *private_key, size_t private_key_length
|
||||||
|
);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
1
javascript/.gitignore
vendored
1
javascript/.gitignore
vendored
|
@ -2,4 +2,5 @@
|
||||||
/node_modules
|
/node_modules
|
||||||
/npm-debug.log
|
/npm-debug.log
|
||||||
/olm.js
|
/olm.js
|
||||||
|
/olm.wasm
|
||||||
/reports
|
/reports
|
||||||
|
|
4
javascript/externs.js
Normal file
4
javascript/externs.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
var OLM_OPTIONS;
|
||||||
|
var olm_exports;
|
||||||
|
var onInitSuccess;
|
||||||
|
var onInitFail;
|
|
@ -1,9 +1,3 @@
|
||||||
/* The 'length' argument to Pointer_stringify doesn't work if the input includes
|
|
||||||
* characters >= 128; we therefore need to add a NULL character to all of our
|
|
||||||
* strings. This acts as a symbolic constant to help show what we're doing.
|
|
||||||
*/
|
|
||||||
var NULL_BYTE_PADDING_LENGTH = 1;
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -77,14 +71,14 @@ InboundGroupSession.prototype['decrypt'] = restore_stack(function(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
message_buffer = malloc(message.length);
|
message_buffer = malloc(message.length);
|
||||||
Module['writeAsciiToMemory'](message, message_buffer, true);
|
writeAsciiToMemory(message, message_buffer, true);
|
||||||
|
|
||||||
var max_plaintext_length = inbound_group_session_method(
|
var max_plaintext_length = inbound_group_session_method(
|
||||||
Module['_olm_group_decrypt_max_plaintext_length']
|
Module['_olm_group_decrypt_max_plaintext_length']
|
||||||
)(this.ptr, message_buffer, message.length);
|
)(this.ptr, message_buffer, message.length);
|
||||||
|
|
||||||
// caculating the length destroys the input buffer, so we need to re-copy it.
|
// caculating the length destroys the input buffer, so we need to re-copy it.
|
||||||
Module['writeAsciiToMemory'](message, message_buffer, true);
|
writeAsciiToMemory(message, message_buffer, true);
|
||||||
|
|
||||||
plaintext_buffer = malloc(max_plaintext_length + NULL_BYTE_PADDING_LENGTH);
|
plaintext_buffer = malloc(max_plaintext_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
var message_index = stack(4);
|
var message_index = stack(4);
|
||||||
|
@ -100,14 +94,14 @@ InboundGroupSession.prototype['decrypt'] = restore_stack(function(
|
||||||
|
|
||||||
// UTF8ToString requires a null-terminated argument, so add the
|
// UTF8ToString requires a null-terminated argument, so add the
|
||||||
// null terminator.
|
// null terminator.
|
||||||
Module['setValue'](
|
setValue(
|
||||||
plaintext_buffer+plaintext_length,
|
plaintext_buffer+plaintext_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"plaintext": UTF8ToString(plaintext_buffer),
|
"plaintext": UTF8ToString(plaintext_buffer),
|
||||||
"message_index": Module['getValue'](message_index, "i32")
|
"message_index": getValue(message_index, "i32")
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
if (message_buffer !== undefined) {
|
if (message_buffer !== undefined) {
|
||||||
|
|
|
@ -1,10 +1,3 @@
|
||||||
/* The 'length' argument to Pointer_stringify doesn't work if the input includes
|
|
||||||
* characters >= 128; we therefore need to add a NULL character to all of our
|
|
||||||
* strings. This acts as a symbolic constant to help show what we're doing.
|
|
||||||
*/
|
|
||||||
var NULL_BYTE_PADDING_LENGTH = 1;
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
@ -66,7 +59,7 @@ OutboundGroupSession.prototype['create'] = restore_stack(function() {
|
||||||
OutboundGroupSession.prototype['encrypt'] = function(plaintext) {
|
OutboundGroupSession.prototype['encrypt'] = function(plaintext) {
|
||||||
var plaintext_buffer, message_buffer, plaintext_length;
|
var plaintext_buffer, message_buffer, plaintext_length;
|
||||||
try {
|
try {
|
||||||
plaintext_length = Module['lengthBytesUTF8'](plaintext);
|
plaintext_length = lengthBytesUTF8(plaintext);
|
||||||
|
|
||||||
var message_length = outbound_group_session_method(
|
var message_length = outbound_group_session_method(
|
||||||
Module['_olm_group_encrypt_message_length']
|
Module['_olm_group_encrypt_message_length']
|
||||||
|
@ -75,7 +68,7 @@ OutboundGroupSession.prototype['encrypt'] = function(plaintext) {
|
||||||
// need to allow space for the terminator (which stringToUTF8 always
|
// need to allow space for the terminator (which stringToUTF8 always
|
||||||
// writes), hence + 1.
|
// writes), hence + 1.
|
||||||
plaintext_buffer = malloc(plaintext_length + 1);
|
plaintext_buffer = malloc(plaintext_length + 1);
|
||||||
Module['stringToUTF8'](plaintext, plaintext_buffer, plaintext_length + 1);
|
stringToUTF8(plaintext, plaintext_buffer, plaintext_length + 1);
|
||||||
|
|
||||||
message_buffer = malloc(message_length + NULL_BYTE_PADDING_LENGTH);
|
message_buffer = malloc(message_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
outbound_group_session_method(Module['_olm_group_encrypt'])(
|
outbound_group_session_method(Module['_olm_group_encrypt'])(
|
||||||
|
@ -86,12 +79,12 @@ OutboundGroupSession.prototype['encrypt'] = function(plaintext) {
|
||||||
|
|
||||||
// UTF8ToString requires a null-terminated argument, so add the
|
// UTF8ToString requires a null-terminated argument, so add the
|
||||||
// null terminator.
|
// null terminator.
|
||||||
Module['setValue'](
|
setValue(
|
||||||
message_buffer+message_length,
|
message_buffer+message_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
|
|
||||||
return Module['UTF8ToString'](message_buffer);
|
return UTF8ToString(message_buffer);
|
||||||
} finally {
|
} finally {
|
||||||
if (plaintext_buffer !== undefined) {
|
if (plaintext_buffer !== undefined) {
|
||||||
// don't leave a copy of the plaintext in the heap.
|
// don't leave a copy of the plaintext in the heap.
|
||||||
|
|
|
@ -35,9 +35,9 @@ PkEncryption.prototype['encrypt'] = restore_stack(function(
|
||||||
) {
|
) {
|
||||||
var plaintext_buffer, ciphertext_buffer, plaintext_length;
|
var plaintext_buffer, ciphertext_buffer, plaintext_length;
|
||||||
try {
|
try {
|
||||||
plaintext_length = Module['lengthBytesUTF8'](plaintext)
|
plaintext_length = lengthBytesUTF8(plaintext)
|
||||||
plaintext_buffer = malloc(plaintext_length + 1);
|
plaintext_buffer = malloc(plaintext_length + 1);
|
||||||
Module['stringToUTF8'](plaintext, plaintext_buffer, plaintext_length + 1);
|
stringToUTF8(plaintext, plaintext_buffer, plaintext_length + 1);
|
||||||
var random_length = pk_encryption_method(
|
var random_length = pk_encryption_method(
|
||||||
Module['_olm_pk_encrypt_random_length']
|
Module['_olm_pk_encrypt_random_length']
|
||||||
)();
|
)();
|
||||||
|
@ -50,16 +50,16 @@ PkEncryption.prototype['encrypt'] = restore_stack(function(
|
||||||
Module['_olm_pk_mac_length']
|
Module['_olm_pk_mac_length']
|
||||||
)(this.ptr);
|
)(this.ptr);
|
||||||
var mac_buffer = stack(mac_length + NULL_BYTE_PADDING_LENGTH);
|
var mac_buffer = stack(mac_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
Module['setValue'](
|
setValue(
|
||||||
mac_buffer+mac_length,
|
mac_buffer + mac_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
var ephemeral_length = pk_encryption_method(
|
var ephemeral_length = pk_encryption_method(
|
||||||
Module['_olm_pk_key_length']
|
Module['_olm_pk_key_length']
|
||||||
)();
|
)();
|
||||||
var ephemeral_buffer = stack(ephemeral_length + NULL_BYTE_PADDING_LENGTH);
|
var ephemeral_buffer = stack(ephemeral_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
Module['setValue'](
|
setValue(
|
||||||
ephemeral_buffer+ephemeral_length,
|
ephemeral_buffer + ephemeral_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
pk_encryption_method(Module['_olm_pk_encrypt'])(
|
pk_encryption_method(Module['_olm_pk_encrypt'])(
|
||||||
|
@ -72,12 +72,12 @@ PkEncryption.prototype['encrypt'] = restore_stack(function(
|
||||||
);
|
);
|
||||||
// UTF8ToString requires a null-terminated argument, so add the
|
// UTF8ToString requires a null-terminated argument, so add the
|
||||||
// null terminator.
|
// null terminator.
|
||||||
Module['setValue'](
|
setValue(
|
||||||
ciphertext_buffer+ciphertext_length,
|
ciphertext_buffer + ciphertext_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
"ciphertext": Module['UTF8ToString'](ciphertext_buffer),
|
"ciphertext": UTF8ToString(ciphertext_buffer),
|
||||||
"mac": Pointer_stringify(mac_buffer),
|
"mac": Pointer_stringify(mac_buffer),
|
||||||
"ephemeral": Pointer_stringify(ephemeral_buffer)
|
"ephemeral": Pointer_stringify(ephemeral_buffer)
|
||||||
};
|
};
|
||||||
|
@ -118,16 +118,32 @@ PkDecryption.prototype['free'] = function() {
|
||||||
free(this.ptr);
|
free(this.ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
PkDecryption.prototype['generate_key'] = restore_stack(function () {
|
PkDecryption.prototype['init_with_private_key'] = restore_stack(function (private_key) {
|
||||||
var random_length = pk_decryption_method(
|
var private_key_buffer = stack(private_key.length);
|
||||||
Module['_olm_pk_generate_key_random_length']
|
Module['HEAPU8'].set(private_key, private_key_buffer);
|
||||||
)();
|
|
||||||
var random_buffer = random_stack(random_length);
|
var pubkey_length = pk_decryption_method(
|
||||||
var pubkey_length = pk_encryption_method(
|
|
||||||
Module['_olm_pk_key_length']
|
Module['_olm_pk_key_length']
|
||||||
)();
|
)();
|
||||||
var pubkey_buffer = stack(pubkey_length + NULL_BYTE_PADDING_LENGTH);
|
var pubkey_buffer = stack(pubkey_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
pk_decryption_method(Module['_olm_pk_generate_key'])(
|
pk_decryption_method(Module['_olm_pk_key_from_private'])(
|
||||||
|
this.ptr,
|
||||||
|
pubkey_buffer, pubkey_length,
|
||||||
|
private_key_buffer, private_key.length
|
||||||
|
);
|
||||||
|
return Pointer_stringify(pubkey_buffer);
|
||||||
|
});
|
||||||
|
|
||||||
|
PkDecryption.prototype['generate_key'] = restore_stack(function () {
|
||||||
|
var random_length = pk_decryption_method(
|
||||||
|
Module['_olm_pk_private_key_length']
|
||||||
|
)();
|
||||||
|
var random_buffer = random_stack(random_length);
|
||||||
|
var pubkey_length = pk_decryption_method(
|
||||||
|
Module['_olm_pk_key_length']
|
||||||
|
)();
|
||||||
|
var pubkey_buffer = stack(pubkey_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
|
pk_decryption_method(Module['_olm_pk_key_from_private'])(
|
||||||
this.ptr,
|
this.ptr,
|
||||||
pubkey_buffer, pubkey_length,
|
pubkey_buffer, pubkey_length,
|
||||||
random_buffer, random_length
|
random_buffer, random_length
|
||||||
|
@ -135,6 +151,18 @@ PkDecryption.prototype['generate_key'] = restore_stack(function () {
|
||||||
return Pointer_stringify(pubkey_buffer);
|
return Pointer_stringify(pubkey_buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PkDecryption.prototype['get_private_key'] = restore_stack(function () {
|
||||||
|
var privkey_length = pk_encryption_method(
|
||||||
|
Module['_olm_pk_private_key_length']
|
||||||
|
)();
|
||||||
|
var privkey_buffer = stack(privkey_length);
|
||||||
|
pk_decryption_method(Module['_olm_pk_get_private_key'])(
|
||||||
|
this.ptr,
|
||||||
|
privkey_buffer, privkey_length
|
||||||
|
);
|
||||||
|
return new Uint8Array(Module['HEAPU8'].buffer, privkey_buffer, privkey_length);
|
||||||
|
});
|
||||||
|
|
||||||
PkDecryption.prototype['pickle'] = restore_stack(function (key) {
|
PkDecryption.prototype['pickle'] = restore_stack(function (key) {
|
||||||
var key_array = array_from_string(key);
|
var key_array = array_from_string(key);
|
||||||
var pickle_length = pk_decryption_method(
|
var pickle_length = pk_decryption_method(
|
||||||
|
@ -169,9 +197,9 @@ PkDecryption.prototype['decrypt'] = restore_stack(function (
|
||||||
) {
|
) {
|
||||||
var plaintext_buffer, ciphertext_buffer, plaintext_max_length;
|
var plaintext_buffer, ciphertext_buffer, plaintext_max_length;
|
||||||
try {
|
try {
|
||||||
ciphertext_length = Module['lengthBytesUTF8'](ciphertext)
|
var ciphertext_length = lengthBytesUTF8(ciphertext)
|
||||||
ciphertext_buffer = malloc(ciphertext_length + 1);
|
ciphertext_buffer = malloc(ciphertext_length + 1);
|
||||||
Module['stringToUTF8'](ciphertext, ciphertext_buffer, ciphertext_length + 1);
|
stringToUTF8(ciphertext, ciphertext_buffer, ciphertext_length + 1);
|
||||||
var ephemeralkey_array = array_from_string(ephemeral_key);
|
var ephemeralkey_array = array_from_string(ephemeral_key);
|
||||||
var ephemeralkey_buffer = stack(ephemeralkey_array);
|
var ephemeralkey_buffer = stack(ephemeralkey_array);
|
||||||
var mac_array = array_from_string(mac);
|
var mac_array = array_from_string(mac);
|
||||||
|
@ -190,11 +218,11 @@ PkDecryption.prototype['decrypt'] = restore_stack(function (
|
||||||
);
|
);
|
||||||
// UTF8ToString requires a null-terminated argument, so add the
|
// UTF8ToString requires a null-terminated argument, so add the
|
||||||
// null terminator.
|
// null terminator.
|
||||||
Module['setValue'](
|
setValue(
|
||||||
plaintext_buffer+plaintext_length,
|
plaintext_buffer + plaintext_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
return Module['UTF8ToString'](plaintext_buffer);
|
return UTF8ToString(plaintext_buffer);
|
||||||
} finally {
|
} finally {
|
||||||
if (plaintext_buffer !== undefined) {
|
if (plaintext_buffer !== undefined) {
|
||||||
// don't leave a copy of the plaintext in the heap.
|
// don't leave a copy of the plaintext in the heap.
|
||||||
|
|
|
@ -1,27 +1,17 @@
|
||||||
var runtime = Module['Runtime'];
|
|
||||||
var malloc = Module['_malloc'];
|
var malloc = Module['_malloc'];
|
||||||
var free = Module['_free'];
|
var free = Module['_free'];
|
||||||
var Pointer_stringify = Module['Pointer_stringify'];
|
var OLM_ERROR;
|
||||||
var OLM_ERROR = Module['_olm_error']();
|
|
||||||
|
|
||||||
/* The 'length' argument to Pointer_stringify doesn't work if the input
|
|
||||||
* includes characters >= 128, which makes Pointer_stringify unreliable. We
|
|
||||||
* could use it on strings which are known to be ascii, but that seems
|
|
||||||
* dangerous. Instead we add a NULL character to all of our strings and just
|
|
||||||
* use UTF8ToString.
|
|
||||||
*/
|
|
||||||
var NULL_BYTE_PADDING_LENGTH = 1;
|
|
||||||
|
|
||||||
/* allocate a number of bytes of storage on the stack.
|
/* allocate a number of bytes of storage on the stack.
|
||||||
*
|
*
|
||||||
* If size_or_array is a Number, allocates that number of zero-initialised bytes.
|
* If size_or_array is a Number, allocates that number of zero-initialised bytes.
|
||||||
*/
|
*/
|
||||||
function stack(size_or_array) {
|
function stack(size_or_array) {
|
||||||
return Module['allocate'](size_or_array, 'i8', Module['ALLOC_STACK']);
|
return allocate(size_or_array, 'i8', Module['ALLOC_STACK']);
|
||||||
}
|
}
|
||||||
|
|
||||||
function array_from_string(string) {
|
function array_from_string(string) {
|
||||||
return Module['intArrayFromString'](string, true);
|
return intArrayFromString(string, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
function random_stack(size) {
|
function random_stack(size) {
|
||||||
|
@ -33,11 +23,11 @@ function random_stack(size) {
|
||||||
|
|
||||||
function restore_stack(wrapped) {
|
function restore_stack(wrapped) {
|
||||||
return function() {
|
return function() {
|
||||||
var sp = runtime.stackSave();
|
var sp = stackSave();
|
||||||
try {
|
try {
|
||||||
return wrapped.apply(this, arguments);
|
return wrapped.apply(this, arguments);
|
||||||
} finally {
|
} finally {
|
||||||
runtime.stackRestore(sp);
|
stackRestore(sp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -315,7 +305,7 @@ Session.prototype['encrypt'] = restore_stack(function(
|
||||||
Module['_olm_encrypt_message_type']
|
Module['_olm_encrypt_message_type']
|
||||||
)(this.ptr);
|
)(this.ptr);
|
||||||
|
|
||||||
plaintext_length = Module['lengthBytesUTF8'](plaintext);
|
plaintext_length = lengthBytesUTF8(plaintext);
|
||||||
var message_length = session_method(
|
var message_length = session_method(
|
||||||
Module['_olm_encrypt_message_length']
|
Module['_olm_encrypt_message_length']
|
||||||
)(this.ptr, plaintext_length);
|
)(this.ptr, plaintext_length);
|
||||||
|
@ -325,7 +315,7 @@ Session.prototype['encrypt'] = restore_stack(function(
|
||||||
// need to allow space for the terminator (which stringToUTF8 always
|
// need to allow space for the terminator (which stringToUTF8 always
|
||||||
// writes), hence + 1.
|
// writes), hence + 1.
|
||||||
plaintext_buffer = malloc(plaintext_length + 1);
|
plaintext_buffer = malloc(plaintext_length + 1);
|
||||||
Module['stringToUTF8'](plaintext, plaintext_buffer, plaintext_length + 1);
|
stringToUTF8(plaintext, plaintext_buffer, plaintext_length + 1);
|
||||||
|
|
||||||
message_buffer = malloc(message_length + NULL_BYTE_PADDING_LENGTH);
|
message_buffer = malloc(message_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
|
|
||||||
|
@ -338,14 +328,14 @@ Session.prototype['encrypt'] = restore_stack(function(
|
||||||
|
|
||||||
// UTF8ToString requires a null-terminated argument, so add the
|
// UTF8ToString requires a null-terminated argument, so add the
|
||||||
// null terminator.
|
// null terminator.
|
||||||
Module['setValue'](
|
setValue(
|
||||||
message_buffer+message_length,
|
message_buffer+message_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"type": message_type,
|
"type": message_type,
|
||||||
"body": Module['UTF8ToString'](message_buffer),
|
"body": UTF8ToString(message_buffer),
|
||||||
};
|
};
|
||||||
} finally {
|
} finally {
|
||||||
if (plaintext_buffer !== undefined) {
|
if (plaintext_buffer !== undefined) {
|
||||||
|
@ -366,14 +356,14 @@ Session.prototype['decrypt'] = restore_stack(function(
|
||||||
|
|
||||||
try {
|
try {
|
||||||
message_buffer = malloc(message.length);
|
message_buffer = malloc(message.length);
|
||||||
Module['writeAsciiToMemory'](message, message_buffer, true);
|
writeAsciiToMemory(message, message_buffer, true);
|
||||||
|
|
||||||
max_plaintext_length = session_method(
|
max_plaintext_length = session_method(
|
||||||
Module['_olm_decrypt_max_plaintext_length']
|
Module['_olm_decrypt_max_plaintext_length']
|
||||||
)(this.ptr, message_type, message_buffer, message.length);
|
)(this.ptr, message_type, message_buffer, message.length);
|
||||||
|
|
||||||
// caculating the length destroys the input buffer, so we need to re-copy it.
|
// caculating the length destroys the input buffer, so we need to re-copy it.
|
||||||
Module['writeAsciiToMemory'](message, message_buffer, true);
|
writeAsciiToMemory(message, message_buffer, true);
|
||||||
|
|
||||||
plaintext_buffer = malloc(max_plaintext_length + NULL_BYTE_PADDING_LENGTH);
|
plaintext_buffer = malloc(max_plaintext_length + NULL_BYTE_PADDING_LENGTH);
|
||||||
|
|
||||||
|
@ -385,7 +375,7 @@ Session.prototype['decrypt'] = restore_stack(function(
|
||||||
|
|
||||||
// UTF8ToString requires a null-terminated argument, so add the
|
// UTF8ToString requires a null-terminated argument, so add the
|
||||||
// null terminator.
|
// null terminator.
|
||||||
Module['setValue'](
|
setValue(
|
||||||
plaintext_buffer+plaintext_length,
|
plaintext_buffer+plaintext_length,
|
||||||
0, "i8"
|
0, "i8"
|
||||||
);
|
);
|
||||||
|
@ -473,22 +463,3 @@ olm_exports["get_library_version"] = restore_stack(function() {
|
||||||
getValue(buf+2, 'i8'),
|
getValue(buf+2, 'i8'),
|
||||||
];
|
];
|
||||||
});
|
});
|
||||||
|
|
||||||
})();
|
|
||||||
|
|
||||||
// export the olm functions into the environment.
|
|
||||||
//
|
|
||||||
// make sure that we do this *after* populating olm_exports, so that we don't
|
|
||||||
// get a half-built window.Olm if there is an exception.
|
|
||||||
|
|
||||||
if (typeof module !== 'undefined' && module.exports) {
|
|
||||||
// node / browserify
|
|
||||||
module.exports = olm_exports;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof(window) !== 'undefined') {
|
|
||||||
// We've been imported directly into a browser. Define the global 'Olm' object.
|
|
||||||
// (we do this even if module.exports was defined, because it's useful to have
|
|
||||||
// Olm in the global scope for browserified and webpacked apps.)
|
|
||||||
window["Olm"] = olm_exports;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
var olm_exports = {};
|
|
||||||
var get_random_values;
|
var get_random_values;
|
||||||
var process; // Shadow the process object so that emscripten won't get
|
|
||||||
// confused by browserify
|
|
||||||
|
|
||||||
if (typeof(window) !== 'undefined') {
|
if (typeof(window) !== 'undefined') {
|
||||||
// We've in a browser (directly, via browserify, or via webpack).
|
// We're in a browser (directly, via browserify, or via webpack).
|
||||||
get_random_values = function(buf) {
|
get_random_values = function(buf) {
|
||||||
window.crypto.getRandomValues(buf);
|
window.crypto.getRandomValues(buf);
|
||||||
};
|
};
|
||||||
|
@ -12,7 +9,9 @@ if (typeof(window) !== 'undefined') {
|
||||||
// We're running in node.
|
// We're running in node.
|
||||||
var nodeCrypto = require("crypto");
|
var nodeCrypto = require("crypto");
|
||||||
get_random_values = function(buf) {
|
get_random_values = function(buf) {
|
||||||
var bytes = nodeCrypto.randomBytes(buf.length);
|
// [''] syntax needed here rather than '.' to prevent
|
||||||
|
// closure compiler from mangling the import(!)
|
||||||
|
var bytes = nodeCrypto['randomBytes'](buf.length);
|
||||||
buf.set(bytes);
|
buf.set(bytes);
|
||||||
};
|
};
|
||||||
process = global["process"];
|
process = global["process"];
|
||||||
|
@ -20,14 +19,31 @@ if (typeof(window) !== 'undefined') {
|
||||||
throw new Error("Cannot find global to attach library to");
|
throw new Error("Cannot find global to attach library to");
|
||||||
}
|
}
|
||||||
|
|
||||||
(function() {
|
/* applications should define OLM_OPTIONS in the environment to override
|
||||||
/* applications should define OLM_OPTIONS in the environment to override
|
* emscripten module settings
|
||||||
* emscripten module settings */
|
*/
|
||||||
var Module = {};
|
if (typeof(OLM_OPTIONS) !== 'undefined') {
|
||||||
if (typeof(OLM_OPTIONS) !== 'undefined') {
|
for (var olm_option_key in OLM_OPTIONS) {
|
||||||
for (var key in OLM_OPTIONS) {
|
if (OLM_OPTIONS.hasOwnProperty(olm_option_key)) {
|
||||||
if (OLM_OPTIONS.hasOwnProperty(key)) {
|
Module[olm_option_key] = OLM_OPTIONS[olm_option_key];
|
||||||
Module[key] = OLM_OPTIONS[key];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The 'length' argument to Pointer_stringify doesn't work if the input
|
||||||
|
* includes characters >= 128, which makes Pointer_stringify unreliable. We
|
||||||
|
* could use it on strings which are known to be ascii, but that seems
|
||||||
|
* dangerous. Instead we add a NULL character to all of our strings and just
|
||||||
|
* use UTF8ToString.
|
||||||
|
*/
|
||||||
|
var NULL_BYTE_PADDING_LENGTH = 1;
|
||||||
|
|
||||||
|
Module['onRuntimeInitialized'] = function() {
|
||||||
|
OLM_ERROR = Module['_olm_error']();
|
||||||
|
olm_exports["PRIVATE_KEY_LENGTH"] = Module['_olm_pk_private_key_length']();
|
||||||
|
if (onInitSuccess) onInitSuccess();
|
||||||
|
};
|
||||||
|
|
||||||
|
Module['onAbort'] = function(err) {
|
||||||
|
if (onInitFail) onInitFail(err);
|
||||||
|
};
|
||||||
|
|
3
javascript/olm_prefix.js
Normal file
3
javascript/olm_prefix.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
var olm_exports = {};
|
||||||
|
var onInitSuccess;
|
||||||
|
var onInitFail;
|
32
javascript/olm_suffix.js
Normal file
32
javascript/olm_suffix.js
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
var olmInitPromise;
|
||||||
|
|
||||||
|
olm_exports['init'] = function(opts) {
|
||||||
|
if (olmInitPromise) return olmInitPromise;
|
||||||
|
|
||||||
|
if (opts) OLM_OPTIONS = opts;
|
||||||
|
|
||||||
|
olmInitPromise = new Promise(function(resolve, reject) {
|
||||||
|
onInitSuccess = function() {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
onInitFail = function(err) {
|
||||||
|
reject(err);
|
||||||
|
};
|
||||||
|
Module();
|
||||||
|
});
|
||||||
|
return olmInitPromise;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof(window) !== 'undefined') {
|
||||||
|
// We've been imported directly into a browser. Define the global 'Olm' object.
|
||||||
|
// (we do this even if module.exports was defined, because it's useful to have
|
||||||
|
// Olm in the global scope for browserified and webpacked apps.)
|
||||||
|
window["Olm"] = olm_exports;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof module === 'object') {
|
||||||
|
// Emscripten sets the module exports to be its module
|
||||||
|
// with wrapped c functions. Clobber it with our higher
|
||||||
|
// level wrapper class.
|
||||||
|
module.exports = olm_exports;
|
||||||
|
}
|
|
@ -5,6 +5,7 @@
|
||||||
"main": "olm.js",
|
"main": "olm.js",
|
||||||
"files": [
|
"files": [
|
||||||
"olm.js",
|
"olm.js",
|
||||||
|
"olm.wasm",
|
||||||
"README.md"
|
"README.md"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -21,9 +22,13 @@ var Olm = require('../olm');
|
||||||
describe("megolm", function() {
|
describe("megolm", function() {
|
||||||
var aliceSession, bobSession;
|
var aliceSession, bobSession;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function(done) {
|
||||||
|
Olm.init().then(function() {
|
||||||
aliceSession = new Olm.OutboundGroupSession();
|
aliceSession = new Olm.OutboundGroupSession();
|
||||||
bobSession = new Olm.InboundGroupSession();
|
bobSession = new Olm.InboundGroupSession();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2016 OpenMarket Ltd
|
Copyright 2016 OpenMarket Ltd
|
||||||
|
Copyright 2018 New Vector Ltd
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -30,11 +31,18 @@ describe("olm", function() {
|
||||||
var aliceAccount, bobAccount;
|
var aliceAccount, bobAccount;
|
||||||
var aliceSession, bobSession;
|
var aliceSession, bobSession;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function(done) {
|
||||||
|
// This should really be in a beforeAll, but jasmine-node
|
||||||
|
// doesn't support that
|
||||||
|
debugger;
|
||||||
|
Olm.init().then(function() {
|
||||||
aliceAccount = new Olm.Account();
|
aliceAccount = new Olm.Account();
|
||||||
bobAccount = new Olm.Account();
|
bobAccount = new Olm.Account();
|
||||||
aliceSession = new Olm.Session();
|
aliceSession = new Olm.Session();
|
||||||
bobSession = new Olm.Session();
|
bobSession = new Olm.Session();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
|
|
|
@ -18,20 +18,16 @@ limitations under the License.
|
||||||
|
|
||||||
var Olm = require('../olm');
|
var Olm = require('../olm');
|
||||||
|
|
||||||
if (!Object.keys) {
|
|
||||||
Object.keys = function(o) {
|
|
||||||
var k=[], p;
|
|
||||||
for (p in o) if (Object.prototype.hasOwnProperty.call(o,p)) k.push(p);
|
|
||||||
return k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("pk", function() {
|
describe("pk", function() {
|
||||||
var encryption, decryption;
|
var encryption, decryption;
|
||||||
|
|
||||||
beforeEach(function() {
|
beforeEach(function(done) {
|
||||||
|
Olm.init().then(function() {
|
||||||
encryption = new Olm.PkEncryption();
|
encryption = new Olm.PkEncryption();
|
||||||
decryption = new Olm.PkDecryption();
|
decryption = new Olm.PkDecryption();
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
|
@ -45,6 +41,20 @@ describe("pk", function() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should import & export keys from private parts', function () {
|
||||||
|
var alice_private = new Uint8Array([
|
||||||
|
0x77, 0x07, 0x6D, 0x0A, 0x73, 0x18, 0xA5, 0x7D,
|
||||||
|
0x3C, 0x16, 0xC1, 0x72, 0x51, 0xB2, 0x66, 0x45,
|
||||||
|
0xDF, 0x4C, 0x2F, 0x87, 0xEB, 0xC0, 0x99, 0x2A,
|
||||||
|
0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
|
||||||
|
]);
|
||||||
|
var alice_public = decryption.init_with_private_key(alice_private);
|
||||||
|
expect(alice_public).toEqual("hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo");
|
||||||
|
|
||||||
|
var alice_private_out = decryption.get_private_key();
|
||||||
|
expect(alice_private_out).toEqual(alice_private);
|
||||||
|
});
|
||||||
|
|
||||||
it('should encrypt and decrypt', function () {
|
it('should encrypt and decrypt', function () {
|
||||||
var TEST_TEXT='têst1';
|
var TEST_TEXT='têst1';
|
||||||
var pubkey = decryption.generate_key();
|
var pubkey = decryption.generate_key();
|
||||||
|
|
|
@ -31,6 +31,7 @@ static const char * ERRORS[] = {
|
||||||
"UNKNOWN_MESSAGE_INDEX",
|
"UNKNOWN_MESSAGE_INDEX",
|
||||||
"BAD_LEGACY_ACCOUNT_PICKLE",
|
"BAD_LEGACY_ACCOUNT_PICKLE",
|
||||||
"BAD_SIGNATURE",
|
"BAD_SIGNATURE",
|
||||||
|
"OLM_INPUT_BUFFER_TOO_SMALL",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char * _olm_error_to_string(enum OlmErrorCode error)
|
const char * _olm_error_to_string(enum OlmErrorCode error)
|
||||||
|
|
97
src/pk.cpp
97
src/pk.cpp
|
@ -22,15 +22,15 @@
|
||||||
#include "olm/pickle_encoding.h"
|
#include "olm/pickle_encoding.h"
|
||||||
#include "olm/pickle.hh"
|
#include "olm/pickle.hh"
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
|
|
||||||
static const std::size_t MAC_LENGTH = 8;
|
static const std::size_t MAC_LENGTH = 8;
|
||||||
|
|
||||||
const struct _olm_cipher_aes_sha_256 olm_pk_cipher_aes_sha256 =
|
const struct _olm_cipher_aes_sha_256 olm_pk_cipher_aes_sha256 =
|
||||||
OLM_CIPHER_INIT_AES_SHA_256("");
|
OLM_CIPHER_INIT_AES_SHA_256("");
|
||||||
const struct _olm_cipher *olm_pk_cipher =
|
const struct _olm_cipher *olm_pk_cipher =
|
||||||
OLM_CIPHER_BASE(&olm_pk_cipher_aes_sha256);
|
OLM_CIPHER_BASE(&olm_pk_cipher_aes_sha256);
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
struct OlmPkEncryption {
|
struct OlmPkEncryption {
|
||||||
OlmErrorCode last_error;
|
OlmErrorCode last_error;
|
||||||
_olm_curve25519_public_key recipient_key;
|
_olm_curve25519_public_key recipient_key;
|
||||||
|
@ -73,7 +73,11 @@ size_t olm_pk_encryption_set_recipient_key (
|
||||||
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL; // FIXME:
|
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL; // FIXME:
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
olm::decode_base64((const uint8_t*)key, olm_pk_key_length(), (uint8_t *)encryption->recipient_key.public_key);
|
olm::decode_base64(
|
||||||
|
(const uint8_t*)key,
|
||||||
|
olm_pk_key_length(),
|
||||||
|
(uint8_t *)encryption->recipient_key.public_key
|
||||||
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +85,9 @@ size_t olm_pk_ciphertext_length(
|
||||||
OlmPkEncryption *encryption,
|
OlmPkEncryption *encryption,
|
||||||
size_t plaintext_length
|
size_t plaintext_length
|
||||||
) {
|
) {
|
||||||
return olm::encode_base64_length(_olm_cipher_aes_sha_256_ops.encrypt_ciphertext_length(olm_pk_cipher, plaintext_length));
|
return olm::encode_base64_length(
|
||||||
|
_olm_cipher_aes_sha_256_ops.encrypt_ciphertext_length(olm_pk_cipher, plaintext_length)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t olm_pk_mac_length(
|
size_t olm_pk_mac_length(
|
||||||
|
@ -122,11 +128,16 @@ size_t olm_pk_encrypt(
|
||||||
|
|
||||||
_olm_curve25519_key_pair ephemeral_keypair;
|
_olm_curve25519_key_pair ephemeral_keypair;
|
||||||
_olm_crypto_curve25519_generate_key((uint8_t *) random, &ephemeral_keypair);
|
_olm_crypto_curve25519_generate_key((uint8_t *) random, &ephemeral_keypair);
|
||||||
olm::encode_base64((const uint8_t *)ephemeral_keypair.public_key.public_key, CURVE25519_KEY_LENGTH, (uint8_t *)ephemeral_key);
|
olm::encode_base64(
|
||||||
|
(const uint8_t *)ephemeral_keypair.public_key.public_key,
|
||||||
|
CURVE25519_KEY_LENGTH,
|
||||||
|
(uint8_t *)ephemeral_key
|
||||||
|
);
|
||||||
|
|
||||||
olm::SharedKey secret;
|
olm::SharedKey secret;
|
||||||
_olm_crypto_curve25519_shared_secret(&ephemeral_keypair, &encryption->recipient_key, secret);
|
_olm_crypto_curve25519_shared_secret(&ephemeral_keypair, &encryption->recipient_key, secret);
|
||||||
size_t raw_ciphertext_length = _olm_cipher_aes_sha_256_ops.encrypt_ciphertext_length(olm_pk_cipher, plaintext_length);
|
size_t raw_ciphertext_length =
|
||||||
|
_olm_cipher_aes_sha_256_ops.encrypt_ciphertext_length(olm_pk_cipher, plaintext_length);
|
||||||
uint8_t *ciphertext_pos = (uint8_t *) ciphertext + ciphertext_length - raw_ciphertext_length;
|
uint8_t *ciphertext_pos = (uint8_t *) ciphertext + ciphertext_length - raw_ciphertext_length;
|
||||||
uint8_t raw_mac[MAC_LENGTH];
|
uint8_t raw_mac[MAC_LENGTH];
|
||||||
size_t result = _olm_cipher_aes_sha_256_ops.encrypt(
|
size_t result = _olm_cipher_aes_sha_256_ops.encrypt(
|
||||||
|
@ -176,35 +187,51 @@ size_t olm_clear_pk_decryption(
|
||||||
return sizeof(OlmPkDecryption);
|
return sizeof(OlmPkDecryption);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t olm_pk_generate_key_random_length(void) {
|
size_t olm_pk_private_key_length(void) {
|
||||||
return CURVE25519_KEY_LENGTH;
|
return CURVE25519_KEY_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t olm_pk_generate_key_random_length(void) {
|
||||||
|
return olm_pk_private_key_length();
|
||||||
|
}
|
||||||
|
|
||||||
size_t olm_pk_key_length(void) {
|
size_t olm_pk_key_length(void) {
|
||||||
return olm::encode_base64_length(CURVE25519_KEY_LENGTH);
|
return olm::encode_base64_length(CURVE25519_KEY_LENGTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t olm_pk_generate_key(
|
size_t olm_pk_key_from_private(
|
||||||
OlmPkDecryption * decryption,
|
OlmPkDecryption * decryption,
|
||||||
void * pubkey, size_t pubkey_length,
|
void * pubkey, size_t pubkey_length,
|
||||||
void * random, size_t random_length
|
void * privkey, size_t privkey_length
|
||||||
) {
|
) {
|
||||||
if (pubkey_length < CURVE25519_KEY_LENGTH) {
|
if (pubkey_length < olm_pk_key_length()) {
|
||||||
decryption->last_error =
|
decryption->last_error =
|
||||||
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
|
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
if (random_length < olm_pk_generate_key_random_length()) {
|
if (privkey_length < olm_pk_private_key_length()) {
|
||||||
decryption->last_error =
|
decryption->last_error =
|
||||||
OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
|
OlmErrorCode::OLM_INPUT_BUFFER_TOO_SMALL;
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
_olm_crypto_curve25519_generate_key((uint8_t *) random, &decryption->key_pair);
|
_olm_crypto_curve25519_generate_key((uint8_t *) privkey, &decryption->key_pair);
|
||||||
olm::encode_base64((const uint8_t *)decryption->key_pair.public_key.public_key, CURVE25519_KEY_LENGTH, (uint8_t *)pubkey);
|
olm::encode_base64(
|
||||||
|
(const uint8_t *)decryption->key_pair.public_key.public_key,
|
||||||
|
CURVE25519_KEY_LENGTH,
|
||||||
|
(uint8_t *)pubkey
|
||||||
|
);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t olm_pk_generate_key(
|
||||||
|
OlmPkDecryption * decryption,
|
||||||
|
void * pubkey, size_t pubkey_length,
|
||||||
|
void * privkey, size_t privkey_length
|
||||||
|
) {
|
||||||
|
return olm_pk_key_from_private(decryption, pubkey, pubkey_length, privkey, privkey_length);
|
||||||
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
static const std::uint32_t PK_DECRYPTION_PICKLE_VERSION = 1;
|
static const std::uint32_t PK_DECRYPTION_PICKLE_VERSION = 1;
|
||||||
|
|
||||||
|
@ -267,7 +294,10 @@ size_t olm_pickle_pk_decryption(
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
pickle(_olm_enc_output_pos(reinterpret_cast<std::uint8_t *>(pickled), raw_length), object);
|
pickle(_olm_enc_output_pos(reinterpret_cast<std::uint8_t *>(pickled), raw_length), object);
|
||||||
return _olm_enc_output(reinterpret_cast<std::uint8_t const *>(key), key_length, reinterpret_cast<std::uint8_t *>(pickled), raw_length);
|
return _olm_enc_output(
|
||||||
|
reinterpret_cast<std::uint8_t const *>(key), key_length,
|
||||||
|
reinterpret_cast<std::uint8_t *>(pickled), raw_length
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t olm_unpickle_pk_decryption(
|
size_t olm_unpickle_pk_decryption(
|
||||||
|
@ -283,7 +313,8 @@ size_t olm_unpickle_pk_decryption(
|
||||||
}
|
}
|
||||||
std::uint8_t * const pos = reinterpret_cast<std::uint8_t *>(pickled);
|
std::uint8_t * const pos = reinterpret_cast<std::uint8_t *>(pickled);
|
||||||
std::size_t raw_length = _olm_enc_input(
|
std::size_t raw_length = _olm_enc_input(
|
||||||
reinterpret_cast<std::uint8_t const *>(key), key_length, pos, pickled_length, &object.last_error
|
reinterpret_cast<std::uint8_t const *>(key), key_length,
|
||||||
|
pos, pickled_length, &object.last_error
|
||||||
);
|
);
|
||||||
if (raw_length == std::size_t(-1)) {
|
if (raw_length == std::size_t(-1)) {
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
|
@ -300,7 +331,11 @@ size_t olm_unpickle_pk_decryption(
|
||||||
return std::size_t(-1);
|
return std::size_t(-1);
|
||||||
}
|
}
|
||||||
if (pubkey != NULL) {
|
if (pubkey != NULL) {
|
||||||
olm::encode_base64((const uint8_t *)object.key_pair.public_key.public_key, CURVE25519_KEY_LENGTH, (uint8_t *)pubkey);
|
olm::encode_base64(
|
||||||
|
(const uint8_t *)object.key_pair.public_key.public_key,
|
||||||
|
CURVE25519_KEY_LENGTH,
|
||||||
|
(uint8_t *)pubkey
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return pickled_length;
|
return pickled_length;
|
||||||
}
|
}
|
||||||
|
@ -309,7 +344,9 @@ size_t olm_pk_max_plaintext_length(
|
||||||
OlmPkDecryption * decryption,
|
OlmPkDecryption * decryption,
|
||||||
size_t ciphertext_length
|
size_t ciphertext_length
|
||||||
) {
|
) {
|
||||||
return _olm_cipher_aes_sha_256_ops.decrypt_max_plaintext_length(olm_pk_cipher, olm::decode_base64_length(ciphertext_length));
|
return _olm_cipher_aes_sha_256_ops.decrypt_max_plaintext_length(
|
||||||
|
olm_pk_cipher, olm::decode_base64_length(ciphertext_length)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t olm_pk_decrypt(
|
size_t olm_pk_decrypt(
|
||||||
|
@ -327,7 +364,10 @@ size_t olm_pk_decrypt(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct _olm_curve25519_public_key ephemeral;
|
struct _olm_curve25519_public_key ephemeral;
|
||||||
olm::decode_base64((const uint8_t*)ephemeral_key, ephemeral_key_length, (uint8_t *)ephemeral.public_key);
|
olm::decode_base64(
|
||||||
|
(const uint8_t*)ephemeral_key, ephemeral_key_length,
|
||||||
|
(uint8_t *)ephemeral.public_key
|
||||||
|
);
|
||||||
olm::SharedKey secret;
|
olm::SharedKey secret;
|
||||||
_olm_crypto_curve25519_shared_secret(&decryption->key_pair, &ephemeral, secret);
|
_olm_crypto_curve25519_shared_secret(&decryption->key_pair, &ephemeral, secret);
|
||||||
uint8_t raw_mac[MAC_LENGTH];
|
uint8_t raw_mac[MAC_LENGTH];
|
||||||
|
@ -352,4 +392,21 @@ size_t olm_pk_decrypt(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t olm_pk_get_private_key(
|
||||||
|
OlmPkDecryption * decryption,
|
||||||
|
void *private_key, size_t private_key_length
|
||||||
|
) {
|
||||||
|
if (private_key_length < olm_pk_private_key_length()) {
|
||||||
|
decryption->last_error =
|
||||||
|
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
|
||||||
|
return std::size_t(-1);
|
||||||
|
}
|
||||||
|
std::memcpy(
|
||||||
|
private_key,
|
||||||
|
decryption->key_pair.private_key.private_key,
|
||||||
|
olm_pk_private_key_length()
|
||||||
|
);
|
||||||
|
return olm_pk_private_key_length();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ std::uint8_t alice_private[32] = {
|
||||||
0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
|
0xB1, 0x77, 0xFB, 0xA5, 0x1D, 0xB9, 0x2C, 0x2A
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::uint8_t *alice_public = (std::uint8_t *) "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmoK";
|
const std::uint8_t *alice_public = (std::uint8_t *) "hSDwCYkwp1R0i33ctD73Wg2/Og0mOBr066SpjqqbTmo";
|
||||||
|
|
||||||
std::uint8_t bob_private[32] = {
|
std::uint8_t bob_private[32] = {
|
||||||
0x5D, 0xAB, 0x08, 0x7E, 0x62, 0x4A, 0x8A, 0x4B,
|
0x5D, 0xAB, 0x08, 0x7E, 0x62, 0x4A, 0x8A, 0x4B,
|
||||||
|
@ -32,11 +32,11 @@ std::uint8_t bob_private[32] = {
|
||||||
0x1C, 0x2F, 0x8B, 0x27, 0xFF, 0x88, 0xE0, 0xEB
|
0x1C, 0x2F, 0x8B, 0x27, 0xFF, 0x88, 0xE0, 0xEB
|
||||||
};
|
};
|
||||||
|
|
||||||
const std::uint8_t *bob_public = (std::uint8_t *) "3p7bfXt9wbTTW2HC7OQ1Nz+DQ8hbeGdNrfx+FG+IK08K";
|
const std::uint8_t *bob_public = (std::uint8_t *) "3p7bfXt9wbTTW2HC7OQ1Nz+DQ8hbeGdNrfx+FG+IK08";
|
||||||
|
|
||||||
std::uint8_t pubkey[::olm_pk_key_length()];
|
std::uint8_t pubkey[::olm_pk_key_length()];
|
||||||
|
|
||||||
olm_pk_generate_key(
|
olm_pk_key_from_private(
|
||||||
decryption,
|
decryption,
|
||||||
pubkey, sizeof(pubkey),
|
pubkey, sizeof(pubkey),
|
||||||
alice_private, sizeof(alice_private)
|
alice_private, sizeof(alice_private)
|
||||||
|
@ -44,6 +44,11 @@ olm_pk_generate_key(
|
||||||
|
|
||||||
assert_equals(alice_public, pubkey, olm_pk_key_length());
|
assert_equals(alice_public, pubkey, olm_pk_key_length());
|
||||||
|
|
||||||
|
uint8_t *alice_private_back_out = (uint8_t *)malloc(olm_pk_private_key_length());
|
||||||
|
olm_pk_get_private_key(decryption, alice_private_back_out, olm_pk_private_key_length());
|
||||||
|
assert_equals(alice_private, alice_private_back_out, olm_pk_private_key_length());
|
||||||
|
free(alice_private_back_out);
|
||||||
|
|
||||||
std::uint8_t encryption_buffer[olm_pk_encryption_size()];
|
std::uint8_t encryption_buffer[olm_pk_encryption_size()];
|
||||||
OlmPkEncryption *encryption = olm_pk_encryption(encryption_buffer);
|
OlmPkEncryption *encryption = olm_pk_encryption(encryption_buffer);
|
||||||
|
|
||||||
|
@ -105,7 +110,7 @@ const std::uint8_t *alice_public = (std::uint8_t *) "hSDwCYkwp1R0i33ctD73Wg2/Og0
|
||||||
|
|
||||||
std::uint8_t pubkey[olm_pk_key_length()];
|
std::uint8_t pubkey[olm_pk_key_length()];
|
||||||
|
|
||||||
olm_pk_generate_key(
|
olm_pk_key_from_private(
|
||||||
decryption,
|
decryption,
|
||||||
pubkey, sizeof(pubkey),
|
pubkey, sizeof(pubkey),
|
||||||
alice_private, sizeof(alice_private)
|
alice_private, sizeof(alice_private)
|
||||||
|
|
Loading…
Reference in a new issue