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>`_
|
||||
|
||||
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++
|
||||
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
|
||||
DEBUG_TARGET := $(BUILD_DIR)/libolm_debug.so.$(VERSION)
|
||||
JS_TARGET := javascript/olm.js
|
||||
DEBUG_TARGET := $(BUILD_DIR)/libolm_debug.$(SO).$(VERSION)
|
||||
JS_WASM_TARGET := javascript/olm.js
|
||||
JS_ASMJS_TARGET := javascript/olm_legacy.js
|
||||
|
||||
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
|
||||
|
||||
|
@ -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))
|
||||
TEST_BINARIES := $(patsubst tests/%,$(BUILD_DIR)/tests/%,$(basename $(TEST_SOURCES)))
|
||||
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_POST := javascript/olm_outbound_group_session.js \
|
||||
javascript/olm_inbound_group_session.js \
|
||||
javascript/olm_pk.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/megolm.html \
|
||||
docs/olm.html \
|
||||
|
@ -60,11 +84,23 @@ CFLAGS += -Wall -Werror -std=c99 -fPIC
|
|||
CXXFLAGS += -Wall -Werror -std=c++11 -fPIC
|
||||
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
|
||||
# longer needed.
|
||||
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.cc = $(EMCC) $(CXXFLAGS) $(CPPFLAGS) -c
|
||||
EMCC_LINK = $(EMCC) $(LDFLAGS) $(EMCCFLAGS)
|
||||
|
@ -99,7 +135,8 @@ $(FUZZER_DEBUG_BINARIES): LDFLAGS += $(DEBUG_OPTIMIZE_FLAGS)
|
|||
|
||||
$(JS_OBJECTS): CFLAGS += $(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
|
||||
ifeq ($(shell echo "check_quotes"),"check_quotes")
|
||||
|
@ -121,21 +158,19 @@ lib: $(RELEASE_TARGET)
|
|||
|
||||
$(RELEASE_TARGET): $(RELEASE_OBJECTS)
|
||||
$(CXX) $(LDFLAGS) --shared -fPIC \
|
||||
-Wl,-soname,libolm.so.$(MAJOR) \
|
||||
-Wl,--version-script,version_script.ver \
|
||||
$(OLM_LDFLAGS) \
|
||||
$(OUTPUT_OPTION) $(RELEASE_OBJECTS)
|
||||
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).$(MAJOR)
|
||||
ln -sf libolm.$(SO).$(VERSION) $(BUILD_DIR)/libolm.$(SO)
|
||||
|
||||
debug: $(DEBUG_TARGET)
|
||||
.PHONY: debug
|
||||
|
||||
$(DEBUG_TARGET): $(DEBUG_OBJECTS)
|
||||
$(CXX) $(LDFLAGS) --shared -fPIC \
|
||||
-Wl,-soname,libolm_debug.so.$(MAJOR) \
|
||||
-Wl,--version-script,version_script.ver \
|
||||
$(OLM_LDFLAGS) \
|
||||
$(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)
|
||||
.PHONY: static
|
||||
|
@ -143,15 +178,35 @@ static: $(STATIC_RELEASE_TARGET)
|
|||
$(STATIC_RELEASE_TARGET): $(RELEASE_OBJECTS)
|
||||
$(AR) rcs $@ $^
|
||||
|
||||
js: $(JS_TARGET)
|
||||
js: $(JS_WASM_TARGET) $(JS_ASMJS_TARGET)
|
||||
.PHONY: js
|
||||
|
||||
$(JS_TARGET): $(JS_OBJECTS) $(JS_PRE) $(JS_POST) $(JS_EXPORTED_FUNCTIONS)
|
||||
$(EMCC_LINK) \
|
||||
# Note that the output file we give to emcc determines the name of the
|
||||
# wasm file baked into the js, hence messing around outputting to olm.js
|
||||
# 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_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
|
||||
|
||||
$(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)
|
||||
|
||||
|
@ -165,7 +220,7 @@ fuzzers: $(FUZZER_BINARIES) $(FUZZER_DEBUG_BINARIES)
|
|||
.PHONY: fuzzers
|
||||
|
||||
$(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 $@
|
||||
|
||||
all: test js lib debug doc
|
||||
|
@ -178,16 +233,16 @@ install-headers: $(PUBLIC_HEADERS)
|
|||
|
||||
install-debug: debug install-headers
|
||||
test -d $(DESTDIR)$(PREFIX)/lib || $(call mkdir,$(DESTDIR)$(PREFIX)/lib)
|
||||
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
|
||||
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)
|
||||
.PHONY: install-debug
|
||||
|
||||
install: lib install-headers
|
||||
test -d $(DESTDIR)$(PREFIX)/lib || $(call mkdir,$(DESTDIR)$(PREFIX)/lib)
|
||||
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
|
||||
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)
|
||||
.PHONY: install
|
||||
|
||||
clean:;
|
||||
|
|
|
@ -31,6 +31,9 @@ To build the javascript bindings, install emscripten from http://kripken.github.
|
|||
|
||||
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:
|
||||
|
||||
.. code:: bash
|
||||
|
|
|
@ -25,6 +25,8 @@ import java.io.ObjectInputStream;
|
|||
import java.io.ObjectOutputStream;
|
||||
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>
|
||||
* 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.
|
||||
* @param aEncryptedMsg the message to be decrypted
|
||||
* @return the decrypted message information
|
||||
* @exception OlmException teh failure reason
|
||||
* @exception OlmException the failure reason
|
||||
*/
|
||||
public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws OlmException {
|
||||
DecryptMessageResult result = new DecryptMessageResult();
|
||||
|
@ -246,6 +248,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
|
|||
|
||||
if (null != decryptedMessageBuffer) {
|
||||
result.mDecryptedMessage = new String(decryptedMessageBuffer, "UTF-8");
|
||||
Arrays.fill(decryptedMessageBuffer, (byte) 0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage());
|
||||
|
|
|
@ -26,6 +26,8 @@ import java.io.ObjectInputStream;
|
|||
import java.io.ObjectOutputStream;
|
||||
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>
|
||||
* 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)) {
|
||||
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) {
|
||||
retValue = new String(encryptedBuffer , "UTF-8");
|
||||
|
|
|
@ -18,6 +18,8 @@ package org.matrix.olm;
|
|||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class OlmPkDecryption {
|
||||
private static final String LOG_TAG = "OlmPkDecryption";
|
||||
|
||||
|
@ -67,7 +69,10 @@ public class OlmPkDecryption {
|
|||
}
|
||||
|
||||
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) {
|
||||
Log.e(LOG_TAG, "## pkDecrypt(): failed " + 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 java.util.Arrays;
|
||||
|
||||
public class OlmPkEncryption {
|
||||
private static final String LOG_TAG = "OlmPkEncryption";
|
||||
|
||||
|
@ -72,7 +74,9 @@ public class OlmPkEncryption {
|
|||
OlmPkMessage encryptedMsgRetValue = new OlmPkMessage();
|
||||
|
||||
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) {
|
||||
encryptedMsgRetValue.mCipherText = new String(ciphertextBuffer, "UTF-8");
|
||||
|
|
|
@ -25,6 +25,8 @@ import java.io.ObjectInputStream;
|
|||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* 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>
|
||||
|
@ -295,7 +297,9 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
|
|||
OlmMessage encryptedMsgRetValue = new OlmMessage();
|
||||
|
||||
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) {
|
||||
encryptedMsgRetValue.mCipherText = new String(encryptedMessageBuffer, "UTF-8");
|
||||
|
@ -330,7 +334,10 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
|
|||
}
|
||||
|
||||
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) {
|
||||
Log.e(LOG_TAG, "## decryptMessage(): failed " + 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;
|
||||
jbyte* clearMsgPtr = NULL;
|
||||
jboolean clearMsgIsCopied = JNI_FALSE;
|
||||
|
||||
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");
|
||||
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");
|
||||
errorMessage = "clear message JNI allocation OOM";
|
||||
|
@ -359,6 +360,10 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE
|
|||
// free alloc
|
||||
if (clearMsgPtr)
|
||||
{
|
||||
if (clearMsgIsCopied)
|
||||
{
|
||||
memset(clearMsgPtr, 0, (size_t)env->GetArrayLength(aClearMsgBuffer));
|
||||
}
|
||||
env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,10 @@ OlmPkEncryption * initializePkEncryptionMemory()
|
|||
{
|
||||
// init encryption object
|
||||
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
|
||||
{
|
||||
|
@ -53,7 +56,10 @@ JNIEXPORT jlong OLM_PK_ENCRYPTION_FUNC_DEF(createNewPkEncryptionJni)(JNIEnv *env
|
|||
else
|
||||
{
|
||||
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)
|
||||
|
@ -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;
|
||||
jbyte *keyPtr = NULL;
|
||||
|
||||
|
@ -116,10 +123,13 @@ JNIEXPORT void OLM_PK_ENCRYPTION_FUNC_DEF(setRecipientKeyJni)(JNIEnv *env, jobje
|
|||
}
|
||||
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);
|
||||
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;
|
||||
const char* errorMessage = NULL;
|
||||
jbyte *plaintextPtr = NULL;
|
||||
jboolean plaintextIsCopied = JNI_FALSE;
|
||||
|
||||
OlmPkEncryption *encryptionPtr = getPkEncryptionInstanceId(env, thiz);
|
||||
jclass encryptedMsgJClass = 0;
|
||||
|
@ -154,15 +166,15 @@ JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(JNIEnv *env, jobject
|
|||
LOGE(" ## pkEncryptJni(): failure - 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");
|
||||
errorMessage = "plaintext JNI allocation OOM";
|
||||
}
|
||||
else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg)))
|
||||
{
|
||||
LOGE(" ## pkEncryptJni(): failure - unable to get crypted message class");
|
||||
errorMessage = "unable to get crypted message class";
|
||||
LOGE(" ## pkEncryptJni(): failure - unable to get encrypted message class");
|
||||
errorMessage = "unable to get encrypted message class";
|
||||
}
|
||||
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
|
||||
{
|
||||
encryptedMsgRet = env->NewByteArray(ciphertextLength);
|
||||
env->SetByteArrayRegion(encryptedMsgRet, 0, ciphertextLength, (jbyte*)ciphertextPtr);
|
||||
env->SetByteArrayRegion(
|
||||
encryptedMsgRet, 0, ciphertextLength, (jbyte*)ciphertextPtr
|
||||
);
|
||||
|
||||
jstring macStr = env->NewStringUTF((char*)macPtr);
|
||||
env->SetObjectField(aEncryptedMsg, macFieldId, macStr);
|
||||
|
@ -256,6 +270,10 @@ JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(JNIEnv *env, jobject
|
|||
|
||||
if (plaintextPtr)
|
||||
{
|
||||
if (plaintextIsCopied)
|
||||
{
|
||||
memset(plaintextPtr, 0, (size_t)env->GetArrayLength(aPlaintextBuffer));
|
||||
}
|
||||
env->ReleaseByteArrayElements(aPlaintextBuffer, plaintextPtr, JNI_ABORT);
|
||||
}
|
||||
|
||||
|
@ -276,7 +294,10 @@ OlmPkDecryption * initializePkDecryptionMemory()
|
|||
{
|
||||
// init decryption object
|
||||
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
|
||||
{
|
||||
|
@ -300,7 +321,10 @@ JNIEXPORT jlong OLM_PK_DECRYPTION_FUNC_DEF(createNewPkDecryptionJni)(JNIEnv *env
|
|||
else
|
||||
{
|
||||
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)
|
||||
|
@ -402,8 +426,9 @@ JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(generateKeyJni)(JNIEnv *env, job
|
|||
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;
|
||||
OlmPkDecryption *decryptionPtr = getPkDecryptionInstanceId(env, thiz);
|
||||
|
||||
|
@ -528,7 +553,10 @@ JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(decryptJni)(JNIEnv *env, jobject
|
|||
{
|
||||
decryptedMsgRet = env->NewByteArray(plaintextLength);
|
||||
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)
|
||||
{
|
||||
memset(plaintextPtr, 0, maxPlaintextLength);
|
||||
free(plaintextPtr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -472,6 +472,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
|
|||
|
||||
OlmSession *sessionPtr = getSessionInstanceId(env, thiz);
|
||||
jbyte *clearMsgPtr = NULL;
|
||||
jboolean clearMsgIsCopied = JNI_FALSE;
|
||||
jclass encryptedMsgJClass = 0;
|
||||
jfieldID typeMsgFieldId;
|
||||
|
||||
|
@ -490,8 +491,9 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
|
|||
else if (!aEncryptedMsg)
|
||||
{
|
||||
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");
|
||||
errorMessage = "clear message JNI allocation OOM";
|
||||
|
@ -580,6 +582,10 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec
|
|||
// free alloc
|
||||
if (clearMsgPtr)
|
||||
{
|
||||
if (clearMsgIsCopied)
|
||||
{
|
||||
memset(clearMsgPtr, 0, (size_t)env->GetArrayLength(aClearMsgBuffer));
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
memset(plainTextMsgPtr, 0, maxPlainTextLength);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -958,4 +966,4 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz,
|
|||
}
|
||||
|
||||
return (jlong)(intptr_t)sessionPtr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,7 +72,7 @@ info.
|
|||
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
|
||||
previous chain key as the key.
|
||||
|
||||
|
@ -338,7 +338,7 @@ The Olm specification (this document) is hereby placed in the public domain.
|
|||
Feedback
|
||||
--------
|
||||
|
||||
Can be sent to mark at matrix.org.
|
||||
Can be sent to olm at matrix.org.
|
||||
|
||||
Acknowledgements
|
||||
----------------
|
||||
|
|
|
@ -113,6 +113,6 @@ This document is licensed under the `Apache License, Version 2.0
|
|||
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/
|
||||
|
|
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_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
|
||||
* this list. */
|
||||
};
|
||||
|
|
|
@ -72,11 +72,15 @@ size_t olm_pk_encrypt_random_length(
|
|||
);
|
||||
|
||||
/** Encrypt a plaintext for the recipient set using
|
||||
* olm_pk_encryption_set_recipient_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
|
||||
* "NOT_ENOUGH_RANDOM". */
|
||||
* olm_pk_encryption_set_recipient_key. Writes to the ciphertext, mac, and
|
||||
* ephemeral_key buffers, whose values should be sent to the recipient. mac is
|
||||
* a Message Authentication Code to ensure that the data is received and
|
||||
* decrypted properly. ephemeral_key is the public part of the ephemeral key
|
||||
* 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(
|
||||
OlmPkEncryption *encryption,
|
||||
void const * plaintext, size_t plaintext_length,
|
||||
|
@ -108,18 +112,36 @@ size_t olm_clear_pk_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);
|
||||
|
||||
/** Generate a new key to use for decrypting messages. The associated public
|
||||
* key will be written to the pubkey buffer. Returns olm_error() on failure. If
|
||||
* the pubkey buffer is too small then olm_pk_decryption_last_error() will be
|
||||
* "OUTPUT_BUFFER_TOO_SMALL". If there weren't enough random bytes then
|
||||
* olm_pk_decryption_last_error() will be "NOT_ENOUGH_RANDOM". */
|
||||
/** Initialise the key from the private part of a key as returned by
|
||||
* olm_pk_get_private_key(). The associated public key will be written to the
|
||||
* pubkey buffer. Returns olm_error() on failure. If the pubkey buffer is too
|
||||
* small then olm_pk_decryption_last_error() will be "OUTPUT_BUFFER_TOO_SMALL".
|
||||
* 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(
|
||||
OlmPkDecryption * decryption,
|
||||
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. */
|
||||
|
@ -159,18 +181,32 @@ size_t olm_pk_max_plaintext_length(
|
|||
size_t ciphertext_length
|
||||
);
|
||||
|
||||
/** Decrypt a ciphertext. The input ciphertext buffer is destroyed. Returns
|
||||
* the length of the plaintext on success. Returns olm_error() on failure. If
|
||||
* the plaintext buffer is too small then olm_pk_encryption_last_error() will
|
||||
* be "OUTPUT_BUFFER_TOO_SMALL". */
|
||||
/** Decrypt a ciphertext. The input ciphertext buffer is destroyed. See the
|
||||
* olm_pk_encrypt function for descriptions of the ephemeral_key and mac
|
||||
* arguments. Returns the length of the plaintext on success. Returns
|
||||
* 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(
|
||||
OlmPkDecryption * decrytion,
|
||||
OlmPkDecryption * decryption,
|
||||
void const * ephemeral_key, size_t ephemeral_key_length,
|
||||
void const * mac, size_t mac_length,
|
||||
void * ciphertext, size_t ciphertext_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
|
||||
}
|
||||
#endif
|
||||
|
|
1
javascript/.gitignore
vendored
1
javascript/.gitignore
vendored
|
@ -2,4 +2,5 @@
|
|||
/node_modules
|
||||
/npm-debug.log
|
||||
/olm.js
|
||||
/olm.wasm
|
||||
/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() {
|
||||
var size = Module['_olm_inbound_group_session_size']();
|
||||
this.buf = malloc(size);
|
||||
|
@ -77,14 +71,14 @@ InboundGroupSession.prototype['decrypt'] = restore_stack(function(
|
|||
|
||||
try {
|
||||
message_buffer = malloc(message.length);
|
||||
Module['writeAsciiToMemory'](message, message_buffer, true);
|
||||
writeAsciiToMemory(message, message_buffer, true);
|
||||
|
||||
var max_plaintext_length = inbound_group_session_method(
|
||||
Module['_olm_group_decrypt_max_plaintext_length']
|
||||
)(this.ptr, message_buffer, message.length);
|
||||
|
||||
// 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);
|
||||
var message_index = stack(4);
|
||||
|
@ -100,14 +94,14 @@ InboundGroupSession.prototype['decrypt'] = restore_stack(function(
|
|||
|
||||
// UTF8ToString requires a null-terminated argument, so add the
|
||||
// null terminator.
|
||||
Module['setValue'](
|
||||
setValue(
|
||||
plaintext_buffer+plaintext_length,
|
||||
0, "i8"
|
||||
);
|
||||
|
||||
return {
|
||||
"plaintext": UTF8ToString(plaintext_buffer),
|
||||
"message_index": Module['getValue'](message_index, "i32")
|
||||
"message_index": getValue(message_index, "i32")
|
||||
}
|
||||
} finally {
|
||||
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() {
|
||||
var size = Module['_olm_outbound_group_session_size']();
|
||||
this.buf = malloc(size);
|
||||
|
@ -66,7 +59,7 @@ OutboundGroupSession.prototype['create'] = restore_stack(function() {
|
|||
OutboundGroupSession.prototype['encrypt'] = function(plaintext) {
|
||||
var plaintext_buffer, message_buffer, plaintext_length;
|
||||
try {
|
||||
plaintext_length = Module['lengthBytesUTF8'](plaintext);
|
||||
plaintext_length = lengthBytesUTF8(plaintext);
|
||||
|
||||
var message_length = outbound_group_session_method(
|
||||
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
|
||||
// writes), hence + 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);
|
||||
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
|
||||
// null terminator.
|
||||
Module['setValue'](
|
||||
setValue(
|
||||
message_buffer+message_length,
|
||||
0, "i8"
|
||||
);
|
||||
|
||||
return Module['UTF8ToString'](message_buffer);
|
||||
return UTF8ToString(message_buffer);
|
||||
} finally {
|
||||
if (plaintext_buffer !== undefined) {
|
||||
// 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;
|
||||
try {
|
||||
plaintext_length = Module['lengthBytesUTF8'](plaintext)
|
||||
plaintext_length = lengthBytesUTF8(plaintext)
|
||||
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(
|
||||
Module['_olm_pk_encrypt_random_length']
|
||||
)();
|
||||
|
@ -50,16 +50,16 @@ PkEncryption.prototype['encrypt'] = restore_stack(function(
|
|||
Module['_olm_pk_mac_length']
|
||||
)(this.ptr);
|
||||
var mac_buffer = stack(mac_length + NULL_BYTE_PADDING_LENGTH);
|
||||
Module['setValue'](
|
||||
mac_buffer+mac_length,
|
||||
setValue(
|
||||
mac_buffer + mac_length,
|
||||
0, "i8"
|
||||
);
|
||||
var ephemeral_length = pk_encryption_method(
|
||||
Module['_olm_pk_key_length']
|
||||
)();
|
||||
var ephemeral_buffer = stack(ephemeral_length + NULL_BYTE_PADDING_LENGTH);
|
||||
Module['setValue'](
|
||||
ephemeral_buffer+ephemeral_length,
|
||||
setValue(
|
||||
ephemeral_buffer + ephemeral_length,
|
||||
0, "i8"
|
||||
);
|
||||
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
|
||||
// null terminator.
|
||||
Module['setValue'](
|
||||
ciphertext_buffer+ciphertext_length,
|
||||
setValue(
|
||||
ciphertext_buffer + ciphertext_length,
|
||||
0, "i8"
|
||||
);
|
||||
return {
|
||||
"ciphertext": Module['UTF8ToString'](ciphertext_buffer),
|
||||
"ciphertext": UTF8ToString(ciphertext_buffer),
|
||||
"mac": Pointer_stringify(mac_buffer),
|
||||
"ephemeral": Pointer_stringify(ephemeral_buffer)
|
||||
};
|
||||
|
@ -118,16 +118,32 @@ PkDecryption.prototype['free'] = function() {
|
|||
free(this.ptr);
|
||||
}
|
||||
|
||||
PkDecryption.prototype['generate_key'] = restore_stack(function () {
|
||||
var random_length = pk_decryption_method(
|
||||
Module['_olm_pk_generate_key_random_length']
|
||||
)();
|
||||
var random_buffer = random_stack(random_length);
|
||||
var pubkey_length = pk_encryption_method(
|
||||
PkDecryption.prototype['init_with_private_key'] = restore_stack(function (private_key) {
|
||||
var private_key_buffer = stack(private_key.length);
|
||||
Module['HEAPU8'].set(private_key, private_key_buffer);
|
||||
|
||||
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_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,
|
||||
pubkey_buffer, pubkey_length,
|
||||
random_buffer, random_length
|
||||
|
@ -135,6 +151,18 @@ PkDecryption.prototype['generate_key'] = restore_stack(function () {
|
|||
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) {
|
||||
var key_array = array_from_string(key);
|
||||
var pickle_length = pk_decryption_method(
|
||||
|
@ -169,9 +197,9 @@ PkDecryption.prototype['decrypt'] = restore_stack(function (
|
|||
) {
|
||||
var plaintext_buffer, ciphertext_buffer, plaintext_max_length;
|
||||
try {
|
||||
ciphertext_length = Module['lengthBytesUTF8'](ciphertext)
|
||||
var ciphertext_length = lengthBytesUTF8(ciphertext)
|
||||
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_buffer = stack(ephemeralkey_array);
|
||||
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
|
||||
// null terminator.
|
||||
Module['setValue'](
|
||||
plaintext_buffer+plaintext_length,
|
||||
setValue(
|
||||
plaintext_buffer + plaintext_length,
|
||||
0, "i8"
|
||||
);
|
||||
return Module['UTF8ToString'](plaintext_buffer);
|
||||
return UTF8ToString(plaintext_buffer);
|
||||
} finally {
|
||||
if (plaintext_buffer !== undefined) {
|
||||
// don't leave a copy of the plaintext in the heap.
|
||||
|
|
|
@ -1,27 +1,17 @@
|
|||
var runtime = Module['Runtime'];
|
||||
var malloc = Module['_malloc'];
|
||||
var free = Module['_free'];
|
||||
var Pointer_stringify = Module['Pointer_stringify'];
|
||||
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;
|
||||
var OLM_ERROR;
|
||||
|
||||
/* allocate a number of bytes of storage on the stack.
|
||||
*
|
||||
* If size_or_array is a Number, allocates that number of zero-initialised bytes.
|
||||
*/
|
||||
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) {
|
||||
return Module['intArrayFromString'](string, true);
|
||||
return intArrayFromString(string, true);
|
||||
}
|
||||
|
||||
function random_stack(size) {
|
||||
|
@ -33,11 +23,11 @@ function random_stack(size) {
|
|||
|
||||
function restore_stack(wrapped) {
|
||||
return function() {
|
||||
var sp = runtime.stackSave();
|
||||
var sp = stackSave();
|
||||
try {
|
||||
return wrapped.apply(this, arguments);
|
||||
} finally {
|
||||
runtime.stackRestore(sp);
|
||||
stackRestore(sp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +305,7 @@ Session.prototype['encrypt'] = restore_stack(function(
|
|||
Module['_olm_encrypt_message_type']
|
||||
)(this.ptr);
|
||||
|
||||
plaintext_length = Module['lengthBytesUTF8'](plaintext);
|
||||
plaintext_length = lengthBytesUTF8(plaintext);
|
||||
var message_length = session_method(
|
||||
Module['_olm_encrypt_message_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
|
||||
// writes), hence + 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);
|
||||
|
||||
|
@ -338,14 +328,14 @@ Session.prototype['encrypt'] = restore_stack(function(
|
|||
|
||||
// UTF8ToString requires a null-terminated argument, so add the
|
||||
// null terminator.
|
||||
Module['setValue'](
|
||||
setValue(
|
||||
message_buffer+message_length,
|
||||
0, "i8"
|
||||
);
|
||||
|
||||
return {
|
||||
"type": message_type,
|
||||
"body": Module['UTF8ToString'](message_buffer),
|
||||
"body": UTF8ToString(message_buffer),
|
||||
};
|
||||
} finally {
|
||||
if (plaintext_buffer !== undefined) {
|
||||
|
@ -366,14 +356,14 @@ Session.prototype['decrypt'] = restore_stack(function(
|
|||
|
||||
try {
|
||||
message_buffer = malloc(message.length);
|
||||
Module['writeAsciiToMemory'](message, message_buffer, true);
|
||||
writeAsciiToMemory(message, message_buffer, true);
|
||||
|
||||
max_plaintext_length = session_method(
|
||||
Module['_olm_decrypt_max_plaintext_length']
|
||||
)(this.ptr, message_type, message_buffer, message.length);
|
||||
|
||||
// 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);
|
||||
|
||||
|
@ -385,7 +375,7 @@ Session.prototype['decrypt'] = restore_stack(function(
|
|||
|
||||
// UTF8ToString requires a null-terminated argument, so add the
|
||||
// null terminator.
|
||||
Module['setValue'](
|
||||
setValue(
|
||||
plaintext_buffer+plaintext_length,
|
||||
0, "i8"
|
||||
);
|
||||
|
@ -473,22 +463,3 @@ olm_exports["get_library_version"] = restore_stack(function() {
|
|||
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 process; // Shadow the process object so that emscripten won't get
|
||||
// confused by browserify
|
||||
|
||||
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) {
|
||||
window.crypto.getRandomValues(buf);
|
||||
};
|
||||
|
@ -12,7 +9,9 @@ if (typeof(window) !== 'undefined') {
|
|||
// We're running in node.
|
||||
var nodeCrypto = require("crypto");
|
||||
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);
|
||||
};
|
||||
process = global["process"];
|
||||
|
@ -20,14 +19,31 @@ if (typeof(window) !== 'undefined') {
|
|||
throw new Error("Cannot find global to attach library to");
|
||||
}
|
||||
|
||||
(function() {
|
||||
/* applications should define OLM_OPTIONS in the environment to override
|
||||
* emscripten module settings */
|
||||
var Module = {};
|
||||
if (typeof(OLM_OPTIONS) !== 'undefined') {
|
||||
for (var key in OLM_OPTIONS) {
|
||||
if (OLM_OPTIONS.hasOwnProperty(key)) {
|
||||
Module[key] = OLM_OPTIONS[key];
|
||||
}
|
||||
/* applications should define OLM_OPTIONS in the environment to override
|
||||
* emscripten module settings
|
||||
*/
|
||||
if (typeof(OLM_OPTIONS) !== 'undefined') {
|
||||
for (var olm_option_key in OLM_OPTIONS) {
|
||||
if (OLM_OPTIONS.hasOwnProperty(olm_option_key)) {
|
||||
Module[olm_option_key] = OLM_OPTIONS[olm_option_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",
|
||||
"files": [
|
||||
"olm.js",
|
||||
"olm.wasm",
|
||||
"README.md"
|
||||
],
|
||||
"scripts": {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (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() {
|
||||
var aliceSession, bobSession;
|
||||
|
||||
beforeEach(function() {
|
||||
aliceSession = new Olm.OutboundGroupSession();
|
||||
bobSession = new Olm.InboundGroupSession();
|
||||
beforeEach(function(done) {
|
||||
Olm.init().then(function() {
|
||||
aliceSession = new Olm.OutboundGroupSession();
|
||||
bobSession = new Olm.InboundGroupSession();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2018 New Vector Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (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 aliceSession, bobSession;
|
||||
|
||||
beforeEach(function() {
|
||||
aliceAccount = new Olm.Account();
|
||||
bobAccount = new Olm.Account();
|
||||
aliceSession = new Olm.Session();
|
||||
bobSession = new Olm.Session();
|
||||
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();
|
||||
bobAccount = new Olm.Account();
|
||||
aliceSession = new Olm.Session();
|
||||
bobSession = new Olm.Session();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
|
|
|
@ -18,20 +18,16 @@ limitations under the License.
|
|||
|
||||
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() {
|
||||
var encryption, decryption;
|
||||
|
||||
beforeEach(function() {
|
||||
encryption = new Olm.PkEncryption();
|
||||
decryption = new Olm.PkDecryption();
|
||||
beforeEach(function(done) {
|
||||
Olm.init().then(function() {
|
||||
encryption = new Olm.PkEncryption();
|
||||
decryption = new Olm.PkDecryption();
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
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 () {
|
||||
var TEST_TEXT='têst1';
|
||||
var pubkey = decryption.generate_key();
|
||||
|
|
|
@ -31,6 +31,7 @@ static const char * ERRORS[] = {
|
|||
"UNKNOWN_MESSAGE_INDEX",
|
||||
"BAD_LEGACY_ACCOUNT_PICKLE",
|
||||
"BAD_SIGNATURE",
|
||||
"OLM_INPUT_BUFFER_TOO_SMALL",
|
||||
};
|
||||
|
||||
const char * _olm_error_to_string(enum OlmErrorCode error)
|
||||
|
|
101
src/pk.cpp
101
src/pk.cpp
|
@ -22,15 +22,15 @@
|
|||
#include "olm/pickle_encoding.h"
|
||||
#include "olm/pickle.hh"
|
||||
|
||||
extern "C" {
|
||||
|
||||
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("");
|
||||
const struct _olm_cipher *olm_pk_cipher =
|
||||
OLM_CIPHER_BASE(&olm_pk_cipher_aes_sha256);
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct OlmPkEncryption {
|
||||
OlmErrorCode last_error;
|
||||
_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:
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -81,7 +85,9 @@ size_t olm_pk_ciphertext_length(
|
|||
OlmPkEncryption *encryption,
|
||||
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(
|
||||
|
@ -106,9 +112,9 @@ size_t olm_pk_encrypt(
|
|||
) {
|
||||
if (ciphertext_length
|
||||
< olm_pk_ciphertext_length(encryption, plaintext_length)
|
||||
|| mac_length
|
||||
|| mac_length
|
||||
< _olm_cipher_aes_sha_256_ops.mac_length(olm_pk_cipher)
|
||||
|| ephemeral_key_size
|
||||
|| ephemeral_key_size
|
||||
< olm_pk_key_length()) {
|
||||
encryption->last_error =
|
||||
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
|
||||
|
@ -122,11 +128,16 @@ size_t olm_pk_encrypt(
|
|||
|
||||
_olm_curve25519_key_pair 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_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 raw_mac[MAC_LENGTH];
|
||||
size_t result = _olm_cipher_aes_sha_256_ops.encrypt(
|
||||
|
@ -176,35 +187,51 @@ size_t olm_clear_pk_decryption(
|
|||
return sizeof(OlmPkDecryption);
|
||||
}
|
||||
|
||||
size_t olm_pk_generate_key_random_length(void) {
|
||||
size_t olm_pk_private_key_length(void) {
|
||||
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) {
|
||||
return olm::encode_base64_length(CURVE25519_KEY_LENGTH);
|
||||
}
|
||||
|
||||
size_t olm_pk_generate_key(
|
||||
size_t olm_pk_key_from_private(
|
||||
OlmPkDecryption * decryption,
|
||||
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 =
|
||||
OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
|
||||
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 =
|
||||
OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
|
||||
OlmErrorCode::OLM_INPUT_BUFFER_TOO_SMALL;
|
||||
return std::size_t(-1);
|
||||
}
|
||||
|
||||
_olm_crypto_curve25519_generate_key((uint8_t *) random, &decryption->key_pair);
|
||||
olm::encode_base64((const uint8_t *)decryption->key_pair.public_key.public_key, CURVE25519_KEY_LENGTH, (uint8_t *)pubkey);
|
||||
_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
|
||||
);
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
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(
|
||||
|
@ -283,7 +313,8 @@ size_t olm_unpickle_pk_decryption(
|
|||
}
|
||||
std::uint8_t * const pos = reinterpret_cast<std::uint8_t *>(pickled);
|
||||
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)) {
|
||||
return std::size_t(-1);
|
||||
|
@ -300,7 +331,11 @@ size_t olm_unpickle_pk_decryption(
|
|||
return std::size_t(-1);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -309,7 +344,9 @@ size_t olm_pk_max_plaintext_length(
|
|||
OlmPkDecryption * decryption,
|
||||
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(
|
||||
|
@ -327,7 +364,10 @@ size_t olm_pk_decrypt(
|
|||
}
|
||||
|
||||
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_crypto_curve25519_shared_secret(&decryption->key_pair, &ephemeral, secret);
|
||||
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
|
||||
};
|
||||
|
||||
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] = {
|
||||
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
|
||||
};
|
||||
|
||||
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()];
|
||||
|
||||
olm_pk_generate_key(
|
||||
olm_pk_key_from_private(
|
||||
decryption,
|
||||
pubkey, sizeof(pubkey),
|
||||
alice_private, sizeof(alice_private)
|
||||
|
@ -44,6 +44,11 @@ olm_pk_generate_key(
|
|||
|
||||
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()];
|
||||
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()];
|
||||
|
||||
olm_pk_generate_key(
|
||||
olm_pk_key_from_private(
|
||||
decryption,
|
||||
pubkey, sizeof(pubkey),
|
||||
alice_private, sizeof(alice_private)
|
||||
|
|
Loading…
Reference in a new issue