From 3136826e02ee379858ff5a1c3aa9140f0136e813 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 5 Oct 2016 15:31:52 +0200 Subject: First commit on depo - Add file --- .../src/main/java/org/matrix/olm/OlmAccount.java | 197 +++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java new file mode 100644 index 0000000..299a07d --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -0,0 +1,197 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +public class OlmAccount { + private static final String LOG_TAG = "OlmAccount"; + + // JSON keys used in the JSON objects returned by JNI + public static String JSON_KEY_ONE_TIME_KEY = "curve25519"; + public static String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; + + /** instance unique identifier, used in JNI to match the corresponding native class **/ + private int mJavaInstanceId; + + /** account raw pointer value (OlmAccount*) returned by JNI. + * this value identifies uniquely the native account instance. + */ + private long mNativeOlmAccountId; + + public OlmAccount() { + mJavaInstanceId = hashCode(); + //initNewAccount(); + } + + /** + * Getter on the account ID. + * @return native account ID + */ + public long getOlmAccountId(){ + return mNativeOlmAccountId; + } + + /** + * Destroy the corresponding OLM account native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #initNewAccountJni()}. + */ + private native void releaseAccountJni(); + + /** + * Release native account and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseAccountJni()}. + * To be called before any other API call. + */ + public void releaseAccount(){ + releaseAccountJni(); + + mNativeOlmAccountId = 0; + } + + /** + * Create the corresponding OLM account in native side.
+ * The return value is a long casted C ptr on the OlmAccount. + * Do not forget to call {@link #releaseAccount()} when JAVA side is done. + * @return native account instance identifier (see {@link #mNativeOlmAccountId}) + */ + private native long initNewAccountJni(); + + /** + * Create and save the account native instance ID. + * Wrapper for {@link #initNewAccountJni()}.
+ * To be called before any other API call. + * @return true if init succeed, false otherwise. + */ + public boolean initNewAccount() { + boolean retCode = false; + if(0 != (mNativeOlmAccountId = initNewAccountJni())){ + retCode = true; + } + return retCode; + } + + /** + * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
+ * Keys are Base64 encoded. + * These keys must be published on the server. + * @return byte array containing the identity keys if operation succeed, null otherwise + */ + private native byte[] identityKeysJni(); + + /** + * Return the identity keys in a JSON array.
+ * Public API for {@link #identityKeysJni()}. + * @return identity keys in JSON array format if operation succeed, null otherwise + */ + public JSONObject identityKeys() { + JSONObject identityKeysJsonObj = null; + byte identityKeysBuffer[]; + + if( null != (identityKeysBuffer = identityKeysJni())) { + try { + identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); + Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); + } catch (JSONException e) { + identityKeysJsonObj = null; + Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); + } + } else { + Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); + } + + return identityKeysJsonObj; + } + + /** + * Return the largest number of "one time keys" this account can store. + * @return the max number of "one time keys", -1 otherwise + */ + public native long maxOneTimeKeys(); + + /** + * Generate a number of new one time keys.
If total number of keys stored + * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. + * @param aNumberOfKeys number of keys to generate + * @return 0 if operation succeed, -1 otherwise + */ + public native int generateOneTimeKeys(int aNumberOfKeys); + + /** + * Get the public parts of the unpublished "one time keys" for the account.
+ * The returned data is a JSON-formatted object with the single property + * curve25519, which is itself an object mapping key id to + * base64-encoded Curve25519 key. + * These keys must be published on the server. + * @return byte array containing the one time keys if operation succeed, null otherwise + */ + private native byte[] oneTimeKeysJni(); + + /** + * Return the "one time keys" in a JSON array.
+ * Public API for {@link #oneTimeKeysJni()}. + * @return one time keys in JSON array format if operation succeed, null otherwise + */ + public JSONObject oneTimeKeys() { + byte identityKeysBuffer[]; + JSONObject identityKeysJsonObj = null; + + if( null != (identityKeysBuffer = oneTimeKeysJni())) { + try { + identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); + Log.d(LOG_TAG, "## oneTimeKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); + } catch (JSONException e) { + identityKeysJsonObj = null; + Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); + } + } else { + Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); + } + + return identityKeysJsonObj; + } + + /** + * Remove the "one time keys" that the session used from the account. + * @param aNativeOlmSessionId native session instance identifier + * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed + */ + public native int removeOneTimeKeysForSession(long aNativeOlmSessionId); + + /** + * Marks the current set of "one time keys" as being published. + * @return 0 if operation succeed, -1 otherwise + */ + public native int markOneTimeKeysAsPublished(); + + /** + * Sign a message with the ed25519 fingerprint key for this account. + * @param aMessage message to sign + * @return the signed message if operation succeed, null otherwise + */ + public native String signMessage(String aMessage); + + @Override + public String toString() { + return super.toString(); + } +} -- cgit v1.2.3 From 5573d3ab23de21b93b1ecc50d4fce96b02a42886 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 5 Oct 2016 18:25:09 +0200 Subject: First commit adding Olm Lib for Android - Add Android Studio project --- java/android/OlmLibSdk/build.gradle | 23 + java/android/OlmLibSdk/gradle.properties | 19 + java/android/OlmLibSdk/gradlew | 160 +++++++ java/android/OlmLibSdk/gradlew.bat | 90 ++++ java/android/OlmLibSdk/olm-sdk/build.gradle | 72 +++ .../java/org/matrix/olm/OlmAccountTest.java | 223 ++++++++++ .../OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml | 11 + .../src/main/java/org/matrix/olm/OlmAccount.java | 5 +- .../src/main/java/org/matrix/olm/OlmManager.java | 32 ++ .../src/main/java/org/matrix/olm/OlmSession.java | 327 ++++++++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 52 +++ .../OlmLibSdk/olm-sdk/src/main/jni/Application.mk | 3 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 491 +++++++++++++++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 34 ++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 46 ++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 476 ++++++++++++++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 38 ++ java/android/OlmLibSdk/settings.gradle | 1 + 18 files changed, 2102 insertions(+), 1 deletion(-) create mode 100644 java/android/OlmLibSdk/build.gradle create mode 100644 java/android/OlmLibSdk/gradle.properties create mode 100644 java/android/OlmLibSdk/gradlew create mode 100644 java/android/OlmLibSdk/gradlew.bat create mode 100644 java/android/OlmLibSdk/olm-sdk/build.gradle create mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h create mode 100644 java/android/OlmLibSdk/settings.gradle diff --git a/java/android/OlmLibSdk/build.gradle b/java/android/OlmLibSdk/build.gradle new file mode 100644 index 0000000..77ce66e --- /dev/null +++ b/java/android/OlmLibSdk/build.gradle @@ -0,0 +1,23 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.1.3' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/java/android/OlmLibSdk/gradle.properties b/java/android/OlmLibSdk/gradle.properties new file mode 100644 index 0000000..13d64a5 --- /dev/null +++ b/java/android/OlmLibSdk/gradle.properties @@ -0,0 +1,19 @@ +## Project-wide Gradle settings. +# +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +#Wed Oct 05 11:49:34 CEST 2016 +systemProp.https.proxyPort=8080 +systemProp.http.proxyHost=batproxy +systemProp.https.proxyHost=batproxy +systemProp.http.proxyPort=8080 diff --git a/java/android/OlmLibSdk/gradlew b/java/android/OlmLibSdk/gradlew new file mode 100644 index 0000000..9d82f78 --- /dev/null +++ b/java/android/OlmLibSdk/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/java/android/OlmLibSdk/gradlew.bat b/java/android/OlmLibSdk/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/java/android/OlmLibSdk/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle new file mode 100644 index 0000000..96eaaf7 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/build.gradle @@ -0,0 +1,72 @@ +import org.apache.tools.ant.taskdefs.condition.Os + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 21 + buildToolsVersion '21.1.2' + + defaultConfig { + minSdkVersion 11 + targetSdkVersion 21 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + sourceSets.main { + jniLibs.srcDir 'src/main/libs' + jni.srcDirs = [] + } + + task ndkBuildNative(type: Exec, description: 'NDK building..') { + workingDir file('src/main') + commandLine getNdkBuildCmd() //, '-B', 'NDK_DEBUG=1' + } + + task cleanNative(type: Exec, description: 'Clean NDK build') { + workingDir file('src/main') + commandLine getNdkBuildCmd(), 'clean' + } + + tasks.withType(JavaCompile) { + compileTask -> compileTask.dependsOn ndkBuildNative + } + + clean.dependsOn cleanNative + +} + +def getNdkFolder() { + Properties properties = new Properties() + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + def ndkFolder = properties.getProperty('ndk.dir', null) + if (ndkFolder == null) + throw new GradleException("NDK location missing. Define it with ndk.dir in the local.properties file") + + return ndkFolder +} + +def getNdkBuildCmd() { + def ndkBuildCmd = getNdkFolder() + "/ndk-build" + if (Os.isFamily(Os.FAMILY_WINDOWS)) + ndkBuildCmd += ".cmd" + + return ndkBuildCmd +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + compile 'com.android.support:appcompat-v7:21.+' + + testCompile 'junit:junit:4.12' + androidTestCompile 'junit:junit:4.12' + androidTestCompile 'com.android.support:support-annotations:21.0.0' + androidTestCompile 'com.android.support.test:runner:0.5' + androidTestCompile 'com.android.support.test:rules:0.5' +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java new file mode 100644 index 0000000..3d7568f --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -0,0 +1,223 @@ +package org.matrix.olm; + +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmAccountTest { + private static final String LOG_TAG = "OlmAccountTest"; + private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50; + + private static OlmAccount mOlmAccount; + private static OlmManager mOlmManager; + private boolean mIsAccountCreated; + + public static final String TEST_STRING = "This is a string"; + public static final long TEST_LONG = 12345678L; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + @AfterClass + public static void tearDownClass() { + // TBD + } + + @Before + public void setUp() { + if(mIsAccountCreated) { + assertNotNull(mOlmAccount); + } + } + + + @After + public void tearDown() { + // TBD + } + + @Test + public void test1CreateAccount() { + Log.d(LOG_TAG,"## testInitNewAccount"); + mOlmAccount = new OlmAccount(); + assertNotNull(mOlmAccount); + } + + @Test + public void test2InitNewAccount() { + Log.d(LOG_TAG,"## testInitNewAccount"); + assertTrue(mOlmAccount.initNewAccount()); + mIsAccountCreated = true; + } + + @Test + public void test3GetOlmAccountId() { + Log.d(LOG_TAG,"## testGetOlmAccountId"); + + long olmNativeInstance = mOlmAccount.getOlmAccountId(); + assertTrue(0!=olmNativeInstance); + } + + @Test + public void test4IdentityKeys() { + Log.d(LOG_TAG,"## testIdentityKeys"); + + JSONObject identityKeysJson = mOlmAccount.identityKeys(); + assertNotNull(identityKeysJson); + Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson); + + try { + String fingerPrintKey = identityKeysJson.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); + assertFalse("fingerprint key missing",TextUtils.isEmpty(fingerPrintKey)); + } catch (JSONException e) { + e.printStackTrace(); + assertTrue("Exception MSg="+e.getMessage(), false); + } + + try { + String identityKey = identityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); + assertFalse("identity key missing",TextUtils.isEmpty(identityKey)); + } catch (JSONException e) { + e.printStackTrace(); + assertTrue("Exception MSg="+e.getMessage(), false); + } + + + } + + + //**************************************************** + //** ************** One time keys TESTS ************** + //**************************************************** + @Test + public void test5MaxOneTimeKeys() { + Log.d(LOG_TAG,"## testMaxOneTimeKeys"); + + long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys(); + Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys); + + assertTrue(maxOneTimeKeys>0); + } + + @Test + public void test6GenerateOneTimeKeys() { + Log.d(LOG_TAG,"## testGenerateOneTimeKeys"); + int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); + assertTrue(0==retValue); + } + + @Test + public void test7OneTimeKeysJsonFormat() { + Log.d(LOG_TAG,"## testIdentityKeys"); + JSONObject generatedKeysJsonObj; + JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys(); + assertNotNull(oneTimeKeysJson); + + try { + generatedKeysJsonObj = oneTimeKeysJson.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertFalse(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null==generatedKeysJsonObj); + + /*String oneTimeKeyA = generatedKeysJsonObj.getString(OlmAccount.JSON_KEY_ONE_TIME_KEY_GENERATED_A); + assertFalse(" one time KeyA object is missing", TextUtils.isEmpty(oneTimeKeyA)); + + String oneTimeKeyB = generatedKeysJsonObj.getString(OlmAccount.JSON_KEY_ONE_TIME_KEY_GENERATED_B); + assertFalse(" one time KeyA object is missing", TextUtils.isEmpty(oneTimeKeyA));*/ + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + } + + // TODO testRemoveOneTimeKeysForSession when session is available + /*@Test + public void testRemoveOneTimeKeysForSession() { + Log.d(LOG_TAG,"## testRemoveOneTimeKeysForSession"); + OLMSession olmSession = new OLMSession(); + + JSONArray keysJsonArray = mOlmAccount.removeOneTimeKeysForSession(olmSession); + + assertNotNull(keysJsonArray); + // TODO add extra test to test the JSON content format.. + }*/ + + @Test + public void test8MarkOneTimeKeysAsPublished() { + Log.d(LOG_TAG,"## testMarkOneTimeKeysAsPublished"); + + int retCode = mOlmAccount.markOneTimeKeysAsPublished(); + // if OK => retCode=0 + assertTrue(0 == retCode); + } + + @Test + public void test9SignMessage() { + Log.d(LOG_TAG,"## testMarkOneTimeKeysAsPublished"); + + String clearMsg = "String to be signed by olm"; + String signedMsg = mOlmAccount.signMessage(clearMsg); + assertNotNull(signedMsg); + // TODO add test to unsign the signedMsg and compare it ot clearMsg + } + + + private void testJni(){ + OlmManager mgr = new OlmManager(); + String versionLib = mgr.getOlmLibVersion(); + Log.d(LOG_TAG, "## testJni(): lib version="+versionLib); + + OlmAccount account = new OlmAccount(); + boolean initStatus = account.initNewAccount(); + + long accountNativeId = account.getOlmAccountId(); + Log.d(LOG_TAG, "## testJni(): lib accountNativeId="+accountNativeId); + + JSONObject identityKeys = account.identityKeys(); + Log.d(LOG_TAG, "## testJni(): identityKeysJson="+identityKeys.toString()); + + long maxOneTimeKeys = account.maxOneTimeKeys(); + Log.d(LOG_TAG, "## testJni(): lib maxOneTimeKeys="+maxOneTimeKeys); + + int generateRetCode = account.generateOneTimeKeys(50); + Log.d(LOG_TAG, "## testJni(): generateRetCode="+generateRetCode); + + JSONObject onteTimeKeysKeysJson = account.oneTimeKeys(); + Log.d(LOG_TAG, "## testJni(): onteTimeKeysKeysJson="+onteTimeKeysKeysJson.toString()); + + // TODO removeOneTimeKeysForSession(session); + + int asPublishedRetCode = account.markOneTimeKeysAsPublished(); + Log.d(LOG_TAG, "## testJni(): asPublishedRetCode="+asPublishedRetCode); + + String clearMsg ="My clear message"; + String signedMsg = account.signMessage(clearMsg); + Log.d(LOG_TAG, "## testJni(): signedMsg="+signedMsg); + + account.releaseAccount(); + } + + +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml b/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml new file mode 100644 index 0000000..8a8747f --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 299a07d..ac8e12d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -26,7 +26,10 @@ public class OlmAccount { // JSON keys used in the JSON objects returned by JNI public static String JSON_KEY_ONE_TIME_KEY = "curve25519"; + public static String JSON_KEY_IDENTITY_KEY = "curve25519"; public static String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; + public static String JSON_KEY_ONE_TIME_KEY_GENERATED_A = "AAAAAA"; + public static String JSON_KEY_ONE_TIME_KEY_GENERATED_B = "AAAAAB"; /** instance unique identifier, used in JNI to match the corresponding native class **/ private int mJavaInstanceId; @@ -99,7 +102,7 @@ public class OlmAccount { private native byte[] identityKeysJni(); /** - * Return the identity keys in a JSON array.
+ * Return the identity keys (identity & fingerprint keys) in a JSON array.
* Public API for {@link #identityKeysJni()}. * @return identity keys in JSON array format if operation succeed, null otherwise */ diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java new file mode 100644 index 0000000..55b9910 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + + +public class OlmManager { + + static { + java.lang.System.loadLibrary("olm"); + } + + /** + * Get the OLM lib version. + * @return the lib version as a string + */ + public native String getOlmLibVersion(); +} + diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java new file mode 100644 index 0000000..28324da --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -0,0 +1,327 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; + +public class OlmSession { + private static final String LOG_TAG = "OlmSession"; + /** session raw pointer value (OlmSession*) returned by JNI. + * this value uniquely identifies the native session instance. + **/ + private long mNativeOlmSessionId; + + /** account instance associated with this session. **/ + private OlmAccount mOlmAccount; + + public OlmSession() { + //initNewSession(); + } + + /** + * Getter on the session ID. + * @return native session ID + */ + public long getOlmSessionId(){ + return mNativeOlmSessionId; + } + + /** + * Destroy the corresponding OLM session native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #initNewSessionJni()}. + */ + private native void releaseSessionJni(); + + /** + * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}. + * To be called before any other API call. + */ + public void releaseSession(){ + releaseSessionJni(); + + mNativeOlmSessionId = 0; + } + + + /** + * Create and save the session native instance ID. + * Wrapper for {@link #initNewSessionJni()}.
+ * To be called before any other API call. + * @return true if init succeed, false otherwise. + */ + public boolean initNewSession() { + boolean retCode = false; + if(0 != (mNativeOlmSessionId = initNewSessionJni())){ + retCode = true; + } + return retCode; + } + + /** + * Create the corresponding OLM session in native side.
+ * The return value is a long casted C ptr on the OlmSession. + * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native session instance identifier (see {@link #mNativeOlmSessionId}) + */ + private native long initNewSessionJni(); + + + /** + * Creates a new out-bound session for sending messages to a recipient + * identified by an identity key and a one time key.
+ * Public API for {@link #initOutboundSessionWithAccount(OlmAccount, String, String)}. + * @param aAccount the account to associate with this session + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient + * @return this if operation succeed, null otherwise + */ + public OlmSession initOutboundSessionWithAccount(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) { + OlmSession retObj=null; + + if((null==aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)){ + Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); + } else { + // set the account of this session + mOlmAccount = aAccount; + + int retCode = initOutboundSessionJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey); + retObj = this; + } + + return retObj; + } + + private native int initOutboundSessionJni(long aOlmAccountId, String aTheirIdentityKey, String aTheirOneTimeKey); + + + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
+ * Public API for {@link #initInboundSessionJni(long, String)}. + * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aAccount the account to associate with this session + * @param aOneTimeKeyMsg PRE KEY message TODO TBC + * @return this if operation succeed, null otherwise + */ + public OlmSession initInboundSessionWithAccount(OlmAccount aAccount, String aOneTimeKeyMsg) { + OlmSession retObj=null; + + if((null==aAccount) || TextUtils.isEmpty(aOneTimeKeyMsg)){ + Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); + } else { + // set the account of this session + mOlmAccount = aAccount; + + if( 0 == initInboundSessionJni(mOlmAccount.getOlmAccountId(), aOneTimeKeyMsg)) { + retObj = this; + } + } + + return retObj; + } + + private native int initInboundSessionJni(long aOlmAccountId, String aOneTimeKeyMsg); + + + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message based on the sender identity key TODO TBC!.
+ * Public API for {@link #initInboundSessionFromIdKeyJni(long, String, String)}. + * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aAccount the account to associate with this session + * @param aTheirIdentityKey the sender identity key + * @param aOneTimeKeyMsg PRE KEY message TODO TBC + * @return this if operation succeed, null otherwise + */ + public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aOneTimeKeyMsg) { + OlmSession retObj=null; + + if((null==aAccount) || TextUtils.isEmpty(aOneTimeKeyMsg)){ + Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); + } else { + // set the account of this session + mOlmAccount = aAccount; + + if(0 == initInboundSessionFromIdKeyJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aOneTimeKeyMsg)){ + retObj = this; + } + } + + return retObj; + } + + private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, String aTheirIdentityKey, String aOneTimeKeyMsg); + + + /** + * Checks if the PRE_KEY message is for this in-bound session.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * Public API for {@link #matchesInboundSessionJni(String)}. + * @param aOneTimeKeyMsg PRE KEY message + * @return this if operation succeed, null otherwise + */ + public boolean matchesInboundSession(String aOneTimeKeyMsg) { + boolean retCode = false; + + if(0 == matchesInboundSessionJni(aOneTimeKeyMsg)){ + retCode = true; + } + return retCode; + } + + private native int matchesInboundSessionJni(String aOneTimeKeyMsg); + + + /** + * Get the session identifier.
Will be the same for both ends of the + * conversation. The session identifier is returned as a String object. + * Session Id sample: "session_id":"M4fOVwD6AABrkTKl" + * Public API for {@link #getSessionIdentifierJni()}. + * @return the session ID as a String if operation succeed, null otherwise + */ + public String sessionIdentifier() { + return getSessionIdentifierJni(); + } + + private native String getSessionIdentifierJni(); + +/* +- (BOOL) matchesInboundSession:(NSString*)oneTimeKeyMessage; +- (BOOL) matchesInboundSessionFrom:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage; + +// UTF-8 plaintext -> base64 ciphertext +- (OLMMessage*) encryptMessage:(NSString*)message; + +// base64 ciphertext -> UTF-8 plaintext +- (NSString*) decryptMessage:(OLMMessage*)message; +*/ + + + /** + * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
+ * Keys are Base64 encoded. + * These keys must be published on the server. + * @return byte array containing the identity keys if operation succeed, null otherwise + */ + private native byte[] identityKeysJni(); + + /** + * Return the identity keys in a JSON array.
+ * Public API for {@link #identityKeysJni()}. + * @return identity keys in JSON array format if operation succeed, null otherwise + */ + public JSONObject identityKeys() { + JSONObject identityKeysJsonObj = null; + byte identityKeysBuffer[]; + + if( null != (identityKeysBuffer = identityKeysJni())) { + try { + identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); + Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); + } catch (JSONException e) { + identityKeysJsonObj = null; + Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); + } + } else { + Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); + } + + return identityKeysJsonObj; + } + + /** + * Return the largest number of "one time keys" this account can store. + * @return the max number of "one time keys", -1 otherwise + */ + public native long maxOneTimeKeys(); + + /** + * Generate a number of new one time keys.
If total number of keys stored + * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. + * @param aNumberOfKeys number of keys to generate + * @return 0 if operation succeed, -1 otherwise + */ + public native int generateOneTimeKeys(int aNumberOfKeys); + + /** + * Get the public parts of the unpublished "one time keys" for the account.
+ * The returned data is a JSON-formatted object with the single property + * curve25519, which is itself an object mapping key id to + * base64-encoded Curve25519 key. + * These keys must be published on the server. + * @return byte array containing the one time keys if operation succeed, null otherwise + */ + private native byte[] oneTimeKeysJni(); + + /** + * Return the "one time keys" in a JSON array.
+ * Public API for {@link #oneTimeKeysJni()}. + * @return one time keys in JSON array format if operation succeed, null otherwise + */ + public JSONObject oneTimeKeys() { + byte identityKeysBuffer[]; + JSONObject identityKeysJsonObj = null; + + if( null != (identityKeysBuffer = oneTimeKeysJni())) { + try { + identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); + Log.d(LOG_TAG, "## oneTimeKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); + } catch (JSONException e) { + identityKeysJsonObj = null; + Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); + } + } else { + Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); + } + + return identityKeysJsonObj; + } + + /** + * Remove the "one time keys" that the session used from the account. + * @param aNativeOlmSessionId native session instance identifier + * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed + */ + public native int removeOneTimeKeysForSession(long aNativeOlmSessionId); + + /** + * Marks the current set of "one time keys" as being published. + * @return 0 if operation succeed, -1 otherwise + */ + public native int markOneTimeKeysAsPublished(); + + /** + * Sign a message with the ed25519 fingerprint key for this account. + * @param aMessage message to sign + * @return the signed message if operation succeed, null otherwise + */ + public native String signMessage(String aMessage); + + @Override + public String toString() { + return super.toString(); + } + +} + diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk new file mode 100644 index 0000000..d59f916 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -0,0 +1,52 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := olm +MAJOR := 1 +MINOR := 3 +PATCH := 0 +OLM_VERSION := $(MAJOR).$(MINOR).$(PATCH) +SRC_ROOT_DIR := ../../../../../../.. + +$(info LOCAL_PATH=$(LOCAL_PATH)) +$(info SRC_ROOT_DIR=$(SRC_ROOT_DIR)) +$(info OLM_VERSION=$(OLM_VERSION)) + +LOCAL_CPPFLAGS+= -std=c++11 -Wall +LOCAL_CONLYFLAGS+= -std=c99 +LOCAL_CFLAGS+= -DOLMLIB_VERSION_MAJOR=$(MAJOR) \ +-DOLMLIB_VERSION_MINOR=$(MINOR) \ +-DOLMLIB_VERSION_PATCH=$(PATCH) + +LOCAL_C_INCLUDES+= $(LOCAL_PATH)/$(SRC_ROOT_DIR)/include/ \ +$(LOCAL_PATH)/$(SRC_ROOT_DIR)/lib + +$(info LOCAL_C_INCLUDES=$(LOCAL_C_INCLUDES)) + +LOCAL_SRC_FILES := $(SRC_ROOT_DIR)/src/account.cpp \ +$(SRC_ROOT_DIR)/src/base64.cpp \ +$(SRC_ROOT_DIR)/src/cipher.cpp \ +$(SRC_ROOT_DIR)/src/crypto.cpp \ +$(SRC_ROOT_DIR)/src/memory.cpp \ +$(SRC_ROOT_DIR)/src/message.cpp \ +$(SRC_ROOT_DIR)/src/olm.cpp \ +$(SRC_ROOT_DIR)/src/pickle.cpp \ +$(SRC_ROOT_DIR)/src/ratchet.cpp \ +$(SRC_ROOT_DIR)/src/session.cpp \ +$(SRC_ROOT_DIR)/src/utility.cpp \ +$(SRC_ROOT_DIR)/src/ed25519.c \ +$(SRC_ROOT_DIR)/src/error.c \ +$(SRC_ROOT_DIR)/src/inbound_group_session.c \ +$(SRC_ROOT_DIR)/src/megolm.c \ +$(SRC_ROOT_DIR)/src/outbound_group_session.c \ +$(SRC_ROOT_DIR)/src/pickle_encoding.c \ +$(SRC_ROOT_DIR)/lib/crypto-algorithms/sha256.c \ +$(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \ +$(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \ +olm_account.cpp \ +olm_session.cpp + +LOCAL_LDLIBS := -llog + +include $(BUILD_SHARED_LIBRARY) + diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk new file mode 100644 index 0000000..29a4296 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk @@ -0,0 +1,3 @@ +APP_PLATFORM := android-21 +APP_ABI := arm64-v8a #armeabi-v7a armeabi x86 x86_64 +APP_STL := gnustl_static \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp new file mode 100644 index 0000000..d8ee409 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -0,0 +1,491 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_account.h" + + +/** +* Init memory allocation for account creation. +* @return valid memory alocation, NULL otherwise +**/ +OlmAccount* initializeAccountMemory() +{ + OlmAccount* accountPtr = NULL; + size_t accountSize = olm_account_size(); + + if(NULL != (accountPtr=(OlmAccount*)malloc(accountSize))) + { // init account object + accountPtr = olm_account(accountPtr); + LOGD("## initializeAccountMemory(): success - OLM account size=%lu",accountSize); + } + else + { + LOGE("## initializeAccountMemory(): failure - OOM"); + } + + return accountPtr; +} + +/** + * Release the account allocation made by initializeAccountMemory().
+ * This method MUST be called when java counter part account instance is done. + * + */ +JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv *env, jobject thiz) +{ + OlmAccount* accountPtr = NULL; + + LOGD("## releaseAccountJni(): accountPtr=%p",accountPtr); + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## releaseAccountJni(): failure - invalid Account ptr=NULL"); + } + else + { // even if free(NULL) does not crash, a test is performed for debug purpose + LOGD("## releaseAccountJni(): IN"); + free(accountPtr); + LOGD("## releaseAccountJni(): OUT"); + } +} + +/** +* Initialize a new account and return it to JAVA side.
+* Since a C prt is returned as a jlong, special care will be taken +* to make the cast (OlmAccount* => jlong) platform independant. +* @return the initialized OlmAccount* instance if init succeed, NULL otherwise +**/ +JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv *env, jobject thiz) +{ + OlmAccount* accountPtr = NULL; + size_t accountRetCode; + uint8_t* randomBuffPtr = NULL; + int randomSize; + + // init account memory allocation + if(NULL == (accountPtr = initializeAccountMemory())) + { + LOGE("## initNewAccount(): failure - init account OOM"); + } + else + { + // allocate random buffer + randomSize = olm_create_account_random_length(accountPtr); + if(NULL == (randomBuffPtr = (std::uint8_t*)malloc(randomSize*sizeof(std::uint8_t)))) + { + LOGE("## initNewAccount(): failure - random buffer OOM"); + } + else + { // create random buffer + LOGD("## initNewAccount(): randomSize=%d",randomSize); + + srand(time(NULL)); // init seed + for(int i=0;i +* The keys are returned in the byte array. +* @return a valid byte array if operation succeed, null otherwise +**/ +JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_identityKeysJni(JNIEnv *env, jobject thiz) +{ + OlmAccount* accountPtr = NULL; + size_t identityKeysLength; + uint8_t *identityKeysBytesPtr; + size_t keysResult; + jbyteArray byteArrayRetValue = NULL; + + LOGD("## identityKeys(): accountPtr =%p",accountPtr); + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## identityKeys(): failure - invalid Account ptr=NULL"); + } + else + { // identity keys allocation + identityKeysLength = olm_account_identity_keys_length(accountPtr); + if(NULL == (identityKeysBytesPtr=(uint8_t *)malloc(identityKeysLength*sizeof(std::uint8_t)))) + { + LOGE("## identityKeys(): failure - identity keys array OOM"); + } + else + { // retrieve key pairs in identityKeysBytesPtr + keysResult = olm_account_identity_keys(accountPtr, identityKeysBytesPtr, identityKeysLength); + if(keysResult == olm_error()) { + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGE("## identityKeys(): failure - error getting identity keys Msg=%s",errorMsgPtr); + } + else + { // allocate the byte array to be returned to java + if(NULL == (byteArrayRetValue=env->NewByteArray(identityKeysLength))) + { + LOGE("## identityKeys(): failure - return byte array OOM"); + } + else + { + env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, identityKeysLength, (const jbyte*)identityKeysBytesPtr); + LOGD("## identityKeys(): success - result=%ld", keysResult); + } + } + + free(identityKeysBytesPtr); + } + } + + return byteArrayRetValue; +} + +// ********************************************************************* +// ************************* ONE TIME KEYS API ************************* +// ********************************************************************* +/** + * Get the maximum number of "one time keys" the account can store. + * +**/ +JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_maxOneTimeKeys(JNIEnv *env, jobject thiz) +{ + OlmAccount* accountPtr = NULL; + size_t maxKeys = -1; + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## maxOneTimeKey(): failure - invalid Account ptr=NULL"); + } + else + { + maxKeys = olm_account_max_number_of_one_time_keys(accountPtr); + } + LOGD("## maxOneTimeKey(): Max keys=%ld", maxKeys); + + return (jlong)maxKeys; +} + +/** + * Generate "one time keys". + * @param aNumberOfKeys number of keys to generate + * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise +**/ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv *env, jobject thiz, jint aNumberOfKeys) +{ + OlmAccount* accountPtr = NULL;; + jint retCode = ERROR_CODE_KO; + size_t length; + void* keysBytesPtr; // TODO check type: or uint8_t? + size_t result; + + LOGD("## generateOneTimeKeys(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## generateOneTimeKeys(): failure - invalid Account ptr"); + } + else + { // keys memory allocation + length = olm_account_generate_one_time_keys_random_length(accountPtr, aNumberOfKeys); + LOGD("## generateOneTimeKeys(): randomLength=%ld", length); + if(NULL == (keysBytesPtr=(void*)malloc(length*sizeof(void*)))) + { + LOGE("## generateOneTimeKeys(): failure - random allocation OOM"); + } + else + { // retrieve key pairs in keysBytesPtr + result = olm_account_generate_one_time_keys(accountPtr, aNumberOfKeys, keysBytesPtr, length); + if(result == olm_error()) { + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGE("## generateOneTimeKeys(): failure - error generating one time keys Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## generateOneTimeKeys(): success - result=%ld", result); + } + + free(keysBytesPtr); + } + } + + return retCode; +} + +/** + * Get "one time keys". + * Return the public parts of the unpublished "one time keys" for the account + * @return a valid byte array if operation succeed, null otherwise +**/ +JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_oneTimeKeysJni(JNIEnv *env, jobject thiz) +{ + OlmAccount* accountPtr = NULL; + size_t keysLength; + uint8_t *keysBytesPtr; + size_t keysResult; + jbyteArray byteArrayRetValue = NULL; + + LOGD("## oneTimeKeys(): accountPtr =%p",accountPtr); + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## oneTimeKeys(): failure - invalid Account ptr"); + } + else + { // keys memory allocation + keysLength = olm_account_one_time_keys_length(accountPtr); + if(NULL == (keysBytesPtr=(uint8_t *)malloc(keysLength*sizeof(uint8_t)))) + { + LOGE("## oneTimeKeys(): failure - one time keys array OOM"); + } + else + { // retrieve key pairs in keysBytesPtr + keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); + if(keysResult == olm_error()) { + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGE("## oneTimeKeys(): failure - error getting one time keys Msg=%s",errorMsgPtr); + } + else + { // allocate the byte array to be returned to java + if(NULL == (byteArrayRetValue=env->NewByteArray(keysLength))) + { + LOGE("## oneTimeKeys(): failure - return byte array OOM"); + } + else + { + env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, keysLength, (const jbyte*)keysBytesPtr); + LOGD("## oneTimeKeys(): success"); + } + } + + free(keysBytesPtr); + } + } + + return byteArrayRetValue; +} + +/** + * Remove the "one time keys" that the session used from the account. + * Return the public parts of the unpublished "one time keys" for the account + * @param aNativeOlmSessionId session instance + * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS if no matching keys, ERROR_CODE_KO otherwise +**/ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_removeOneTimeKeysForSession(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) +{ + jint retCode = ERROR_CODE_KO; + OlmAccount* accountPtr = NULL; + OlmSession* sessionPtr = (OlmSession*)aNativeOlmSessionId; + size_t result; + + if(NULL == sessionPtr) + { + LOGE("## removeOneTimeKeysForSession(): failure - invalid session ptr"); + } + else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## removeOneTimeKeysForSession(): failure - invalid account ptr"); + } + else + { + result = olm_remove_one_time_keys(accountPtr, sessionPtr); + if(result == olm_error()) + { // the account doesn't have any matching "one time keys".. + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGW("## removeOneTimeKeysForSession(): failure - removing one time keys Msg=%s",errorMsgPtr); + + retCode = ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS; + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## removeOneTimeKeysForSession(): success"); + } + } + + return retCode; +} + +/** + * Mark the current set of "one time keys" as being published. + * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise +**/ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_markOneTimeKeysAsPublished(JNIEnv *env, jobject thiz) +{ + jint retCode = ERROR_CODE_OK; + OlmAccount* accountPtr = NULL; + size_t result; + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## markOneTimeKeysPublished(): failure - invalid account ptr"); + retCode = ERROR_CODE_KO; + } + else + { + result = olm_account_mark_keys_as_published(accountPtr); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGW("## markOneTimeKeysPublished(): failure - Msg=%s",errorMsgPtr); + retCode = ERROR_CODE_KO; + } + else + { + LOGD("## markOneTimeKeysPublished(): success - retCode=%ld",result); + } + } + + return retCode; +} + +/** + * Sign a message with the ed25519 key (fingerprint) for this account. + * @param aMessage message to sign + * @return the corresponding signed message, null otherwise +**/ +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env, jobject thiz, jstring aMessage) +{ + OlmAccount* accountPtr = NULL; + size_t signatureLength; + void* signaturePtr; + size_t resultSign; + jstring signedMsgRetValue = NULL; + + if(NULL == aMessage) + { + LOGE("## signMessage(): failure - invalid aMessage param"); + } + else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## signMessage(): failure - invalid account ptr"); + } + else + { + // convert message from JAVA to C string + const char* messageToSign = env->GetStringUTFChars(aMessage, 0); + if(NULL == messageToSign) + { + LOGE("## signMessage(): failure - message JNI allocation OOM"); + } + else + { + int messageLength = env->GetStringUTFLength(aMessage); + + // signature memory allocation + signatureLength = olm_account_signature_length(accountPtr); + if(NULL == (signaturePtr=(void *)malloc(signatureLength*sizeof(void*)))) + { + LOGE("## signMessage(): failure - signature allocation OOM"); + } + else + { // sign message + resultSign = olm_account_sign(accountPtr, (void*)messageToSign, messageLength, signaturePtr, signatureLength); + if(resultSign == olm_error()) + { + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGE("## signMessage(): failure - error signing message Msg=%s",errorMsgPtr); + } + else + { // convert to jstring + // TODO check how UTF conversion can impact the content? + // why not consider return jbyteArray? and convert in JAVA side.. + signedMsgRetValue = env->NewStringUTF((const char*)signaturePtr); // UTF8 + LOGD("## signMessage(): success - retCode=%ld",resultSign); + } + + free(signaturePtr); + } + + // release messageToSign + env->ReleaseStringUTFChars(aMessage, messageToSign); + } + } + + return signedMsgRetValue; +} + + +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmManager_getOlmLibVersion(JNIEnv* env, jobject thiz) +{ + uint8_t majorVer=0, minorVer=0, patchVer=0; + jstring returnValueStr=0; + char buff[150]; + + olm_get_library_version(&majorVer, &minorVer, &patchVer); + LOGD("## getOlmLibVersion(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); + + snprintf(buff, sizeof(buff), " V%d.%d.%d", majorVer, minorVer, patchVer); + returnValueStr = env->NewStringUTF((const char*)buff); + + return returnValueStr; +} + + +/** +* Read the account instance ID of the calling object. +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId); + } + else + { + LOGD("## getAccountInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL"); + } + LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId); + return instanceId; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h new file mode 100644 index 0000000..8ba1633 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -0,0 +1,34 @@ +#ifndef _OMLACCOUNT_H +#define _OMLACCOUNT_H + +#include "olm_jni.h" + +#ifdef __cplusplus +extern "C" { +#endif + +jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmManager_getOlmLibVersion(JNIEnv *env, jobject thiz); + +// account creation/destruction +JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv *env, jobject thiz); +JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv *env, jobject thiz); + +// identity keys +JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_identityKeysJni(JNIEnv *env, jobject thiz); + +// one time keys +JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_oneTimeKeysJni(JNIEnv *env, jobject thiz); +JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_maxOneTimeKeys(JNIEnv *env, jobject thiz); +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv *env, jobject thiz, jint aNumberOfKeys); +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_removeOneTimeKeysForSession(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_markOneTimeKeysAsPublished(JNIEnv *env, jobject thiz); + +// signing +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env, jobject thiz, jstring aMessage); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h new file mode 100644 index 0000000..a504333 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -0,0 +1,46 @@ +#ifndef _OMLJNI_H +#define _OMLJNI_H + +#include +#include +#include +#include +#include +#include +#include + +#include "olm/olm.h" + +#define TAG "OlmJniNative" + +/* logging macros */ +#define ENABLE_LOGS + +#ifdef ENABLE_LOGS + #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) + #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) + #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) + #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) +#else + #define LOGV(...) + #define LOGD(...) + #define LOGW(...) + #define LOGE(...) +#endif + +// Error codes definition +static const int ERROR_CODE_OK = 0; +static const int ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS = ERROR_CODE_OK+1; +static const int ERROR_CODE_KO = -1; + +// constants +static const int ACCOUNT_CREATION_RANDOM_MODULO = 500; + + +typedef struct _AccountContext +{ + OlmAccount* mAccountPtr; + _AccountContext(): mAccountPtr(NULL){} +} AccountContext; + +#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp new file mode 100644 index 0000000..22544d4 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -0,0 +1,476 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_session.h" + + +/** +* Init memory allocation for session creation. +* @return valid memory allocation, NULL otherwise +**/ +OlmSession* initializeSessionMemory() +{ + OlmSession* sessionPtr = NULL; + size_t sessionSize = olm_session_size(); + + if(NULL != (sessionPtr=(OlmSession*)malloc(sessionSize))) + { // init session object + sessionPtr = olm_session(sessionPtr); + LOGD("## initializeSessionMemory(): success - OLM session size=%lu",sessionSize); + } + else + { + LOGE("## initializeSessionMemory(): failure - OOM"); + } + + return sessionPtr; +} + +JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv *env, jobject thiz) +{ + OlmSession* sessionPtr = NULL; + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); + } + else + { // even if free(NULL) does not crash, a test is performed for debug purpose + LOGD("## releaseSessionJni(): IN"); + free(sessionPtr); + LOGD("## releaseSessionJni(): OUT"); + } +} + +/** +* Initialize a new session and return it to JAVA side.
+* Since a C prt is returned as a jlong, special care will be taken +* to make the cast (OlmSession* => jlong) platform independent. +* @return the initialized OlmSession* instance if init succeed, NULL otherwise +**/ +JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmSession_initNewSessionJni(JNIEnv *env, jobject thiz) +{ + OlmSession* sessionPtr = NULL; + + // init account memory allocation + if(NULL == (sessionPtr = initializeSessionMemory())) + { + LOGE("## initNewSessionJni(): failure - init session OOM"); + } + else + { + LOGD("## initNewSessionJni(): success - OLM session created"); + } + + return (jlong)(intptr_t)sessionPtr; +} + +// ********************************************************************* +// ********************** OUTBOUND SESSION ***************************** +// ********************************************************************* +/** +* Create a new in-bound session for sending/receiving messages from an +* incoming PRE_KEY message.
The recipient is defined as the entity +* with whom the session is established. +* @param aOlmAccountId account instance +* @param aTheirIdentityKey the identity key of the recipient +* @param aTheirOneTimeKey the one time key of the recipient +* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise +**/ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey) +{ + jint retCode = ERROR_CODE_KO; + OlmSession* sessionPtr = NULL; + OlmAccount* accountPtr = NULL; + void *randomBuffPtr; + size_t sessionResult; + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## initOutboundSessionJni(): failure - invalid Session ptr=NULL"); + } + else if(NULL == (accountPtr = (OlmAccount*)aOlmAccountId)) + { + LOGE("## initOutboundSessionJni(): failure - invalid Account ptr=NULL"); + } + else if((0==aTheirIdentityKey) || (0==aTheirOneTimeKey)) + { + LOGE("## initOutboundSessionJni(): failure - invalid keys"); + } + else + { // allocate random buffer + size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); + if(NULL == (randomBuffPtr = (void*)malloc(randomSize*sizeof(void*)))) + { + LOGE("## initOutboundSessionJni(): failure - random buffer OOM"); + } + else + { // convert identity & one time keys to C strings + const char* theirIdentityKeyPtr = NULL; + const char* theirOneTimeKeyPtr = NULL; + + if(NULL == (theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + { + LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM"); + } + else if(NULL == (theirOneTimeKeyPtr = env->GetStringUTFChars(aTheirOneTimeKey, 0))) + { + LOGE("## initOutboundSessionJni(): failure - one time Key JNI allocation OOM"); + } + else + { + int theirIdentityKeyLength = env->GetStringUTFLength(aTheirIdentityKey); + int theirOneTimeKeyLength = env->GetStringUTFLength(aTheirOneTimeKey); + LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr); + + sessionResult = olm_create_outbound_session(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, theirOneTimeKeyPtr, theirOneTimeKeyLength, randomBuffPtr, randomSize); + if(sessionResult == olm_error()) { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## initOutboundSessionJni(): success - result=%ld", sessionResult); + } + } + + // free local alloc + free(randomBuffPtr); + if(NULL!= theirIdentityKeyPtr) + { + env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + } + if(NULL!= theirOneTimeKeyPtr) + { + env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr); + } + } + } + + return retCode; +} + + +// ********************************************************************* +// *********************** INBOUND SESSION ***************************** +// ********************************************************************* +/** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
+ * @param aOlmAccountId account instance + * @param aOneTimeKeyMsg PRE_KEY message TODO TBC + * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise + */ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg) +{ + jint retCode = ERROR_CODE_KO; + OlmSession *sessionPtr = NULL; + OlmAccount *accountPtr = NULL; + size_t sessionResult; + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## initInboundSessionJni(): failure - invalid Session ptr=NULL"); + } + else if(NULL == (accountPtr = (OlmAccount*)aOlmAccountId)) + { + LOGE("## initInboundSessionJni(): failure - invalid Account ptr=NULL"); + } + else if(0==aOneTimeKeyMsg) + { + LOGE("## initOutboundSessionJni(): failure - invalid message"); + } + else + { // convert message to C strings + const char *messagePtr = NULL; + if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + { + LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM"); + } + else + { + int messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); + LOGD("## initInboundSessionJni(): message=%s messageLength=%d",messagePtr,messageLength); + + sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); + if(sessionResult == olm_error()) { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## initInboundSessionJni(): success - result=%ld", sessionResult); + } + + // free local alloc + env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + } + } + return retCode; +} + +/** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message based on the recipient identity key.
+ * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aOneTimeKeyMsg encrypted message + * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise + */ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) +{ + jint retCode = ERROR_CODE_KO; + OlmSession *sessionPtr = NULL; + OlmAccount *accountPtr = NULL; + const char *messagePtr = NULL; + const char *theirIdentityKeyPtr = NULL; + size_t sessionResult; + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); + } + else if(NULL == (accountPtr = (OlmAccount*)aOlmAccountId)) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Account ptr=NULL"); + } + else if(0 == aTheirIdentityKey) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); + } + else if(0==aOneTimeKeyMsg) + { + LOGE("## initOutboundSessionJni(): failure - invalid one time key message"); + } + else if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - message JNI allocation OOM"); + } + else if(NULL == (theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); + } + else + { + size_t messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); + size_t theirIdentityKeyLength = env->GetStringUTFLength(aTheirIdentityKey); + + LOGD("## initInboundSessionFromIdKeyJni(): message=%s messageLength=%lu",messagePtr,messageLength); + + sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); + if(sessionResult == olm_error()) { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## initInboundSessionFromIdKeyJni(): success - result=%ld", sessionResult); + } + } + + // free local alloc + if(NULL!= messagePtr) + { + env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + } + if(NULL!= theirIdentityKeyPtr) + { + env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + } + + return retCode; +} + +/** + * Checks if the PRE_KEY message is for this in-bound session.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aOneTimeKeyMsg PRE KEY message + * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + */ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg) +{ + jint retCode = ERROR_CODE_KO; + OlmSession *sessionPtr = NULL; + const char *messagePtr = NULL; + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## matchesInboundSessionJni(): failure - invalid Session ptr=NULL"); + } + else if(0==aOneTimeKeyMsg) + { + LOGE("## matchesInboundSessionJni(): failure - invalid one time key message"); + } + else if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + { + LOGE("## matchesInboundSessionJni(): failure - one time key JNI allocation OOM"); + } + else + { + size_t messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); + + size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); + if(matchResult == olm_error()) { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## matchesInboundSessionJni(): failure - no match Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## matchesInboundSessionJni(): success - result=%ld", matchResult); + } + } + + return retCode; +} + + +/** + * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aTheirIdentityKey the identity key of the sender + * @param aOneTimeKeyMsg PRE KEY message + * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + */ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) +{ + jint retCode = ERROR_CODE_KO; + OlmSession *sessionPtr = NULL; + const char *messagePtr = NULL; + const char *theirIdentityKeyPtr = NULL; + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); + } + else if(0 == aTheirIdentityKey) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); + } + else if(NULL == (theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); + } + else if(0==aOneTimeKeyMsg) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid one time key message"); + } + else if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - one time key JNI allocation OOM"); + } + else + { + size_t identityKeyLength = env->GetStringUTFLength(aTheirIdentityKey); + size_t messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); + + size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); + if(matchResult == olm_error()) { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - no match Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## matchesInboundSessionFromIdKeyJni(): success - result=%lu", matchResult); + } + } + + return retCode; +} + + +/** +* Get the session identifier for this session. +* @return the session identifier if operation succeed, null otherwise +*/ +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz) +{ + OlmSession *sessionPtr = NULL; + void *sessionIdPtr = NULL; + jstring returnValueStr=0; + + // get the size to alloc to contain the id + size_t lengthSessId = olm_session_id_length(sessionPtr); + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); + } + else if(NULL == (sessionIdPtr = (void*)malloc(lengthSessId*sizeof(void*)))) + { + LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); + } + else + { + size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessId); + if (result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + } + else + { + returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + } + free(sessionIdPtr); + } + + return returnValueStr; +} + +/** +* Read the account instance ID of the calling object (aJavaObject) passed in parameter. +* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) + { + instanceId = aJniEnv->GetIntField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); + return instanceId; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h new file mode 100644 index 0000000..edd1012 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -0,0 +1,38 @@ +#ifndef _OMLSESSION_H +#define _OMLSESSION_H + +#include "olm_jni.h" + +#ifdef __cplusplus +extern "C" { +#endif + +jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); + +// session creation/destruction +JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv *env, jobject thiz); +JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmSession_initNewSessionJni(JNIEnv *env, jobject thiz); + +// outbound session +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey); + +// inbound sessions: establishment based on PRE KEY message +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg); +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); + +// match inbound sessions: based on PRE KEY message +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg); +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); + +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz); + + +// signing + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/java/android/OlmLibSdk/settings.gradle b/java/android/OlmLibSdk/settings.gradle new file mode 100644 index 0000000..d11302c --- /dev/null +++ b/java/android/OlmLibSdk/settings.gradle @@ -0,0 +1 @@ +include ':olm-sdk' -- cgit v1.2.3 From 573713dd000323208e0b520e39229e60e7699ac5 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 6 Oct 2016 08:40:21 +0200 Subject: - Add missing file --- java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml b/java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml new file mode 100644 index 0000000..93bea1d --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + OlmSdk + -- cgit v1.2.3 From 0393ad68438669f60a6679c9e0f8010c7366c5ed Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 6 Oct 2016 10:30:24 +0200 Subject: Update Account unit tests --- .../java/org/matrix/olm/OlmAccountTest.java | 25 ++++++++++++---------- .../src/main/java/org/matrix/olm/OlmAccount.java | 8 +++---- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 3d7568f..061c79d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -15,9 +15,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; -import static org.junit.Assert.assertFalse; +import java.util.Iterator; + import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; @RunWith(AndroidJUnit4.class) @@ -93,7 +93,7 @@ public class OlmAccountTest { try { String fingerPrintKey = identityKeysJson.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); - assertFalse("fingerprint key missing",TextUtils.isEmpty(fingerPrintKey)); + assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); } catch (JSONException e) { e.printStackTrace(); assertTrue("Exception MSg="+e.getMessage(), false); @@ -101,7 +101,7 @@ public class OlmAccountTest { try { String identityKey = identityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); - assertFalse("identity key missing",TextUtils.isEmpty(identityKey)); + assertTrue("identity key missing",!TextUtils.isEmpty(identityKey)); } catch (JSONException e) { e.printStackTrace(); assertTrue("Exception MSg="+e.getMessage(), false); @@ -110,7 +110,6 @@ public class OlmAccountTest { } - //**************************************************** //** ************** One time keys TESTS ************** //**************************************************** @@ -133,20 +132,24 @@ public class OlmAccountTest { @Test public void test7OneTimeKeysJsonFormat() { - Log.d(LOG_TAG,"## testIdentityKeys"); + Log.d(LOG_TAG,"## test7OneTimeKeysJsonFormat"); + int oneTimeKeysCount = 0; JSONObject generatedKeysJsonObj; JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys(); assertNotNull(oneTimeKeysJson); try { generatedKeysJsonObj = oneTimeKeysJson.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); - assertFalse(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null==generatedKeysJsonObj); + assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=generatedKeysJsonObj); - /*String oneTimeKeyA = generatedKeysJsonObj.getString(OlmAccount.JSON_KEY_ONE_TIME_KEY_GENERATED_A); - assertFalse(" one time KeyA object is missing", TextUtils.isEmpty(oneTimeKeyA)); + // test the count of the generated one time keys: + Iterator generatedKeysIt = generatedKeysJsonObj.keys(); + while(generatedKeysIt.hasNext()){ + generatedKeysIt.next(); + oneTimeKeysCount++; + } + assertTrue("Expected count="+GENERATION_ONE_TIME_KEYS_NUMBER+" found="+oneTimeKeysCount,GENERATION_ONE_TIME_KEYS_NUMBER==oneTimeKeysCount); - String oneTimeKeyB = generatedKeysJsonObj.getString(OlmAccount.JSON_KEY_ONE_TIME_KEY_GENERATED_B); - assertFalse(" one time KeyA object is missing", TextUtils.isEmpty(oneTimeKeyA));*/ } catch (JSONException e) { assertTrue("Exception MSg="+e.getMessage(), false); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index ac8e12d..15de09c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -25,11 +25,9 @@ public class OlmAccount { private static final String LOG_TAG = "OlmAccount"; // JSON keys used in the JSON objects returned by JNI - public static String JSON_KEY_ONE_TIME_KEY = "curve25519"; - public static String JSON_KEY_IDENTITY_KEY = "curve25519"; - public static String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; - public static String JSON_KEY_ONE_TIME_KEY_GENERATED_A = "AAAAAA"; - public static String JSON_KEY_ONE_TIME_KEY_GENERATED_B = "AAAAAB"; + public static final String JSON_KEY_ONE_TIME_KEY = "curve25519"; + public static final String JSON_KEY_IDENTITY_KEY = "curve25519"; + public static final String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; /** instance unique identifier, used in JNI to match the corresponding native class **/ private int mJavaInstanceId; -- cgit v1.2.3 From 655c841cc3720d1bb9892d60a2d7ca136c90cfbd Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 6 Oct 2016 19:55:03 +0200 Subject: - Update Unit tests for OlmAccount - new file olm_utility.cpp to have a stand alone function to initialize/alloc a random buffer - new class OlmMessage - complete OlmSession API with encryptMessage() - comments review - OlmAccount unit tests are green - new gradle to compile the shared lib according to debug mode --- java/android/OlmLibSdk/olm-sdk/build.gradle | 24 ++- .../java/org/matrix/olm/OlmAccountTest.java | 16 +- .../src/main/java/org/matrix/olm/OlmMessage.java | 30 ++++ .../src/main/java/org/matrix/olm/OlmSession.java | 146 +++++------------ .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 3 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 56 +++---- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 174 ++++++++++++++++++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 2 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 60 +++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 16 ++ 11 files changed, 353 insertions(+), 176 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle index 96eaaf7..2f92151 100644 --- a/java/android/OlmLibSdk/olm-sdk/build.gradle +++ b/java/android/OlmLibSdk/olm-sdk/build.gradle @@ -24,9 +24,16 @@ android { jni.srcDirs = [] } - task ndkBuildNative(type: Exec, description: 'NDK building..') { + task ndkBuildNativeRelease(type: Exec, description: 'NDK building..') { + println 'ndkBuildNativeRelease starts..' workingDir file('src/main') - commandLine getNdkBuildCmd() //, '-B', 'NDK_DEBUG=1' + commandLine getNdkBuildCmd(), 'NDK_DEBUG=0' + } + + task ndkBuildNativeDebug(type: Exec, description: 'NDK building..') { + println 'ndkBuildNativeDebug starts..' + workingDir file('src/main') + commandLine getNdkBuildCmd(), 'NDK_DEBUG=1' } task cleanNative(type: Exec, description: 'Clean NDK build') { @@ -34,10 +41,21 @@ android { commandLine getNdkBuildCmd(), 'clean' } - tasks.withType(JavaCompile) { + /*tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuildNative + }*/ + + tasks.withType(JavaCompile) { + compileTask -> if (compileTask.name.startsWith('compileDebugJava')) { + println 'test compile: Debug' + compileTask.dependsOn ndkBuildNativeDebug + } else if (compileTask.name.startsWith('compileReleaseJava')) { + println 'test compile: Release' + compileTask.dependsOn ndkBuildNativeRelease + } } + clean.dependsOn cleanNative } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 061c79d..f592aa4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -55,7 +55,6 @@ public class OlmAccountTest { } } - @After public void tearDown() { // TBD @@ -63,30 +62,25 @@ public class OlmAccountTest { @Test public void test1CreateAccount() { - Log.d(LOG_TAG,"## testInitNewAccount"); mOlmAccount = new OlmAccount(); assertNotNull(mOlmAccount); } @Test public void test2InitNewAccount() { - Log.d(LOG_TAG,"## testInitNewAccount"); assertTrue(mOlmAccount.initNewAccount()); mIsAccountCreated = true; } @Test public void test3GetOlmAccountId() { - Log.d(LOG_TAG,"## testGetOlmAccountId"); - long olmNativeInstance = mOlmAccount.getOlmAccountId(); + Log.d(LOG_TAG,"## testGetOlmAccountId olmNativeInstance="+olmNativeInstance); assertTrue(0!=olmNativeInstance); } @Test public void test4IdentityKeys() { - Log.d(LOG_TAG,"## testIdentityKeys"); - JSONObject identityKeysJson = mOlmAccount.identityKeys(); assertNotNull(identityKeysJson); Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson); @@ -115,8 +109,6 @@ public class OlmAccountTest { //**************************************************** @Test public void test5MaxOneTimeKeys() { - Log.d(LOG_TAG,"## testMaxOneTimeKeys"); - long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys(); Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys); @@ -125,14 +117,12 @@ public class OlmAccountTest { @Test public void test6GenerateOneTimeKeys() { - Log.d(LOG_TAG,"## testGenerateOneTimeKeys"); int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); assertTrue(0==retValue); } @Test public void test7OneTimeKeysJsonFormat() { - Log.d(LOG_TAG,"## test7OneTimeKeysJsonFormat"); int oneTimeKeysCount = 0; JSONObject generatedKeysJsonObj; JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys(); @@ -169,8 +159,6 @@ public class OlmAccountTest { @Test public void test8MarkOneTimeKeysAsPublished() { - Log.d(LOG_TAG,"## testMarkOneTimeKeysAsPublished"); - int retCode = mOlmAccount.markOneTimeKeysAsPublished(); // if OK => retCode=0 assertTrue(0 == retCode); @@ -178,8 +166,6 @@ public class OlmAccountTest { @Test public void test9SignMessage() { - Log.d(LOG_TAG,"## testMarkOneTimeKeysAsPublished"); - String clearMsg = "String to be signed by olm"; String signedMsg = mOlmAccount.signMessage(clearMsg); assertNotNull(signedMsg); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java new file mode 100644 index 0000000..047db97 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java @@ -0,0 +1,30 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +public class OlmMessage { + /** PRE KEY message type (used to establish new Olm session) **/ + public final static int MESSAGE_TYPE_PRE_KEY = 0; + /** normal message type **/ + public final static int MESSAGE_TYPE_MESSAGE = 1; + + /** the encrypted message (ie. )**/ + public String mCipherText; + + /** defined by {@link #MESSAGE_TYPE_MESSAGE} or {@link #MESSAGE_TYPE_PRE_KEY}**/ + public long mType; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 28324da..24a4215 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -146,12 +146,12 @@ public class OlmSession { /** * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message based on the sender identity key TODO TBC!.
+ * incoming PRE_KEY message based on the sender identity key.
* Public API for {@link #initInboundSessionFromIdKeyJni(long, String, String)}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session * @param aTheirIdentityKey the sender identity key - * @param aOneTimeKeyMsg PRE KEY message TODO TBC + * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise */ public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aOneTimeKeyMsg) { @@ -173,6 +173,18 @@ public class OlmSession { private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, String aTheirIdentityKey, String aOneTimeKeyMsg); + /** + * Get the session identifier.
Will be the same for both ends of the + * conversation. The session identifier is returned as a String object. + * Session Id sample: "session_id":"M4fOVwD6AABrkTKl" + * Public API for {@link #getSessionIdentifierJni()}. + * @return the session ID as a String if operation succeed, null otherwise + */ + public String sessionIdentifier() { + return getSessionIdentifierJni(); + } + + private native String getSessionIdentifierJni(); /** * Checks if the PRE_KEY message is for this in-bound session.
@@ -194,129 +206,43 @@ public class OlmSession { /** - * Get the session identifier.
Will be the same for both ends of the - * conversation. The session identifier is returned as a String object. - * Session Id sample: "session_id":"M4fOVwD6AABrkTKl" - * Public API for {@link #getSessionIdentifierJni()}. - * @return the session ID as a String if operation succeed, null otherwise - */ - public String sessionIdentifier() { - return getSessionIdentifierJni(); - } - - private native String getSessionIdentifierJni(); - -/* -- (BOOL) matchesInboundSession:(NSString*)oneTimeKeyMessage; -- (BOOL) matchesInboundSessionFrom:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage; - -// UTF-8 plaintext -> base64 ciphertext -- (OLMMessage*) encryptMessage:(NSString*)message; - -// base64 ciphertext -> UTF-8 plaintext -- (NSString*) decryptMessage:(OLMMessage*)message; -*/ - - - /** - * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
- * Keys are Base64 encoded. - * These keys must be published on the server. - * @return byte array containing the identity keys if operation succeed, null otherwise + * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * Public API for {@link #matchesInboundSessionJni(String)}. + * @param aTheirIdentityKey the sender identity key + * @param aOneTimeKeyMsg PRE KEY message + * @return this if operation succeed, null otherwise */ - private native byte[] identityKeysJni(); + public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) { + boolean retCode = false; - /** - * Return the identity keys in a JSON array.
- * Public API for {@link #identityKeysJni()}. - * @return identity keys in JSON array format if operation succeed, null otherwise - */ - public JSONObject identityKeys() { - JSONObject identityKeysJsonObj = null; - byte identityKeysBuffer[]; - - if( null != (identityKeysBuffer = identityKeysJni())) { - try { - identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); - Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); - } catch (JSONException e) { - identityKeysJsonObj = null; - Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); - } - } else { - Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); + if(0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey, aOneTimeKeyMsg)){ + retCode = true; } - - return identityKeysJsonObj; + return retCode; } - /** - * Return the largest number of "one time keys" this account can store. - * @return the max number of "one time keys", -1 otherwise - */ - public native long maxOneTimeKeys(); + private native int matchesInboundSessionFromIdKeyJni(String aTheirIdentityKey, String aOneTimeKeyMsg); - /** - * Generate a number of new one time keys.
If total number of keys stored - * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. - * @param aNumberOfKeys number of keys to generate - * @return 0 if operation succeed, -1 otherwise - */ - public native int generateOneTimeKeys(int aNumberOfKeys); /** - * Get the public parts of the unpublished "one time keys" for the account.
- * The returned data is a JSON-formatted object with the single property - * curve25519, which is itself an object mapping key id to - * base64-encoded Curve25519 key. - * These keys must be published on the server. - * @return byte array containing the one time keys if operation succeed, null otherwise + * Encrypt a message using the session.
+ * Public API for {@link #encryptMessageJni(String, OlmMessage)}. + * @param aClearMsg message to encrypted + * @return the encrypted message if operation succeed, null otherwise */ - private native byte[] oneTimeKeysJni(); + public OlmMessage encryptMessage(String aClearMsg) { + OlmMessage encryptedMsgRetValue = new OlmMessage(); - /** - * Return the "one time keys" in a JSON array.
- * Public API for {@link #oneTimeKeysJni()}. - * @return one time keys in JSON array format if operation succeed, null otherwise - */ - public JSONObject oneTimeKeys() { - byte identityKeysBuffer[]; - JSONObject identityKeysJsonObj = null; - - if( null != (identityKeysBuffer = oneTimeKeysJni())) { - try { - identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); - Log.d(LOG_TAG, "## oneTimeKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); - } catch (JSONException e) { - identityKeysJsonObj = null; - Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); - } - } else { - Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); + if(0 != encryptMessageJni(aClearMsg, encryptedMsgRetValue)){ + encryptedMsgRetValue = null; } - return identityKeysJsonObj; + return encryptedMsgRetValue; } - /** - * Remove the "one time keys" that the session used from the account. - * @param aNativeOlmSessionId native session instance identifier - * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed - */ - public native int removeOneTimeKeysForSession(long aNativeOlmSessionId); + private native int encryptMessageJni(String aClearMsg, OlmMessage aEncryptedMsg); - /** - * Marks the current set of "one time keys" as being published. - * @return 0 if operation succeed, -1 otherwise - */ - public native int markOneTimeKeysAsPublished(); - - /** - * Sign a message with the ed25519 fingerprint key for this account. - * @param aMessage message to sign - * @return the signed message if operation succeed, null otherwise - */ - public native String signMessage(String aMessage); @Override public String toString() { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index d59f916..26a6a90 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -44,7 +44,8 @@ $(SRC_ROOT_DIR)/lib/crypto-algorithms/sha256.c \ $(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \ $(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \ olm_account.cpp \ -olm_session.cpp +olm_session.cpp \ +olm_utility.cpp LOCAL_LDLIBS := -llog diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index d8ee409..51c0ca8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -15,7 +15,7 @@ */ #include "olm_account.h" - +#include "olm_utility.h" /** * Init memory allocation for account creation. @@ -70,10 +70,10 @@ JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv * **/ JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv *env, jobject thiz) { - OlmAccount* accountPtr = NULL; + OlmAccount *accountPtr = NULL; + uint8_t *randomBuffPtr = NULL; size_t accountRetCode; - uint8_t* randomBuffPtr = NULL; - int randomSize; + size_t randomSize; // init account memory allocation if(NULL == (accountPtr = initializeAccountMemory())) @@ -84,36 +84,34 @@ JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv { // allocate random buffer randomSize = olm_create_account_random_length(accountPtr); - if(NULL == (randomBuffPtr = (std::uint8_t*)malloc(randomSize*sizeof(std::uint8_t)))) + if(false == setRandomInBuffer(&randomBuffPtr, randomSize)) { - LOGE("## initNewAccount(): failure - random buffer OOM"); + LOGE("## initNewAccount(): failure - random buffer init"); } else - { // create random buffer - LOGD("## initNewAccount(): randomSize=%d",randomSize); - - srand(time(NULL)); // init seed - for(int i=0;iGetStringUTFChars(aTheirIdentityKey, 0))) { LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM"); @@ -136,7 +136,14 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI int theirOneTimeKeyLength = env->GetStringUTFLength(aTheirOneTimeKey); LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr); - sessionResult = olm_create_outbound_session(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, theirOneTimeKeyPtr, theirOneTimeKeyLength, randomBuffPtr, randomSize); + sessionResult = olm_create_outbound_session(sessionPtr, + accountPtr, + theirIdentityKeyPtr, + theirIdentityKeyLength, + theirOneTimeKeyPtr, + theirOneTimeKeyLength, + (void*)randomBuffPtr, + randomSize); if(sessionResult == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s",errorMsgPtr); @@ -147,20 +154,25 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI LOGD("## initOutboundSessionJni(): success - result=%ld", sessionResult); } } - - // free local alloc - free(randomBuffPtr); - if(NULL!= theirIdentityKeyPtr) - { - env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); - } - if(NULL!= theirOneTimeKeyPtr) - { - env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr); - } } } + // **** free mem alloc *** + if(NULL!= randomBuffPtr) + { + free(randomBuffPtr); + } + + if(NULL!= theirIdentityKeyPtr) + { + env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + } + + if(NULL!= theirOneTimeKeyPtr) + { + env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr); + } + return retCode; } @@ -172,7 +184,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY message.
* @param aOlmAccountId account instance - * @param aOneTimeKeyMsg PRE_KEY message TODO TBC + * @param aOneTimeKeyMsg PRE_KEY message * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg) @@ -337,6 +349,12 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(J } } + // free local alloc + if(NULL!= messagePtr) + { + env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + } + return retCode; } @@ -392,10 +410,128 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromI } } + // free local alloc + if(NULL!= theirIdentityKeyPtr) + { + env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + } + + if(NULL!= messagePtr) + { + env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + } + return retCode; } +/** + * Encrypt a message using the session. to a base64 ciphertext.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aTheirIdentityKey the identity key of the sender + * @param aOneTimeKeyMsg PRE KEY message + * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + */ +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg) +{ + jint retCode = ERROR_CODE_KO; + OlmSession *sessionPtr = NULL; + const char *clearMsgPtr = NULL; + uint8_t *randomBuffPtr = NULL; + void *encryptedMsgPtr = NULL; + jclass encryptedMsgJClass; + jfieldID encryptedMsgFieldId; + jfieldID typeMsgFieldId; + + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); + } + else if(0 == aClearMsg) + { + LOGE("## encryptMessageJni(): failure - invalid clear message"); + } + else if(0 == aEncryptedMsg) + { + LOGE("## encryptMessageJni(): failure - invalid clear message"); + } + else if(NULL == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) + { + LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM"); + } + else if(0 == (encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) + { + LOGE("## encryptMessageJni(): failure - unable to get crypted message class"); + } + else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) + { + LOGE("## encryptMessageJni(): failure - unable to get message field"); + } + else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","I"))) + { + LOGE("## encryptMessageJni(): failure - unable to get message type field"); + } + else + { + // compute random buffer + size_t randomLength = olm_encrypt_random_length(sessionPtr); + if(false == setRandomInBuffer(&randomBuffPtr, randomLength)) + { + LOGE("## encryptMessageJni(): failure - random buffer init"); + } + else + { + // alloc buffer for encrypted message + size_t clearMsgLength = env->GetStringUTFLength(aClearMsg); + size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); + if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(void*)))) + { + LOGE("## encryptMessageJni(): failure - random buffer OOM"); + } + + size_t result = olm_encrypt(sessionPtr, + (void const *)clearMsgPtr, + clearMsgLength, + randomBuffPtr, + randomLength, + encryptedMsgPtr, + encryptedMsgLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## encryptMessageJni(): failure - Msg=%s",errorMsgPtr); + } + else + { + // update type: PRE KEY message or normal message + size_t messageType = olm_encrypt_message_type(sessionPtr); + env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); + + // update message + jstring encryptedStr = env->NewStringUTF((const char*)encryptedMsgPtr); + env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedStr); + + retCode = ERROR_CODE_OK; + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%s", result, messageType, (const char*)encryptedMsgPtr); + } + } + } + + // free alloc + if(NULL != clearMsgPtr) + { + env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr); + } + + if(NULL != randomBuffPtr) + { + free(randomBuffPtr); + } + + return retCode; +} + /** * Get the session identifier for this session. * @return the session identifier if operation succeed, null otherwise diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index edd1012..8e162b0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -24,6 +24,8 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKe JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg); JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); +JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); + JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp new file mode 100644 index 0000000..9abd228 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -0,0 +1,60 @@ +/** + * Created by pedrocon on 06/10/2016. + */ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_jni.h" +#include "olm_utility.h" + +/** +* Init a buffer with a given number of random values. +* @param aBuffer2Ptr the buffer to be initialized +* @param aRandomSize the number of random values to apply +* @return true if operation succeed, false otherwise +**/ +bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) +{ + bool retCode = false; + if(NULL == aBuffer2Ptr) + { + LOGD("## setRandomInBuffer(): failure - aBuffer=NULL"); + } + else if(0 == aRandomSize) + { + LOGD("## setRandomInBuffer(): failure - random size=0"); + } + else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t)))) + { + LOGD("## setRandomInBuffer(): failure - alloc mem OOM"); + } + else + { + LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize); + + srand(time(NULL)); // init seed + for(size_t i=0;i Date: Fri, 7 Oct 2016 17:35:27 +0200 Subject: - Add decryptMessageJni() to olm_session.cpp API - review comments header - refactor utility functions --- .../src/main/java/org/matrix/olm/OlmAccount.java | 10 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 56 +---- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 1 - .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 232 ++++++++++++++------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 9 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 87 +++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 2 + 7 files changed, 264 insertions(+), 133 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 15de09c..156ec1a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -131,7 +131,8 @@ public class OlmAccount { /** * Generate a number of new one time keys.
If total number of keys stored - * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. + * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded.
+ * The corresponding keys are retrieved by {@link #oneTimeKeys()}. * @param aNumberOfKeys number of keys to generate * @return 0 if operation succeed, -1 otherwise */ @@ -141,15 +142,16 @@ public class OlmAccount { * Get the public parts of the unpublished "one time keys" for the account.
* The returned data is a JSON-formatted object with the single property * curve25519, which is itself an object mapping key id to - * base64-encoded Curve25519 key. - * These keys must be published on the server. + * base64-encoded Curve25519 key.
* @return byte array containing the one time keys if operation succeed, null otherwise */ private native byte[] oneTimeKeysJni(); /** * Return the "one time keys" in a JSON array.
- * Public API for {@link #oneTimeKeysJni()}. + * The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}
+ * Public API for {@link #oneTimeKeysJni()}.
+ * Note: these keys are to be published on the server. * @return one time keys in JSON array format if operation succeed, null otherwise */ public JSONObject oneTimeKeys() { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 51c0ca8..ac48fd2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -137,7 +137,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_identityKeysJni(JNIE else { // identity keys allocation identityKeysLength = olm_account_identity_keys_length(accountPtr); - if(NULL == (identityKeysBytesPtr=(uint8_t *)malloc(identityKeysLength*sizeof(std::uint8_t)))) + if(NULL == (identityKeysBytesPtr=(uint8_t*)malloc(identityKeysLength*sizeof(uint8_t)))) { LOGE("## identityKeys(): failure - identity keys array OOM"); } @@ -245,7 +245,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv } /** - * Get "one time keys". + * Get "one time keys".
* Return the public parts of the unpublished "one time keys" for the account * @return a valid byte array if operation succeed, null otherwise **/ @@ -372,15 +372,16 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_markOneTimeKeysAsPublished } /** - * Sign a message with the ed25519 key (fingerprint) for this account. + * Sign a message with the ed25519 key (fingerprint) for this account.
+ * The signed message is returned by the function. * @param aMessage message to sign - * @return the corresponding signed message, null otherwise + * @return the signed message, null otherwise **/ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env, jobject thiz, jstring aMessage) { OlmAccount* accountPtr = NULL; size_t signatureLength; - void* signaturePtr; + void* signedMsgPtr; size_t resultSign; jstring signedMsgRetValue = NULL; @@ -406,13 +407,13 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env // signature memory allocation signatureLength = olm_account_signature_length(accountPtr); - if(NULL == (signaturePtr=(void *)malloc(signatureLength*sizeof(void*)))) + if(NULL == (signedMsgPtr = (void*)malloc(signatureLength*sizeof(uint8_t)))) { LOGE("## signMessage(): failure - signature allocation OOM"); } else { // sign message - resultSign = olm_account_sign(accountPtr, (void*)messageToSign, messageLength, signaturePtr, signatureLength); + resultSign = olm_account_sign(accountPtr, (void*)messageToSign, messageLength, signedMsgPtr, signatureLength); if(resultSign == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); @@ -422,11 +423,11 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env { // convert to jstring // TODO check how UTF conversion can impact the content? // why not consider return jbyteArray? and convert in JAVA side.. - signedMsgRetValue = env->NewStringUTF((const char*)signaturePtr); // UTF8 + signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 LOGD("## signMessage(): success - retCode=%ld",resultSign); } - free(signaturePtr); + free(signedMsgPtr); } // release messageToSign @@ -454,40 +455,3 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmManager_getOlmLibVersion(JNIEnv } -/** -* Read the account instance ID of the calling object. -* @return the instance ID if read succeed, -1 otherwise. -**/ -jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - jlong instanceId=-1; - jfieldID instanceIdField; - jclass loaderClass; - - if(NULL!=aJniEnv) - { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId); - } - else - { - LOGD("## getAccountInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL"); - } - LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId); - return instanceId; -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 8ba1633..9c32912 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -7,7 +7,6 @@ extern "C" { #endif -jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmManager_getOlmLibVersion(JNIEnv *env, jobject thiz); // account creation/destruction diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 93b0658..dae905d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -19,7 +19,8 @@ /** -* Init memory allocation for session creation. +* Init memory allocation for a session creation.
+* Make sure releaseSessionJni() is called when one is done with the session instance. * @return valid memory allocation, NULL otherwise **/ OlmSession* initializeSessionMemory() @@ -192,6 +193,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIE jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; OlmAccount *accountPtr = NULL; + const char *messagePtr = NULL; size_t sessionResult; if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) @@ -208,7 +210,6 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIE } else { // convert message to C strings - const char *messagePtr = NULL; if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) { LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM"); @@ -426,11 +427,10 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromI /** - * Encrypt a message using the session. to a base64 ciphertext.
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * @param aTheirIdentityKey the identity key of the sender - * @param aOneTimeKeyMsg PRE KEY message - * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + * Encrypt a message using the session.
+ * @param aClearMsg clear text message + * @param [out] aEncryptedMsg ciphered message + * @return ERROR_CODE_OK if encrypt operation succeed, ERROR_CODE_KO otherwise */ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg) { @@ -439,11 +439,10 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv * const char *clearMsgPtr = NULL; uint8_t *randomBuffPtr = NULL; void *encryptedMsgPtr = NULL; - jclass encryptedMsgJClass; + jclass encryptedMsgJClass = 0; jfieldID encryptedMsgFieldId; jfieldID typeMsgFieldId; - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); @@ -485,35 +484,38 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv * // alloc buffer for encrypted message size_t clearMsgLength = env->GetStringUTFLength(aClearMsg); size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); - if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(void*)))) + if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(uint8_t)))) { LOGE("## encryptMessageJni(): failure - random buffer OOM"); } - - size_t result = olm_encrypt(sessionPtr, - (void const *)clearMsgPtr, - clearMsgLength, - randomBuffPtr, - randomLength, - encryptedMsgPtr, - encryptedMsgLength); - if(result == olm_error()) - { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## encryptMessageJni(): failure - Msg=%s",errorMsgPtr); - } else - { - // update type: PRE KEY message or normal message - size_t messageType = olm_encrypt_message_type(sessionPtr); - env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); + { // encrypt message + size_t result = olm_encrypt(sessionPtr, + (void const *)clearMsgPtr, + clearMsgLength, + randomBuffPtr, + randomLength, + encryptedMsgPtr, + encryptedMsgLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## encryptMessageJni(): failure - Msg=%s",errorMsgPtr); + } + else + { + // update message type: PRE KEY or normal + size_t messageType = olm_encrypt_message_type(sessionPtr); + env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); - // update message - jstring encryptedStr = env->NewStringUTF((const char*)encryptedMsgPtr); - env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedStr); + // update message: encryptedMsgPtr => encryptedJstring + jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr); + env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring); + // TODO mem leak: check if free(encryptedMsgPtr); does not interfer with line above - retCode = ERROR_CODE_OK; - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%s", result, messageType, (const char*)encryptedMsgPtr); + retCode = ERROR_CODE_OK; + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%s", result, messageType, (const char*)encryptedMsgPtr); + } } } } @@ -529,9 +531,134 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv * free(randomBuffPtr); } + if(NULL != encryptedMsgPtr) + { + free(encryptedMsgPtr); + } + return retCode; } + +/** + * Decrypt a message using the session. to a base64 ciphertext.
+ * @param aEncryptedMsg message to decrypt + * @return decrypted message if operation succeed, null otherwise + */ +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) +{ + jstring decryptedMsgRetValue = 0; + jclass encryptedMsgJclass = 0; + jstring encryptedMsgJstring = 0; // <= obtained from encryptedMsgFieldId + // field IDs + jfieldID encryptedMsgFieldId; + jfieldID typeMsgFieldId; + // ptrs + OlmSession *sessionPtr = NULL; + const char *encryptedMsgPtr = NULL; // <= obtained from encryptedMsgJstring + void *decryptedMsgPtr = NULL; + char *tempEncryptedPtr = NULL; + + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); + } + else if(0 == aEncryptedMsg) + { + LOGE("## decryptMessageJni(): failure - invalid clear message"); + } + else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg))) + { + LOGE("## decryptMessageJni(): failure - unable to get crypted message class"); + } + else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;"))) + { + LOGE("## decryptMessageJni(): failure - unable to get message field"); + } + else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","I"))) + { + LOGE("## decryptMessageJni(): failure - unable to get message type field"); + } + else if(0 == (encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) + { + LOGE("## decryptMessageJni(): failure - JNI encrypted object "); + } + else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) + { + LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + } + else + { + // get message type + jlong encryptedMsgType = env->GetLongField(aEncryptedMsg, typeMsgFieldId); + // get encrypted message length + size_t encryptedMsgLength = env->GetStringUTFLength(encryptedMsgJstring); + + // create a dedicated temp buffer to be used in next Olm API calls + tempEncryptedPtr = (char*)malloc(encryptedMsgLength*sizeof(uint8_t)); + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + LOGD("## decryptMessageJni(): encryptedMsgType=%lld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); + + // get max plaintext length + size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(sessionPtr, + encryptedMsgType, + (void*)tempEncryptedPtr, + encryptedMsgLength); + // Note: tempEncryptedPtr was destroyed by olm_decrypt_max_plaintext_length() + + if(maxPlaintextLength == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + } + else + { + // allocate output decrypted message + decryptedMsgPtr = (void*)malloc(maxPlaintextLength*sizeof(uint8_t)); + + // decrypt but before reload encrypted buffer (previous one was destroyed) + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + size_t plaintextLength = olm_decrypt(sessionPtr, + encryptedMsgType, + (void*)encryptedMsgPtr, + encryptedMsgLength, + (void*)decryptedMsgPtr, + maxPlaintextLength); + if(plaintextLength == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",errorMsgPtr); + } + else + { + decryptedMsgRetValue = env->NewStringUTF((const char*)decryptedMsgPtr); + } + } + } + + // free alloc + if(NULL != encryptedMsgPtr) + { + env->ReleaseStringUTFChars(encryptedMsgJstring, encryptedMsgPtr); + } + + if(NULL != tempEncryptedPtr) + { + free(tempEncryptedPtr); + } + + if(NULL != decryptedMsgPtr) + { + free(decryptedMsgPtr); + } + + return decryptedMsgRetValue; +} + + + + /** * Get the session identifier for this session. * @return the session identifier if operation succeed, null otherwise @@ -549,7 +676,7 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni { LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); } - else if(NULL == (sessionIdPtr = (void*)malloc(lengthSessId*sizeof(void*)))) + else if(NULL == (sessionIdPtr = (void*)malloc(lengthSessId*sizeof(uint8_t)))) { LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); } @@ -571,42 +698,3 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni return returnValueStr; } -/** -* Read the account instance ID of the calling object (aJavaObject) passed in parameter. -* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. -**/ -jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - jlong instanceId=-1; - jfieldID instanceIdField; - jclass loaderClass; - - if(NULL!=aJniEnv) - { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) - { - instanceId = aJniEnv->GetIntField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); - } - - LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); - return instanceId; -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 8e162b0..b04e71e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -7,8 +7,6 @@ extern "C" { #endif -jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); - // session creation/destruction JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv *env, jobject thiz); JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmSession_initNewSessionJni(JNIEnv *env, jobject thiz); @@ -24,15 +22,12 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKe JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg); JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); +// encrypt/decrypt JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz); - -// signing - - - #ifdef __cplusplus } #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 9abd228..4f96e10 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -50,11 +50,92 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) { (*aBuffer2Ptr)[i] = (uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO); - // TODO debug purpose - remove asap - LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]); + // debug purpose + //LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]); } retCode = true; } return retCode; -} \ No newline at end of file +} + + +/** +* Read the account instance ID of the calling object. +* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if operation succeed, -1 if instance ID was not found. +**/ +jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId); + } + else + { + LOGD("## getAccountInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL"); + } + LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId); + return instanceId; +} + +/** +* Read the account instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) + { + instanceId = aJniEnv->GetIntField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); + return instanceId; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index bf29eed..6683c68 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -7,6 +7,8 @@ extern "C" { #endif bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize); +jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); #ifdef __cplusplus } -- cgit v1.2.3 From f2ca1ce304deee9e8e858ea4a71ea22ba38a342b Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 11 Oct 2016 15:53:49 +0200 Subject: - Add OlmSession unit test - Simplify JNI function signatures definition (Account & Session) --- .../java/org/matrix/olm/OlmAccountTest.java | 62 +++++++----- .../java/org/matrix/olm/OlmSessionTest.java | 110 +++++++++++++++++++++ .../src/main/java/org/matrix/olm/OlmAccount.java | 26 ++--- .../src/main/java/org/matrix/olm/OlmSession.java | 33 ++++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 31 +++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 3 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 2 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 105 +++++++++++--------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 2 +- 10 files changed, 269 insertions(+), 109 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index f592aa4..05480fc 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -30,9 +30,6 @@ public class OlmAccountTest { private static OlmManager mOlmManager; private boolean mIsAccountCreated; - public static final String TEST_STRING = "This is a string"; - public static final long TEST_LONG = 12345678L; - @BeforeClass public static void setUpClass(){ // load native lib @@ -61,26 +58,35 @@ public class OlmAccountTest { } @Test - public void test1CreateAccount() { + public void test01CreateReleaseAccount() { + mOlmAccount = new OlmAccount(); + assertNotNull(mOlmAccount); + + mOlmAccount.releaseAccount(); + assertTrue(0 == mOlmAccount.getOlmAccountId()); + } + + @Test + public void test02CreateAccount() { mOlmAccount = new OlmAccount(); assertNotNull(mOlmAccount); } @Test - public void test2InitNewAccount() { + public void test03InitNewAccount() { assertTrue(mOlmAccount.initNewAccount()); mIsAccountCreated = true; } @Test - public void test3GetOlmAccountId() { + public void test04GetOlmAccountId() { long olmNativeInstance = mOlmAccount.getOlmAccountId(); Log.d(LOG_TAG,"## testGetOlmAccountId olmNativeInstance="+olmNativeInstance); assertTrue(0!=olmNativeInstance); } @Test - public void test4IdentityKeys() { + public void test05IdentityKeys() { JSONObject identityKeysJson = mOlmAccount.identityKeys(); assertNotNull(identityKeysJson); Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson); @@ -108,7 +114,7 @@ public class OlmAccountTest { //** ************** One time keys TESTS ************** //**************************************************** @Test - public void test5MaxOneTimeKeys() { + public void test06MaxOneTimeKeys() { long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys(); Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys); @@ -116,13 +122,13 @@ public class OlmAccountTest { } @Test - public void test6GenerateOneTimeKeys() { + public void test07GenerateOneTimeKeys() { int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); assertTrue(0==retValue); } @Test - public void test7OneTimeKeysJsonFormat() { + public void test08OneTimeKeysJsonFormat() { int oneTimeKeysCount = 0; JSONObject generatedKeysJsonObj; JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys(); @@ -145,27 +151,31 @@ public class OlmAccountTest { } } - // TODO testRemoveOneTimeKeysForSession when session is available - /*@Test - public void testRemoveOneTimeKeysForSession() { - Log.d(LOG_TAG,"## testRemoveOneTimeKeysForSession"); - OLMSession olmSession = new OLMSession(); - - JSONArray keysJsonArray = mOlmAccount.removeOneTimeKeysForSession(olmSession); - - assertNotNull(keysJsonArray); - // TODO add extra test to test the JSON content format.. - }*/ + @Test + public void test10RemoveOneTimeKeysForSession() { + OlmSession olmSession = new OlmSession(); + olmSession.initNewSession(); + long sessionId = olmSession.getOlmSessionId(); + assertTrue(0 != sessionId); + + int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(sessionId); + // no one time key has been use in the session, so removeOneTimeKeysForSession() returns an error + assertTrue(0 != sessionRetCode); + + olmSession.releaseSession(); + sessionId = olmSession.getOlmSessionId(); + assertTrue("sessionRetCode="+sessionRetCode,0 == sessionId); + } @Test - public void test8MarkOneTimeKeysAsPublished() { + public void test11MarkOneTimeKeysAsPublished() { int retCode = mOlmAccount.markOneTimeKeysAsPublished(); // if OK => retCode=0 assertTrue(0 == retCode); } @Test - public void test9SignMessage() { + public void test12SignMessage() { String clearMsg = "String to be signed by olm"; String signedMsg = mOlmAccount.signMessage(clearMsg); assertNotNull(signedMsg); @@ -193,10 +203,8 @@ public class OlmAccountTest { int generateRetCode = account.generateOneTimeKeys(50); Log.d(LOG_TAG, "## testJni(): generateRetCode="+generateRetCode); - JSONObject onteTimeKeysKeysJson = account.oneTimeKeys(); - Log.d(LOG_TAG, "## testJni(): onteTimeKeysKeysJson="+onteTimeKeysKeysJson.toString()); - - // TODO removeOneTimeKeysForSession(session); + JSONObject oneTimeKeysKeysJson = account.oneTimeKeys(); + Log.d(LOG_TAG, "## testJni(): oneTimeKeysKeysJson="+oneTimeKeysKeysJson.toString()); int asPublishedRetCode = account.markOneTimeKeysAsPublished(); Log.d(LOG_TAG, "## testJni(): asPublishedRetCode="+asPublishedRetCode); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java new file mode 100644 index 0000000..fb2eebc --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -0,0 +1,110 @@ +package org.matrix.olm; + +import android.support.test.runner.AndroidJUnit4; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import java.util.Iterator; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmSessionTest { + private static final String LOG_TAG = "OlmSessionTest"; + + private static OlmManager mOlmManager; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + @Test + public void test01AliceToBob() { + String bobIdentityKey = null; + String bobOneTimeKey=null; + + // creates alice & bob accounts + OlmAccount aliceAccount = new OlmAccount(); + aliceAccount.initNewAccount(); + + OlmAccount bobAccount = new OlmAccount(); + bobAccount.initNewAccount(); + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // get bob identity key + JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); + assertNotNull(bobIdentityKeysJson); + try { + bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); + assertTrue(null!=bobIdentityKey); + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // get bob one time keys + assertTrue(0==bobAccount.generateOneTimeKeys(5)); + JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); + assertNotNull(bobOneTimeKeysJsonObj); + try { + JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys); + + // test the count of the generated one time keys: + Iterator generatedKeysIt = generatedKeys.keys(); + if(generatedKeysIt.hasNext()) { + bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); + } + assertNotNull(bobOneTimeKey); + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // CREATE ALICE SESSION + OlmSession aliceSession = new OlmSession(); + aliceSession.initNewSession(); + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE ALICE OUTBOUND SESSION and encrypt message to bob + assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + String clearMsg = "Heloo bob , this is alice!"; + OlmMessage encryptedMsgToBob = aliceSession.encryptMessage(clearMsg); + assertNotNull(encryptedMsgToBob); + Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText); + + // CREATE BOB INBOUND SESSION and decrypt message from alice + OlmSession bobSession = new OlmSession(); + bobSession.initNewSession(); + assertTrue(0!=bobSession.getOlmSessionId()); + assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); + String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); + assertNotNull(decryptedMsg); + + // MESSAGE COMPARISON: decrypted vs encrypted + assertTrue(clearMsg.equals(decryptedMsg)); + + // clean objects.. + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId())); + bobAccount.releaseAccount(); + aliceAccount.releaseAccount(); + bobSession.releaseSession(); + aliceSession.releaseSession(); + } +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 156ec1a..e9eddc7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -29,16 +29,12 @@ public class OlmAccount { public static final String JSON_KEY_IDENTITY_KEY = "curve25519"; public static final String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; - /** instance unique identifier, used in JNI to match the corresponding native class **/ - private int mJavaInstanceId; - /** account raw pointer value (OlmAccount*) returned by JNI. * this value identifies uniquely the native account instance. */ private long mNativeOlmAccountId; public OlmAccount() { - mJavaInstanceId = hashCode(); //initNewAccount(); } @@ -101,8 +97,13 @@ public class OlmAccount { /** * Return the identity keys (identity & fingerprint keys) in a JSON array.
- * Public API for {@link #identityKeysJni()}. - * @return identity keys in JSON array format if operation succeed, null otherwise + * Public API for {@link #identityKeysJni()}.
+ * Ex: + * { + * "curve25519":"Vam++zZPMqDQM6ANKpO/uAl5ViJSHxV9hd+b0/fwRAg", + * "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I" + * } + * @return identity keys in JSON array if operation succeed, null otherwise */ public JSONObject identityKeys() { JSONObject identityKeysJsonObj = null; @@ -150,6 +151,14 @@ public class OlmAccount { /** * Return the "one time keys" in a JSON array.
* The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}
+ * Ex: + * { "curve25519": + * { + * "AAAABQ":"qefVZd8qvjOpsFzoKSAdfUnJVkIreyxWFlipCHjSQQg", + * "AAAABA":"/X8szMU+p+lsTnr56wKjaLgjTMQQkCk8EIWEAilZtQ8", + * "AAAAAw":"qxNxxFHzevFntaaPdT0fhhO7tc7pco4+xB/5VRG81hA", + * } + * }
* Public API for {@link #oneTimeKeysJni()}.
* Note: these keys are to be published on the server. * @return one time keys in JSON array format if operation succeed, null otherwise @@ -192,9 +201,4 @@ public class OlmAccount { * @return the signed message if operation succeed, null otherwise */ public native String signMessage(String aMessage); - - @Override - public String toString() { - return super.toString(); - } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 24a4215..0c2888c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -19,11 +19,9 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; -import org.json.JSONException; -import org.json.JSONObject; - public class OlmSession { private static final String LOG_TAG = "OlmSession"; + /** session raw pointer value (OlmSession*) returned by JNI. * this value uniquely identifies the native session instance. **/ @@ -44,6 +42,14 @@ public class OlmSession { return mNativeOlmSessionId; } + /** + * Getter on the session ID. + * @return native session ID + */ + public OlmAccount getOlmAccountId(){ + return mOlmAccount; + } + /** * Destroy the corresponding OLM session native object.
* This method must ALWAYS be called when this JAVA instance @@ -105,8 +111,9 @@ public class OlmSession { // set the account of this session mOlmAccount = aAccount; - int retCode = initOutboundSessionJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey); - retObj = this; + if(0 == initOutboundSessionJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey)) { + retObj = this; + } } return retObj; @@ -121,7 +128,7 @@ public class OlmSession { * Public API for {@link #initInboundSessionJni(long, String)}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session - * @param aOneTimeKeyMsg PRE KEY message TODO TBC + * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise */ public OlmSession initInboundSessionWithAccount(OlmAccount aAccount, String aOneTimeKeyMsg) { @@ -227,6 +234,7 @@ public class OlmSession { /** * Encrypt a message using the session.
+ * The encrypted message is returned in a OlmMessage object. * Public API for {@link #encryptMessageJni(String, OlmMessage)}. * @param aClearMsg message to encrypted * @return the encrypted message if operation succeed, null otherwise @@ -243,11 +251,12 @@ public class OlmSession { private native int encryptMessageJni(String aClearMsg, OlmMessage aEncryptedMsg); - - @Override - public String toString() { - return super.toString(); - } - + /** + * Decrypt a message using the session.
+ * The encrypted message is given as a OlmMessage object. + * @param aEncryptedMsg message to decrypt + * @return the decrypted message if operation succeed, null otherwise + */ + public native String decryptMessage(OlmMessage aEncryptedMsg); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index ac48fd2..e663fc9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -44,7 +44,7 @@ OlmAccount* initializeAccountMemory() * This method MUST be called when java counter part account instance is done. * */ -JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv *env, jobject thiz) +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) { OlmAccount* accountPtr = NULL; @@ -55,8 +55,11 @@ JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv * LOGE("## releaseAccountJni(): failure - invalid Account ptr=NULL"); } else - { // even if free(NULL) does not crash, a test is performed for debug purpose + { + olm_clear_account(accountPtr); + LOGD("## releaseAccountJni(): IN"); + // even if free(NULL) does not crash, logs are performed for debug purpose free(accountPtr); LOGD("## releaseAccountJni(): OUT"); } @@ -68,7 +71,7 @@ JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv * * to make the cast (OlmAccount* => jlong) platform independant. * @return the initialized OlmAccount* instance if init succeed, NULL otherwise **/ -JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz) { OlmAccount *accountPtr = NULL; uint8_t *randomBuffPtr = NULL; @@ -120,7 +123,7 @@ JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv * The keys are returned in the byte array. * @return a valid byte array if operation succeed, null otherwise **/ -JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_identityKeysJni(JNIEnv *env, jobject thiz) +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz) { OlmAccount* accountPtr = NULL; size_t identityKeysLength; @@ -175,7 +178,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_identityKeysJni(JNIE * Get the maximum number of "one time keys" the account can store. * **/ -JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_maxOneTimeKeys(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz) { OlmAccount* accountPtr = NULL; size_t maxKeys = -1; @@ -198,7 +201,7 @@ JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_maxOneTimeKeys(JNIEnv *en * @param aNumberOfKeys number of keys to generate * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv *env, jobject thiz, jint aNumberOfKeys) +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) { OlmAccount *accountPtr = NULL; uint8_t *randomBufferPtr = NULL; @@ -206,7 +209,6 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv size_t randomLength; size_t result; - LOGD("## generateOneTimeKeys(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { @@ -222,7 +224,10 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv LOGE("## generateOneTimeKeys(): failure - random buffer init"); } else - { // retrieve key pairs in keysBytesPtr + { + LOGD("## generateOneTimeKeys(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); + + // retrieve key pairs in keysBytesPtr result = olm_account_generate_one_time_keys(accountPtr, aNumberOfKeys, (void*)randomBufferPtr, randomLength); if(result == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); @@ -249,7 +254,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv * Return the public parts of the unpublished "one time keys" for the account * @return a valid byte array if operation succeed, null otherwise **/ -JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_oneTimeKeysJni(JNIEnv *env, jobject thiz) +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz) { OlmAccount* accountPtr = NULL; size_t keysLength; @@ -303,7 +308,7 @@ JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_oneTimeKeysJni(JNIEn * @param aNativeOlmSessionId session instance * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS if no matching keys, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_removeOneTimeKeysForSession(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) { jint retCode = ERROR_CODE_KO; OlmAccount* accountPtr = NULL; @@ -342,7 +347,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_removeOneTimeKeysForSessio * Mark the current set of "one time keys" as being published. * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_markOneTimeKeysAsPublished(JNIEnv *env, jobject thiz) +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz) { jint retCode = ERROR_CODE_OK; OlmAccount* accountPtr = NULL; @@ -377,7 +382,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_markOneTimeKeysAsPublished * @param aMessage message to sign * @return the signed message, null otherwise **/ -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env, jobject thiz, jstring aMessage) +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage) { OlmAccount* accountPtr = NULL; size_t signatureLength; @@ -439,7 +444,7 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env } -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmManager_getOlmLibVersion(JNIEnv* env, jobject thiz) +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv* env, jobject thiz) { uint8_t majorVer=0, minorVer=0, patchVer=0; jstring returnValueStr=0; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 9c32912..33fc65c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -3,6 +3,9 @@ #include "olm_jni.h" +#define OLM_ACCOUNT_FUNC_DEF(func_name) FUNC_DEF(OlmAccount,func_name) +#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name) + #ifdef __cplusplus extern "C" { #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 1e85cc1..d811c3f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -28,6 +28,8 @@ #define LOGE(...) #endif +#define FUNC_DEF(class_name,func_name) JNICALL Java_org_matrix_olm_##class_name##_##func_name + // Error codes definition static const int ERROR_CODE_OK = 0; static const int ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS = ERROR_CODE_OK+1; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index dae905d..0febc02 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -41,7 +41,7 @@ OlmSession* initializeSessionMemory() return sessionPtr; } -JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv *env, jobject thiz) +JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { OlmSession* sessionPtr = NULL; @@ -50,8 +50,11 @@ JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv * LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); } else - { // even if free(NULL) does not crash, a test is performed for debug purpose + { + olm_clear_session(sessionPtr); + LOGD("## releaseSessionJni(): IN"); + // even if free(NULL) does not crash, logs are performed for debug purpose free(sessionPtr); LOGD("## releaseSessionJni(): OUT"); } @@ -63,7 +66,7 @@ JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv * * to make the cast (OlmSession* => jlong) platform independent. * @return the initialized OlmSession* instance if init succeed, NULL otherwise **/ -JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmSession_initNewSessionJni(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) { OlmSession* sessionPtr = NULL; @@ -92,7 +95,7 @@ JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmSession_initNewSessionJni(JNIEnv * @param aTheirOneTimeKey the one time key of the recipient * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey) { jint retCode = ERROR_CODE_KO; OlmSession* sessionPtr = NULL; @@ -117,7 +120,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI else { // allocate random buffer size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); - if(false == setRandomInBuffer(&randomBuffPtr, randomSize)) + if((0!=randomSize) && (false == setRandomInBuffer(&randomBuffPtr, randomSize))) { LOGE("## initOutboundSessionJni(): failure - random buffer init"); } @@ -188,7 +191,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI * @param aOneTimeKeyMsg PRE_KEY message * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; @@ -206,7 +209,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIE } else if(0==aOneTimeKeyMsg) { - LOGE("## initOutboundSessionJni(): failure - invalid message"); + LOGE("## initInboundSessionJni(): failure - invalid message"); } else { // convert message to C strings @@ -217,7 +220,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIE else { int messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); - LOGD("## initInboundSessionJni(): message=%s messageLength=%d",messagePtr,messageLength); + LOGD("## initInboundSessionJni(): messageLength=%d message=%s", messageLength, messagePtr); sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); if(sessionResult == olm_error()) { @@ -245,7 +248,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIE * @param aOneTimeKeyMsg encrypted message * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; @@ -268,7 +271,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKe } else if(0==aOneTimeKeyMsg) { - LOGE("## initOutboundSessionJni(): failure - invalid one time key message"); + LOGE("## initInboundSessionJni(): failure - invalid one time key message"); } else if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) { @@ -316,7 +319,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKe * @param aOneTimeKeyMsg PRE KEY message * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise */ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; @@ -367,7 +370,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(J * @param aOneTimeKeyMsg PRE KEY message * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise */ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) +JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; @@ -432,7 +435,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromI * @param [out] aEncryptedMsg ciphered message * @return ERROR_CODE_OK if encrypt operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; @@ -467,15 +470,21 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv * { LOGE("## encryptMessageJni(): failure - unable to get message field"); } - else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","I"))) + else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) { LOGE("## encryptMessageJni(): failure - unable to get message type field"); } else { + // get message type + size_t messageType = olm_encrypt_message_type(sessionPtr); + // compute random buffer + // Note: olm_encrypt_random_length() can return 0, which means + // it just does not need new random data to encrypt a new message size_t randomLength = olm_encrypt_random_length(sessionPtr); - if(false == setRandomInBuffer(&randomBuffPtr, randomLength)) + LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu",messageType,randomLength); + if( (0!=randomLength) && (false == setRandomInBuffer(&randomBuffPtr, randomLength))) { LOGE("## encryptMessageJni(): failure - random buffer init"); } @@ -486,10 +495,16 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv * size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(uint8_t)))) { - LOGE("## encryptMessageJni(): failure - random buffer OOM"); + LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); } else - { // encrypt message + { + if(0==randomLength) + { + LOGW("## encryptMessageJni(): random buffer is not required"); + } + + // encrypt message size_t result = olm_encrypt(sessionPtr, (void const *)clearMsgPtr, clearMsgLength, @@ -505,13 +520,11 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv * else { // update message type: PRE KEY or normal - size_t messageType = olm_encrypt_message_type(sessionPtr); env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); // update message: encryptedMsgPtr => encryptedJstring jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr); env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring); - // TODO mem leak: check if free(encryptedMsgPtr); does not interfer with line above retCode = ERROR_CODE_OK; LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%s", result, messageType, (const char*)encryptedMsgPtr); @@ -541,11 +554,11 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv * /** - * Decrypt a message using the session. to a base64 ciphertext.
+ * Decrypt a message using the session.
* @param aEncryptedMsg message to decrypt * @return decrypted message if operation succeed, null otherwise */ -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) { jstring decryptedMsgRetValue = 0; jclass encryptedMsgJclass = 0; @@ -556,37 +569,37 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEn // ptrs OlmSession *sessionPtr = NULL; const char *encryptedMsgPtr = NULL; // <= obtained from encryptedMsgJstring - void *decryptedMsgPtr = NULL; + void *plainTextMsgPtr = NULL; char *tempEncryptedPtr = NULL; if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { - LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); + LOGE("## decryptMessage(): failure - invalid Session ptr=NULL"); } else if(0 == aEncryptedMsg) { - LOGE("## decryptMessageJni(): failure - invalid clear message"); + LOGE("## decryptMessage(): failure - invalid clear message"); } else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg))) { - LOGE("## decryptMessageJni(): failure - unable to get crypted message class"); + LOGE("## decryptMessage(): failure - unable to get crypted message class"); } else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;"))) { - LOGE("## decryptMessageJni(): failure - unable to get message field"); + LOGE("## decryptMessage(): failure - unable to get message field"); } - else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","I"))) + else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","J"))) { - LOGE("## decryptMessageJni(): failure - unable to get message type field"); + LOGE("## decryptMessage(): failure - unable to get message type field"); } else if(0 == (encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) { - LOGE("## decryptMessageJni(): failure - JNI encrypted object "); + LOGE("## decryptMessage(): failure - JNI encrypted object "); } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) { - LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + LOGE("## decryptMessage(): failure - encrypted message JNI allocation OOM"); } else { @@ -596,43 +609,47 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEn size_t encryptedMsgLength = env->GetStringUTFLength(encryptedMsgJstring); // create a dedicated temp buffer to be used in next Olm API calls - tempEncryptedPtr = (char*)malloc(encryptedMsgLength*sizeof(uint8_t)); + tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); LOGD("## decryptMessageJni(): encryptedMsgType=%lld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); // get max plaintext length - size_t maxPlaintextLength = olm_decrypt_max_plaintext_length(sessionPtr, + size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, encryptedMsgType, - (void*)tempEncryptedPtr, + static_cast(tempEncryptedPtr), encryptedMsgLength); - // Note: tempEncryptedPtr was destroyed by olm_decrypt_max_plaintext_length() + // Note: tempEncryptedPtr is destroyed by olm_decrypt_max_plaintext_length() - if(maxPlaintextLength == olm_error()) + if(maxPlainTextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); } else { + LOGD("## decryptMessage(): maxPlaintextLength=%lu",maxPlainTextLength); + // allocate output decrypted message - decryptedMsgPtr = (void*)malloc(maxPlaintextLength*sizeof(uint8_t)); + plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); - // decrypt but before reload encrypted buffer (previous one was destroyed) + // decrypt, but before reload encrypted buffer (previous one was destroyed) memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); size_t plaintextLength = olm_decrypt(sessionPtr, encryptedMsgType, (void*)encryptedMsgPtr, encryptedMsgLength, - (void*)decryptedMsgPtr, - maxPlaintextLength); + (void*)plainTextMsgPtr, + maxPlainTextLength); if(plaintextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",errorMsgPtr); + LOGE("## decryptMessage(): failure - olm_decrypt Msg=%s",errorMsgPtr); } else { - decryptedMsgRetValue = env->NewStringUTF((const char*)decryptedMsgPtr); + (static_cast(plainTextMsgPtr))[plaintextLength] = static_cast('\0'); + LOGD("## decryptMessage(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); + decryptedMsgRetValue = env->NewStringUTF(static_cast(plainTextMsgPtr)); } } } @@ -648,9 +665,9 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEn free(tempEncryptedPtr); } - if(NULL != decryptedMsgPtr) + if(NULL != plainTextMsgPtr) { - free(decryptedMsgPtr); + free(plainTextMsgPtr); } return decryptedMsgRetValue; @@ -663,7 +680,7 @@ JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEn * Get the session identifier for this session. * @return the session identifier if operation succeed, null otherwise */ -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) { OlmSession *sessionPtr = NULL; void *sessionIdPtr = NULL; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index b04e71e..9b3c30f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -3,6 +3,8 @@ #include "olm_jni.h" +#define OLM_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmSession,func_name) + #ifdef __cplusplus extern "C" { #endif @@ -24,7 +26,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromI // encrypt/decrypt JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessageJni(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); +JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessage(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 4f96e10..99df7f5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -118,7 +118,7 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) { - instanceId = aJniEnv->GetIntField(aJavaObject, instanceIdField); + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); aJniEnv->DeleteLocalRef(loaderClass); } else -- cgit v1.2.3 From 1679c4513f8e4965ad44b4fdad22cfda609e16fc Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 12 Oct 2016 19:04:50 +0200 Subject: Temp commit: debug in progress --- .../java/org/matrix/olm/OlmSessionTest.java | 136 ++++++++++++++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 27 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 2 +- 3 files changed, 150 insertions(+), 15 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index fb2eebc..93e70c5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -33,8 +33,18 @@ public class OlmSessionTest { Log.d(LOG_TAG, "## setUpClass(): lib version="+version); } + /** + * Basic test: + * - alice creates an account + * - bob creates an account + * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey) + * - alice encrypts a message with its session + * - bob creates an inbound session based on alice's encrypted message + * - bob decrypts the encrypted message with its session + */ @Test public void test01AliceToBob() { + final int ONE_TIME_KEYS_NUMBER = 5; String bobIdentityKey = null; String bobOneTimeKey=null; @@ -60,14 +70,13 @@ public class OlmSessionTest { } // get bob one time keys - assertTrue(0==bobAccount.generateOneTimeKeys(5)); + assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); assertNotNull(bobOneTimeKeysJsonObj); try { JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys); - // test the count of the generated one time keys: Iterator generatedKeysIt = generatedKeys.keys(); if(generatedKeysIt.hasNext()) { bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); @@ -102,9 +111,132 @@ public class OlmSessionTest { // clean objects.. assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId())); + // release accounts bobAccount.releaseAccount(); aliceAccount.releaseAccount(); + // release sessions bobSession.releaseSession(); aliceSession.releaseSession(); } + + + /** + * Same as test01AliceToBob but with bob who's encrypting messages + * to alice and alice decrypt them.
+ * - alice creates an account + * - bob creates an account + * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey) + * - alice encrypts a message with its own session + * - bob creates an inbound session based on alice's encrypted message + * - bob decrypts the encrypted message with its own session + * - bob encrypts messages with its own session + * - alice decrypts bob's messages with its own message + */ + @Test + public void test02AliceToBobBackAndForth() { + final int ONE_TIME_KEYS_NUMBER = 1; + String bobIdentityKey = null; + String bobOneTimeKey=null; + + // creates alice & bob accounts + OlmAccount aliceAccount = new OlmAccount(); + aliceAccount.initNewAccount(); + + OlmAccount bobAccount = new OlmAccount(); + bobAccount.initNewAccount(); + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // get bob identity key + JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); + assertNotNull(bobIdentityKeysJson); + try { + bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); + assertTrue(null!=bobIdentityKey); + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // get bob one time keys + assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); + JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); + assertNotNull(bobOneTimeKeysJsonObj); + try { + JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys); + + Iterator generatedKeysIt = generatedKeys.keys(); + if(generatedKeysIt.hasNext()) { + bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); + } + assertNotNull(bobOneTimeKey); + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // CREATE ALICE SESSION + OlmSession aliceSession = new OlmSession(); + aliceSession.initNewSession(); + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE ALICE OUTBOUND SESSION and encrypt message to bob + assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + String helloClearMsg = "Hello I'm Alice!"; + String goodbyeClearMsg = "Goodbye Alice"; + OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + //OlmMessage encryptedAliceToBobMsg2 = aliceSession.encryptMessage(goodbyeClearMsg); + assertNotNull(encryptedAliceToBobMsg1); + //assertNotNull(encryptedAliceToBobMsg2); + Log.d(LOG_TAG,"## test02AliceToBobBackAndForth(): encryptedMsg="+encryptedAliceToBobMsg1.mCipherText); + + // CREATE BOB INBOUND SESSION and decrypt message from alice + OlmSession bobSession = new OlmSession(); + bobSession.initNewSession(); + assertTrue(0!=bobSession.getOlmSessionId()); + assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + + // DECRYPT MESSAGE FROM ALICE + String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + //String decryptedMsg02 = bobSession.decryptMessage(encryptedAliceToBobMsg2); + assertNotNull(decryptedMsg01); + //assertNotNull(decryptedMsg02); + + // MESSAGE COMPARISON: decrypted vs encrypted + assertTrue(helloClearMsg.equals(decryptedMsg01)); + //assertTrue(goodbyeClearMsg.equals(decryptedMsg02)); + + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId())); + + // BACK/FORTH MESSAGE COMPARISON + String clearMsg1 = "Hello I'm Bob!"; + String clearMsg2 = "Isn't life grand?"; + String clearMsg3 = "Let's go to the opera."; + + OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + assertNotNull(encryptedMsg1); + /*OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + assertNotNull(encryptedMsg2); + OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + assertNotNull(encryptedMsg3);*/ + + String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); + //assertNotNull(decryptedMsg1); + /*String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); + //assertNotNull(decryptedMsg2); + String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); + //assertNotNull(decryptedMsg3);*/ + + /*assertTrue(clearMsg1.equals(decryptedMsg1)); +/* assertTrue(clearMsg2.equals(decryptedMsg2)); + assertTrue(clearMsg3.equals(decryptedMsg3));*/ + + // clean objects.. + bobAccount.releaseAccount(); + aliceAccount.releaseAccount(); + bobSession.releaseSession(); + aliceSession.releaseSession(); + } + } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 0febc02..23cbaee 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -446,6 +446,8 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz jfieldID encryptedMsgFieldId; jfieldID typeMsgFieldId; + LOGD("## encryptMessageJni(): IN "); + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); @@ -572,34 +574,35 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz void *plainTextMsgPtr = NULL; char *tempEncryptedPtr = NULL; + LOGD("## decryptMessage(): IN "); if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { - LOGE("## decryptMessage(): failure - invalid Session ptr=NULL"); + LOGE("## decryptMessage(): failure - invalid Session ptr=NULL"); } else if(0 == aEncryptedMsg) { - LOGE("## decryptMessage(): failure - invalid clear message"); + LOGE("## decryptMessage(): failure - invalid clear message"); } else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg))) { - LOGE("## decryptMessage(): failure - unable to get crypted message class"); + LOGE("## decryptMessage(): failure - unable to get crypted message class"); } else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;"))) { - LOGE("## decryptMessage(): failure - unable to get message field"); + LOGE("## decryptMessage(): failure - unable to get message field"); } else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","J"))) { - LOGE("## decryptMessage(): failure - unable to get message type field"); + LOGE("## decryptMessage(): failure - unable to get message type field"); } else if(0 == (encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) { - LOGE("## decryptMessage(): failure - JNI encrypted object "); + LOGE("## decryptMessage(): failure - JNI encrypted object "); } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) { - LOGE("## decryptMessage(): failure - encrypted message JNI allocation OOM"); + LOGE("## decryptMessage(): failure - encrypted message JNI allocation OOM"); } else { @@ -611,7 +614,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz // create a dedicated temp buffer to be used in next Olm API calls tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): encryptedMsgType=%lld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); + LOGD("## decryptMessageJni(): encryptedMsgType=%lld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, @@ -623,11 +626,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz if(maxPlainTextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + LOGE("## decryptMessage(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); } else { - LOGD("## decryptMessage(): maxPlaintextLength=%lu",maxPlainTextLength); + LOGD("## decryptMessage(): maxPlaintextLength=%lu",maxPlainTextLength); // allocate output decrypted message plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); @@ -643,12 +646,12 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz if(plaintextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessage(): failure - olm_decrypt Msg=%s",errorMsgPtr); + LOGE("## decryptMessage(): failure - olm_decrypt Msg=%s",errorMsgPtr); } else { (static_cast(plainTextMsgPtr))[plaintextLength] = static_cast('\0'); - LOGD("## decryptMessage(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); + LOGD("## decryptMessage(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); decryptedMsgRetValue = env->NewStringUTF(static_cast(plainTextMsgPtr)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 99df7f5..c27fe7c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -136,6 +136,6 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); } - LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); + //LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); return instanceId; } -- cgit v1.2.3 From f88ee7677ccee62ae2ddb1d0125ec673b0b39bd7 Mon Sep 17 00:00:00 2001 From: PedroGitt Date: Thu, 13 Oct 2016 00:19:47 +0200 Subject: - Fix encrypt API (update lencrypted ength) - Fix warning compiler --- .../java/org/matrix/olm/OlmSessionTest.java | 59 ++++++++++++++++------ .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 10 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 53 +++++++++++-------- 3 files changed, 80 insertions(+), 42 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 93e70c5..56048cc 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -184,12 +184,9 @@ public class OlmSessionTest { // CREATE ALICE OUTBOUND SESSION and encrypt message to bob assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); String helloClearMsg = "Hello I'm Alice!"; - String goodbyeClearMsg = "Goodbye Alice"; + OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); - //OlmMessage encryptedAliceToBobMsg2 = aliceSession.encryptMessage(goodbyeClearMsg); assertNotNull(encryptedAliceToBobMsg1); - //assertNotNull(encryptedAliceToBobMsg2); - Log.d(LOG_TAG,"## test02AliceToBobBackAndForth(): encryptedMsg="+encryptedAliceToBobMsg1.mCipherText); // CREATE BOB INBOUND SESSION and decrypt message from alice OlmSession bobSession = new OlmSession(); @@ -199,13 +196,10 @@ public class OlmSessionTest { // DECRYPT MESSAGE FROM ALICE String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); - //String decryptedMsg02 = bobSession.decryptMessage(encryptedAliceToBobMsg2); assertNotNull(decryptedMsg01); - //assertNotNull(decryptedMsg02); // MESSAGE COMPARISON: decrypted vs encrypted assertTrue(helloClearMsg.equals(decryptedMsg01)); - //assertTrue(goodbyeClearMsg.equals(decryptedMsg02)); assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId())); @@ -216,21 +210,21 @@ public class OlmSessionTest { OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); assertNotNull(encryptedMsg1); - /*OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); assertNotNull(encryptedMsg2); OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); - assertNotNull(encryptedMsg3);*/ + assertNotNull(encryptedMsg3); String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); - //assertNotNull(decryptedMsg1); - /*String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); - //assertNotNull(decryptedMsg2); + assertNotNull(decryptedMsg1); + String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); + assertNotNull(decryptedMsg2); String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); - //assertNotNull(decryptedMsg3);*/ + assertNotNull(decryptedMsg3); - /*assertTrue(clearMsg1.equals(decryptedMsg1)); -/* assertTrue(clearMsg2.equals(decryptedMsg2)); - assertTrue(clearMsg3.equals(decryptedMsg3));*/ + assertTrue(clearMsg1.equals(decryptedMsg1)); + assertTrue(clearMsg2.equals(decryptedMsg2)); + assertTrue(clearMsg3.equals(decryptedMsg3)); // clean objects.. bobAccount.releaseAccount(); @@ -239,4 +233,37 @@ public class OlmSessionTest { aliceSession.releaseSession(); } + @Test + public void test03AliceBobSessionId() { + // creates alice & bob accounts + OlmAccount aliceAccount = new OlmAccount(); + aliceAccount.initNewAccount(); + + OlmAccount bobAccount = new OlmAccount(); + bobAccount.initNewAccount(); + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // CREATE ALICE SESSION + OlmSession aliceSession = new OlmSession(); + aliceSession.initNewSession(); + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE BOB INBOUND SESSION and decrypt message from alice + OlmSession bobSession = new OlmSession(); + bobSession.initNewSession(); + assertTrue(0!=bobSession.getOlmSessionId()); + + String aliceSessionId = aliceSession.sessionIdentifier(); + assertNotNull(aliceSessionId); + + String bobSessionId = bobSession.sessionIdentifier(); + assertNotNull(bobSessionId); + + // must be the same for both ends of the conversation + assertTrue(aliceSessionId.equals(bobSessionId)); + } + } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index e663fc9..2a5ab6f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -87,7 +87,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi { // allocate random buffer randomSize = olm_create_account_random_length(accountPtr); - if(false == setRandomInBuffer(&randomBuffPtr, randomSize)) + if(!setRandomInBuffer(&randomBuffPtr, randomSize)) { LOGE("## initNewAccount(): failure - random buffer init"); } @@ -216,10 +216,10 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th } else { // keys memory allocation - randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, aNumberOfKeys); + randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); LOGD("## generateOneTimeKeys(): randomLength=%ld", randomLength); - if(false == setRandomInBuffer(&randomBufferPtr, randomLength)) + if(!setRandomInBuffer(&randomBufferPtr, randomLength)) { LOGE("## generateOneTimeKeys(): failure - random buffer init"); } @@ -228,7 +228,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th LOGD("## generateOneTimeKeys(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); // retrieve key pairs in keysBytesPtr - result = olm_account_generate_one_time_keys(accountPtr, aNumberOfKeys, (void*)randomBufferPtr, randomLength); + result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); if(result == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); LOGE("## generateOneTimeKeys(): failure - error generating one time keys Msg=%s",errorMsgPtr); @@ -418,7 +418,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j } else { // sign message - resultSign = olm_account_sign(accountPtr, (void*)messageToSign, messageLength, signedMsgPtr, signatureLength); + resultSign = olm_account_sign(accountPtr, (void*)messageToSign, (size_t)messageLength, signedMsgPtr, signatureLength); if(resultSign == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 23cbaee..bdc2239 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -120,7 +120,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject else { // allocate random buffer size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); - if((0!=randomSize) && (false == setRandomInBuffer(&randomBuffPtr, randomSize))) + if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize)) { LOGE("## initOutboundSessionJni(): failure - random buffer init"); } @@ -136,8 +136,8 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject } else { - int theirIdentityKeyLength = env->GetStringUTFLength(aTheirIdentityKey); - int theirOneTimeKeyLength = env->GetStringUTFLength(aTheirOneTimeKey); + size_t theirIdentityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); + size_t theirOneTimeKeyLength = (size_t)env->GetStringUTFLength(aTheirOneTimeKey); LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr); sessionResult = olm_create_outbound_session(sessionPtr, @@ -219,7 +219,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject } else { - int messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); + size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); LOGD("## initInboundSessionJni(): messageLength=%d message=%s", messageLength, messagePtr); sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); @@ -283,8 +283,8 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, } else { - size_t messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); - size_t theirIdentityKeyLength = env->GetStringUTFLength(aTheirIdentityKey); + size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); + size_t theirIdentityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); LOGD("## initInboundSessionFromIdKeyJni(): message=%s messageLength=%lu",messagePtr,messageLength); @@ -339,7 +339,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje } else { - size_t messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); + size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); if(matchResult == olm_error()) { @@ -399,8 +399,8 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J } else { - size_t identityKeyLength = env->GetStringUTFLength(aTheirIdentityKey); - size_t messageLength = env->GetStringUTFLength(aOneTimeKeyMsg); + size_t identityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); + size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); if(matchResult == olm_error()) { @@ -485,15 +485,15 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // Note: olm_encrypt_random_length() can return 0, which means // it just does not need new random data to encrypt a new message size_t randomLength = olm_encrypt_random_length(sessionPtr); - LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu",messageType,randomLength); - if( (0!=randomLength) && (false == setRandomInBuffer(&randomBuffPtr, randomLength))) + + if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) { LOGE("## encryptMessageJni(): failure - random buffer init"); } else { // alloc buffer for encrypted message - size_t clearMsgLength = env->GetStringUTFLength(aClearMsg); + size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg); size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(uint8_t)))) { @@ -506,6 +506,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz LOGW("## encryptMessageJni(): random buffer is not required"); } + LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu clearMsgLength=%lu encryptedMsgLength=%lu",messageType,randomLength, clearMsgLength, encryptedMsgLength); // encrypt message size_t result = olm_encrypt(sessionPtr, (void const *)clearMsgPtr, @@ -521,15 +522,19 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz } else { + // update encrypted buffer size + (static_cast(encryptedMsgPtr))[result] = static_cast('\0'); + // update message type: PRE KEY or normal env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); // update message: encryptedMsgPtr => encryptedJstring jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr); + size_t encryptedUtfMsgLength = (size_t)env->GetStringUTFLength(encryptedJstring); env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring); retCode = ERROR_CODE_OK; - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%s", result, messageType, (const char*)encryptedMsgPtr); + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", result, messageType, encryptedUtfMsgLength, (const char*)encryptedMsgPtr); } } } @@ -607,18 +612,18 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz else { // get message type - jlong encryptedMsgType = env->GetLongField(aEncryptedMsg, typeMsgFieldId); + size_t encryptedMsgType = (size_t)env->GetLongField(aEncryptedMsg, typeMsgFieldId); // get encrypted message length - size_t encryptedMsgLength = env->GetStringUTFLength(encryptedMsgJstring); + size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(encryptedMsgJstring); // create a dedicated temp buffer to be used in next Olm API calls tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): encryptedMsgType=%lld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); + LOGD("## decryptMessage(): MsgType=%ld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, - encryptedMsgType, + static_cast(encryptedMsgType), static_cast(tempEncryptedPtr), encryptedMsgLength); // Note: tempEncryptedPtr is destroyed by olm_decrypt_max_plaintext_length() @@ -641,7 +646,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz encryptedMsgType, (void*)encryptedMsgPtr, encryptedMsgLength, - (void*)plainTextMsgPtr, + plainTextMsgPtr, maxPlainTextLength); if(plaintextLength == olm_error()) { @@ -650,7 +655,9 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz } else { + // update decrypted buffer size (static_cast(plainTextMsgPtr))[plaintextLength] = static_cast('\0'); + LOGD("## decryptMessage(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); decryptedMsgRetValue = env->NewStringUTF(static_cast(plainTextMsgPtr)); } @@ -690,19 +697,19 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job jstring returnValueStr=0; // get the size to alloc to contain the id - size_t lengthSessId = olm_session_id_length(sessionPtr); + size_t lengthSessionId = olm_session_id_length(sessionPtr); if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); } - else if(NULL == (sessionIdPtr = (void*)malloc(lengthSessId*sizeof(uint8_t)))) + else if(NULL == (sessionIdPtr = (void*)malloc(lengthSessionId*sizeof(uint8_t)))) { LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); } else { - size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessId); + size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId); if (result == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); @@ -710,6 +717,10 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job } else { + // update decrypted buffer size + (static_cast(sessionIdPtr))[result] = static_cast('\0'); + + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); } free(sessionIdPtr); -- cgit v1.2.3 From 293a12a1386e008b0c9f40115a96072a5e44729c Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 13 Oct 2016 10:26:27 +0200 Subject: Fix warning compiler --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index bdc2239..5def863 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -220,7 +220,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject else { size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); - LOGD("## initInboundSessionJni(): messageLength=%d message=%s", messageLength, messagePtr); + LOGD("## initInboundSessionJni(): messageLength=%lu message=%s", messageLength, messagePtr); sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); if(sessionResult == olm_error()) { -- cgit v1.2.3 From 42c85adbc4ade043034d1cc620c49fc7583ed06b Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 13 Oct 2016 10:27:24 +0200 Subject: Update function API signatures with macros --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 20 ++++++++++---------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 20 ++++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 33fc65c..be19571 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -10,24 +10,24 @@ extern "C" { #endif -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmManager_getOlmLibVersion(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv *env, jobject thiz); // account creation/destruction -JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv *env, jobject thiz); -JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz); // identity keys -JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_identityKeysJni(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz); // one time keys -JNIEXPORT jbyteArray JNICALL Java_org_matrix_olm_OlmAccount_oneTimeKeysJni(JNIEnv *env, jobject thiz); -JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_maxOneTimeKeys(JNIEnv *env, jobject thiz); -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv *env, jobject thiz, jint aNumberOfKeys); -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_removeOneTimeKeysForSession(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_markOneTimeKeysAsPublished(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz); +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz); // signing -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmAccount_signMessage(JNIEnv *env, jobject thiz, jstring aMessage); +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 9b3c30f..70a8d5f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -10,25 +10,25 @@ extern "C" { #endif // session creation/destruction -JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv *env, jobject thiz); -JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmSession_initNewSessionJni(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); // outbound session -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey); // inbound sessions: establishment based on PRE KEY message -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg); -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); // match inbound sessions: based on PRE KEY message -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg); -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); // encrypt/decrypt -JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessage(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); -JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); #ifdef __cplusplus } -- cgit v1.2.3 From 618eab0086e9f0911fe6ee8071068b163bec4ecd Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 13 Oct 2016 10:30:08 +0200 Subject: Update SDK JAVA API making initNewAccount() private and called in the respective constructors --- .../androidTest/java/org/matrix/olm/OlmAccountTest.java | 7 ------- .../androidTest/java/org/matrix/olm/OlmSessionTest.java | 15 --------------- .../olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java | 4 ++-- .../olm-sdk/src/main/java/org/matrix/olm/OlmSession.java | 4 ++-- 4 files changed, 4 insertions(+), 26 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 05480fc..ec1d49c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -70,11 +70,6 @@ public class OlmAccountTest { public void test02CreateAccount() { mOlmAccount = new OlmAccount(); assertNotNull(mOlmAccount); - } - - @Test - public void test03InitNewAccount() { - assertTrue(mOlmAccount.initNewAccount()); mIsAccountCreated = true; } @@ -154,7 +149,6 @@ public class OlmAccountTest { @Test public void test10RemoveOneTimeKeysForSession() { OlmSession olmSession = new OlmSession(); - olmSession.initNewSession(); long sessionId = olmSession.getOlmSessionId(); assertTrue(0 != sessionId); @@ -189,7 +183,6 @@ public class OlmAccountTest { Log.d(LOG_TAG, "## testJni(): lib version="+versionLib); OlmAccount account = new OlmAccount(); - boolean initStatus = account.initNewAccount(); long accountNativeId = account.getOlmAccountId(); Log.d(LOG_TAG, "## testJni(): lib accountNativeId="+accountNativeId); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 56048cc..0b8e6b4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -50,10 +50,7 @@ public class OlmSessionTest { // creates alice & bob accounts OlmAccount aliceAccount = new OlmAccount(); - aliceAccount.initNewAccount(); - OlmAccount bobAccount = new OlmAccount(); - bobAccount.initNewAccount(); // test accounts creation assertTrue(0!=bobAccount.getOlmAccountId()); @@ -88,7 +85,6 @@ public class OlmSessionTest { // CREATE ALICE SESSION OlmSession aliceSession = new OlmSession(); - aliceSession.initNewSession(); assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob @@ -100,7 +96,6 @@ public class OlmSessionTest { // CREATE BOB INBOUND SESSION and decrypt message from alice OlmSession bobSession = new OlmSession(); - bobSession.initNewSession(); assertTrue(0!=bobSession.getOlmSessionId()); assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); @@ -140,10 +135,7 @@ public class OlmSessionTest { // creates alice & bob accounts OlmAccount aliceAccount = new OlmAccount(); - aliceAccount.initNewAccount(); - OlmAccount bobAccount = new OlmAccount(); - bobAccount.initNewAccount(); // test accounts creation assertTrue(0!=bobAccount.getOlmAccountId()); @@ -178,7 +170,6 @@ public class OlmSessionTest { // CREATE ALICE SESSION OlmSession aliceSession = new OlmSession(); - aliceSession.initNewSession(); assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob @@ -190,7 +181,6 @@ public class OlmSessionTest { // CREATE BOB INBOUND SESSION and decrypt message from alice OlmSession bobSession = new OlmSession(); - bobSession.initNewSession(); assertTrue(0!=bobSession.getOlmSessionId()); assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); @@ -237,10 +227,7 @@ public class OlmSessionTest { public void test03AliceBobSessionId() { // creates alice & bob accounts OlmAccount aliceAccount = new OlmAccount(); - aliceAccount.initNewAccount(); - OlmAccount bobAccount = new OlmAccount(); - bobAccount.initNewAccount(); // test accounts creation assertTrue(0!=bobAccount.getOlmAccountId()); @@ -248,12 +235,10 @@ public class OlmSessionTest { // CREATE ALICE SESSION OlmSession aliceSession = new OlmSession(); - aliceSession.initNewSession(); assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE BOB INBOUND SESSION and decrypt message from alice OlmSession bobSession = new OlmSession(); - bobSession.initNewSession(); assertTrue(0!=bobSession.getOlmSessionId()); String aliceSessionId = aliceSession.sessionIdentifier(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index e9eddc7..963f0a4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -35,7 +35,7 @@ public class OlmAccount { private long mNativeOlmAccountId; public OlmAccount() { - //initNewAccount(); + initNewAccount(); } /** @@ -79,7 +79,7 @@ public class OlmAccount { * To be called before any other API call. * @return true if init succeed, false otherwise. */ - public boolean initNewAccount() { + private boolean initNewAccount() { boolean retCode = false; if(0 != (mNativeOlmAccountId = initNewAccountJni())){ retCode = true; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 0c2888c..06e2fcf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -31,7 +31,7 @@ public class OlmSession { private OlmAccount mOlmAccount; public OlmSession() { - //initNewSession(); + initNewSession(); } /** @@ -76,7 +76,7 @@ public class OlmSession { * To be called before any other API call. * @return true if init succeed, false otherwise. */ - public boolean initNewSession() { + private boolean initNewSession() { boolean retCode = false; if(0 != (mNativeOlmSessionId = initNewSessionJni())){ retCode = true; -- cgit v1.2.3 From e59ee33b673bab22994afc9031413185b5ed598f Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 13 Oct 2016 10:33:43 +0200 Subject: Add missing copyright headers --- .../android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 16 ++++++++++++++++ java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 16 ++++++++++++++++ .../android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 16 ++++++++++++++++ .../android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 16 ++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index be19571..23c9687 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -1,3 +1,19 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef _OMLACCOUNT_H #define _OMLACCOUNT_H diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index d811c3f..38269f9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -1,3 +1,19 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef _OMLJNI_H #define _OMLJNI_H diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 70a8d5f..8880d67 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -1,3 +1,19 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef _OMLSESSION_H #define _OMLSESSION_H diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index 6683c68..bf35955 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -1,3 +1,19 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #ifndef _OMLUTILITY_H #define _OMLUTILITY_H -- cgit v1.2.3 From 572c7cd464c63243e78979615657bdf4460c49d9 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 13 Oct 2016 10:44:59 +0200 Subject: Renaming JNI API decryptMessage in decryptMessageJni --- .../src/main/java/org/matrix/olm/OlmSession.java | 7 ++++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 28 +++++++++++----------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 2 +- 3 files changed, 20 insertions(+), 17 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 06e2fcf..fc1f76f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -69,7 +69,6 @@ public class OlmSession { mNativeOlmSessionId = 0; } - /** * Create and save the session native instance ID. * Wrapper for {@link #initNewSessionJni()}.
@@ -257,6 +256,10 @@ public class OlmSession { * @param aEncryptedMsg message to decrypt * @return the decrypted message if operation succeed, null otherwise */ - public native String decryptMessage(OlmMessage aEncryptedMsg); + public String decryptMessage(OlmMessage aEncryptedMsg) { + return decryptMessageJni(aEncryptedMsg); + } + + private native String decryptMessageJni(OlmMessage aEncryptedMsg); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 5def863..d33ab72 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -565,7 +565,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz * @param aEncryptedMsg message to decrypt * @return decrypted message if operation succeed, null otherwise */ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) { jstring decryptedMsgRetValue = 0; jclass encryptedMsgJclass = 0; @@ -579,35 +579,35 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz void *plainTextMsgPtr = NULL; char *tempEncryptedPtr = NULL; - LOGD("## decryptMessage(): IN "); + LOGD("## decryptMessageJni(): IN "); if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { - LOGE("## decryptMessage(): failure - invalid Session ptr=NULL"); + LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); } else if(0 == aEncryptedMsg) { - LOGE("## decryptMessage(): failure - invalid clear message"); + LOGE("## decryptMessageJni(): failure - invalid clear message"); } else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg))) { - LOGE("## decryptMessage(): failure - unable to get crypted message class"); + LOGE("## decryptMessageJni(): failure - unable to get crypted message class"); } else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;"))) { - LOGE("## decryptMessage(): failure - unable to get message field"); + LOGE("## decryptMessageJni(): failure - unable to get message field"); } else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","J"))) { - LOGE("## decryptMessage(): failure - unable to get message type field"); + LOGE("## decryptMessageJni(): failure - unable to get message type field"); } else if(0 == (encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) { - LOGE("## decryptMessage(): failure - JNI encrypted object "); + LOGE("## decryptMessageJni(): failure - JNI encrypted object "); } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) { - LOGE("## decryptMessage(): failure - encrypted message JNI allocation OOM"); + LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } else { @@ -619,7 +619,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz // create a dedicated temp buffer to be used in next Olm API calls tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessage(): MsgType=%ld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); + LOGD("## decryptMessageJni(): MsgType=%ld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, @@ -631,11 +631,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz if(maxPlainTextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessage(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); } else { - LOGD("## decryptMessage(): maxPlaintextLength=%lu",maxPlainTextLength); + LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); // allocate output decrypted message plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); @@ -651,14 +651,14 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz if(plaintextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessage(): failure - olm_decrypt Msg=%s",errorMsgPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",errorMsgPtr); } else { // update decrypted buffer size (static_cast(plainTextMsgPtr))[plaintextLength] = static_cast('\0'); - LOGD("## decryptMessage(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); + LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); decryptedMsgRetValue = env->NewStringUTF(static_cast(plainTextMsgPtr)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 8880d67..babb3bd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -42,7 +42,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *e // encrypt/decrypt JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); -- cgit v1.2.3 From 147df845d05b224e3919ed5379ced200f0144c63 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 13 Oct 2016 14:39:44 +0200 Subject: Enbale all ABI platforms --- java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk index 29a4296..72a8175 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk @@ -1,3 +1,3 @@ APP_PLATFORM := android-21 -APP_ABI := arm64-v8a #armeabi-v7a armeabi x86 x86_64 +APP_ABI := arm64-v8a armeabi-v7a armeabi x86 x86_64 APP_STL := gnustl_static \ No newline at end of file -- cgit v1.2.3 From 57ec6fff885e25b32e749d3e63788ff010b1fdfd Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 13 Oct 2016 19:21:01 +0200 Subject: Temp commit.. adding group session API in progress --- .../java/org/matrix/olm/OlmAccountTest.java | 5 +- .../java/org/matrix/olm/OlmGroupTest.java | 95 +++++++ .../java/org/matrix/olm/OlmSessionTest.java | 4 +- .../src/main/java/org/matrix/olm/OlmAccount.java | 72 +++-- .../org/matrix/olm/OlmInboundGroupSession.java | 126 +++++++++ .../org/matrix/olm/OlmOutboundGroupSession.java | 135 ++++++++++ .../src/main/java/org/matrix/olm/OlmSession.java | 13 +- .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 3 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 48 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 7 +- .../src/main/jni/olm_inbound_group_session.cpp | 262 ++++++++++++++++++ .../src/main/jni/olm_inbound_group_session.h | 43 +++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 8 - .../src/main/jni/olm_outbound_group_session.cpp | 293 +++++++++++++++++++++ .../src/main/jni/olm_outbound_group_session.h | 43 +++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 10 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 82 +++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 1 + 19 files changed, 1182 insertions(+), 69 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index ec1d49c..ad875c5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -152,9 +152,8 @@ public class OlmAccountTest { long sessionId = olmSession.getOlmSessionId(); assertTrue(0 != sessionId); - int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(sessionId); - // no one time key has been use in the session, so removeOneTimeKeysForSession() returns an error - assertTrue(0 != sessionRetCode); + int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(olmSession); + assertTrue(0 == sessionRetCode); olmSession.releaseSession(); sessionId = olmSession.getOlmSessionId(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java new file mode 100644 index 0000000..482ae0f --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java @@ -0,0 +1,95 @@ +package org.matrix.olm; + +import android.support.test.runner.AndroidJUnit4; +import android.util.Log; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmGroupTest { + private static final String LOG_TAG = "OlmSessionTest"; + + private static OlmManager mOlmManager; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + @Test + public void test00AliceToBob() { + // TBD + } + + /** + * Basic test: + * - alice creates an account + * - bob creates an account + * - alice creates an outbound group session + * - bob creates an inbound group session with alice's outbound session key + * - alice encrypts a message with its session + * - bob decrypts the encrypted message with its session + */ + //@Test + public void test01AliceToBob() { + // creates alice outbound session + OlmOutboundGroupSession aliceOutboundSession = new OlmOutboundGroupSession(); + + // test accounts creation + String aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier(); + assertNotNull(aliceSessionIdentifier); + assertTrue(aliceSessionIdentifier.length()>0); + + String aliceOutboundSessionKey = aliceOutboundSession.sessionKey(); + assertNotNull(aliceOutboundSessionKey); + assertTrue(aliceOutboundSessionKey.length()>0); + + long messageIndex = aliceOutboundSession.messageIndex(); + assertTrue(0==messageIndex); + + String clearMessage = "Hello!"; + String encryptedMessage = aliceOutboundSession.encryptMessage(clearMessage); + assertNotNull(encryptedMessage); + + messageIndex = aliceOutboundSession.messageIndex(); + assertTrue(1==messageIndex); + + assertTrue(encryptedMessage.length()>=0); + + OlmInboundGroupSession bobInboundSession = new OlmInboundGroupSession(); + bobInboundSession.initInboundGroupSessionWithSessionKey(aliceOutboundSessionKey); + // check session identifiers are equals + aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier(); + String bobSessionIdentifier = aliceOutboundSession.sessionIdentifier(); + assertTrue(aliceSessionIdentifier.equals(bobSessionIdentifier )); + + String decryptedMessage = bobInboundSession.decryptMessage(encryptedMessage); + assertTrue(decryptedMessage.equals(bobSessionIdentifier )); + } + + //@Test + public void test02InboundGroupSession() { + // creates alice outbound session + OlmInboundGroupSession aliceInboundSession = new OlmInboundGroupSession(); + + // test session identifier + String sessionIdentifier = aliceInboundSession.sessionIdentifier(); + assertNotNull(sessionIdentifier); + assertTrue(sessionIdentifier.length()>0); + } + +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 0b8e6b4..6056466 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -105,7 +105,7 @@ public class OlmSessionTest { assertTrue(clearMsg.equals(decryptedMsg)); // clean objects.. - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId())); + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); // release accounts bobAccount.releaseAccount(); aliceAccount.releaseAccount(); @@ -191,7 +191,7 @@ public class OlmSessionTest { // MESSAGE COMPARISON: decrypted vs encrypted assertTrue(helloClearMsg.equals(decryptedMsg01)); - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId())); + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); // BACK/FORTH MESSAGE COMPARISON String clearMsg1 = "Hello I'm Bob!"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 963f0a4..95a6eb5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -21,7 +21,9 @@ import android.util.Log; import org.json.JSONException; import org.json.JSONObject; -public class OlmAccount { +import java.io.Serializable; + +public class OlmAccount implements Serializable { private static final String LOG_TAG = "OlmAccount"; // JSON keys used in the JSON objects returned by JNI @@ -67,7 +69,6 @@ public class OlmAccount { /** * Create the corresponding OLM account in native side.
- * The return value is a long casted C ptr on the OlmAccount. * Do not forget to call {@link #releaseAccount()} when JAVA side is done. * @return native account instance identifier (see {@link #mNativeOlmAccountId}) */ @@ -87,14 +88,6 @@ public class OlmAccount { return retCode; } - /** - * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
- * Keys are Base64 encoded. - * These keys must be published on the server. - * @return byte array containing the identity keys if operation succeed, null otherwise - */ - private native byte[] identityKeysJni(); - /** * Return the identity keys (identity & fingerprint keys) in a JSON array.
* Public API for {@link #identityKeysJni()}.
@@ -123,6 +116,13 @@ public class OlmAccount { return identityKeysJsonObj; } + /** + * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
+ * Keys are Base64 encoded. + * These keys must be published on the server. + * @return byte array containing the identity keys if operation succeed, null otherwise + */ + private native byte[] identityKeysJni(); /** * Return the largest number of "one time keys" this account can store. @@ -139,15 +139,6 @@ public class OlmAccount { */ public native int generateOneTimeKeys(int aNumberOfKeys); - /** - * Get the public parts of the unpublished "one time keys" for the account.
- * The returned data is a JSON-formatted object with the single property - * curve25519, which is itself an object mapping key id to - * base64-encoded Curve25519 key.
- * @return byte array containing the one time keys if operation succeed, null otherwise - */ - private native byte[] oneTimeKeysJni(); - /** * Return the "one time keys" in a JSON array.
* The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}
@@ -181,24 +172,61 @@ public class OlmAccount { return identityKeysJsonObj; } + /** + * Get the public parts of the unpublished "one time keys" for the account.
+ * The returned data is a JSON-formatted object with the single property + * curve25519, which is itself an object mapping key id to + * base64-encoded Curve25519 key.
+ * @return byte array containing the one time keys if operation succeed, null otherwise + */ + private native byte[] oneTimeKeysJni(); + + /** + * Remove the "one time keys" that the session used from the account. + * @param aSession session instance + * @return 0 if operation succeed, -1 otherwise + */ + public int removeOneTimeKeysForSession(OlmSession aSession) { + int retCode = 0; + + if(null != aSession) { + int result = removeOneTimeKeysForSessionJni(aSession.getOlmSessionId()); + Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result="+result); + if(-1 == result) { + retCode = -1; + } + } + return retCode; + } /** * Remove the "one time keys" that the session used from the account. * @param aNativeOlmSessionId native session instance identifier * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed */ - public native int removeOneTimeKeysForSession(long aNativeOlmSessionId); + private native int removeOneTimeKeysForSessionJni(long aNativeOlmSessionId); /** * Marks the current set of "one time keys" as being published. * @return 0 if operation succeed, -1 otherwise */ - public native int markOneTimeKeysAsPublished(); + public int markOneTimeKeysAsPublished() { + return markOneTimeKeysAsPublishedJni(); + } + private native int markOneTimeKeysAsPublishedJni(); /** * Sign a message with the ed25519 fingerprint key for this account. * @param aMessage message to sign * @return the signed message if operation succeed, null otherwise */ - public native String signMessage(String aMessage); + public String signMessage(String aMessage){ + return signMessageJni(aMessage); + } + private native String signMessageJni(String aMessage); + + // TODO missing API: initWithSerializedData + // TODO missing API: serializeDataWithKey + // TODO missing API: initWithCoder + // TODO missing API: encodeWithCoder } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java new file mode 100644 index 0000000..53ef7a3 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -0,0 +1,126 @@ +/** + * Created by pedrocon on 13/10/2016. + */ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + + +import android.text.TextUtils; +import android.util.Log; + +import java.io.Serializable; + +public class OlmInboundGroupSession implements Serializable { + + private static final String LOG_TAG = "OlmInboundGroupSession"; + + /** session raw pointer value returned by JNI.
+ * this value uniquely identifies the native inbound group session instance. + */ + private long mNativeOlmInboundGroupSessionId; + + + public OlmInboundGroupSession() { + initNewSession(); + } + + /** + * Getter on the native inbound group session ID. + * @return native inbound group session ID + */ + public long getOlmInboundGroupSessionId(){ + return mNativeOlmInboundGroupSessionId; + } + + /** + * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}. + * To be called before any other API call. + */ + public void releaseSession(){ + releaseSessionJni(); + + mNativeOlmInboundGroupSessionId = 0; + } + + /** + * Destroy the corresponding OLM inbound group session native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #initNewSessionJni()}. + */ + private native void releaseSessionJni(); + + /** + * Create and save the session native instance ID. + * Wrapper for {@link #initNewSessionJni()}.
+ * To be called before any other API call. + * @return true if init succeed, false otherwise. + */ + private boolean initNewSession() { + boolean retCode = false; + if(0 != (mNativeOlmInboundGroupSessionId = initNewSessionJni())){ + retCode = true; + } + return retCode; + } + + /** + * Create the corresponding OLM inbound group session in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native session instance identifier (see {@link #mNativeOlmInboundGroupSessionId}) + */ + private native long initNewSessionJni(); + + /** + * Creates a new inbound group session.
+ * The session key parameter is retrieved from a outbound group session. + * @param aSessionKey session key + * @return 0 if operation succeed, -1 otherwise + */ + public int initInboundGroupSessionWithSessionKey(String aSessionKey) { + int retCode = -1; + + if(TextUtils.isEmpty(aSessionKey)){ + Log.e(LOG_TAG, "## initInboundGroupSessionWithSessionKey(): invalid session key"); + } else { + retCode = initInboundGroupSessionWithSessionKeyJni(aSessionKey); + } + + return retCode; + } + private native int initInboundGroupSessionWithSessionKeyJni(String aSessionKey); + + + public String sessionIdentifier() { + return sessionIdentifierJni(); + } + private native String sessionIdentifierJni(); + + + public String decryptMessage(String aEncryptedMsg) { + return decryptMessageJni(aEncryptedMsg); + } + private native String decryptMessageJni(String aEncryptedMsg); + + + // TODO missing API: initWithSerializedData + // TODO missing API: serializeDataWithKey + // TODO missing API: initWithCoder + // TODO missing API: encodeWithCoder +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java new file mode 100644 index 0000000..63c0c36 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -0,0 +1,135 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + + +import android.text.TextUtils; +import android.util.Log; + +public class OlmOutboundGroupSession { + private static final String LOG_TAG = "OlmOutboundGroupSession"; + + /** session raw pointer value returned by JNI.
+ * this value uniquely identifies the native inbound group session instance. + */ + private long mNativeOlmOutboundGroupSessionId; + + public OlmOutboundGroupSession() { + initNewSession(); + } + + /** + * Getter on the native outbound group session ID. + * @return native outbound group session ID + */ + public long getOlmInboundGroupSessionId(){ + return mNativeOlmInboundGroupSessionId; + } + + /** + * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}. + * To be called before any other API call. + */ + public void releaseSession(){ + releaseSessionJni(); + + mNativeOlmOutboundGroupSessionId = 0; + } + + /** + * Destroy the corresponding OLM outbound group session native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #initNewSessionJni()}. + */ + private native void releaseSessionJni(); + + /** + * Create and save the session native instance ID. + * Wrapper for {@link #initNewSessionJni()}.
+ * To be called before any other API call. + * @return true if init succeed, false otherwise. + */ + private boolean initNewSession() { + boolean retCode = false; + if(0 != (mNativeOlmOutboundGroupSessionId = initNewSessionJni())){ + retCode = true; + } + return retCode; + } + + /** + * Create the corresponding OLM outbound group session in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native session instance identifier (see {@link #mNativeOlmOutboundGroupSessionId}) + */ + private native long initNewSessionJni(); + + + /** + * Creates a new outbound group session.
+ * The session key parameter is retrieved from a outbound group session. + * @return 0 if operation succeed, -1 otherwise + */ + public int initOutboundGroupSession() { + return initOutboundGroupSessionJni(); + } + public native int initOutboundGroupSessionJni(); + + + + + public String sessionIdentifier() { + String retValue = null; + //retValue = sessionIdentifierJni(); + + return retValue; + } + public native String sessionIdentifierJni(); + + + + + public long messageIndex() { + long retValue =0; + //retValue = messageIndexJni(); + + return retValue; + } + private native long messageIndexJni(); + + + + + public String sessionKey() { + String retValue = null; + //retValue = sessionKeyJni(); + + return retValue; + } + private native String sessionKeyJni(); + + + public String encryptMessage(String aClearMsg) { + String retValue = null; + //retValue = encryptMessageJni(aClearMsg); + + return retValue; + } + private native String encryptMessageJni(String aClearMsg); +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index fc1f76f..2df5ea7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -19,7 +19,9 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; -public class OlmSession { +import java.io.Serializable; + +public class OlmSession implements Serializable { private static final String LOG_TAG = "OlmSession"; /** session raw pointer value (OlmSession*) returned by JNI. @@ -85,7 +87,6 @@ public class OlmSession { /** * Create the corresponding OLM session in native side.
- * The return value is a long casted C ptr on the OlmSession. * Do not forget to call {@link #releaseSession()} when JAVA side is done. * @return native session instance identifier (see {@link #mNativeOlmSessionId}) */ @@ -159,6 +160,7 @@ public class OlmSession { * @param aTheirIdentityKey the sender identity key * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise + * TODO unit test missing: initInboundSessionWithAccountFrom */ public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aOneTimeKeyMsg) { OlmSession retObj=null; @@ -198,6 +200,7 @@ public class OlmSession { * Public API for {@link #matchesInboundSessionJni(String)}. * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise + * TODO unit test missing: matchesInboundSession */ public boolean matchesInboundSession(String aOneTimeKeyMsg) { boolean retCode = false; @@ -218,6 +221,7 @@ public class OlmSession { * @param aTheirIdentityKey the sender identity key * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise + * TODO unit test missing: matchesInboundSessionFrom */ public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) { boolean retCode = false; @@ -261,5 +265,10 @@ public class OlmSession { } private native String decryptMessageJni(OlmMessage aEncryptedMsg); + + // TODO missing API: initWithSerializedData + // TODO missing API: serializeDataWithKey + // TODO missing API: initWithCoder + // TODO missing API: encodeWithCoder } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index 26a6a90..01c0dc9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -45,7 +45,8 @@ $(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \ $(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \ olm_account.cpp \ olm_session.cpp \ -olm_utility.cpp +olm_utility.cpp \ +olm_inbound_group_session.cpp LOCAL_LDLIBS := -llog diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 2a5ab6f..ba15c13 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -19,7 +19,7 @@ /** * Init memory allocation for account creation. -* @return valid memory alocation, NULL otherwise +* @return valid memory allocation, NULL otherwise **/ OlmAccount* initializeAccountMemory() { @@ -68,7 +68,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz /** * Initialize a new account and return it to JAVA side.
* Since a C prt is returned as a jlong, special care will be taken -* to make the cast (OlmAccount* => jlong) platform independant. +* to make the cast (OlmAccount* => jlong) platform independent. * @return the initialized OlmAccount* instance if init succeed, NULL otherwise **/ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz) @@ -308,7 +308,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t * @param aNativeOlmSessionId session instance * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS if no matching keys, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) { jint retCode = ERROR_CODE_KO; OlmAccount* accountPtr = NULL; @@ -317,11 +317,11 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo if(NULL == sessionPtr) { - LOGE("## removeOneTimeKeysForSession(): failure - invalid session ptr"); + LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid session ptr"); } else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE("## removeOneTimeKeysForSession(): failure - invalid account ptr"); + LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid account ptr"); } else { @@ -329,14 +329,14 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo if(result == olm_error()) { // the account doesn't have any matching "one time keys".. const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGW("## removeOneTimeKeysForSession(): failure - removing one time keys Msg=%s",errorMsgPtr); + LOGW("## removeOneTimeKeysForSessionJni(): failure - removing one time keys Msg=%s",errorMsgPtr); retCode = ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS; } else { retCode = ERROR_CODE_OK; - LOGD("## removeOneTimeKeysForSession(): success"); + LOGD("## removeOneTimeKeysForSessionJni(): success"); } } @@ -347,7 +347,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo * Mark the current set of "one time keys" as being published. * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz) +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) { jint retCode = ERROR_CODE_OK; OlmAccount* accountPtr = NULL; @@ -355,7 +355,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE("## markOneTimeKeysPublished(): failure - invalid account ptr"); + LOGE("## markOneTimeKeysAsPublishedJni(): failure - invalid account ptr"); retCode = ERROR_CODE_KO; } else @@ -364,12 +364,12 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job if(result == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGW("## markOneTimeKeysPublished(): failure - Msg=%s",errorMsgPtr); + LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",errorMsgPtr); retCode = ERROR_CODE_KO; } else { - LOGD("## markOneTimeKeysPublished(): success - retCode=%ld",result); + LOGD("## markOneTimeKeysAsPublishedJni(): success - retCode=%ld",result); } } @@ -382,7 +382,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job * @param aMessage message to sign * @return the signed message, null otherwise **/ -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage) +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage) { OlmAccount* accountPtr = NULL; size_t signatureLength; @@ -392,11 +392,11 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j if(NULL == aMessage) { - LOGE("## signMessage(): failure - invalid aMessage param"); + LOGE("## signMessageJni(): failure - invalid aMessage param"); } else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE("## signMessage(): failure - invalid account ptr"); + LOGE("## signMessageJni(): failure - invalid account ptr"); } else { @@ -404,7 +404,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j const char* messageToSign = env->GetStringUTFChars(aMessage, 0); if(NULL == messageToSign) { - LOGE("## signMessage(): failure - message JNI allocation OOM"); + LOGE("## signMessageJni(): failure - message JNI allocation OOM"); } else { @@ -414,22 +414,26 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j signatureLength = olm_account_signature_length(accountPtr); if(NULL == (signedMsgPtr = (void*)malloc(signatureLength*sizeof(uint8_t)))) { - LOGE("## signMessage(): failure - signature allocation OOM"); + LOGE("## signMessageJni(): failure - signature allocation OOM"); } else { // sign message - resultSign = olm_account_sign(accountPtr, (void*)messageToSign, (size_t)messageLength, signedMsgPtr, signatureLength); + resultSign = olm_account_sign(accountPtr, + (void*)messageToSign, + (size_t)messageLength, + signedMsgPtr, + signatureLength); if(resultSign == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE("## signMessage(): failure - error signing message Msg=%s",errorMsgPtr); + LOGE("## signMessageJni(): failure - error signing message Msg=%s",errorMsgPtr); } else - { // convert to jstring - // TODO check how UTF conversion can impact the content? - // why not consider return jbyteArray? and convert in JAVA side.. + { + // TODO check if signedMsgPtr needs to be null ended: signedMsgPtr[resultSign]='\0' + // convert to jstring signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 - LOGD("## signMessage(): success - retCode=%ld",resultSign); + LOGD("## signMessageJni(): success - retCode=%ld",resultSign); } free(signedMsgPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 23c9687..63ec3ef 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -18,6 +18,7 @@ #define _OMLACCOUNT_H #include "olm_jni.h" +#include "olm/olm.h" #define OLM_ACCOUNT_FUNC_DEF(func_name) FUNC_DEF(OlmAccount,func_name) #define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name) @@ -39,11 +40,11 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz); +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); // signing -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage); +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp new file mode 100644 index 0000000..43e9e20 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -0,0 +1,262 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_inbound_group_session.h" +#include "olm_utility.h" + + +/** + * Release the session allocation made by initializeInboundGroupSessionMemory().
+ * This method MUST be called when java counter part account instance is done. + * + */ +JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) +{ + OlmInboundGroupSession* sessionPtr = NULL; + + LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr); + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); + } + else + { + size_t retCode = olm_clear_inbound_group_session(sessionPtr); + LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); + + LOGD("## releaseSessionJni(): IN"); + free(sessionPtr); + LOGD("## releaseSessionJni(): OUT"); + } +} + +/** +* Initialize a new inbound group session and return it to JAVA side.
+* Since a C prt is returned as a jlong, special care will be taken +* to make the cast (OlmInboundGroupSession* => jlong) platform independent. +* @return the initialized OlmInboundGroupSession* instance if init succeed, NULL otherwise +**/ +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) +{ + OlmInboundGroupSession* sessionPtr = NULL; + size_t sessionSize = olm_inbound_group_session_size(); + + if(0 == sessionSize) + { + LOGE("## initNewSessionJni(): failure - inbound group session size = 0"); + } + else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize))) + { + sessionPtr = olm_inbound_group_session(sessionPtr); + LOGD("## initNewSessionJni(): success - inbound group session size=%lu",sessionSize); + } + else + { + LOGE("## initNewSessionJni(): failure - inbound group session OOM"); + } + + return (jlong)(intptr_t)sessionPtr; +} + +/** + * Create a new in-bound session.
+ * @param aSessionKey session key from an outbound session + * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise + */ +JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey) +{ + jint retCode = ERROR_CODE_KO; + OlmInboundGroupSession *sessionPtr = NULL; + const uint8_t *sessionKeyPtr = NULL; + size_t sessionResult; + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance"); + } + else if(0 == aSessionKey) + { + LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); + } + else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0))) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); + } + else + { + size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey); + LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength); + + sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); + if(sessionResult == olm_error()) { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); + } + } + + // free local alloc + if(NULL!= sessionKeyPtr) + { + env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr); + } + + return retCode; +} + + +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +{ + OlmInboundGroupSession *sessionPtr = NULL; + uint8_t *sessionIdPtr = NULL; + jstring returnValueStr=0; + + // get the size to alloc to contain the id + size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance"); + } + else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) + { + LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM"); + } + else + { + size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + if (result == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + } + else + { + // update length + sessionIdPtr[result] = static_cast('\0'); + + LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); + returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + } + free(sessionIdPtr); + } + + return returnValueStr; +} + +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg) +{ + jstring decryptedMsgRetValue = 0; + OlmInboundGroupSession *sessionPtr = NULL; + const char *encryptedMsgPtr = NULL; + uint8_t *plainTextMsgPtr = NULL; + uint8_t *tempEncryptedPtr = NULL; + + LOGD("## decryptMessageJni(): IN"); + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); + } + else if(0 == aEncryptedMsg) + { + LOGE("## decryptMessageJni(): failure - invalid clear message"); + } + else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) + { + LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + } + else + { + // get encrypted message length + size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg); + + // create a dedicated temp buffer to be used in next Olm API calls + if(NULL == (tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))))) + { + LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); + } + else + { + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr); + + // get max plaintext length + size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, + tempEncryptedPtr, + encryptedMsgLength); + if(maxPlainTextLength == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + } + else + { + LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); + + // allocate output decrypted message + plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); + + // decrypt, but before reload encrypted buffer (previous one was destroyed) + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + size_t plaintextLength = olm_group_decrypt(sessionPtr, + tempEncryptedPtr, + encryptedMsgLength, + plainTextMsgPtr, + maxPlainTextLength); + if(plaintextLength == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); + } + else + { + // update decrypted buffer size + plainTextMsgPtr[plaintextLength] = static_cast('\0'); + + LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr); + decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); + } + } + } + } + + // free alloc + if(NULL != encryptedMsgPtr) + { + env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr); + } + + if(NULL != tempEncryptedPtr) + { + free(tempEncryptedPtr); + } + + if(NULL != plainTextMsgPtr) + { + free(plainTextMsgPtr); + } + + return decryptedMsgRetValue; +} + + + diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h new file mode 100644 index 0000000..1eb8238 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -0,0 +1,43 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLINBOUND_GROUP_SESSION_H +#define _OMLINBOUND_GROUP_SESSION_H + +#include "olm_jni.h" +#include "olm/olm.h" +#include "olm/inbound_group_session.h" + +#define OLM_INBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmInboundGroupSession,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +// session creation/destruction +JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); + +JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 38269f9..8f1555d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -25,7 +25,6 @@ #include #include -#include "olm/olm.h" #define TAG "OlmJniNative" @@ -54,11 +53,4 @@ static const int ERROR_CODE_KO = -1; // constants static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; - -typedef struct _AccountContext -{ - OlmAccount* mAccountPtr; - _AccountContext(): mAccountPtr(NULL){} -} AccountContext; - #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp new file mode 100644 index 0000000..40af39d --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -0,0 +1,293 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_outbound_group_session.h" +#include "olm_utility.h" + + +/** + * Release the session allocation made by initializeOutboundGroupSessionMemory().
+ * This method MUST be called when java counter part account instance is done. + * + */ +JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) +{ + OlmOutboundGroupSession* sessionPtr = NULL; + + LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr); + + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); + } + else + { + size_t retCode = olm_clear_outbound_group_session(sessionPtr); + LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); + + LOGD("## releaseSessionJni(): IN"); + free(sessionPtr); + LOGD("## releaseSessionJni(): OUT"); + } +} + +/** +* Initialize a new outbound group session and return it to JAVA side.
+* Since a C prt is returned as a jlong, special care will be taken +* to make the cast (OlmOutboundGroupSession* => jlong) platform independent. +* @return the initialized OlmOutboundGroupSession* instance if init succeed, NULL otherwise +**/ +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) +{ + OlmOutboundGroupSession* sessionPtr = NULL; + size_t sessionSize = olm_outbound_group_session_size(); + + if(0 == sessionSize) + { + LOGE("## initNewSessionJni(): failure - outbound group session size = 0"); + } + else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize))) + { + sessionPtr = olm_outbound_group_session(sessionPtr); + LOGD("## initNewSessionJni(): success - outbound group session size=%lu",sessionSize); + } + else + { + LOGE("## initNewSessionJni(): failure - outbound group session OOM"); + } + + return (jlong)(intptr_t)sessionPtr; +} + +/** + * Create a new outbound session.
+ * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise + */ +JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) +{ + jint retCode = ERROR_CODE_KO; + OlmOutboundGroupSession *sessionPtr = NULL; + uint8_t *randomBuffPtr = NULL; + size_t sessionResult; + + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## initOutboundGroupSessionJni(): failure - invalid inbound group session instance"); + } + else + { + // compute random buffer + size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); + + if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) + { + LOGE("## initOutboundGroupSessionJni(): failure - random buffer init"); + } + else + { + if(0==randomLength) + { + LOGW("## initOutboundGroupSessionJni(): random buffer is not required"); + } + + size_t sessionResult = olm_init_outbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); + if(sessionResult == olm_error()) { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); + } + + + } + } + + + else if(0 == aSessionKey) + { + LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); + } + else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0))) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); + } + else + { + size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey); + LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength); + + sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); + if(sessionResult == olm_error()) { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + } + else + { + retCode = ERROR_CODE_OK; + LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); + } + } + + // free local alloc + if(NULL!= sessionKeyPtr) + { + env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr); + } + + return retCode; +} + + +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +{ + OlmInboundGroupSession *sessionPtr = NULL; + uint8_t *sessionIdPtr = NULL; + jstring returnValueStr=0; + + // get the size to alloc to contain the id + size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance"); + } + else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) + { + LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM"); + } + else + { + size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + if (result == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + } + else + { + // update length + sessionIdPtr[result] = static_cast('\0'); + + LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); + returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + } + free(sessionIdPtr); + } + + return returnValueStr; +} + +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg) +{ + jstring decryptedMsgRetValue = 0; + OlmInboundGroupSession *sessionPtr = NULL; + const char *encryptedMsgPtr = NULL; + uint8_t *plainTextMsgPtr = NULL; + uint8_t *tempEncryptedPtr = NULL; + + LOGD("## decryptMessageJni(): IN"); + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); + } + else if(0 == aEncryptedMsg) + { + LOGE("## decryptMessageJni(): failure - invalid clear message"); + } + else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) + { + LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + } + else + { + // get encrypted message length + size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg); + + // create a dedicated temp buffer to be used in next Olm API calls + if(NULL == (tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))))) + { + LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); + } + else + { + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr); + + // get max plaintext length + size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, + tempEncryptedPtr, + encryptedMsgLength); + if(maxPlainTextLength == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + } + else + { + LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); + + // allocate output decrypted message + plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); + + // decrypt, but before reload encrypted buffer (previous one was destroyed) + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + size_t plaintextLength = olm_group_decrypt(sessionPtr, + tempEncryptedPtr, + encryptedMsgLength, + plainTextMsgPtr, + maxPlainTextLength); + if(plaintextLength == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); + } + else + { + // update decrypted buffer size + plainTextMsgPtr[plaintextLength] = static_cast('\0'); + + LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr); + decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); + } + } + } + } + + // free alloc + if(NULL != encryptedMsgPtr) + { + env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr); + } + + if(NULL != tempEncryptedPtr) + { + free(tempEncryptedPtr); + } + + if(NULL != plainTextMsgPtr) + { + free(plainTextMsgPtr); + } + + return decryptedMsgRetValue; +} + + + diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h new file mode 100644 index 0000000..1270dc2 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -0,0 +1,43 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLOUTBOUND_GROUP_SESSION_H +#define _OMLOUTBOUND_GROUP_SESSION_H + +#include "olm_jni.h" +#include "olm/olm.h" +#include "olm/outbound_group_session.h" + +#define OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmOutboundGroupSession,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +// session creation/destruction +JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); + +JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index d33ab72..435540c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -458,7 +458,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz } else if(0 == aEncryptedMsg) { - LOGE("## encryptMessageJni(): failure - invalid clear message"); + LOGE("## encryptMessageJni(): failure - invalid encrypted message"); } else if(NULL == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) { @@ -587,11 +587,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } else if(0 == aEncryptedMsg) { - LOGE("## decryptMessageJni(): failure - invalid clear message"); + LOGE("## decryptMessageJni(): failure - invalid encrypted message"); } else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg))) { - LOGE("## decryptMessageJni(): failure - unable to get crypted message class"); + LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); } else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;"))) { @@ -644,7 +644,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); size_t plaintextLength = olm_decrypt(sessionPtr, encryptedMsgType, - (void*)encryptedMsgPtr, + (void*)tempEncryptedPtr, encryptedMsgLength, plainTextMsgPtr, maxPlainTextLength); @@ -717,7 +717,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job } else { - // update decrypted buffer size + // update length (static_cast(sessionIdPtr))[result] = static_cast('\0'); LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index babb3bd..f79dcaa 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -18,6 +18,7 @@ #define _OMLSESSION_H #include "olm_jni.h" +#include "olm/olm.h" #define OLM_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmSession,func_name) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index c27fe7c..bd920fe 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -101,7 +101,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) } /** -* Read the account instance ID of the calling object (aJavaObject).
+* Read the session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked * @return the instance ID if read succeed, -1 otherwise. @@ -139,3 +139,83 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) //LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); return instanceId; } + + +/** +* Read the inbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + return instanceId; +} + + +/** +* Read the outbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + return instanceId; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index bf35955..b16e915 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -25,6 +25,7 @@ extern "C" { bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize); jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); #ifdef __cplusplus } -- cgit v1.2.3 From 102809955026d92a3f5cf29e05998d91a992de9c Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 14 Oct 2016 15:27:20 +0200 Subject: - Add inbound and outbound group sessions - Modify constructors for inbound and outbound group sessions - Add new Ecxception class --- .../org/matrix/olm/OlmInboundGroupSession.java | 33 ++- .../org/matrix/olm/OlmOutboundGroupSession.java | 87 ++++--- .../java/org/matrix/olm/OlmUtilsException.java | 35 +++ .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 5 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 10 +- .../src/main/jni/olm_inbound_group_session.cpp | 44 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 17 ++ .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 220 +++++++++++++++++ .../src/main/jni/olm_outbound_group_session.cpp | 270 ++++++++++++--------- .../src/main/jni/olm_outbound_group_session.h | 7 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 4 +- 11 files changed, 546 insertions(+), 186 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 53ef7a3..aa15c32 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -34,19 +34,33 @@ public class OlmInboundGroupSession implements Serializable { */ private long mNativeOlmInboundGroupSessionId; - - public OlmInboundGroupSession() { - initNewSession(); - } - /** * Getter on the native inbound group session ID. * @return native inbound group session ID */ - public long getOlmInboundGroupSessionId(){ + public long getOlmInboundGroupSessionId() { return mNativeOlmInboundGroupSessionId; } + /** + * Constructor.
+ * Create and save a new native session instance ID and start a new inbound group session. + * The session key parameter is retrieved from a outbound group session + * See {@link #initNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)} + * @param aSessionKey session key + * @throws OlmUtilsException + */ + public OlmInboundGroupSession(String aSessionKey) throws OlmUtilsException { + if(initNewSession()) { + if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { + releaseSession();// prevent memory leak before throwing + throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION); + } + } else { + throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); + } + } + /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. @@ -88,12 +102,13 @@ public class OlmInboundGroupSession implements Serializable { private native long initNewSessionJni(); /** - * Creates a new inbound group session.
- * The session key parameter is retrieved from a outbound group session. + * Start a new inbound group session.
+ * The session key parameter is retrieved from a outbound group session + * see {@link OlmOutboundGroupSession#sessionKey()} * @param aSessionKey session key * @return 0 if operation succeed, -1 otherwise */ - public int initInboundGroupSessionWithSessionKey(String aSessionKey) { + private int initInboundGroupSessionWithSessionKey(String aSessionKey) { int retCode = -1; if(TextUtils.isEmpty(aSessionKey)){ diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 63c0c36..bbe2718 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -28,16 +28,30 @@ public class OlmOutboundGroupSession { */ private long mNativeOlmOutboundGroupSessionId; - public OlmOutboundGroupSession() { - initNewSession(); - } - /** * Getter on the native outbound group session ID. * @return native outbound group session ID */ public long getOlmInboundGroupSessionId(){ - return mNativeOlmInboundGroupSessionId; + return mNativeOlmOutboundGroupSessionId; + } + + /** + * Constructor.
+ * Create and save a new session native instance ID and + * initialise a new outbound group session.
+ * See {@link #initNewSession()} and {@link #initOutboundGroupSession()} + * @throws OlmUtilsException + */ + public OlmOutboundGroupSession() throws OlmUtilsException { + if(initNewSession()) { + if( 0 != initOutboundGroupSession()) { + releaseSession();// prevent memory leak before throwing + throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION); + } + } else { + throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); + } } /** @@ -45,9 +59,8 @@ public class OlmOutboundGroupSession { * Public API for {@link #releaseSessionJni()}. * To be called before any other API call. */ - public void releaseSession(){ - releaseSessionJni(); - + public void releaseSession() { + releaseSessionJni(); mNativeOlmOutboundGroupSessionId = 0; } @@ -80,54 +93,66 @@ public class OlmOutboundGroupSession { */ private native long initNewSessionJni(); - /** - * Creates a new outbound group session.
- * The session key parameter is retrieved from a outbound group session. + * Start a new outbound group session.
* @return 0 if operation succeed, -1 otherwise */ - public int initOutboundGroupSession() { + private int initOutboundGroupSession() { return initOutboundGroupSessionJni(); } - public native int initOutboundGroupSessionJni(); - - - + private native int initOutboundGroupSessionJni(); + /** + * Get a base64-encoded identifier for this session. + * @return session identifier if operation succeed, null otherwise. + */ public String sessionIdentifier() { String retValue = null; - //retValue = sessionIdentifierJni(); + retValue = sessionIdentifierJni(); return retValue; } - public native String sessionIdentifierJni(); - + private native String sessionIdentifierJni(); - - - public long messageIndex() { - long retValue =0; - //retValue = messageIndexJni(); + /** + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * @return current session index + */ + public int messageIndex() { + int retValue =0; + retValue = messageIndexJni(); return retValue; } - private native long messageIndexJni(); - - - + private native int messageIndexJni(); + /** + * Get the base64-encoded current ratchet key for this session.
+ * Each message is sent with a different ratchet key. This method returns the + * ratchet key that will be used for the next message. + * @return outbound session key + */ public String sessionKey() { String retValue = null; - //retValue = sessionKeyJni(); + retValue = sessionKeyJni(); return retValue; } private native String sessionKeyJni(); - + /** + * Encrypt some plain-text message.
+ * @param aClearMsg message to be encrypted + * @return the encrypted message if operation succeed, null otherwise + */ public String encryptMessage(String aClearMsg) { String retValue = null; - //retValue = encryptMessageJni(aClearMsg); + + if(!TextUtils.isEmpty(aClearMsg)) { + retValue = encryptMessageJni(aClearMsg); + } return retValue; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java new file mode 100644 index 0000000..f0cdc83 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +public class OlmUtilsException extends Exception { + // exception codes + public static final int EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE = 0; + public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 1; + public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 2; + + private final int mCode; + + public OlmUtilsException(int aExceptionCode) { + super(); + mCode = aExceptionCode; + } + + public int getExceptionCode() { + return mCode; + } +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index 01c0dc9..92a9359 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -45,8 +45,9 @@ $(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \ $(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \ olm_account.cpp \ olm_session.cpp \ -olm_utility.cpp \ -olm_inbound_group_session.cpp +olm_jni_helper.cpp \ +olm_inbound_group_session.cpp \ +olm_outbound_group_session.cpp LOCAL_LDLIBS := -llog diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index ba15c13..860ff3e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -15,7 +15,6 @@ */ #include "olm_account.h" -#include "olm_utility.h" /** * Init memory allocation for account creation. @@ -85,9 +84,12 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi } else { - // allocate random buffer + // get random buffer size randomSize = olm_create_account_random_length(accountPtr); - if(!setRandomInBuffer(&randomBuffPtr, randomSize)) + LOGD("## initNewAccount(): randomSize=%lu", randomSize); + + // allocate random buffer + if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize)) { LOGE("## initNewAccount(): failure - random buffer init"); } @@ -219,7 +221,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); LOGD("## generateOneTimeKeys(): randomLength=%ld", randomLength); - if(!setRandomInBuffer(&randomBufferPtr, randomLength)) + if((0!=randomLength) && !setRandomInBuffer(&randomBufferPtr, randomLength)) { LOGE("## generateOneTimeKeys(): failure - random buffer init"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 43e9e20..16e5a0b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -15,7 +15,6 @@ */ #include "olm_inbound_group_session.h" -#include "olm_utility.h" /** @@ -123,45 +122,54 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes } +/** +* Get a base64-encoded identifier for this inbound group session. +*/ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { OlmInboundGroupSession *sessionPtr = NULL; uint8_t *sessionIdPtr = NULL; jstring returnValueStr=0; - // get the size to alloc to contain the id - size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); + LOGD("## sessionIdentifierJni(): inbound group session IN"); if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance"); } - else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) - { - LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM"); - } else { - size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - if (result == olm_error()) + // get the size to alloc + size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); + LOGD("## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId); + + if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + LOGE("## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); } else { - // update length - sessionIdPtr[result] = static_cast('\0'); - - LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); - returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + if (result == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE("## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",errorMsgPtr); + } + else + { + // update length + sessionIdPtr[result] = static_cast('\0'); + LOGD("## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",result, (char*)sessionIdPtr); + returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + } + free(sessionIdPtr); } - free(sessionIdPtr); } return returnValueStr; } + JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg) { jstring decryptedMsgRetValue = 0; @@ -178,7 +186,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * } else if(0 == aEncryptedMsg) { - LOGE("## decryptMessageJni(): failure - invalid clear message"); + LOGE("## decryptMessageJni(): failure - invalid encrypted message"); } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 8f1555d..2bfb9f8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -53,4 +53,21 @@ static const int ERROR_CODE_KO = -1; // constants static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; +#ifdef __cplusplus +extern "C" { +#endif + +// internal helper functions +bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize); +jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); + + +#ifdef __cplusplus +} +#endif + + #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp new file mode 100644 index 0000000..1d64d75 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -0,0 +1,220 @@ +/** + * Created by pedrocon on 06/10/2016. + */ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_jni.h" + +/** +* Init a buffer with a given number of random values. +* @param aBuffer2Ptr the buffer to be initialized +* @param aRandomSize the number of random values to apply +* @return true if operation succeed, false otherwise +**/ +bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) +{ + bool retCode = false; + if(NULL == aBuffer2Ptr) + { + LOGD("## setRandomInBuffer(): failure - aBuffer=NULL"); + } + else if(0 == aRandomSize) + { + LOGD("## setRandomInBuffer(): failure - random size=0"); + } + else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t)))) + { + LOGD("## setRandomInBuffer(): failure - alloc mem OOM"); + } + else + { + LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize); + + srand(time(NULL)); // init seed + for(size_t i=0;iGetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId); + } + else + { + LOGD("## getAccountInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL"); + } + LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId); + return instanceId; +} + +/** +* Read the session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + //LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); + return instanceId; +} + + +/** +* Read the inbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getInboundGroupSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getInboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getInboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + return instanceId; +} + + +/** +* Read the outbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + + if(NULL!=aJniEnv) + { + if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getOutboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + return instanceId; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 40af39d..46c0ee4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -15,7 +15,6 @@ */ #include "olm_outbound_group_session.h" -#include "olm_utility.h" /** @@ -31,12 +30,12 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); + LOGE("## releaseSessionJni(): failure - invalid outbound group session instance"); } else { size_t retCode = olm_clear_outbound_group_session(sessionPtr); - LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); + LOGD("## releaseSessionJni(): clear_outbound_group_session=%lu",retCode); LOGD("## releaseSessionJni(): IN"); free(sessionPtr); @@ -73,25 +72,26 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *e } /** - * Create a new outbound session.
+ * Start a new outbound session.
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) { jint retCode = ERROR_CODE_KO; OlmOutboundGroupSession *sessionPtr = NULL; uint8_t *randomBuffPtr = NULL; - size_t sessionResult; + + LOGD("## initOutboundGroupSessionJni(): IN"); if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## initOutboundGroupSessionJni(): failure - invalid inbound group session instance"); + LOGE("## initOutboundGroupSessionJni(): failure - invalid outbound group session instance"); } else { // compute random buffer size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); - + LOGW("## initOutboundGroupSessionJni(): randomLength=%lu",randomLength); if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) { LOGE("## initOutboundGroupSessionJni(): failure - random buffer init"); @@ -103,190 +103,224 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(J LOGW("## initOutboundGroupSessionJni(): random buffer is not required"); } - size_t sessionResult = olm_init_outbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); + size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); if(sessionResult == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); + LOGE("## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s",errorMsgPtr); } else { retCode = ERROR_CODE_OK; - LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); + LOGD("## initOutboundGroupSessionJni(): success - result=%lu", sessionResult); } - - } } - - else if(0 == aSessionKey) + if(NULL != randomBuffPtr) { - LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); + free(randomBuffPtr); } - else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0))) + + return retCode; +} + +/** +* Get a base64-encoded identifier for this outbound group session. +*/ +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +{ + OlmOutboundGroupSession *sessionPtr = NULL; + uint8_t *sessionIdPtr = NULL; + jstring returnValueStr=0; + + LOGD("## sessionIdentifierJni(): outbound group session IN"); + + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); + LOGE("## sessionIdentifierJni(): failure - invalid outbound group session instance"); } else { - size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey); - LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength); + // get the size to alloc + size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); + LOGD("## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",lengthSessionId); - sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); - if(sessionResult == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) + { + LOGE("## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); } else { - retCode = ERROR_CODE_OK; - LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); - } - } + size_t result = olm_outbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + if (result == olm_error()) + { + const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); + LOGE("## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",errorMsgPtr); + } + else + { + // update length + sessionIdPtr[result] = static_cast('\0'); + LOGD("## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",result, (char*)sessionIdPtr); + returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + } - // free local alloc - if(NULL!= sessionKeyPtr) - { - env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr); - } + // free alloc + free(sessionIdPtr); + } + } - return retCode; + return returnValueStr; } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +/** +* Get the current message index for this session.
+* Each message is sent with an increasing index, this +* method returns the index for the next message. +* @return current session index +*/ +JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz) { - OlmInboundGroupSession *sessionPtr = NULL; - uint8_t *sessionIdPtr = NULL; - jstring returnValueStr=0; + OlmOutboundGroupSession *sessionPtr = NULL; + jint indexRetValue = 0; - // get the size to alloc to contain the id - size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); + LOGD("## messageIndexJni(): IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## messageIndexJni(): failure - invalid outbound group session instance"); + } + else { - LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance"); + indexRetValue = static_cast(olm_outbound_group_session_message_index(sessionPtr)); } - else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) + LOGD("## messageIndexJni(): success - index=%d",indexRetValue); + + return indexRetValue; +} + + +/** +* Get the base64-encoded current ratchet key for this session.
+*/ +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) +{ + OlmOutboundGroupSession *sessionPtr = NULL; + uint8_t *sessionKeyPtr = NULL; + jstring returnValueStr=0; + + LOGD("## sessionKeyJni(): outbound group session IN"); + + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM"); + LOGE(" ## sessionKeyJni(): failure - invalid outbound group session instance"); } else { - size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - if (result == olm_error()) + // get the size to alloc + size_t sessionKeyLength = olm_outbound_group_session_key_length(sessionPtr); + LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",sessionKeyLength); + + if(NULL == (sessionKeyPtr = (uint8_t*)malloc(sessionKeyLength*sizeof(uint8_t)))) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + LOGE(" ## sessionKeyJni(): failure - session key allocation OOM"); } else { - // update length - sessionIdPtr[result] = static_cast('\0'); + size_t result = olm_outbound_group_session_key(sessionPtr, sessionKeyPtr, sessionKeyLength); + if (result == olm_error()) + { + const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s",errorMsgPtr); + } + else + { + // update length + sessionKeyPtr[result] = static_cast('\0'); + LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%s",result, (char*)sessionKeyPtr); + returnValueStr = env->NewStringUTF((const char*)sessionKeyPtr); + } - LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); - returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + // free alloc + free(sessionKeyPtr); } - free(sessionIdPtr); } return returnValueStr; } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg) + +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg) { - jstring decryptedMsgRetValue = 0; - OlmInboundGroupSession *sessionPtr = NULL; - const char *encryptedMsgPtr = NULL; - uint8_t *plainTextMsgPtr = NULL; - uint8_t *tempEncryptedPtr = NULL; + jstring encryptedMsgRetValue = 0; + OlmOutboundGroupSession *sessionPtr = NULL; + const char *clearMsgPtr = NULL; + uint8_t *encryptedMsgPtr = NULL; - LOGD("## decryptMessageJni(): IN"); + LOGD("## encryptMessageJni(): IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); + LOGE(" ## encryptMessageJni(): failure - invalid outbound group session ptr=NULL"); } - else if(0 == aEncryptedMsg) + else if(0 == aClearMsg) { - LOGE("## decryptMessageJni(): failure - invalid clear message"); + LOGE(" ## encryptMessageJni(): failure - invalid clear message"); } - else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) + else if(0 == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) { - LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM"); } else { - // get encrypted message length - size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg); + // get clear message length + size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg); + LOGD(" ## encryptMessageJni(): clearMsgLength=%lu",clearMsgLength); - // create a dedicated temp buffer to be used in next Olm API calls - if(NULL == (tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))))) + // compute max encrypted length + size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); + if(NULL == (encryptedMsgPtr = (uint8_t*)malloc(encryptedMsgLength*sizeof(uint8_t)))) { - LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); + LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); } else { - memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr); - - // get max plaintext length - size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, - tempEncryptedPtr, - encryptedMsgLength); - if(maxPlainTextLength == olm_error()) + LOGD(" ## encryptMessageJni(): estimated encryptedMsgLength=%lu",encryptedMsgLength); + + size_t decryptedLength = olm_group_encrypt(sessionPtr, + (uint8_t*)clearMsgPtr, + clearMsgLength, + encryptedMsgPtr, + encryptedMsgLength); + if(decryptedLength == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); } else { - LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); - - // allocate output decrypted message - plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); - - // decrypt, but before reload encrypted buffer (previous one was destroyed) - memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - size_t plaintextLength = olm_group_decrypt(sessionPtr, - tempEncryptedPtr, - encryptedMsgLength, - plainTextMsgPtr, - maxPlainTextLength); - if(plaintextLength == olm_error()) - { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); - } - else - { - // update decrypted buffer size - plainTextMsgPtr[plaintextLength] = static_cast('\0'); - - LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr); - decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); - } + // update decrypted buffer size + encryptedMsgPtr[decryptedLength] = static_cast('\0'); + + LOGD(" ## encryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",decryptedLength, (char*)encryptedMsgPtr); + encryptedMsgRetValue = env->NewStringUTF((const char*)encryptedMsgPtr); } } - } + } // free alloc - if(NULL != encryptedMsgPtr) + if(NULL != clearMsgPtr) { - env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr); + env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr); } - if(NULL != tempEncryptedPtr) - { - free(tempEncryptedPtr); - } - - if(NULL != plainTextMsgPtr) + if(NULL != encryptedMsgPtr) { - free(plainTextMsgPtr); + free(encryptedMsgPtr); } - return decryptedMsgRetValue; + return encryptedMsgRetValue; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 1270dc2..6e264aa 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -31,9 +31,12 @@ extern "C" { JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); +JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg); +JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); + +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsgPtr); #ifdef __cplusplus diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 435540c..5911591 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -15,7 +15,6 @@ */ #include "olm_session.h" -#include "olm_utility.h" /** @@ -120,6 +119,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject else { // allocate random buffer size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); + LOGD("## initOutboundSessionJni(): randomSize=%lu",randomSize); if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize)) { LOGE("## initOutboundSessionJni(): failure - random buffer init"); @@ -485,7 +485,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // Note: olm_encrypt_random_length() can return 0, which means // it just does not need new random data to encrypt a new message size_t randomLength = olm_encrypt_random_length(sessionPtr); - + LOGD("## encryptMessageJni(): randomLength=%lu", randomLength); if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) { LOGE("## encryptMessageJni(): failure - random buffer init"); -- cgit v1.2.3 From ebfcd03ce5b627236edf2c2c1f334f5c59f9d291 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 14 Oct 2016 18:43:57 +0200 Subject: - Add in/outbound group unit test OK --- .../java/org/matrix/olm/OlmGroupTest.java | 139 ++++++++++---- .../src/main/java/org/matrix/olm/OlmException.java | 35 ++++ .../org/matrix/olm/OlmInboundGroupSession.java | 8 +- .../org/matrix/olm/OlmOutboundGroupSession.java | 9 +- .../java/org/matrix/olm/OlmUtilsException.java | 35 ---- .../src/main/jni/olm_inbound_group_session.cpp | 65 ++++--- .../src/main/jni/olm_outbound_group_session.cpp | 61 +++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 6 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 206 ++------------------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 7 +- 10 files changed, 228 insertions(+), 343 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java index 482ae0f..5a5ca57 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java @@ -1,6 +1,7 @@ package org.matrix.olm; import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; import android.util.Log; import org.junit.BeforeClass; @@ -10,6 +11,7 @@ import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -19,6 +21,15 @@ public class OlmGroupTest { private static final String LOG_TAG = "OlmSessionTest"; private static OlmManager mOlmManager; + private static OlmOutboundGroupSession mAliceOutboundSession; + private static String mAliceSessionIdentifier; + private static long mAliceMessageIndex; + public static final String CLEAR_MESSAGE1 = "Hello!"; + private static String mAliceToBobMessage; + private static OlmInboundGroupSession mBobInboundSession; + private static String mAliceOutboundSessionKey; + private static String mBobSessionIdentifier; + private static String mBobDecryptedMessage; @BeforeClass public static void setUpClass(){ @@ -30,66 +41,112 @@ public class OlmGroupTest { Log.d(LOG_TAG, "## setUpClass(): lib version="+version); } - @Test - public void test00AliceToBob() { - // TBD - } - /** * Basic test: - * - alice creates an account - * - bob creates an account * - alice creates an outbound group session * - bob creates an inbound group session with alice's outbound session key * - alice encrypts a message with its session * - bob decrypts the encrypted message with its session + * - decrypted message is identical to original alice message */ - //@Test - public void test01AliceToBob() { - // creates alice outbound session - OlmOutboundGroupSession aliceOutboundSession = new OlmOutboundGroupSession(); + @Test + public void test01CreateOutboundSession() { + // alice creates OUTBOUND GROUP SESSION + try { + mAliceOutboundSession = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + } - // test accounts creation - String aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier(); - assertNotNull(aliceSessionIdentifier); - assertTrue(aliceSessionIdentifier.length()>0); + @Test + public void test02GetOutboundGroupSessionIdentifier() { + // test session ID + mAliceSessionIdentifier = mAliceOutboundSession.sessionIdentifier(); + assertNotNull(mAliceSessionIdentifier); + assertTrue(mAliceSessionIdentifier.length() > 0); + } - String aliceOutboundSessionKey = aliceOutboundSession.sessionKey(); - assertNotNull(aliceOutboundSessionKey); - assertTrue(aliceOutboundSessionKey.length()>0); + @Test + public void test03GetOutboundGroupSessionKey() { + // test session Key + mAliceOutboundSessionKey = mAliceOutboundSession.sessionKey(); + assertNotNull(mAliceOutboundSessionKey); + assertTrue(mAliceOutboundSessionKey.length() > 0); + } - long messageIndex = aliceOutboundSession.messageIndex(); - assertTrue(0==messageIndex); + @Test + public void test04GetOutboundGroupMessageIndex() { + // test message index before any encryption + mAliceMessageIndex = mAliceOutboundSession.messageIndex(); + assertTrue(0 == mAliceMessageIndex); + } - String clearMessage = "Hello!"; - String encryptedMessage = aliceOutboundSession.encryptMessage(clearMessage); - assertNotNull(encryptedMessage); + @Test + public void test05OutboundGroupEncryptMessage() { + // alice encrypts a message to bob + mAliceToBobMessage = mAliceOutboundSession.encryptMessage(CLEAR_MESSAGE1); + assertFalse(TextUtils.isEmpty(mAliceToBobMessage)); + + // test message index after encryption is incremented + mAliceMessageIndex = mAliceOutboundSession.messageIndex(); + assertTrue(1== mAliceMessageIndex); + } + + @Test + public void test06CreateInboundGroupSession() { + // bob creates INBOUND GROUP SESSION with alice outbound key + try { + mBobInboundSession = new OlmInboundGroupSession(mAliceOutboundSessionKey); + } catch (OlmException e) { + assertTrue("Exception in bob OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + } - messageIndex = aliceOutboundSession.messageIndex(); - assertTrue(1==messageIndex); + @Test + public void test07OutboundGroupSessionIdentifiers() { + // check session identifiers are equals + mAliceSessionIdentifier = mAliceOutboundSession.sessionIdentifier(); + assertFalse(TextUtils.isEmpty(mAliceSessionIdentifier)); + } - assertTrue(encryptedMessage.length()>=0); + @Test + public void test08InboundGroupSessionIdentifiers() { + // check session identifiers are equals + mBobSessionIdentifier = mBobInboundSession.sessionIdentifier(); + assertFalse(TextUtils.isEmpty(mBobSessionIdentifier)); + assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier)); + } - OlmInboundGroupSession bobInboundSession = new OlmInboundGroupSession(); - bobInboundSession.initInboundGroupSessionWithSessionKey(aliceOutboundSessionKey); + @Test + public void test09SessionIdentifiersIdentical() { // check session identifiers are equals - aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier(); - String bobSessionIdentifier = aliceOutboundSession.sessionIdentifier(); - assertTrue(aliceSessionIdentifier.equals(bobSessionIdentifier )); + assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier)); + } - String decryptedMessage = bobInboundSession.decryptMessage(encryptedMessage); - assertTrue(decryptedMessage.equals(bobSessionIdentifier )); + @Test + public void test10InboundDecryptMessage() { + // test decrypted message + mBobDecryptedMessage = mBobInboundSession.decryptMessage(mAliceToBobMessage); + assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); + assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); } - //@Test - public void test02InboundGroupSession() { - // creates alice outbound session - OlmInboundGroupSession aliceInboundSession = new OlmInboundGroupSession(); + @Test + public void test11InboundDecryptedMessageIdentical() { + // test decrypted message + assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); + } - // test session identifier - String sessionIdentifier = aliceInboundSession.sessionIdentifier(); - assertNotNull(sessionIdentifier); - assertTrue(sessionIdentifier.length()>0); + @Test + public void test12ReleaseOutboundSession() { + // release group sessions + mAliceOutboundSession.releaseSession(); } + @Test + public void test13ReleaseInboundSession() { + // release group sessions + mBobInboundSession.releaseSession(); + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java new file mode 100644 index 0000000..d4c642f --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -0,0 +1,35 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +public class OlmException extends Exception { + // exception codes + public static final int EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE = 0; + public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 1; + public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 2; + + private final int mCode; + + public OlmException(int aExceptionCode) { + super(); + mCode = aExceptionCode; + } + + public int getExceptionCode() { + return mCode; + } +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index aa15c32..86f86c4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -48,16 +48,16 @@ public class OlmInboundGroupSession implements Serializable { * The session key parameter is retrieved from a outbound group session * See {@link #initNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)} * @param aSessionKey session key - * @throws OlmUtilsException + * @throws OlmException */ - public OlmInboundGroupSession(String aSessionKey) throws OlmUtilsException { + public OlmInboundGroupSession(String aSessionKey) throws OlmException { if(initNewSession()) { if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { releaseSession();// prevent memory leak before throwing - throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION); } } else { - throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index bbe2718..bca7ab3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -18,7 +18,6 @@ package org.matrix.olm; import android.text.TextUtils; -import android.util.Log; public class OlmOutboundGroupSession { private static final String LOG_TAG = "OlmOutboundGroupSession"; @@ -41,16 +40,16 @@ public class OlmOutboundGroupSession { * Create and save a new session native instance ID and * initialise a new outbound group session.
* See {@link #initNewSession()} and {@link #initOutboundGroupSession()} - * @throws OlmUtilsException + * @throws OlmException */ - public OlmOutboundGroupSession() throws OlmUtilsException { + public OlmOutboundGroupSession() throws OlmException { if(initNewSession()) { if( 0 != initOutboundGroupSession()) { releaseSession();// prevent memory leak before throwing - throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION); } } else { - throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java deleted file mode 100644 index f0cdc83..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtilsException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -public class OlmUtilsException extends Exception { - // exception codes - public static final int EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE = 0; - public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 1; - public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 2; - - private final int mCode; - - public OlmUtilsException(int aExceptionCode) { - super(); - mCode = aExceptionCode; - } - - public int getExceptionCode() { - return mCode; - } -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 16e5a0b..09995ab 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -26,7 +26,7 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env { OlmInboundGroupSession* sessionPtr = NULL; - LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr); + LOGD("## releaseSessionJni(): intbound group session"); if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { @@ -34,12 +34,14 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env } else { + LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); + size_t retCode = olm_clear_inbound_group_session(sessionPtr); - LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); + LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); - LOGD("## releaseSessionJni(): IN"); + LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); - LOGD("## releaseSessionJni(): OUT"); + LOGD(" ## releaseSessionJni(): free OUT"); } } @@ -52,20 +54,23 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) { OlmInboundGroupSession* sessionPtr = NULL; - size_t sessionSize = olm_inbound_group_session_size(); + size_t sessionSize = 0; + + LOGD("## initNewSessionJni(): inbound group session IN"); + sessionSize = olm_inbound_group_session_size(); if(0 == sessionSize) { - LOGE("## initNewSessionJni(): failure - inbound group session size = 0"); + LOGE(" ## initNewSessionJni(): failure - inbound group session size = 0"); } else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize))) { sessionPtr = olm_inbound_group_session(sessionPtr); - LOGD("## initNewSessionJni(): success - inbound group session size=%lu",sessionSize); + LOGD(" ## initNewSessionJni(): success - inbound group session size=%lu",sessionSize); } else { - LOGE("## initNewSessionJni(): failure - inbound group session OOM"); + LOGE(" ## initNewSessionJni(): failure - inbound group session OOM"); } return (jlong)(intptr_t)sessionPtr; @@ -83,32 +88,34 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes const uint8_t *sessionKeyPtr = NULL; size_t sessionResult; + LOGD("## initInboundGroupSessionWithSessionKeyJni(): inbound group session IN"); + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { - LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance"); + LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance"); } else if(0 == aSessionKey) { - LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); + LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); } else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0))) { - LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); + LOGE(" ## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); } else { size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey); - LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength); + LOGD(" ## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength); sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); if(sessionResult == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + LOGE(" ## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); } else { retCode = ERROR_CODE_OK; - LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); + LOGD(" ## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); } } @@ -135,17 +142,17 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { - LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance"); + LOGE(" ## sessionIdentifierJni(): failure - invalid inbound group session instance"); } else { // get the size to alloc size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); - LOGD("## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId); + LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId); if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) { - LOGE("## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); + LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); } else { @@ -153,13 +160,13 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn if (result == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",errorMsgPtr); + LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",errorMsgPtr); } else { // update length sessionIdPtr[result] = static_cast('\0'); - LOGD("## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",result, (char*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",result, (char*)sessionIdPtr); returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); } free(sessionIdPtr); @@ -178,19 +185,19 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * uint8_t *plainTextMsgPtr = NULL; uint8_t *tempEncryptedPtr = NULL; - LOGD("## decryptMessageJni(): IN"); + LOGD("## decryptMessageJni(): inbound group session IN"); if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { - LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); + LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); } else if(0 == aEncryptedMsg) { - LOGE("## decryptMessageJni(): failure - invalid encrypted message"); + LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) { - LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } else { @@ -200,12 +207,12 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * // create a dedicated temp buffer to be used in next Olm API calls if(NULL == (tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))))) { - LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); + LOGE(" ## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); } else { memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr); + LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, @@ -214,11 +221,11 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * if(maxPlainTextLength == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); } else { - LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); + LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); // allocate output decrypted message plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); @@ -233,14 +240,14 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * if(plaintextLength == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); } else { // update decrypted buffer size plainTextMsgPtr[plaintextLength] = static_cast('\0'); - LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr); + LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr); decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 46c0ee4..42d8901 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -26,20 +26,22 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en { OlmOutboundGroupSession* sessionPtr = NULL; - LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr); + LOGD("## releaseSessionJni(): outbound group session"); if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## releaseSessionJni(): failure - invalid outbound group session instance"); + LOGE(" ## releaseSessionJni(): failure - invalid outbound group session instance"); } else { + LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); + size_t retCode = olm_clear_outbound_group_session(sessionPtr); - LOGD("## releaseSessionJni(): clear_outbound_group_session=%lu",retCode); + LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",retCode); - LOGD("## releaseSessionJni(): IN"); + LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); - LOGD("## releaseSessionJni(): OUT"); + LOGD(" ## releaseSessionJni(): free OUT"); } } @@ -52,20 +54,23 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) { OlmOutboundGroupSession* sessionPtr = NULL; - size_t sessionSize = olm_outbound_group_session_size(); + size_t sessionSize = 0; + + LOGD("## initNewSessionJni(): outbound group session IN"); + sessionSize = olm_outbound_group_session_size(); if(0 == sessionSize) { - LOGE("## initNewSessionJni(): failure - outbound group session size = 0"); + LOGE(" ## initNewSessionJni(): failure - outbound group session size = 0"); } else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize))) { sessionPtr = olm_outbound_group_session(sessionPtr); - LOGD("## initNewSessionJni(): success - outbound group session size=%lu",sessionSize); + LOGD(" ## initNewSessionJni(): success - outbound group session size=%lu",sessionSize); } else { - LOGE("## initNewSessionJni(): failure - outbound group session OOM"); + LOGE(" ## initNewSessionJni(): failure - outbound group session OOM"); } return (jlong)(intptr_t)sessionPtr; @@ -85,33 +90,33 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## initOutboundGroupSessionJni(): failure - invalid outbound group session instance"); + LOGE(" ## initOutboundGroupSessionJni(): failure - invalid outbound group session instance"); } else { // compute random buffer size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); - LOGW("## initOutboundGroupSessionJni(): randomLength=%lu",randomLength); + LOGW(" ## initOutboundGroupSessionJni(): randomLength=%lu",randomLength); if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) { - LOGE("## initOutboundGroupSessionJni(): failure - random buffer init"); + LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init"); } else { if(0==randomLength) { - LOGW("## initOutboundGroupSessionJni(): random buffer is not required"); + LOGW(" ## initOutboundGroupSessionJni(): random buffer is not required"); } size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); if(sessionResult == olm_error()) { const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE("## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s",errorMsgPtr); + LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s",errorMsgPtr); } else { retCode = ERROR_CODE_OK; - LOGD("## initOutboundGroupSessionJni(): success - result=%lu", sessionResult); + LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", sessionResult); } } } @@ -137,17 +142,17 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## sessionIdentifierJni(): failure - invalid outbound group session instance"); + LOGE(" ## sessionIdentifierJni(): failure - invalid outbound group session instance"); } else { // get the size to alloc size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); - LOGD("## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",lengthSessionId); + LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",lengthSessionId); if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) { - LOGE("## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); + LOGE(" ## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); } else { @@ -155,13 +160,13 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE if (result == olm_error()) { const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE("## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",errorMsgPtr); + LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",errorMsgPtr); } else { // update length sessionIdPtr[result] = static_cast('\0'); - LOGD("## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",result, (char*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",result, (char*)sessionIdPtr); returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); } @@ -189,13 +194,13 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE("## messageIndexJni(): failure - invalid outbound group session instance"); + LOGE(" ## messageIndexJni(): failure - invalid outbound group session instance"); } else { indexRetValue = static_cast(olm_outbound_group_session_message_index(sessionPtr)); } - LOGD("## messageIndexJni(): success - index=%d",indexRetValue); + LOGD(" ## messageIndexJni(): success - index=%d",indexRetValue); return indexRetValue; } @@ -282,28 +287,28 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); if(NULL == (encryptedMsgPtr = (uint8_t*)malloc(encryptedMsgLength*sizeof(uint8_t)))) { - LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); + LOGE(" ## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); } else { LOGD(" ## encryptMessageJni(): estimated encryptedMsgLength=%lu",encryptedMsgLength); - size_t decryptedLength = olm_group_encrypt(sessionPtr, + size_t encryptedLength = olm_group_encrypt(sessionPtr, (uint8_t*)clearMsgPtr, clearMsgLength, encryptedMsgPtr, encryptedMsgLength); - if(decryptedLength == olm_error()) + if(encryptedLength == olm_error()) { const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); + LOGE(" ## encryptMessageJni(): failure - olm_group_encrypt Msg=%s",errorMsgPtr); } else { // update decrypted buffer size - encryptedMsgPtr[decryptedLength] = static_cast('\0'); + encryptedMsgPtr[encryptedLength] = static_cast('\0'); - LOGD(" ## encryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",decryptedLength, (char*)encryptedMsgPtr); + LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%s",encryptedLength, (char*)encryptedMsgPtr); encryptedMsgRetValue = env->NewStringUTF((const char*)encryptedMsgPtr); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 5911591..889e993 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -69,14 +69,16 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi { OlmSession* sessionPtr = NULL; + LOGD("## initNewSessionJni(): OlmSession IN"); + // init account memory allocation if(NULL == (sessionPtr = initializeSessionMemory())) { - LOGE("## initNewSessionJni(): failure - init session OOM"); + LOGE(" ## initNewSessionJni(): failure - init session OOM"); } else { - LOGD("## initNewSessionJni(): success - OLM session created"); + LOGD(" ## initNewSessionJni(): success - OLM session created"); } return (jlong)(intptr_t)sessionPtr; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index bd920fe..fb9c9c5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -1,6 +1,3 @@ -/** - * Created by pedrocon on 06/10/2016. - */ /* * Copyright 2016 OpenMarket Ltd * @@ -21,201 +18,20 @@ #include "olm_utility.h" /** -* Init a buffer with a given number of random values. -* @param aBuffer2Ptr the buffer to be initialized -* @param aRandomSize the number of random values to apply -* @return true if operation succeed, false otherwise -**/ -bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) + * Verify an ed25519 signature. + * If the key was too small then the message will be "OLM.INVALID_BASE64". + * If the signature was invalid then the message will be "OLM.BAD_MESSAGE_MAC". + * @param aKey the ed25519 key. + * @param aMessage the message which was signed. + * @param aSignature the base64-encoded signature to be checked. + * @param the result error if there is a problem with the verification. + * @return true if validation succeed, false otherwise + */ +JNIEXPORT bool OLM_UTILITY_FUNC_DEF(ed25519VerifyJni)(JNIEnv *env, jobject thiz, jstring aKey, jstring aMessage, jstring aSignature, jobject aErrorMessage) { bool retCode = false; - if(NULL == aBuffer2Ptr) - { - LOGD("## setRandomInBuffer(): failure - aBuffer=NULL"); - } - else if(0 == aRandomSize) - { - LOGD("## setRandomInBuffer(): failure - random size=0"); - } - else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t)))) - { - LOGD("## setRandomInBuffer(): failure - alloc mem OOM"); - } - else - { - LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize); - srand(time(NULL)); // init seed - for(size_t i=0;iGetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId); - } - else - { - LOGD("## getAccountInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL"); - } - LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId); - return instanceId; -} - -/** -* Read the session instance ID of the calling object (aJavaObject).
-* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. -**/ -jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - jlong instanceId=-1; - jfieldID instanceIdField; - jclass loaderClass; - - if(NULL!=aJniEnv) - { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); - } - - //LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); - return instanceId; -} - - -/** -* Read the inbound group session instance ID of the calling object (aJavaObject).
-* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. -**/ -jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - jlong instanceId=-1; - jfieldID instanceIdField; - jclass loaderClass; - - if(NULL!=aJniEnv) - { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); - } - - return instanceId; -} - - -/** -* Read the outbound group session instance ID of the calling object (aJavaObject).
-* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. -**/ -jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - jlong instanceId=-1; - jfieldID instanceIdField; - jclass loaderClass; - - if(NULL!=aJniEnv) - { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); - } - - return instanceId; -} +} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index b16e915..4e5772c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -17,19 +17,18 @@ #ifndef _OMLUTILITY_H #define _OMLUTILITY_H +#define OLM_UTILITY_FUNC_DEF(func_name) FUNC_DEF(OlmUtility,func_name) #ifdef __cplusplus extern "C" { #endif -bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize); -jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +JNIEXPORT bool OLM_UTILITY_FUNC_DEF(ed25519VerifyJni)(JNIEnv *env, jobject thiz, jstring aKey, jstring aMessage, jstring aSignature, jobject aErrorMessage); #ifdef __cplusplus } #endif + #endif -- cgit v1.2.3 From 7e69d96afcb05fed7d5b75b6cbe786c0c1a86965 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 17 Oct 2016 16:48:29 +0200 Subject: Add extra tests to check if the calling JAVA instance is the expected one --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 9 ++- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 76 ++++++++++++++++++++-- 2 files changed, 80 insertions(+), 5 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 2bfb9f8..e1fea02 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -53,6 +52,14 @@ static const int ERROR_CODE_KO = -1; // constants static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; + +// strings +static const char *CLASS_OLM_OUTBOUND_GROUP_SESSION = "org/matrix/olm/OlmOutboundGroupSession"; +static const char *CLASS_OLM_INBOUND_GROUP_SESSION = "org/matrix/olm/OlmInboundGroupSession"; +static const char *CLASS_OLM_SESSION = "org/matrix/olm/OlmSession"; +static const char *CLASS_OLM_ACCOUNT = "org/matrix/olm/OlmAccount"; +static const char *CLASS_OLM_UTILITY = "org/matrix/olm/OlmUtility"; + #ifdef __cplusplus extern "C" { #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 1d64d75..c518578 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -70,10 +70,17 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) jlong instanceId=-1; jfieldID instanceIdField; jclass loaderClass; + jclass requiredClass = 0; if(NULL!=aJniEnv) { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + requiredClass = aJniEnv->FindClass(CLASS_OLM_ACCOUNT); + + if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) + { + LOGD("## getAccountInstanceId() failure - invalid instance of"); + } + else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J"))) { @@ -110,10 +117,17 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) jlong instanceId=-1; jfieldID instanceIdField; jclass loaderClass; + jclass requiredClass = 0; if(NULL!=aJniEnv) { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + requiredClass = aJniEnv->FindClass(CLASS_OLM_SESSION); + + if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) + { + LOGD("## getSessionInstanceId() failure - invalid instance of"); + } + else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) { @@ -151,10 +165,17 @@ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) jlong instanceId=-1; jfieldID instanceIdField; jclass loaderClass; + jclass requiredClass = 0; if(NULL!=aJniEnv) { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + requiredClass = aJniEnv->FindClass(CLASS_OLM_INBOUND_GROUP_SESSION); + + if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) + { + LOGD("## getInboundGroupSessionInstanceId() failure - invalid instance of"); + } + else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J"))) { @@ -191,10 +212,57 @@ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) jlong instanceId=-1; jfieldID instanceIdField; jclass loaderClass; + jclass requiredClass = 0; + + if(NULL!=aJniEnv) + { + requiredClass = aJniEnv->FindClass(CLASS_OLM_OUTBOUND_GROUP_SESSION); + + if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) + { + LOGD("## getOutboundGroupSessionInstanceId() failure - invalid instance of"); + } + else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + { + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J"))) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetFieldID=null"); + } + } + else + { + LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGD("## getOutboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); + } + + return instanceId; +} + +jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId=-1; + jfieldID instanceIdField; + jclass loaderClass; + jclass requiredClass = 0; if(NULL!=aJniEnv) { - if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + requiredClass = aJniEnv->FindClass(CLASS_OLM_UTILITY); + + if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) + { + LOGD("## getOutboundGroupSessionInstanceId() failure - invalid instance of"); + } + else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J"))) { -- cgit v1.2.3 From 4545b7bc190afb20eadb4cd7ed92494015247d51 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 17 Oct 2016 16:53:36 +0200 Subject: Fix "invalid address or address of corrupt passed to dlfree" in 32bits platform devices --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp | 4 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp | 6 +++--- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 09995ab..297f0f5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -150,7 +150,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId); - if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) + if(NULL == (sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) { LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); } @@ -228,7 +228,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); // allocate output decrypted message - plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); + plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); // decrypt, but before reload encrypted buffer (previous one was destroyed) memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 42d8901..4cbd10b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -150,7 +150,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",lengthSessionId); - if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)))) + if(NULL == (sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) { LOGE(" ## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); } @@ -227,7 +227,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env size_t sessionKeyLength = olm_outbound_group_session_key_length(sessionPtr); LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",sessionKeyLength); - if(NULL == (sessionKeyPtr = (uint8_t*)malloc(sessionKeyLength*sizeof(uint8_t)))) + if(NULL == (sessionKeyPtr = (uint8_t*)malloc((sessionKeyLength+1)*sizeof(uint8_t)))) { LOGE(" ## sessionKeyJni(): failure - session key allocation OOM"); } @@ -285,7 +285,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv // compute max encrypted length size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); - if(NULL == (encryptedMsgPtr = (uint8_t*)malloc(encryptedMsgLength*sizeof(uint8_t)))) + if(NULL == (encryptedMsgPtr = (uint8_t*)malloc((encryptedMsgLength+1)*sizeof(uint8_t)))) { LOGE(" ## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 889e993..c02d390 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -497,7 +497,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // alloc buffer for encrypted message size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg); size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); - if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(uint8_t)))) + if(NULL == (encryptedMsgPtr = (void*)malloc((encryptedMsgLength+1)*sizeof(uint8_t)))) { LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); } @@ -640,7 +640,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); // allocate output decrypted message - plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); + plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); // decrypt, but before reload encrypted buffer (previous one was destroyed) memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); @@ -705,7 +705,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job { LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); } - else if(NULL == (sessionIdPtr = (void*)malloc(lengthSessionId*sizeof(uint8_t)))) + else if(NULL == (sessionIdPtr = (void*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) { LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); } -- cgit v1.2.3 From b6cf3f1eecbad229861be60026d24df32fcdfa01 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 17 Oct 2016 16:55:14 +0200 Subject: Update Javadoc method headers with direct link to PRE_KEY definition --- .../olm-sdk/src/main/java/org/matrix/olm/OlmSession.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 2df5ea7..b356cbb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -124,7 +124,7 @@ public class OlmSession implements Serializable { /** * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message.
+ * incoming PRE_KEY ({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message.
* Public API for {@link #initInboundSessionJni(long, String)}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session @@ -153,7 +153,7 @@ public class OlmSession implements Serializable { /** * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message based on the sender identity key.
+ * incoming PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message based on the sender identity key.
* Public API for {@link #initInboundSessionFromIdKeyJni(long, String, String)}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session @@ -195,7 +195,7 @@ public class OlmSession implements Serializable { private native String getSessionIdentifierJni(); /** - * Checks if the PRE_KEY message is for this in-bound session.
+ * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * Public API for {@link #matchesInboundSessionJni(String)}. * @param aOneTimeKeyMsg PRE KEY message @@ -215,7 +215,7 @@ public class OlmSession implements Serializable { /** - * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
+ * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session based on the sender identity key.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * Public API for {@link #matchesInboundSessionJni(String)}. * @param aTheirIdentityKey the sender identity key -- cgit v1.2.3 From 4ccc45ab0aed3f1a6bd3180e00bedc215bb58dc6 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 17 Oct 2016 16:58:19 +0200 Subject: - Update Javadoc for keys constants definitions - change return code from removeOneTimeKeysForSession() (direct value from JNI is now returned) --- .../java/org/matrix/olm/OlmAccountTest.java | 3 ++- .../src/main/java/org/matrix/olm/OlmAccount.java | 26 +++++++++++++++------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index ad875c5..70db63e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -153,7 +153,8 @@ public class OlmAccountTest { assertTrue(0 != sessionId); int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(olmSession); - assertTrue(0 == sessionRetCode); + // test against no matching keys + assertTrue(1 == sessionRetCode); olmSession.releaseSession(); sessionId = olmSession.getOlmSessionId(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 95a6eb5..bc9c936 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -27,8 +27,20 @@ public class OlmAccount implements Serializable { private static final String LOG_TAG = "OlmAccount"; // JSON keys used in the JSON objects returned by JNI + /** As well as the identity key, each device creates a number of Curve25519 key pairs which are + also used to establish Olm sessions, but can only be used once. Once again, the private part + remains on the device. but the public part is published to the Matrix network **/ public static final String JSON_KEY_ONE_TIME_KEY = "curve25519"; + + /** Curve25519 identity key is a public-key cryptographic system which can be used to establish a shared + secret.
In Matrix, each device has a long-lived Curve25519 identity key which is used to establish + Olm sessions with that device. The private key should never leave the device, but the + public part is signed with the Ed25519 fingerprint key ({@link #JSON_KEY_FINGER_PRINT_KEY}) and published to the network. **/ public static final String JSON_KEY_IDENTITY_KEY = "curve25519"; + + /** Ed25519 finger print is a public-key cryptographic system for signing messages.
In Matrix, each device has + an Ed25519 key pair which serves to identify that device. The private the key should + never leave the device, but the public part is published to the Matrix network. **/ public static final String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; /** account raw pointer value (OlmAccount*) returned by JNI. @@ -89,7 +101,7 @@ public class OlmAccount implements Serializable { } /** - * Return the identity keys (identity & fingerprint keys) in a JSON array.
+ * Return the identity keys (identity & fingerprint keys) in a JSON array.
* Public API for {@link #identityKeysJni()}.
* Ex: * { @@ -184,17 +196,14 @@ public class OlmAccount implements Serializable { /** * Remove the "one time keys" that the session used from the account. * @param aSession session instance - * @return 0 if operation succeed, -1 otherwise + * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed */ public int removeOneTimeKeysForSession(OlmSession aSession) { int retCode = 0; if(null != aSession) { - int result = removeOneTimeKeysForSessionJni(aSession.getOlmSessionId()); - Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result="+result); - if(-1 == result) { - retCode = -1; - } + retCode = removeOneTimeKeysForSessionJni(aSession.getOlmSessionId()); + Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result="+retCode); } return retCode; @@ -217,10 +226,11 @@ public class OlmAccount implements Serializable { /** * Sign a message with the ed25519 fingerprint key for this account. + * The signed message is returned by the method. * @param aMessage message to sign * @return the signed message if operation succeed, null otherwise */ - public String signMessage(String aMessage){ + public String signMessage(String aMessage) { return signMessageJni(aMessage); } private native String signMessageJni(String aMessage); -- cgit v1.2.3 From 034fa6be40b1a354dad5394cdb43651f435f8adb Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 18 Oct 2016 15:59:36 +0200 Subject: - Add new API for OlmUtility - Introducing namespace AndroidOlmSdk - Fix logs (function names mixed up) - Add new check based on the calling java object instance type (IsInstanceOf()) - Fix return value for getXXXInstanceId() in case of failure. Now 0 is returned. --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 14 +- .../src/main/jni/olm_inbound_group_session.cpp | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 27 ++- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 62 +++--- .../olm-sdk/src/main/jni/olm_jni_helper.h | 30 +++ .../src/main/jni/olm_outbound_group_session.cpp | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 62 +++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 210 ++++++++++++++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 9 +- 9 files changed, 329 insertions(+), 87 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 860ff3e..a10b8e0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -16,6 +16,8 @@ #include "olm_account.h" +using namespace AndroidOlmSdk; + /** * Init memory allocation for account creation. * @return valid memory allocation, NULL otherwise @@ -264,36 +266,36 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t size_t keysResult; jbyteArray byteArrayRetValue = NULL; - LOGD("## oneTimeKeys(): accountPtr =%p",accountPtr); + LOGD("## oneTimeKeysJni(): IN"); if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE("## oneTimeKeys(): failure - invalid Account ptr"); + LOGE("## oneTimeKeysJni(): failure - invalid Account ptr"); } else { // keys memory allocation keysLength = olm_account_one_time_keys_length(accountPtr); if(NULL == (keysBytesPtr=(uint8_t *)malloc(keysLength*sizeof(uint8_t)))) { - LOGE("## oneTimeKeys(): failure - one time keys array OOM"); + LOGE("## oneTimeKeysJni(): failure - one time keys array OOM"); } else { // retrieve key pairs in keysBytesPtr keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); if(keysResult == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE("## oneTimeKeys(): failure - error getting one time keys Msg=%s",errorMsgPtr); + LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",errorMsgPtr); } else { // allocate the byte array to be returned to java if(NULL == (byteArrayRetValue=env->NewByteArray(keysLength))) { - LOGE("## oneTimeKeys(): failure - return byte array OOM"); + LOGE("## oneTimeKeysJni(): failure - return byte array OOM"); } else { env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, keysLength, (const jbyte*)keysBytesPtr); - LOGD("## oneTimeKeys(): success"); + LOGD("## oneTimeKeysJni(): success"); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 297f0f5..d10a05b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -16,6 +16,7 @@ #include "olm_inbound_group_session.h" +using namespace AndroidOlmSdk; /** * Release the session allocation made by initializeInboundGroupSessionMemory().
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index e1fea02..70267ff 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -44,21 +44,16 @@ #define FUNC_DEF(class_name,func_name) JNICALL Java_org_matrix_olm_##class_name##_##func_name -// Error codes definition -static const int ERROR_CODE_OK = 0; -static const int ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS = ERROR_CODE_OK+1; -static const int ERROR_CODE_KO = -1; - -// constants -static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; - - -// strings -static const char *CLASS_OLM_OUTBOUND_GROUP_SESSION = "org/matrix/olm/OlmOutboundGroupSession"; -static const char *CLASS_OLM_INBOUND_GROUP_SESSION = "org/matrix/olm/OlmInboundGroupSession"; -static const char *CLASS_OLM_SESSION = "org/matrix/olm/OlmSession"; -static const char *CLASS_OLM_ACCOUNT = "org/matrix/olm/OlmAccount"; -static const char *CLASS_OLM_UTILITY = "org/matrix/olm/OlmUtility"; +namespace AndroidOlmSdk +{ + // Error codes definition + static const int ERROR_CODE_OK = 0; + static const int ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS = ERROR_CODE_OK+1; + static const int ERROR_CODE_KO = -1; + + // constants + static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; +} #ifdef __cplusplus extern "C" { @@ -70,7 +65,7 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); - +jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index c518578..98baae1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -17,7 +17,9 @@ * limitations under the License. */ -#include "olm_jni.h" +#include "olm_jni_helper.h" + +using namespace AndroidOlmSdk; /** * Init a buffer with a given number of random values. @@ -30,15 +32,15 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) bool retCode = false; if(NULL == aBuffer2Ptr) { - LOGD("## setRandomInBuffer(): failure - aBuffer=NULL"); + LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); } else if(0 == aRandomSize) { - LOGD("## setRandomInBuffer(): failure - random size=0"); + LOGE("## setRandomInBuffer(): failure - random size=0"); } else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t)))) { - LOGD("## setRandomInBuffer(): failure - alloc mem OOM"); + LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); } else { @@ -67,7 +69,7 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) **/ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId=-1; + jlong instanceId = 0; jfieldID instanceIdField; jclass loaderClass; jclass requiredClass = 0; @@ -78,7 +80,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) { - LOGD("## getAccountInstanceId() failure - invalid instance of"); + LOGE("## getAccountInstanceId() failure - invalid instance of"); } else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { @@ -90,17 +92,17 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) } else { - LOGD("## getAccountInstanceId() ERROR! GetFieldID=null"); + LOGE("## getAccountInstanceId() ERROR! GetFieldID=null"); } } else { - LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null"); + LOGE("## getAccountInstanceId() ERROR! GetObjectClass=null"); } } else { - LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL"); + LOGE("## getAccountInstanceId() ERROR! aJniEnv=NULL"); } LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId); return instanceId; @@ -114,7 +116,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId=-1; + jlong instanceId = 0; jfieldID instanceIdField; jclass loaderClass; jclass requiredClass = 0; @@ -125,7 +127,7 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) { - LOGD("## getSessionInstanceId() failure - invalid instance of"); + LOGE("## getSessionInstanceId() failure - invalid instance of"); } else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { @@ -136,17 +138,17 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) } else { - LOGD("## getSessionInstanceId() ERROR! GetFieldID=null"); + LOGE("## getSessionInstanceId() ERROR! GetFieldID=null"); } } else { - LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null"); + LOGE("## getSessionInstanceId() ERROR! GetObjectClass=null"); } } else { - LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL"); + LOGE("## getSessionInstanceId() ERROR! aJniEnv=NULL"); } //LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); @@ -162,7 +164,7 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId=-1; + jlong instanceId = 0; jfieldID instanceIdField; jclass loaderClass; jclass requiredClass = 0; @@ -173,7 +175,7 @@ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) { - LOGD("## getInboundGroupSessionInstanceId() failure - invalid instance of"); + LOGE("## getInboundGroupSessionInstanceId() failure - invalid instance of"); } else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { @@ -184,17 +186,17 @@ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) } else { - LOGD("## getInboundGroupSessionInstanceId() ERROR! GetFieldID=null"); + LOGE("## getInboundGroupSessionInstanceId() ERROR! GetFieldID=null"); } } else { - LOGD("## getInboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); + LOGE("## getInboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); } } else { - LOGD("## getInboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); + LOGE("## getInboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); } return instanceId; @@ -209,7 +211,7 @@ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId=-1; + jlong instanceId = 0; jfieldID instanceIdField; jclass loaderClass; jclass requiredClass = 0; @@ -220,7 +222,7 @@ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) { - LOGD("## getOutboundGroupSessionInstanceId() failure - invalid instance of"); + LOGE("## getOutboundGroupSessionInstanceId() failure - invalid instance of"); } else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { @@ -231,17 +233,17 @@ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) } else { - LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetFieldID=null"); + LOGE("## getOutboundGroupSessionInstanceId() ERROR! GetFieldID=null"); } } else { - LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); + LOGE("## getOutboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); } } else { - LOGD("## getOutboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); + LOGE("## getOutboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); } return instanceId; @@ -249,7 +251,7 @@ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId=-1; + jlong instanceId = 0; jfieldID instanceIdField; jclass loaderClass; jclass requiredClass = 0; @@ -260,28 +262,28 @@ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) { - LOGD("## getOutboundGroupSessionInstanceId() failure - invalid instance of"); + LOGE("## getUtilityInstanceId() failure - invalid instance of"); } else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J"))) + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmUtilityId", "J"))) { instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); aJniEnv->DeleteLocalRef(loaderClass); } else { - LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetFieldID=null"); + LOGE("## getUtilityInstanceId() ERROR! GetFieldID=null"); } } else { - LOGD("## getOutboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); + LOGE("## getUtilityInstanceId() ERROR! GetObjectClass=null"); } } else { - LOGD("## getOutboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); + LOGE("## getUtilityInstanceId() ERROR! aJniEnv=NULL"); } return instanceId; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h new file mode 100644 index 0000000..986a5a2 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h @@ -0,0 +1,30 @@ +/** + * Created by pedrocon on 06/10/2016. + */ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_jni.h" + +// constant strings +namespace AndroidOlmSdk +{ + static const char *CLASS_OLM_INBOUND_GROUP_SESSION = "org/matrix/olm/OlmInboundGroupSession"; + static const char *CLASS_OLM_OUTBOUND_GROUP_SESSION = "org/matrix/olm/OlmOutboundGroupSession"; + static const char *CLASS_OLM_SESSION = "org/matrix/olm/OlmSession"; + static const char *CLASS_OLM_ACCOUNT = "org/matrix/olm/OlmAccount"; + static const char *CLASS_OLM_UTILITY = "org/matrix/olm/OlmUtility"; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 4cbd10b..55c6539 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -16,6 +16,7 @@ #include "olm_outbound_group_session.h" +using namespace AndroidOlmSdk; /** * Release the session allocation made by initializeOutboundGroupSessionMemory().
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index c02d390..188fe19 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -16,6 +16,7 @@ #include "olm_session.h" +using namespace AndroidOlmSdk; /** * Init memory allocation for a session creation.
@@ -585,31 +586,31 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { - LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); + LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); } else if(0 == aEncryptedMsg) { - LOGE("## decryptMessageJni(): failure - invalid encrypted message"); + LOGE("## decryptMessageJni(): failure - invalid encrypted message"); } else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg))) { - LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); + LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); } else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;"))) { - LOGE("## decryptMessageJni(): failure - unable to get message field"); + LOGE("## decryptMessageJni(): failure - unable to get message field"); } else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","J"))) { - LOGE("## decryptMessageJni(): failure - unable to get message type field"); + LOGE("## decryptMessageJni(): failure - unable to get message type field"); } else if(0 == (encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) { - LOGE("## decryptMessageJni(): failure - JNI encrypted object "); + LOGE("## decryptMessageJni(): failure - JNI encrypted object "); } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) { - LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } else { @@ -621,7 +622,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t // create a dedicated temp buffer to be used in next Olm API calls tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): MsgType=%ld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); + LOGD("## decryptMessageJni(): MsgType=%ld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, @@ -633,11 +634,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t if(maxPlainTextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); } else { - LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); + LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); // allocate output decrypted message plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); @@ -653,14 +654,14 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t if(plaintextLength == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",errorMsgPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",errorMsgPtr); } else { // update decrypted buffer size (static_cast(plainTextMsgPtr))[plaintextLength] = static_cast('\0'); - LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); + LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); decryptedMsgRetValue = env->NewStringUTF(static_cast(plainTextMsgPtr)); } } @@ -698,34 +699,41 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job void *sessionIdPtr = NULL; jstring returnValueStr=0; - // get the size to alloc to contain the id - size_t lengthSessionId = olm_session_id_length(sessionPtr); + LOGD("## getSessionIdentifierJni(): IN "); if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); } - else if(NULL == (sessionIdPtr = (void*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) - { - LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); - } else { - size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - if (result == olm_error()) + // get the size to alloc to contain the id + size_t lengthSessionId = olm_session_id_length(sessionPtr); + LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",lengthSessionId); + + if(NULL == (sessionIdPtr = (void*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); } else { - // update length - (static_cast(sessionIdPtr))[result] = static_cast('\0'); + size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); - returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + if (result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + } + else + { + // update length + (static_cast(sessionIdPtr))[result] = static_cast('\0'); + + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); + returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + } + free(sessionIdPtr); } - free(sessionIdPtr); } return returnValueStr; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index fb9c9c5..1bd82a0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -14,24 +14,220 @@ * limitations under the License. */ -#include "olm_jni.h" #include "olm_utility.h" +using namespace AndroidOlmSdk; + +OlmUtility* initializeUtilityMemory() +{ + OlmUtility* utilityPtr = NULL; + size_t utilitySize = olm_utility_size(); + + if(NULL != (utilityPtr=(OlmUtility*)malloc(utilitySize))) + { + utilityPtr = olm_utility(utilityPtr); + LOGD("## initializeUtilityMemory(): success - OLM utility size=%lu",utilitySize); + } + else + { + LOGE("## initializeUtilityMemory(): failure - OOM"); + } + + return utilityPtr; +} + + +JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz) +{ + OlmUtility* utilityPtr = NULL; + + LOGD("## initUtilityJni(): IN"); + + // init account memory allocation + if(NULL == (utilityPtr = initializeUtilityMemory())) + { + LOGE(" ## initUtilityJni(): failure - init OOM"); + } + else + { + LOGD(" ## initUtilityJni(): success"); + } + + return (jlong)(intptr_t)utilityPtr; +} + + +JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz) +{ + OlmUtility* utilityPtr = NULL; + + if(NULL == (utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) + { + LOGE("## releaseUtilityJni(): failure - utility ptr=NULL"); + } + else + { + olm_clear_utility(utilityPtr); + free(utilityPtr); + } +} + + /** * Verify an ed25519 signature. * If the key was too small then the message will be "OLM.INVALID_BASE64". * If the signature was invalid then the message will be "OLM.BAD_MESSAGE_MAC". - * @param aKey the ed25519 key. - * @param aMessage the message which was signed. - * @param aSignature the base64-encoded signature to be checked. + * + * @param aSignature the base64-encoded message signature to be checked. + * @param aKey the ed25519 key (fingerprint key) + * @param aMessage the message which was signed * @param the result error if there is a problem with the verification. * @return true if validation succeed, false otherwise */ -JNIEXPORT bool OLM_UTILITY_FUNC_DEF(ed25519VerifyJni)(JNIEnv *env, jobject thiz, jstring aKey, jstring aMessage, jstring aSignature, jobject aErrorMessage) +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage) +{ + jstring errorMessageRetValue = 0; + OlmUtility* utilityPtr = NULL; + const char* signaturePtr = NULL; + const char* keyPtr = NULL; + const char* messagePtr = NULL; + + LOGD("## verifyEd25519SignatureJni(): IN"); + + if(NULL == (utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - invalid utility ptr=NULL"); + } + else if((0 == aSignature) || (0 == aKey) || (0 == aMessage)) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - invalid input parameters "); + } + else if(0 == (signaturePtr = env->GetStringUTFChars(aSignature, 0))) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - signature JNI allocation OOM"); + } + else if(0 == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - key JNI allocation OOM"); + } + else if(0 == (messagePtr = env->GetStringUTFChars(aMessage, 0))) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - message JNI allocation OOM"); + } + else + { + size_t signatureLength = (size_t)env->GetStringUTFLength(aSignature); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t messageLength = (size_t)env->GetStringUTFLength(aMessage); + LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",signatureLength,keyLength,messageLength); + + size_t result = olm_ed25519_verify(utilityPtr, + (void const *)keyPtr, + keyLength, + (void const *)messagePtr, + messageLength, + (void*)signaturePtr, + signatureLength); + if(result == olm_error()) { + const char *errorMsgPtr = olm_utility_last_error(utilityPtr); + errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + LOGE("## verifyEd25519SignatureJni(): failure - session creation Msg=%s",errorMsgPtr); + } + else + { + LOGD("## verifyEd25519SignatureJni(): success - result=%ld", result); + } + } + + // free alloc + if(NULL != signaturePtr) + { + env->ReleaseStringUTFChars(aSignature, signaturePtr); + } + + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != messagePtr) + { + env->ReleaseStringUTFChars(aMessage, messagePtr); + } + + return errorMessageRetValue; +} + +/** +* Compute the digest (SHA 256) for the message passed in parameter.
+* The digest value is the function return value. +* @param aMessage +* @return digest of the message if operation succeed, null otherwise +**/ +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jstring aMessageToHash) { - bool retCode = false; + jstring sha256RetValue = 0; + OlmUtility* utilityPtr = NULL; + const char* messagePtr = NULL; + void *hashValuePtr = NULL; + + LOGD("## sha256Jni(): IN"); + + if(NULL == (utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) + { + LOGE(" ## sha256Jni(): failure - invalid utility ptr=NULL"); + } + else if(0 == aMessageToHash) + { + LOGE(" ## sha256Jni(): failure - invalid message parameters "); + } + else if(0 == (messagePtr = env->GetStringUTFChars(aMessageToHash, 0))) + { + LOGE(" ## sha256Jni(): failure - message JNI allocation OOM"); + } + else + { + // get lengths + size_t messageLength = (size_t)env->GetStringUTFLength(aMessageToHash); + size_t hashLength = olm_sha256_length(utilityPtr); + + if(NULL == (hashValuePtr = static_cast(malloc((hashLength+1)*sizeof(uint8_t))))) + { + LOGE("## sha256Jni(): failure - hash value allocation OOM"); + } + else + { + size_t result = olm_sha256(utilityPtr, + (void const *)messagePtr, + messageLength, + (void *)hashValuePtr, + hashLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_utility_last_error(utilityPtr); + LOGE("## sha256Jni(): failure - hash creation Msg=%s",errorMsgPtr); + } + else + { + // update length + (static_cast(hashValuePtr))[result] = static_cast('\0'); + + LOGD("## sha256Jni(): success - result=%lu hashValue=%s",result, (char*)hashValuePtr); + sha256RetValue = env->NewStringUTF((const char*)hashValuePtr); + } + } + + } + if(NULL != hashValuePtr) + { + free(hashValuePtr); + } + if(NULL != messagePtr) + { + env->ReleaseStringUTFChars(aMessageToHash, messagePtr); + } - return retCode; + return sha256RetValue; } \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index 4e5772c..0bbbb52 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -17,13 +17,20 @@ #ifndef _OMLUTILITY_H #define _OMLUTILITY_H +#include "olm_jni.h" +#include "olm/olm.h" + #define OLM_UTILITY_FUNC_DEF(func_name) FUNC_DEF(OlmUtility,func_name) + #ifdef __cplusplus extern "C" { #endif -JNIEXPORT bool OLM_UTILITY_FUNC_DEF(ed25519VerifyJni)(JNIEnv *env, jobject thiz, jstring aKey, jstring aMessage, jstring aSignature, jobject aErrorMessage); +JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage); +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jstring aMessageToHash); #ifdef __cplusplus } -- cgit v1.2.3 From 139402611aff5919844109f2c7f126bec5c31534 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 18 Oct 2016 16:05:28 +0200 Subject: Add OlmUtility class - add unit tests for OlmUtility - rename OlmGroupTest to OlmGroupSessionTest - update OlmException --- .../java/org/matrix/olm/OlmAccountTest.java | 37 +---- .../java/org/matrix/olm/OlmGroupSessionTest.java | 144 +++++++++++++++++++ .../java/org/matrix/olm/OlmGroupTest.java | 152 --------------------- .../java/org/matrix/olm/OlmSessionTest.java | 1 - .../java/org/matrix/olm/OlmUtilityTest.java | 89 ++++++++++++ .../src/main/java/org/matrix/olm/OlmAccount.java | 1 - .../src/main/java/org/matrix/olm/OlmException.java | 24 +++- .../org/matrix/olm/OlmInboundGroupSession.java | 12 +- .../org/matrix/olm/OlmOutboundGroupSession.java | 7 +- .../src/main/java/org/matrix/olm/OlmSession.java | 18 +-- .../src/main/java/org/matrix/olm/OlmUtility.java | 127 +++++++++++++++++ 11 files changed, 398 insertions(+), 214 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 70db63e..45f6e63 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -173,41 +173,6 @@ public class OlmAccountTest { String clearMsg = "String to be signed by olm"; String signedMsg = mOlmAccount.signMessage(clearMsg); assertNotNull(signedMsg); - // TODO add test to unsign the signedMsg and compare it ot clearMsg + // additional tests are performed in test01VerifyEd25519Signing() } - - - private void testJni(){ - OlmManager mgr = new OlmManager(); - String versionLib = mgr.getOlmLibVersion(); - Log.d(LOG_TAG, "## testJni(): lib version="+versionLib); - - OlmAccount account = new OlmAccount(); - - long accountNativeId = account.getOlmAccountId(); - Log.d(LOG_TAG, "## testJni(): lib accountNativeId="+accountNativeId); - - JSONObject identityKeys = account.identityKeys(); - Log.d(LOG_TAG, "## testJni(): identityKeysJson="+identityKeys.toString()); - - long maxOneTimeKeys = account.maxOneTimeKeys(); - Log.d(LOG_TAG, "## testJni(): lib maxOneTimeKeys="+maxOneTimeKeys); - - int generateRetCode = account.generateOneTimeKeys(50); - Log.d(LOG_TAG, "## testJni(): generateRetCode="+generateRetCode); - - JSONObject oneTimeKeysKeysJson = account.oneTimeKeys(); - Log.d(LOG_TAG, "## testJni(): oneTimeKeysKeysJson="+oneTimeKeysKeysJson.toString()); - - int asPublishedRetCode = account.markOneTimeKeysAsPublished(); - Log.d(LOG_TAG, "## testJni(): asPublishedRetCode="+asPublishedRetCode); - - String clearMsg ="My clear message"; - String signedMsg = account.signMessage(clearMsg); - Log.d(LOG_TAG, "## testJni(): signedMsg="+signedMsg); - - account.releaseAccount(); - } - - } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java new file mode 100644 index 0000000..fc3c1f0 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -0,0 +1,144 @@ +package org.matrix.olm; + +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmGroupSessionTest { + private static final String LOG_TAG = "OlmSessionTest"; + + private static OlmManager mOlmManager; + private static OlmOutboundGroupSession mAliceOutboundGroupSession; + private static String mAliceSessionIdentifier; + private static long mAliceMessageIndex; + public static final String CLEAR_MESSAGE1 = "Hello!"; + private static String mAliceToBobMessage; + private static OlmInboundGroupSession mBobInboundGroupSession; + private static String mAliceOutboundSessionKey; + private static String mBobSessionIdentifier; + private static String mBobDecryptedMessage; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + /** + * Basic test: + * - alice creates an outbound group session + * - bob creates an inbound group session with alice's outbound session key + * - alice encrypts a message with its session + * - bob decrypts the encrypted message with its session + * - decrypted message is identical to original alice message + */ + @Test + public void test01CreateOutboundSession() { + // alice creates OUTBOUND GROUP SESSION + try { + mAliceOutboundGroupSession = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + } + + @Test + public void test02GetOutboundGroupSessionIdentifier() { + // test session ID + mAliceSessionIdentifier = mAliceOutboundGroupSession.sessionIdentifier(); + assertNotNull(mAliceSessionIdentifier); + assertTrue(mAliceSessionIdentifier.length() > 0); + } + + @Test + public void test03GetOutboundGroupSessionKey() { + // test session Key + mAliceOutboundSessionKey = mAliceOutboundGroupSession.sessionKey(); + assertNotNull(mAliceOutboundSessionKey); + assertTrue(mAliceOutboundSessionKey.length() > 0); + } + + @Test + public void test04GetOutboundGroupMessageIndex() { + // test message index before any encryption + mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex(); + assertTrue(0 == mAliceMessageIndex); + } + + @Test + public void test05OutboundGroupEncryptMessage() { + // alice encrypts a message to bob + mAliceToBobMessage = mAliceOutboundGroupSession.encryptMessage(CLEAR_MESSAGE1); + assertFalse(TextUtils.isEmpty(mAliceToBobMessage)); + + // test message index after encryption is incremented + mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex(); + assertTrue(1 == mAliceMessageIndex); + } + + @Test + public void test06CreateInboundGroupSession() { + // bob creates INBOUND GROUP SESSION with alice outbound key + try { + mBobInboundGroupSession = new OlmInboundGroupSession(mAliceOutboundSessionKey); + } catch (OlmException e) { + assertTrue("Exception in bob OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + } + + @Test + public void test08GetInboundGroupSessionIdentifier() { + // check both session identifiers are equals + mBobSessionIdentifier = mBobInboundGroupSession.sessionIdentifier(); + assertFalse(TextUtils.isEmpty(mBobSessionIdentifier)); + } + + @Test + public void test09SessionIdentifiersAreIdentical() { + // check both session identifiers are equals: alice vs bob + assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier)); + } + + @Test + public void test10InboundDecryptMessage() { + // test decrypted message + mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage); + assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); + assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); + } + + @Test + public void test11InboundDecryptedMessageIdentical() { + // test decrypted message + assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); + } + + @Test + public void test12ReleaseOutboundSession() { + // release group sessions + mAliceOutboundGroupSession.releaseSession(); + } + + @Test + public void test13ReleaseInboundSession() { + // release group sessions + mBobInboundGroupSession.releaseSession(); + } +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java deleted file mode 100644 index 5a5ca57..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.matrix.olm; - -import android.support.test.runner.AndroidJUnit4; -import android.text.TextUtils; -import android.util.Log; - -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class OlmGroupTest { - private static final String LOG_TAG = "OlmSessionTest"; - - private static OlmManager mOlmManager; - private static OlmOutboundGroupSession mAliceOutboundSession; - private static String mAliceSessionIdentifier; - private static long mAliceMessageIndex; - public static final String CLEAR_MESSAGE1 = "Hello!"; - private static String mAliceToBobMessage; - private static OlmInboundGroupSession mBobInboundSession; - private static String mAliceOutboundSessionKey; - private static String mBobSessionIdentifier; - private static String mBobDecryptedMessage; - - @BeforeClass - public static void setUpClass(){ - // load native lib - mOlmManager = new OlmManager(); - - String version = mOlmManager.getOlmLibVersion(); - assertNotNull(version); - Log.d(LOG_TAG, "## setUpClass(): lib version="+version); - } - - /** - * Basic test: - * - alice creates an outbound group session - * - bob creates an inbound group session with alice's outbound session key - * - alice encrypts a message with its session - * - bob decrypts the encrypted message with its session - * - decrypted message is identical to original alice message - */ - @Test - public void test01CreateOutboundSession() { - // alice creates OUTBOUND GROUP SESSION - try { - mAliceOutboundSession = new OlmOutboundGroupSession(); - } catch (OlmException e) { - assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - } - - @Test - public void test02GetOutboundGroupSessionIdentifier() { - // test session ID - mAliceSessionIdentifier = mAliceOutboundSession.sessionIdentifier(); - assertNotNull(mAliceSessionIdentifier); - assertTrue(mAliceSessionIdentifier.length() > 0); - } - - @Test - public void test03GetOutboundGroupSessionKey() { - // test session Key - mAliceOutboundSessionKey = mAliceOutboundSession.sessionKey(); - assertNotNull(mAliceOutboundSessionKey); - assertTrue(mAliceOutboundSessionKey.length() > 0); - } - - @Test - public void test04GetOutboundGroupMessageIndex() { - // test message index before any encryption - mAliceMessageIndex = mAliceOutboundSession.messageIndex(); - assertTrue(0 == mAliceMessageIndex); - } - - @Test - public void test05OutboundGroupEncryptMessage() { - // alice encrypts a message to bob - mAliceToBobMessage = mAliceOutboundSession.encryptMessage(CLEAR_MESSAGE1); - assertFalse(TextUtils.isEmpty(mAliceToBobMessage)); - - // test message index after encryption is incremented - mAliceMessageIndex = mAliceOutboundSession.messageIndex(); - assertTrue(1== mAliceMessageIndex); - } - - @Test - public void test06CreateInboundGroupSession() { - // bob creates INBOUND GROUP SESSION with alice outbound key - try { - mBobInboundSession = new OlmInboundGroupSession(mAliceOutboundSessionKey); - } catch (OlmException e) { - assertTrue("Exception in bob OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - } - - @Test - public void test07OutboundGroupSessionIdentifiers() { - // check session identifiers are equals - mAliceSessionIdentifier = mAliceOutboundSession.sessionIdentifier(); - assertFalse(TextUtils.isEmpty(mAliceSessionIdentifier)); - } - - @Test - public void test08InboundGroupSessionIdentifiers() { - // check session identifiers are equals - mBobSessionIdentifier = mBobInboundSession.sessionIdentifier(); - assertFalse(TextUtils.isEmpty(mBobSessionIdentifier)); - assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier)); - } - - @Test - public void test09SessionIdentifiersIdentical() { - // check session identifiers are equals - assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier)); - } - - @Test - public void test10InboundDecryptMessage() { - // test decrypted message - mBobDecryptedMessage = mBobInboundSession.decryptMessage(mAliceToBobMessage); - assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); - assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); - } - - @Test - public void test11InboundDecryptedMessageIdentical() { - // test decrypted message - assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); - } - - @Test - public void test12ReleaseOutboundSession() { - // release group sessions - mAliceOutboundSession.releaseSession(); - } - - @Test - public void test13ReleaseInboundSession() { - // release group sessions - mBobInboundSession.releaseSession(); - } -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 6056466..311d6a8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -250,5 +250,4 @@ public class OlmSessionTest { // must be the same for both ends of the conversation assertTrue(aliceSessionId.equals(bobSessionId)); } - } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java new file mode 100644 index 0000000..5175424 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -0,0 +1,89 @@ +package org.matrix.olm; + +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import java.util.Iterator; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmUtilityTest { + private static final String LOG_TAG = "OlmAccountTest"; + private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50; + + private static OlmManager mOlmManager; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + /** + * Test the signing API + */ + @Test + public void test01VerifyEd25519Signing() { + String fingerPrintKey = null; + String errorMsg = new String(); + String message = "{\"key1\":\"value1\",\"key2\":\"value2\"};"; + + // create account + OlmAccount account = new OlmAccount(); + assertNotNull(account); + + // sign message + String messageSignature = account.signMessage(message); + assertNotNull(messageSignature); + + // get identity key + JSONObject identityKeysJson = account.identityKeys(); + assertNotNull(identityKeysJson); + try { + fingerPrintKey = identityKeysJson.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); + assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); + } catch (JSONException e) { + e.printStackTrace(); + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // instance utility + OlmUtility utility = new OlmUtility(); + boolean isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message, errorMsg); + assertTrue(isVerified); + + utility.releaseUtility(); + } + + + @Test + public void test02sha256() { + OlmUtility utility = new OlmUtility(); + String msgToHash = "The quick brown fox jumps over the lazy dog"; + + String hashResult = utility.sha256(msgToHash); + assertFalse(TextUtils.isEmpty(hashResult)); + + utility.releaseUtility(); + } +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index bc9c936..ea8d618 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -71,7 +71,6 @@ public class OlmAccount implements Serializable { /** * Release native account and invalid its JAVA reference counter part.
* Public API for {@link #releaseAccountJni()}. - * To be called before any other API call. */ public void releaseAccount(){ releaseAccountJni(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index d4c642f..68e02fd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -16,17 +16,33 @@ package org.matrix.olm; +/** + * Exception class to identify specific Olm SDk exceptions. + */ public class OlmException extends Exception { // exception codes - public static final int EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE = 0; - public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 1; - public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 2; + public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 0; + public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 1; + public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 2; + public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 3; + + // exception human readable messages + public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; + public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "failed to create a new inbound group Session"; + public static final String EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION = "failed to initialize a new outbound group Session"; + public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = "failed to initialize a new inbound group Session"; + /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION} + * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}**/ private final int mCode; - public OlmException(int aExceptionCode) { + /** Human readable message description **/ + private final String mMessage; + + public OlmException(int aExceptionCode, String aExceptionMessage) { super(); mCode = aExceptionCode; + mMessage = aExceptionMessage; } public int getExceptionCode() { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 86f86c4..d7d9a1c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -45,26 +45,25 @@ public class OlmInboundGroupSession implements Serializable { /** * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. - * The session key parameter is retrieved from a outbound group session + * The session key parameter is retrieved from an outbound group session * See {@link #initNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)} * @param aSessionKey session key - * @throws OlmException + * @throws OlmException constructor failure */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { if(initNewSession()) { if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { releaseSession();// prevent memory leak before throwing - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION,OlmException.EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION); } } else { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); + throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION); } } /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. - * To be called before any other API call. */ public void releaseSession(){ releaseSessionJni(); @@ -81,8 +80,7 @@ public class OlmInboundGroupSession implements Serializable { private native void releaseSessionJni(); /** - * Create and save the session native instance ID. - * Wrapper for {@link #initNewSessionJni()}.
+ * Create and save the session native instance ID.
* To be called before any other API call. * @return true if init succeed, false otherwise. */ diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index bca7ab3..7c2c42b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -40,23 +40,22 @@ public class OlmOutboundGroupSession { * Create and save a new session native instance ID and * initialise a new outbound group session.
* See {@link #initNewSession()} and {@link #initOutboundGroupSession()} - * @throws OlmException + * @throws OlmException constructor failure */ public OlmOutboundGroupSession() throws OlmException { if(initNewSession()) { if( 0 != initOutboundGroupSession()) { releaseSession();// prevent memory leak before throwing - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION); } } else { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE); + throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION); } } /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. - * To be called before any other API call. */ public void releaseSession() { releaseSessionJni(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index b356cbb..8574f95 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -63,7 +63,6 @@ public class OlmSession implements Serializable { /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. - * To be called before any other API call. */ public void releaseSession(){ releaseSessionJni(); @@ -128,19 +127,19 @@ public class OlmSession implements Serializable { * Public API for {@link #initInboundSessionJni(long, String)}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session - * @param aOneTimeKeyMsg PRE KEY message + * @param aPreKeyMsg PRE KEY message * @return this if operation succeed, null otherwise */ - public OlmSession initInboundSessionWithAccount(OlmAccount aAccount, String aOneTimeKeyMsg) { + public OlmSession initInboundSessionWithAccount(OlmAccount aAccount, String aPreKeyMsg) { OlmSession retObj=null; - if((null==aAccount) || TextUtils.isEmpty(aOneTimeKeyMsg)){ + if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { // set the account of this session mOlmAccount = aAccount; - if( 0 == initInboundSessionJni(mOlmAccount.getOlmAccountId(), aOneTimeKeyMsg)) { + if( 0 == initInboundSessionJni(mOlmAccount.getOlmAccountId(), aPreKeyMsg)) { retObj = this; } } @@ -156,22 +155,23 @@ public class OlmSession implements Serializable { * incoming PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message based on the sender identity key.
* Public API for {@link #initInboundSessionFromIdKeyJni(long, String, String)}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * This method must only be called the first time a pre-key message is received from an inbound session. * @param aAccount the account to associate with this session * @param aTheirIdentityKey the sender identity key - * @param aOneTimeKeyMsg PRE KEY message + * @param aPreKeyMsg PRE KEY message * @return this if operation succeed, null otherwise * TODO unit test missing: initInboundSessionWithAccountFrom */ - public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aOneTimeKeyMsg) { + public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) { OlmSession retObj=null; - if((null==aAccount) || TextUtils.isEmpty(aOneTimeKeyMsg)){ + if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { // set the account of this session mOlmAccount = aAccount; - if(0 == initInboundSessionFromIdKeyJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aOneTimeKeyMsg)){ + if(0 == initInboundSessionFromIdKeyJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg)){ retObj = this; } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java new file mode 100644 index 0000000..e2a085d --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -0,0 +1,127 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.text.TextUtils; +import android.util.Log; + +import java.io.Serializable; + +public class OlmUtility implements Serializable { + private static final String LOG_TAG = "OlmUtility"; + + /** raw pointer value returned by JNI. + * this value uniquely identifies this utility instance. + **/ + private long mNativeOlmUtilityId; + + public OlmUtility() { + initUtility(); + } + + /** + * Getter on the session ID. + * @return native session ID + */ + public long getOlmUtilityId(){ + return mNativeOlmUtilityId; + } + + /** + * Create a native utility instance. + * To be called before any other API call. + * @return true if init succeed, false otherwise. + */ + private boolean initUtility() { + boolean retCode = false; + if(0 != (mNativeOlmUtilityId = initUtilityJni())){ + retCode = true; + } + return retCode; + } + private native long initUtilityJni(); + + /** + * Release native instance.
+ * Public API for {@link #releaseUtilityJni()}. + */ + public void releaseUtility(){ + releaseUtilityJni(); + mNativeOlmUtilityId = 0; + } + private native void releaseUtilityJni(); + + /** + * Verify an ed25519 signature.
+ * If the signature is verified, the method returns true. If false is returned, an error description is provided in aError. + * If the key was too small, aError is set to "OLM.INVALID_BASE64". + * If the signature was invalid, aError is set to "OLM.BAD_MESSAGE_MAC".
+ * @param aSignature the base64-encoded message signature to be checked. + * @param aFingerprintKey the ed25519 key + * @param aMessage the message which was signed + * @param aError error message description + * @return true if the signature is verified, false otherwise + */ + public boolean verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage, String aError) { + boolean retCode = false; + OlmUtility retObj=null; + + if(null == aError) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input error parameter"); + } + else if(TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)){ + Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); + } else { + String errorRetValue = verifyEd25519SignatureJni(aSignature,aFingerprintKey, aMessage); + if(null == errorRetValue) { + aError=""; + retCode = true; + } else { + aError = errorRetValue; + } + } + + return retCode; + } + private native String verifyEd25519SignatureJni(String aSignature, String aFingerprintKey, String aMessage); + + + /** + * Compute the hash(SHA-256) value of the string given in parameter(aMessageToHash).
+ * The hash value is the returned by the method. + * @param aMessageToHash message to be hashed + * @return hash value if operation succeed, null otherwise + */ + public String sha256(String aMessageToHash) { + String hashRetValue = null; + + if(null != aMessageToHash){ + hashRetValue = sha256Jni(aMessageToHash); + } + + return hashRetValue; + + } + private native String sha256Jni(String aMessage); + + + // TODO missing API: initWithSerializedData + // TODO missing API: serializeDataWithKey + // TODO missing API: initWithCoder + // TODO missing API: encodeWithCoder +} + -- cgit v1.2.3 From a6913c49c26b54a4856f883daeb27970f9ab59a4 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 18 Oct 2016 19:00:23 +0200 Subject: Fix javadoc header comment --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 1bd82a0..2bda36c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -81,8 +81,7 @@ JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz * @param aSignature the base64-encoded message signature to be checked. * @param aKey the ed25519 key (fingerprint key) * @param aMessage the message which was signed - * @param the result error if there is a problem with the verification. - * @return true if validation succeed, false otherwise + * @return 0 if validation succeed, an error message string if operation failed */ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage) { -- cgit v1.2.3 From 26d9934fc84f3da742e4c38f37ee50a9ddb5237b Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 18 Oct 2016 19:02:18 +0200 Subject: Fix verifyEd25519Signature() API to properly return the error message in case signature verification failed - update unit tests --- .../java/org/matrix/olm/OlmUtilityTest.java | 14 ++++++++++-- .../src/main/java/org/matrix/olm/OlmUtility.java | 25 +++++++++++++++------- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 5175424..b500cdf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -45,7 +45,7 @@ public class OlmUtilityTest { @Test public void test01VerifyEd25519Signing() { String fingerPrintKey = null; - String errorMsg = new String(); + StringBuffer errorMsg = new StringBuffer(); String message = "{\"key1\":\"value1\",\"key2\":\"value2\"};"; // create account @@ -67,10 +67,20 @@ public class OlmUtilityTest { assertTrue("Exception MSg="+e.getMessage(), false); } - // instance utility + // instantiate utility object OlmUtility utility = new OlmUtility(); + + // verify signature + errorMsg.append("init with anything"); boolean isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message, errorMsg); assertTrue(isVerified); + assertTrue(String.valueOf(errorMsg).isEmpty()); + + // check a bad signature is detected and the error message is not empty + messageSignature = "Bad signature Bad signature Bad signature.."; + isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message, errorMsg); + assertFalse(isVerified); + assertFalse(String.valueOf(errorMsg).isEmpty()); utility.releaseUtility(); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index e2a085d..a6e9c4f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -71,14 +71,14 @@ public class OlmUtility implements Serializable { * If the key was too small, aError is set to "OLM.INVALID_BASE64". * If the signature was invalid, aError is set to "OLM.BAD_MESSAGE_MAC".
* @param aSignature the base64-encoded message signature to be checked. - * @param aFingerprintKey the ed25519 key - * @param aMessage the message which was signed + * @param aFingerprintKey the ed25519 key (fingerprint key) + * @param aMessage the signed message * @param aError error message description * @return true if the signature is verified, false otherwise */ - public boolean verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage, String aError) { + public boolean verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage, StringBuffer aError) { boolean retCode = false; - OlmUtility retObj=null; + String errorRetValue = null; if(null == aError) { Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input error parameter"); @@ -86,17 +86,26 @@ public class OlmUtility implements Serializable { else if(TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)){ Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); } else { - String errorRetValue = verifyEd25519SignatureJni(aSignature,aFingerprintKey, aMessage); - if(null == errorRetValue) { - aError=""; + aError.setLength(0); + + if( null == (errorRetValue = verifyEd25519SignatureJni(aSignature,aFingerprintKey, aMessage))) { retCode = true; } else { - aError = errorRetValue; + aError.append(errorRetValue); } } return retCode; } + + /** + * Verify an ed25519 signature. + * Return a human readable error message in case of verification failure. + * @param aSignature the base64-encoded message signature to be checked. + * @param aFingerprintKey the ed25519 key + * @param aMessage the signed message + * @return null if validation succeed, the error message string if operation failed + */ private native String verifyEd25519SignatureJni(String aSignature, String aFingerprintKey, String aMessage); -- cgit v1.2.3 From 5b524efc44a91837934c2252c62b58eaaf6847aa Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 19 Oct 2016 15:23:19 +0200 Subject: Update due to the de/serialization API --- .../olm-sdk/src/main/java/org/matrix/olm/OlmException.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 68e02fd..3977b7b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -25,12 +25,18 @@ public class OlmException extends Exception { public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 1; public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 2; public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 3; + public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 4; + public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 5; + public static final int EXCEPTION_CODE_SESSION_SERIALIZATION = 6; + public static final int EXCEPTION_CODE_SESSION_DESERIALIZATION = 7; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "failed to create a new inbound group Session"; public static final String EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION = "failed to initialize a new outbound group Session"; public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = "failed to initialize a new inbound group Session"; + public static final String EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION = "initNewAccount() failure"; + public static final String EXCEPTION_MSG_INIT_ACCOUNT_DESERIALIZATION = "initWithSerializedData() failure"; /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION} * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}**/ @@ -48,4 +54,9 @@ public class OlmException extends Exception { public int getExceptionCode() { return mCode; } + + @Override + public String getMessage() { + return mMessage; + } } -- cgit v1.2.3 From e45c03c9e0874d4f001c7cb62adf0fc36b53bf65 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 19 Oct 2016 18:18:12 +0200 Subject: Add new exception message for deserialization --- .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java | 1 + 1 file changed, 1 insertion(+) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 3977b7b..97589f0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -37,6 +37,7 @@ public class OlmException extends Exception { public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = "failed to initialize a new inbound group Session"; public static final String EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION = "initNewAccount() failure"; public static final String EXCEPTION_MSG_INIT_ACCOUNT_DESERIALIZATION = "initWithSerializedData() failure"; + public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid deserialized parameters"; /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION} * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}**/ -- cgit v1.2.3 From 250af953304300239052744b0fd5e42d6d7c3e2f Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 20 Oct 2016 14:40:10 +0200 Subject: First update with serialization mechanism --- .../src/main/java/org/matrix/olm/OlmAccount.java | 136 ++++++++++++++++++++- 1 file changed, 133 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index ea8d618..5b2418a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -16,15 +16,27 @@ package org.matrix.olm; +import android.text.TextUtils; import android.util.Log; import org.json.JSONException; import org.json.JSONObject; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.util.Arrays; +import java.util.Random; public class OlmAccount implements Serializable { + private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; + private static final int MAX_BITS_LENGTH = 128; + private static final int RANDOM_TAB_SIZE = 32; + private static final int RANDOM_MAX = 256; // JSON keys used in the JSON objects returned by JNI /** As well as the identity key, each device creates a number of Curve25519 key pairs which are @@ -46,11 +58,129 @@ public class OlmAccount implements Serializable { /** account raw pointer value (OlmAccount*) returned by JNI. * this value identifies uniquely the native account instance. */ - private long mNativeOlmAccountId; + private transient long mNativeOlmAccountId; + + private transient SecureRandom mSecureRandom; public OlmAccount() { initNewAccount(); + mSecureRandom = new SecureRandom(); + } + + private String getRandomKey() { + //String keyRetValue = new BigInteger(MAX_BITS_LENGTH, mSecureRandom).toString(RANDOM_TAB_SIZE); + String keyRetValue; + Random rand = new Random(); + + StringBuilder strBuilder = new StringBuilder(); + + for(int i=0;i + * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + } + + return pickleRetValue; + } + private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serializeDataWithKey(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + * @param aErrorMsg error message description + * @return true if operation succeed, false otherwise + */ + private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + boolean retCode = false; + String jniError; + + if(null == aErrorMsg) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); + } else { + aErrorMsg.setLength(0); + + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } + + return retCode; } + private native String initWithSerializedDataJni(String aSerializedData, String aKey); /** * Getter on the account ID. @@ -86,8 +216,8 @@ public class OlmAccount implements Serializable { private native long initNewAccountJni(); /** - * Create and save the account native instance ID. - * Wrapper for {@link #initNewAccountJni()}.
+ * Create and initialize a new native account instance.
+ * Wrapper for {@link #initNewAccountJni()}. * To be called before any other API call. * @return true if init succeed, false otherwise. */ -- cgit v1.2.3 From 867ef94ced8d3d32c63e7d6dac74574c6d7da813 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 20 Oct 2016 14:40:59 +0200 Subject: First update with serialization mechanism --- .../java/org/matrix/olm/OlmAccountTest.java | 90 +++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 45f6e63..19b8b63 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -1,5 +1,8 @@ package org.matrix.olm; +import android.accounts.Account; +import android.content.Context; +import android.content.SharedPreferences; import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import android.util.Log; @@ -15,9 +18,19 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Iterator; +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @RunWith(AndroidJUnit4.class) @@ -106,7 +119,7 @@ public class OlmAccountTest { } //**************************************************** - //** ************** One time keys TESTS ************** + //***************** ONE TIME KEYS TESTS ************** //**************************************************** @Test public void test06MaxOneTimeKeys() { @@ -175,4 +188,79 @@ public class OlmAccountTest { assertNotNull(signedMsg); // additional tests are performed in test01VerifyEd25519Signing() } + + + // ******************************************************** + // ************* SERIALIZATION TEST *********************** + // ******************************************************** + + @Test + public void test13Serialization() { + FileOutputStream fileOutput = null; + ObjectOutputStream objectOutput = null; + OlmAccount accountRef = new OlmAccount(); + OlmAccount accountDeserial = null; + OlmException exception; + + int retValue = accountRef.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); + assertTrue(0==retValue); + + JSONObject identityKeysRef = accountRef.identityKeys(); + JSONObject oneTimeKeysRef = accountRef.oneTimeKeys(); + final String FILE_NAME = "testfile"; + + /*Context context = getInstrumentation().getContext(); + SharedPreferences sharedPref = context.getSharedPreferences("TestPref",Context.MODE_PRIVATE); + SharedPreferences.Editor editPref = sharedPref.edit(); + editPref.putLong();*/ + + try { + Context context = getInstrumentation().getContext(); + context.getFilesDir(); + //File serialFile = new File(FILE_NAME); + //fileOutput = new FileOutputStream(serialFile); + fileOutput = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); + + objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(accountRef); + objectOutput.flush(); + objectOutput.close(); + + //FileInputStream fileInput = new FileInputStream(serialFile); + FileInputStream fileInput = context.openFileInput(FILE_NAME); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + accountDeserial = (OlmAccount) objectInput.readObject(); + objectInput.close(); + + assertNotNull(accountDeserial); + + JSONObject identityKeys2 = accountDeserial.identityKeys(); + JSONObject oneTimeKeys2 = accountDeserial.oneTimeKeys(); + assertEquals(identityKeysRef, identityKeys2); + assertEquals(oneTimeKeysRef, oneTimeKeys2); + + accountRef.releaseAccount(); + accountDeserial.releaseAccount(); + + } + + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception IOException Msg==" + e.getMessage()); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception Msg==" + e.getMessage()); + } + + } + + } -- cgit v1.2.3 From 0cb45abdf3b0d7e61f28fbd9dc514d8753ff61c1 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 20 Oct 2016 17:36:20 +0200 Subject: Update logs --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 98baae1..b8dcbd1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -104,7 +104,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { LOGE("## getAccountInstanceId() ERROR! aJniEnv=NULL"); } - LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId); + LOGD("## getAccountInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); return instanceId; } -- cgit v1.2.3 From 09fd7246eacddc0f9fe43f614dd59596c6944dbc Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 20 Oct 2016 17:36:53 +0200 Subject: Format update --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 2bda36c..6248d34 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -141,17 +141,17 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j // free alloc if(NULL != signaturePtr) { - env->ReleaseStringUTFChars(aSignature, signaturePtr); + env->ReleaseStringUTFChars(aSignature, signaturePtr); } if(NULL != keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseStringUTFChars(aKey, keyPtr); } if(NULL != messagePtr) { - env->ReleaseStringUTFChars(aMessage, messagePtr); + env->ReleaseStringUTFChars(aMessage, messagePtr); } return errorMessageRetValue; -- cgit v1.2.3 From 50bf60499ab6b2147d42fc3943eea173de64a601 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 20 Oct 2016 17:39:09 +0200 Subject: Update verifyEd25519Signature() to fix error message processing --- .../olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index a6e9c4f..2843f0f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -78,20 +78,20 @@ public class OlmUtility implements Serializable { */ public boolean verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage, StringBuffer aError) { boolean retCode = false; - String errorRetValue = null; + String jniError; - if(null == aError) { + if (null == aError) { Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input error parameter"); - } - else if(TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)){ - Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); } else { aError.setLength(0); - if( null == (errorRetValue = verifyEd25519SignatureJni(aSignature,aFingerprintKey, aMessage))) { + if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); + aError.append("JAVA sanity check failure - invalid input parameters"); + } else if (null == (jniError = verifyEd25519SignatureJni(aSignature, aFingerprintKey, aMessage))) { retCode = true; } else { - aError.append(errorRetValue); + aError.append(jniError); } } -- cgit v1.2.3 From 8b050e5e1e10794fa92ca574c8f562830d15dd68 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 20 Oct 2016 17:40:20 +0200 Subject: Local variable renaming --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 188fe19..22316cb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -571,7 +571,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) { jstring decryptedMsgRetValue = 0; - jclass encryptedMsgJclass = 0; + jclass encryptedMsgJClass = 0; jstring encryptedMsgJstring = 0; // <= obtained from encryptedMsgFieldId // field IDs jfieldID encryptedMsgFieldId; @@ -592,15 +592,15 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t { LOGE("## decryptMessageJni(): failure - invalid encrypted message"); } - else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg))) + else if(0 == (encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) { LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); } - else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;"))) + else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) { LOGE("## decryptMessageJni(): failure - unable to get message field"); } - else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","J"))) + else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) { LOGE("## decryptMessageJni(): failure - unable to get message type field"); } -- cgit v1.2.3 From 1511962df194b9b414b3629b37b6fd3a42081295 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 20 Oct 2016 17:42:57 +0200 Subject: Add serialization feature to OlmAccount - new JNI API: serializeDataWithKeyJni() and initWithSerializedDataJni() - update account unit test - modify OlmAccount constructor API: an exception may be thrown --- .../java/org/matrix/olm/OlmAccountTest.java | 41 +++-- .../java/org/matrix/olm/OlmSessionTest.java | 32 +++- .../java/org/matrix/olm/OlmUtilityTest.java | 7 +- .../src/main/java/org/matrix/olm/OlmAccount.java | 72 ++++---- .../src/main/java/org/matrix/olm/OlmException.java | 2 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 183 ++++++++++++++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 5 + 7 files changed, 291 insertions(+), 51 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 19b8b63..385fc0a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -42,6 +42,7 @@ public class OlmAccountTest { private static OlmAccount mOlmAccount; private static OlmManager mOlmManager; private boolean mIsAccountCreated; + final String FILE_NAME = "SerialTestFile"; @BeforeClass public static void setUpClass(){ @@ -72,7 +73,11 @@ public class OlmAccountTest { @Test public void test01CreateReleaseAccount() { - mOlmAccount = new OlmAccount(); + try { + mOlmAccount = new OlmAccount(); + } catch (OlmException e) { + e.printStackTrace(); + } assertNotNull(mOlmAccount); mOlmAccount.releaseAccount(); @@ -81,7 +86,11 @@ public class OlmAccountTest { @Test public void test02CreateAccount() { - mOlmAccount = new OlmAccount(); + try { + mOlmAccount = new OlmAccount(); + } catch (OlmException e) { + e.printStackTrace(); + } assertNotNull(mOlmAccount); mIsAccountCreated = true; } @@ -198,16 +207,21 @@ public class OlmAccountTest { public void test13Serialization() { FileOutputStream fileOutput = null; ObjectOutputStream objectOutput = null; - OlmAccount accountRef = new OlmAccount(); + OlmAccount accountRef = null; OlmAccount accountDeserial = null; - OlmException exception; + + try { + accountRef = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } int retValue = accountRef.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); assertTrue(0==retValue); + // get keys references JSONObject identityKeysRef = accountRef.identityKeys(); JSONObject oneTimeKeysRef = accountRef.oneTimeKeys(); - final String FILE_NAME = "testfile"; /*Context context = getInstrumentation().getContext(); SharedPreferences sharedPref = context.getSharedPreferences("TestPref",Context.MODE_PRIVATE); @@ -217,16 +231,15 @@ public class OlmAccountTest { try { Context context = getInstrumentation().getContext(); context.getFilesDir(); - //File serialFile = new File(FILE_NAME); - //fileOutput = new FileOutputStream(serialFile); fileOutput = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); + // serialize objectOutput = new ObjectOutputStream(fileOutput); objectOutput.writeObject(accountRef); objectOutput.flush(); objectOutput.close(); - //FileInputStream fileInput = new FileInputStream(serialFile); + // deserialize FileInputStream fileInput = context.openFileInput(FILE_NAME); ObjectInputStream objectInput = new ObjectInputStream(fileInput); accountDeserial = (OlmAccount) objectInput.readObject(); @@ -234,14 +247,20 @@ public class OlmAccountTest { assertNotNull(accountDeserial); + // get de-serialized keys JSONObject identityKeys2 = accountDeserial.identityKeys(); + assertNotNull(identityKeys2); JSONObject oneTimeKeys2 = accountDeserial.oneTimeKeys(); - assertEquals(identityKeysRef, identityKeys2); - assertEquals(oneTimeKeysRef, oneTimeKeys2); + assertNotNull(oneTimeKeys2); + + // compare identity keys + assertTrue(identityKeys2.toString().equals(identityKeysRef.toString())); + + // compare onetime keys + assertTrue(oneTimeKeys2.toString().equals(oneTimeKeysRef.toString())); accountRef.releaseAccount(); accountDeserial.releaseAccount(); - } catch (FileNotFoundException e) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 311d6a8..4d7c5b0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -47,10 +47,16 @@ public class OlmSessionTest { final int ONE_TIME_KEYS_NUMBER = 5; String bobIdentityKey = null; String bobOneTimeKey=null; - + OlmAccount bobAccount = null; + OlmAccount aliceAccount = null; // creates alice & bob accounts - OlmAccount aliceAccount = new OlmAccount(); - OlmAccount bobAccount = new OlmAccount(); + + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } // test accounts creation assertTrue(0!=bobAccount.getOlmAccountId()); @@ -132,10 +138,16 @@ public class OlmSessionTest { final int ONE_TIME_KEYS_NUMBER = 1; String bobIdentityKey = null; String bobOneTimeKey=null; + OlmAccount aliceAccount = null; + OlmAccount bobAccount = null; // creates alice & bob accounts - OlmAccount aliceAccount = new OlmAccount(); - OlmAccount bobAccount = new OlmAccount(); + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } // test accounts creation assertTrue(0!=bobAccount.getOlmAccountId()); @@ -226,8 +238,14 @@ public class OlmSessionTest { @Test public void test03AliceBobSessionId() { // creates alice & bob accounts - OlmAccount aliceAccount = new OlmAccount(); - OlmAccount bobAccount = new OlmAccount(); + OlmAccount aliceAccount = null; + OlmAccount bobAccount = null; + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } // test accounts creation assertTrue(0!=bobAccount.getOlmAccountId()); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index b500cdf..030bea7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -47,9 +47,14 @@ public class OlmUtilityTest { String fingerPrintKey = null; StringBuffer errorMsg = new StringBuffer(); String message = "{\"key1\":\"value1\",\"key2\":\"value2\"};"; + OlmAccount account = null; // create account - OlmAccount account = new OlmAccount(); + try { + account = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } assertNotNull(account); // sign message diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 5b2418a..61b6c52 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -26,17 +26,13 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.math.BigInteger; -import java.security.SecureRandom; -import java.util.Arrays; import java.util.Random; public class OlmAccount implements Serializable { private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; - private static final int MAX_BITS_LENGTH = 128; - private static final int RANDOM_TAB_SIZE = 32; - private static final int RANDOM_MAX = 256; + private static final int RANDOM_KEY_SIZE = 32; + private static final int RANDOM_RANGE = 256; // JSON keys used in the JSON objects returned by JNI /** As well as the identity key, each device creates a number of Curve25519 key pairs which are @@ -60,24 +56,22 @@ public class OlmAccount implements Serializable { */ private transient long mNativeOlmAccountId; - private transient SecureRandom mSecureRandom; - public OlmAccount() { - initNewAccount(); - mSecureRandom = new SecureRandom(); + public OlmAccount() throws OlmException { + if(!initNewAccount()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); + } } private String getRandomKey() { - //String keyRetValue = new BigInteger(MAX_BITS_LENGTH, mSecureRandom).toString(RANDOM_TAB_SIZE); String keyRetValue; Random rand = new Random(); - StringBuilder strBuilder = new StringBuilder(); - for(int i=0;i + * Public API for {@link #releaseAccountJni()}. + */ + public void releaseAccount(){ + releaseAccountJni(); + + mNativeOlmAccountId = 0; + } + /** * Destroy the corresponding OLM account native object.
* This method must ALWAYS be called when this JAVA instance @@ -199,36 +203,48 @@ public class OlmAccount implements Serializable { private native void releaseAccountJni(); /** - * Release native account and invalid its JAVA reference counter part.
- * Public API for {@link #releaseAccountJni()}. + * Create and initialize a native account instance.
+ * Wrapper for {@link #initNewAccountJni()}. + * To be called before any other API call. + * @return true if init succeed, false otherwise. */ - public void releaseAccount(){ - releaseAccountJni(); - - mNativeOlmAccountId = 0; + private boolean initNewAccount() { + boolean retCode = false; + if(0 != (mNativeOlmAccountId = initNewAccountJni())){ + retCode = true; + } + return retCode; } /** - * Create the corresponding OLM account in native side.
+ * Create and initialize an OLM account in native side.
* Do not forget to call {@link #releaseAccount()} when JAVA side is done. * @return native account instance identifier (see {@link #mNativeOlmAccountId}) */ private native long initNewAccountJni(); /** - * Create and initialize a new native account instance.
- * Wrapper for {@link #initNewAccountJni()}. - * To be called before any other API call. + * Create a native account instance without any initialization.
+ * Since the account is left uninitialized, this + * method is intended to be used in the serialization mechanism (see {@link #readObject(ObjectInputStream)}).
+ * Public wrapper for {@link #createNewAccountJni()}. * @return true if init succeed, false otherwise. */ - private boolean initNewAccount() { + private boolean createNewAccount() { boolean retCode = false; - if(0 != (mNativeOlmAccountId = initNewAccountJni())){ + if(0 != (mNativeOlmAccountId = createNewAccountJni())){ retCode = true; } return retCode; } + /** + * Create an OLM account in native side.
+ * Do not forget to call {@link #releaseAccount()} when JAVA side is done. + * @return native account instance identifier (see {@link #mNativeOlmAccountId}) + */ + private native long createNewAccountJni(); + /** * Return the identity keys (identity & fingerprint keys) in a JSON array.
* Public API for {@link #identityKeysJni()}.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 97589f0..b83e77c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -29,6 +29,7 @@ public class OlmException extends Exception { public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 5; public static final int EXCEPTION_CODE_SESSION_SERIALIZATION = 6; public static final int EXCEPTION_CODE_SESSION_DESERIALIZATION = 7; + public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 8; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; @@ -38,6 +39,7 @@ public class OlmException extends Exception { public static final String EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION = "initNewAccount() failure"; public static final String EXCEPTION_MSG_INIT_ACCOUNT_DESERIALIZATION = "initWithSerializedData() failure"; public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid deserialized parameters"; + public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "Account constructor failure"; /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION} * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}**/ diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index a10b8e0..6f2e6ee 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -40,6 +40,17 @@ OlmAccount* initializeAccountMemory() return accountPtr; } + +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## createNewAccountJni(): IN"); + OlmAccount* accountPtr = initializeAccountMemory(); + + LOGD(" ## createNewAccountJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); + return (jlong)(intptr_t)accountPtr; +} + + /** * Release the account allocation made by initializeAccountMemory().
* This method MUST be called when java counter part account instance is done. @@ -49,20 +60,21 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz { OlmAccount* accountPtr = NULL; - LOGD("## releaseAccountJni(): accountPtr=%p",accountPtr); + LOGD("## releaseAccountJni(): IN"); if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE("## releaseAccountJni(): failure - invalid Account ptr=NULL"); + LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); } else { + LOGD(" ## releaseAccountJni(): accountPtr=%p",accountPtr); olm_clear_account(accountPtr); - LOGD("## releaseAccountJni(): IN"); + LOGD(" ## releaseAccountJni(): IN"); // even if free(NULL) does not crash, logs are performed for debug purpose free(accountPtr); - LOGD("## releaseAccountJni(): OUT"); + LOGD(" ## releaseAccountJni(): OUT"); } } @@ -467,4 +479,167 @@ JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv* env, jobject th return returnValueStr; } +/** +* Serialize and encrypt account instance into a base64 string.
+* @param aKey key used to encrypt the serialized account data +* @param[out] aErrorMsg error message set if operation failed +* @return a base64 string if operation succeed, null otherwise +**/ +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +{ + jstring pickledDataRetValue = 0; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *keyPtr = NULL; + void *pickledPtr = NULL; + OlmAccount* accountPtr = NULL; + + LOGD("## serializeDataWithKeyJni(): IN"); + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); + } + else if(0 == aKey) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + } + else if(0 == aErrorMsg) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = olm_pickle_account_length(accountPtr); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + + if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + } + else + { + size_t result = olm_pickle_account(accountPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } + } + else + { + // build success output + (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + } + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + free(pickledPtr); + } + + return pickledDataRetValue; +} + + +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +{ + OlmAccount* accountPtr = NULL; + jstring errorMessageRetValue = 0; + const char *keyPtr = NULL; + const char *pickledPtr = NULL; + + LOGD("## initWithSerializedDataJni(): IN"); + + if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + //if(NULL == (accountPtr = initializeAccountMemory())) + { + LOGE(" ## initWithSerializedDataJni(): failure - account failure OOM"); + } + else if(0 == aKey) + { + LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + } + else if(0 == aSerializedData) + { + LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + } + else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); + LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + + size_t result = olm_unpickle_account(accountPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_account_last_error(accountPtr); + LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); + errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + } + else + { + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + } + + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + } + return errorMessageRetValue; +} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 63ec3ef..1c8fb96 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -32,6 +32,7 @@ JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv *env, jobject th // account creation/destruction JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz); // identity keys JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz); @@ -46,6 +47,10 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, // signing JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage); +// serialization +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); + #ifdef __cplusplus } #endif -- cgit v1.2.3 From fb87d8feee14b36a76d8022e2b742a6c1d65d0f0 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 21 Oct 2016 18:09:20 +0200 Subject: Serialization for OlmAccount and OlmSession OK --- .../java/org/matrix/olm/OlmAccountTest.java | 17 +- .../java/org/matrix/olm/OlmGroupSessionTest.java | 72 +++++++ .../java/org/matrix/olm/OlmSessionTest.java | 221 ++++++++++++++++++++- .../src/main/java/org/matrix/olm/OlmAccount.java | 35 ++-- .../src/main/java/org/matrix/olm/OlmException.java | 2 + .../src/main/java/org/matrix/olm/OlmSession.java | 174 +++++++++++++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 15 ++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 14 ++ .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 95 +++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 176 +++++++++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 5 + 11 files changed, 760 insertions(+), 66 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 385fc0a..6c1cbf3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -42,7 +42,7 @@ public class OlmAccountTest { private static OlmAccount mOlmAccount; private static OlmManager mOlmManager; private boolean mIsAccountCreated; - final String FILE_NAME = "SerialTestFile"; + private final String FILE_NAME = "SerialTestFile"; @BeforeClass public static void setUpClass(){ @@ -170,7 +170,12 @@ public class OlmAccountTest { @Test public void test10RemoveOneTimeKeysForSession() { - OlmSession olmSession = new OlmSession(); + OlmSession olmSession = null; + try { + olmSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } long sessionId = olmSession.getOlmSessionId(); assertTrue(0 != sessionId); @@ -230,16 +235,16 @@ public class OlmAccountTest { try { Context context = getInstrumentation().getContext(); - context.getFilesDir(); + //context.getFilesDir(); fileOutput = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); - // serialize + // serialize account objectOutput = new ObjectOutputStream(fileOutput); objectOutput.writeObject(accountRef); objectOutput.flush(); objectOutput.close(); - // deserialize + // deserialize account FileInputStream fileInput = context.openFileInput(FILE_NAME); ObjectInputStream objectInput = new ObjectInputStream(fileInput); accountDeserial = (OlmAccount) objectInput.readObject(); @@ -262,7 +267,6 @@ public class OlmAccountTest { accountRef.releaseAccount(); accountDeserial.releaseAccount(); } - catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test13Serialization(): Exception FileNotFoundException Msg=="+e.getMessage()); } @@ -278,7 +282,6 @@ public class OlmAccountTest { catch (Exception e) { Log.e(LOG_TAG, "## test13Serialization(): Exception Msg==" + e.getMessage()); } - } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index fc3c1f0..e488ae0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -1,5 +1,6 @@ package org.matrix.olm; +import android.content.Context; import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import android.util.Log; @@ -11,6 +12,14 @@ import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -19,6 +28,7 @@ import static org.junit.Assert.assertTrue; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class OlmGroupSessionTest { private static final String LOG_TAG = "OlmSessionTest"; + private final String FILE_NAME_SERIAL_SESSION = "SerialGroupSession"; private static OlmManager mOlmManager; private static OlmOutboundGroupSession mAliceOutboundGroupSession; @@ -141,4 +151,66 @@ public class OlmGroupSessionTest { // release group sessions mBobInboundGroupSession.releaseSession(); } + + + @Test + public void test14SerializeOutboundSession() { + OlmOutboundGroupSession outboundGroupSessionRef=null; + OlmOutboundGroupSession outboundGroupSessionSerial=null; + + // alice creates OUTBOUND GROUP SESSION + try { + outboundGroupSessionRef = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + + assertNotNull(outboundGroupSessionRef); + + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(outboundGroupSessionRef); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject(); + objectInput.close(); + + // get sessions IDs + String sessionKeyRef = outboundGroupSessionRef.sessionKey(); + String sessionKeySerial = outboundGroupSessionSerial.sessionKey(); + + // session ID sanity check + assertFalse(TextUtils.isEmpty(sessionKeyRef)); + assertFalse(TextUtils.isEmpty(sessionKeySerial)); + + // session IDs comparison + assertTrue(sessionKeyRef.equals(sessionKeySerial)); + } + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + } + + } + + } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 4d7c5b0..8fd2744 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -1,5 +1,6 @@ package org.matrix.olm; +import android.content.Context; import android.support.test.runner.AndroidJUnit4; import android.util.Log; @@ -11,8 +12,15 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Iterator; +import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -20,6 +28,7 @@ import static org.junit.Assert.assertTrue; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class OlmSessionTest { private static final String LOG_TAG = "OlmSessionTest"; + private final String FILE_NAME_SERIAL_SESSION = "SerialSession"; private static OlmManager mOlmManager; @@ -86,11 +95,16 @@ public class OlmSessionTest { } assertNotNull(bobOneTimeKey); } catch (JSONException e) { - assertTrue("Exception MSg="+e.getMessage(), false); + assertTrue("Exception Msg="+e.getMessage(), false); } // CREATE ALICE SESSION - OlmSession aliceSession = new OlmSession(); + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob @@ -101,7 +115,12 @@ public class OlmSessionTest { Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText); // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = new OlmSession(); + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=bobSession.getOlmSessionId()); assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); @@ -173,6 +192,7 @@ public class OlmSessionTest { Iterator generatedKeysIt = generatedKeys.keys(); if(generatedKeysIt.hasNext()) { + // return first otk bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); } assertNotNull(bobOneTimeKey); @@ -181,7 +201,12 @@ public class OlmSessionTest { } // CREATE ALICE SESSION - OlmSession aliceSession = new OlmSession(); + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob @@ -192,7 +217,12 @@ public class OlmSessionTest { assertNotNull(encryptedAliceToBobMsg1); // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = new OlmSession(); + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=bobSession.getOlmSessionId()); assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); @@ -210,6 +240,7 @@ public class OlmSessionTest { String clearMsg2 = "Isn't life grand?"; String clearMsg3 = "Let's go to the opera."; + // bob encrypts messages OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); assertNotNull(encryptedMsg1); OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); @@ -217,6 +248,7 @@ public class OlmSessionTest { OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); assertNotNull(encryptedMsg3); + // alice decrypts bob's messages String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); assertNotNull(decryptedMsg1); String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); @@ -224,6 +256,7 @@ public class OlmSessionTest { String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); assertNotNull(decryptedMsg3); + // comparison tests assertTrue(clearMsg1.equals(decryptedMsg1)); assertTrue(clearMsg2.equals(decryptedMsg2)); assertTrue(clearMsg3.equals(decryptedMsg3)); @@ -235,6 +268,7 @@ public class OlmSessionTest { aliceSession.releaseSession(); } + @Test public void test03AliceBobSessionId() { // creates alice & bob accounts @@ -252,11 +286,22 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // CREATE ALICE SESSION - OlmSession aliceSession = new OlmSession(); + + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=aliceSession.getOlmSessionId()); - // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = new OlmSession(); + // CREATE ALICE SESSION + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + e.printStackTrace(); + } assertTrue(0!=bobSession.getOlmSessionId()); String aliceSessionId = aliceSession.sessionIdentifier(); @@ -268,4 +313,164 @@ public class OlmSessionTest { // must be the same for both ends of the conversation assertTrue(aliceSessionId.equals(bobSessionId)); } + + // ******************************************************** + // ************* SERIALIZATION TEST *********************** + // ******************************************************** + /** + * Same as test02AliceToBobBackAndForth() but alice's session + * is serialized and de-serialized before performing the final + * comparison (encrypt vs ) + */ + @Test + public void test03SessionSerialization() { + final int ONE_TIME_KEYS_NUMBER = 1; + String bobIdentityKey = null; + String bobOneTimeKey=null; + OlmAccount aliceAccount = null; + OlmAccount bobAccount = null; + OlmSession aliceSessionDeserial; + + // creates alice & bob accounts + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // get bob identity key + JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); + assertNotNull(bobIdentityKeysJson); + try { + bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); + assertTrue(null!=bobIdentityKey); + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // get bob one time keys + assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); + JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); + assertNotNull(bobOneTimeKeysJsonObj); + try { + JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys); + + Iterator generatedKeysIt = generatedKeys.keys(); + if(generatedKeysIt.hasNext()) { + // return first otk + bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); + } + assertNotNull(bobOneTimeKey); + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // CREATE ALICE SESSION + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE ALICE OUTBOUND SESSION and encrypt message to bob + assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + String helloClearMsg = "Hello I'm Alice!"; + + OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + assertNotNull(encryptedAliceToBobMsg1); + + // CREATE BOB INBOUND SESSION and decrypt message from alice + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=bobSession.getOlmSessionId()); + assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + + // DECRYPT MESSAGE FROM ALICE + String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + assertNotNull(decryptedMsg01); + + // MESSAGE COMPARISON: decrypted vs encrypted + assertTrue(helloClearMsg.equals(decryptedMsg01)); + + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + + // BACK/FORTH MESSAGE COMPARISON + String clearMsg1 = "Hello I'm Bob!"; + String clearMsg2 = "Isn't life grand?"; + String clearMsg3 = "Let's go to the opera."; + + // bob encrypts messages + OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + assertNotNull(encryptedMsg1); + OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + assertNotNull(encryptedMsg2); + OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + assertNotNull(encryptedMsg3); + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(aliceSession); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + aliceSessionDeserial = (OlmSession) objectInput.readObject(); + objectInput.close(); + + // test deserialize return value + assertNotNull(aliceSessionDeserial); + + // de-serialized alice session decrypts bob's messages + String decryptedMsg1 = aliceSessionDeserial.decryptMessage(encryptedMsg1); + assertNotNull(decryptedMsg1); + String decryptedMsg2 = aliceSessionDeserial.decryptMessage(encryptedMsg2); + assertNotNull(decryptedMsg2); + String decryptedMsg3 = aliceSessionDeserial.decryptMessage(encryptedMsg3); + assertNotNull(decryptedMsg3); + + // comparison tests + assertTrue(clearMsg1.equals(decryptedMsg1)); + assertTrue(clearMsg2.equals(decryptedMsg2)); + assertTrue(clearMsg3.equals(decryptedMsg3)); + + // clean objects.. + bobAccount.releaseAccount(); + aliceAccount.releaseAccount(); + bobSession.releaseSession(); + aliceSession.releaseSession(); + aliceSessionDeserial.releaseSession(); + } + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + } + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 61b6c52..8d19a0c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -31,8 +31,6 @@ import java.util.Random; public class OlmAccount implements Serializable { private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; - private static final int RANDOM_KEY_SIZE = 32; - private static final int RANDOM_RANGE = 256; // JSON keys used in the JSON objects returned by JNI /** As well as the identity key, each device creates a number of Curve25519 key pairs which are @@ -63,24 +61,17 @@ public class OlmAccount implements Serializable { } } - private String getRandomKey() { - String keyRetValue; - Random rand = new Random(); - StringBuilder strBuilder = new StringBuilder(); - - for(int i = 0; i< OlmAccount.RANDOM_KEY_SIZE; i++) { - strBuilder.append(rand.nextInt(RANDOM_RANGE)); - } - keyRetValue = strBuilder.toString(); - - return keyRetValue; - } - + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException + * @throws OlmException + */ private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { aOutStream.defaultWriteObject(); // generate serialization key - String key = getRandomKey(); + String key = OlmUtility.getRandomKey(); // compute pickle string StringBuffer errorMsg = new StringBuffer(); @@ -94,6 +85,13 @@ public class OlmAccount implements Serializable { } } + /** + * Kick off the deserialization mechanism. + * @param aInStream + * @throws IOException + * @throws ClassNotFoundException + * @throws OlmException + */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { aInStream.defaultReadObject(); StringBuffer errorMsg = new StringBuffer(); @@ -379,9 +377,4 @@ public class OlmAccount implements Serializable { return signMessageJni(aMessage); } private native String signMessageJni(String aMessage); - - // TODO missing API: initWithSerializedData - // TODO missing API: serializeDataWithKey - // TODO missing API: initWithCoder - // TODO missing API: encodeWithCoder } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index b83e77c..280dce1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -30,6 +30,7 @@ public class OlmException extends Exception { public static final int EXCEPTION_CODE_SESSION_SERIALIZATION = 6; public static final int EXCEPTION_CODE_SESSION_DESERIALIZATION = 7; public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 8; + public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 9; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; @@ -40,6 +41,7 @@ public class OlmException extends Exception { public static final String EXCEPTION_MSG_INIT_ACCOUNT_DESERIALIZATION = "initWithSerializedData() failure"; public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid deserialized parameters"; public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "Account constructor failure"; + public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "Session constructor failure"; /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION} * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}**/ diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 8574f95..ca74352 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -19,37 +19,146 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; public class OlmSession implements Serializable { + private static final long serialVersionUID = -8975488639186976419L; private static final String LOG_TAG = "OlmSession"; /** session raw pointer value (OlmSession*) returned by JNI. * this value uniquely identifies the native session instance. **/ - private long mNativeOlmSessionId; + private transient long mNativeOlmSessionId; - /** account instance associated with this session. **/ - private OlmAccount mOlmAccount; - public OlmSession() { - initNewSession(); + public OlmSession() throws OlmException { + if(!initNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, OlmException.EXCEPTION_MSG_INIT_SESSION_CREATION); + } } /** - * Getter on the session ID. - * @return native session ID + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException + * @throws OlmException */ - public long getOlmSessionId(){ - return mNativeOlmSessionId; + private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + aOutStream.defaultWriteObject(); + + // generate serialization key + String key = OlmUtility.getRandomKey(); + + // compute pickle string + StringBuffer errorMsg = new StringBuffer(); + String pickledData = serializeDataWithKey(key, errorMsg); + + if(null == pickledData) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SERIALIZATION, String.valueOf(errorMsg)); + } else { + aOutStream.writeObject(key); + aOutStream.writeObject(pickledData); + } } + /** + * Kick off the deserialization mechanism. + * @param aInStream + * @throws IOException + * @throws ClassNotFoundException + * @throws OlmException + */ + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + aInStream.defaultReadObject(); + StringBuffer errorMsg = new StringBuffer(); + + String key = (String) aInStream.readObject(); + String pickledData = (String) aInStream.readObject(); + + if(TextUtils.isEmpty(key)) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); + + } else if(TextUtils.isEmpty(pickledData)) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); + + } else if(!createNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + + } else if(!initWithSerializedData(pickledData, key, errorMsg)) { + releaseSession(); // prevent memory leak + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, String.valueOf(errorMsg)); + + } else { + Log.d(LOG_TAG,"## readObject(): success"); + } + } + + /** + * Return an account as a base64 string.
+ * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + } + + return pickleRetValue; + } + private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serializeDataWithKey(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + * @param aErrorMsg error message description + * @return true if operation succeed, false otherwise + */ + private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + boolean retCode = false; + String jniError; + + if(null == aErrorMsg) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); + } else { + aErrorMsg.setLength(0); + + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } + + return retCode; + } + private native String initWithSerializedDataJni(String aSerializedData, String aKey); + /** * Getter on the session ID. * @return native session ID */ - public OlmAccount getOlmAccountId(){ - return mOlmAccount; + public long getOlmSessionId(){ + return mNativeOlmSessionId; } /** @@ -92,6 +201,29 @@ public class OlmSession implements Serializable { private native long initNewSessionJni(); + /** + * Create a native account instance without any initialization.
+ * Since the account is left uninitialized, this + * method is intended to be used in the serialization mechanism (see {@link #readObject(ObjectInputStream)}).
+ * Public wrapper for {@link #createNewSessionJni()}. + * @return true if init succeed, false otherwise. + */ + private boolean createNewSession() { + boolean retCode = false; + if(0 != (mNativeOlmSessionId = createNewSessionJni())){ + retCode = true; + } + return retCode; + } + + /** + * Create an OLM account in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native account instance identifier (see {@link #mNativeOlmSessionId}) + */ + private native long createNewSessionJni(); + + /** * Creates a new out-bound session for sending messages to a recipient * identified by an identity key and a one time key.
@@ -107,10 +239,7 @@ public class OlmSession implements Serializable { if((null==aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)){ Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); } else { - // set the account of this session - mOlmAccount = aAccount; - - if(0 == initOutboundSessionJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey)) { + if(0 == initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey)) { retObj = this; } } @@ -136,10 +265,7 @@ public class OlmSession implements Serializable { if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - // set the account of this session - mOlmAccount = aAccount; - - if( 0 == initInboundSessionJni(mOlmAccount.getOlmAccountId(), aPreKeyMsg)) { + if( 0 == initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg)) { retObj = this; } } @@ -168,10 +294,7 @@ public class OlmSession implements Serializable { if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - // set the account of this session - mOlmAccount = aAccount; - - if(0 == initInboundSessionFromIdKeyJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg)){ + if(0 == initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg)){ retObj = this; } } @@ -265,10 +388,5 @@ public class OlmSession implements Serializable { } private native String decryptMessageJni(OlmMessage aEncryptedMsg); - - // TODO missing API: initWithSerializedData - // TODO missing API: serializeDataWithKey - // TODO missing API: initWithCoder - // TODO missing API: encodeWithCoder } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 6f2e6ee..fd3a977 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -18,6 +18,13 @@ using namespace AndroidOlmSdk; +/*jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr aGetLengthFunc, + olmPickleFuncPtr aGetPickleFunc, + olmLastErrorFuncPtr aGetLastErrorFunc);*/ + /** * Init memory allocation for account creation. * @return valid memory allocation, NULL otherwise @@ -487,6 +494,14 @@ JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv* env, jobject th **/ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) { + /*jstring pickledDataRetValue = serializeDataWithKey(env,thiz, + aKey, + aErrorMsg, + olm_pickle_account_length, + olm_pickle_account, + olm_account_last_error); + return pickledDataRetValue;*/ + jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 70267ff..2e31bff 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -55,6 +55,20 @@ namespace AndroidOlmSdk static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; } + +// function pointer templates +template using olmPickleLengthFuncPtr = size_t (*)(T); +template using olmPickleFuncPtr = size_t (*)(T, void const *, size_t, void *, size_t); +template using olmLastErrorFuncPtr = const char* (*)(T); + +template +jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr aGetLengthFunc, + olmPickleFuncPtr aGetPickleFunc, + olmLastErrorFuncPtr aGetLastErrorFunc); + #ifdef __cplusplus extern "C" { #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index b8dcbd1..174739c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -18,6 +18,7 @@ */ #include "olm_jni_helper.h" +#include "olm/olm.h" using namespace AndroidOlmSdk; @@ -288,3 +289,97 @@ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) return instanceId; } + +template +jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr aGetLengthFunc, + olmPickleFuncPtr aGetPickleFunc, + olmLastErrorFuncPtr aGetLastErrorFunc) +{ + jstring pickledDataRetValue = 0; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *keyPtr = NULL; + void *pickledPtr = NULL; + T accountPtr = NULL; + + LOGD("## serializeDataWithKeyJni(): IN"); + + if(NULL == (accountPtr = (T)getAccountInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); + } + else if(0 == aKey) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + } + else if(0 == aErrorMsg) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = aGetLengthFunc(accountPtr); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + + if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + } + else + { + size_t result = aGetPickleFunc(accountPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = aGetLastErrorFunc(accountPtr); + LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } + } + else + { + // build success output + (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + } + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + free(pickledPtr); + } + + return pickledDataRetValue; +} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 22316cb..3422fee 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -41,6 +41,16 @@ OlmSession* initializeSessionMemory() return sessionPtr; } + +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## createNewSessionJni(): IN"); + OlmSession* accountPtr = initializeSessionMemory(); + + LOGD(" ## createNewSessionJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); + return (jlong)(intptr_t)accountPtr; +} + JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { OlmSession* sessionPtr = NULL; @@ -687,8 +697,6 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } - - /** * Get the session identifier for this session. * @return the session identifier if operation succeed, null otherwise @@ -739,3 +747,167 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job return returnValueStr; } + +/** +* Serialize and encrypt session instance into a base64 string.
+* @param aKey key used to encrypt the serialized session data +* @param[out] aErrorMsg error message set if operation failed +* @return a base64 string if operation succeed, null otherwise +**/ +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +{ + jstring pickledDataRetValue = 0; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *keyPtr = NULL; + void *pickledPtr = NULL; + OlmSession* sessionPtr = NULL; + + LOGD("## serializeDataWithKeyJni(): IN"); + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); + } + else if(0 == aKey) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + } + else if(0 == aErrorMsg) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = olm_pickle_session_length(sessionPtr); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + + if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + } + else + { + size_t result = olm_pickle_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } + } + else + { + // build success output + (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + } + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + free(pickledPtr); + } + + return pickledDataRetValue; +} + + +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +{ + OlmSession* sessionPtr = NULL; + jstring errorMessageRetValue = 0; + const char *keyPtr = NULL; + const char *pickledPtr = NULL; + + LOGD("## initWithSerializedDataJni(): IN"); + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); + } + else if(0 == aKey) + { + LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + } + else if(0 == aSerializedData) + { + LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + } + else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); + LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + + size_t result = olm_unpickle_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); + errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + } + else + { + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + } + + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + } + + return errorMessageRetValue; +} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index f79dcaa..a08b775 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -29,6 +29,7 @@ extern "C" { // session creation/destruction JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); // outbound session JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey); @@ -47,6 +48,10 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); +// serialization +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); + #ifdef __cplusplus } #endif -- cgit v1.2.3 From 700b02589ce61b90fb3ee4c9d0a98f7ca195a6bb Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 21 Oct 2016 19:00:46 +0200 Subject: Add getRandomKey() --- .../src/main/java/org/matrix/olm/OlmUtility.java | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 2843f0f..342d8eb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -20,10 +20,14 @@ import android.text.TextUtils; import android.util.Log; import java.io.Serializable; +import java.util.Random; -public class OlmUtility implements Serializable { +public class OlmUtility { private static final String LOG_TAG = "OlmUtility"; + public static final int RANDOM_KEY_SIZE = 32; + public static final int RANDOM_RANGE = 256; + /** raw pointer value returned by JNI. * this value uniquely identifies this utility instance. **/ @@ -128,9 +132,17 @@ public class OlmUtility implements Serializable { private native String sha256Jni(String aMessage); - // TODO missing API: initWithSerializedData - // TODO missing API: serializeDataWithKey - // TODO missing API: initWithCoder - // TODO missing API: encodeWithCoder + public static String getRandomKey() { + String keyRetValue; + Random rand = new Random(); + StringBuilder strBuilder = new StringBuilder(); + + for(int i = 0; i< RANDOM_KEY_SIZE; i++) { + strBuilder.append(rand.nextInt(RANDOM_RANGE)); + } + keyRetValue = strBuilder.toString(); + + return keyRetValue; + } } -- cgit v1.2.3 From 71f57b79e57ca668c4621e1cecf5742f428c5cde Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 21 Oct 2016 19:03:18 +0200 Subject: Update android platform to 16 --- java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk index 72a8175..adff86a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk @@ -1,3 +1,3 @@ -APP_PLATFORM := android-21 -APP_ABI := arm64-v8a armeabi-v7a armeabi x86 x86_64 +APP_PLATFORM := android-16 +APP_ABI := arm64-v8a armeabi-v7a x86 x86_64 armeabi APP_STL := gnustl_static \ No newline at end of file -- cgit v1.2.3 From fae857582c445ce89f527f6331aeac4eb66bc692 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 21 Oct 2016 19:05:20 +0200 Subject: Add serialization for outbound group session --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 17 ++- .../src/main/java/org/matrix/olm/OlmException.java | 4 +- .../org/matrix/olm/OlmInboundGroupSession.java | 2 +- .../src/main/java/org/matrix/olm/OlmManager.java | 11 +- .../org/matrix/olm/OlmOutboundGroupSession.java | 123 +++++++++++++++- .../src/main/java/org/matrix/olm/OlmSession.java | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 3 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 1 - .../src/main/jni/olm_outbound_group_session.cpp | 162 +++++++++++++++++++++ .../src/main/jni/olm_outbound_group_session.h | 3 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 1 - 11 files changed, 318 insertions(+), 13 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index e488ae0..d49ebd4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -183,16 +183,27 @@ public class OlmGroupSessionTest { outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject(); objectInput.close(); - // get sessions IDs + // get sessions keys String sessionKeyRef = outboundGroupSessionRef.sessionKey(); String sessionKeySerial = outboundGroupSessionSerial.sessionKey(); - // session ID sanity check + // session keys sanity check assertFalse(TextUtils.isEmpty(sessionKeyRef)); assertFalse(TextUtils.isEmpty(sessionKeySerial)); - // session IDs comparison + // session keys comparison assertTrue(sessionKeyRef.equals(sessionKeySerial)); + + // get sessions IDs + String sessionIdRef = outboundGroupSessionRef.sessionIdentifier(); + String sessionIdSerial = outboundGroupSessionSerial.sessionIdentifier(); + + // session ID sanity check + assertFalse(TextUtils.isEmpty(sessionIdRef)); + assertFalse(TextUtils.isEmpty(sessionIdSerial)); + + // session IDs comparison + assertTrue(sessionIdRef.equals(sessionIdSerial)); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 280dce1..d74f6e3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -31,6 +31,8 @@ public class OlmException extends Exception { public static final int EXCEPTION_CODE_SESSION_DESERIALIZATION = 7; public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 8; public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 9; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION = 10; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION = 11; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; @@ -39,7 +41,7 @@ public class OlmException extends Exception { public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = "failed to initialize a new inbound group Session"; public static final String EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION = "initNewAccount() failure"; public static final String EXCEPTION_MSG_INIT_ACCOUNT_DESERIALIZATION = "initWithSerializedData() failure"; - public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid deserialized parameters"; + public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters"; public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "Account constructor failure"; public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "Session constructor failure"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index d7d9a1c..e78e259 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -26,7 +26,7 @@ import android.util.Log; import java.io.Serializable; public class OlmInboundGroupSession implements Serializable { - + private static final long serialVersionUID = -772028491251653253L; private static final String LOG_TAG = "OlmInboundGroupSession"; /** session raw pointer value returned by JNI.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 55b9910..403b4b3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -17,10 +17,17 @@ package org.matrix.olm; +import android.util.Log; + public class OlmManager { + private static final String LOG_TAG = "OlmManager"; - static { - java.lang.System.loadLibrary("olm"); + public OlmManager() { + try { + java.lang.System.loadLibrary("olm"); + } catch(UnsatisfiedLinkError e) { + Log.e(LOG_TAG,"Exception loadLibrary() - Msg="+e.getMessage()); + } } /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 7c2c42b..7fdf405 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -18,8 +18,15 @@ package org.matrix.olm; import android.text.TextUtils; +import android.util.Log; -public class OlmOutboundGroupSession { +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +public class OlmOutboundGroupSession implements Serializable { + private static final long serialVersionUID = -3133097431283604416L; private static final String LOG_TAG = "OlmOutboundGroupSession"; /** session raw pointer value returned by JNI.
@@ -53,6 +60,120 @@ public class OlmOutboundGroupSession { } } + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException + * @throws OlmException + */ + private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + aOutStream.defaultWriteObject(); + + // generate serialization key + String key = OlmUtility.getRandomKey(); + + // compute pickle string + StringBuffer errorMsg = new StringBuffer(); + String pickledData = serializeDataWithKey(key, errorMsg); + + if(null == pickledData) { + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg)); + } else { + aOutStream.writeObject(key); + aOutStream.writeObject(pickledData); + } + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream + * @throws IOException + * @throws ClassNotFoundException + * @throws OlmException + */ + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + aInStream.defaultReadObject(); + StringBuffer errorMsg = new StringBuffer(); + + String key = (String) aInStream.readObject(); + String pickledData = (String) aInStream.readObject(); + + if(TextUtils.isEmpty(key)) { + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); + + } else if(TextUtils.isEmpty(pickledData)) { + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); + + } else if(!initNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + + } else if(!initWithSerializedData(pickledData, key, errorMsg)) { + releaseSession(); // prevent memory leak + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg)); + + } else { + Log.d(LOG_TAG,"## readObject(): success"); + } + } + + /** + * Return a session as a base64 string.
+ * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + } + + return pickleRetValue; + } + private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serializeDataWithKey(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + * @param aErrorMsg error message description + * @return true if operation succeed, false otherwise + */ + private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + boolean retCode = false; + String jniError; + + if(null == aErrorMsg) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); + } else { + aErrorMsg.setLength(0); + + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } + + return retCode; + } + private native String initWithSerializedDataJni(String aSerializedData, String aKey); + + /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index ca74352..eaf6110 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -97,7 +97,7 @@ public class OlmSession implements Serializable { } /** - * Return an account as a base64 string.
+ * Return a session as a base64 string.
* The account is serialized and encrypted with aKey. * In case of failure, an error human readable * description is provide in aErrorMsg. @@ -124,7 +124,7 @@ public class OlmSession implements Serializable { /** - * Loads an account from a pickled base64 string.
+ * Loads a session from a pickled base64 string.
* See {@link #serializeDataWithKey(String, StringBuffer)} * @param aSerializedData pickled account in a base64 string format * @param aKey key used to encrypted diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index 92a9359..7a8f20b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -47,7 +47,8 @@ olm_account.cpp \ olm_session.cpp \ olm_jni_helper.cpp \ olm_inbound_group_session.cpp \ -olm_outbound_group_session.cpp +olm_outbound_group_session.cpp \ +olm_utility.cpp LOCAL_LDLIBS := -llog diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index fd3a977..1a1b360 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -642,7 +642,6 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j { LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); } - } // free alloc diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 55c6539..67bf8bd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -330,4 +330,166 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv } +/** +* Serialize and encrypt session instance into a base64 string.
+* @param aKey key used to encrypt the serialized session data +* @param[out] aErrorMsg error message set if operation failed +* @return a base64 string if operation succeed, null otherwise +**/ +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +{ + jstring pickledDataRetValue = 0; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *keyPtr = NULL; + void *pickledPtr = NULL; + OlmOutboundGroupSession* sessionPtr = NULL; + + LOGD("## outbound group session serializeDataWithKeyJni(): IN"); + + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); + } + else if(0 == aKey) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + } + else if(0 == aErrorMsg) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = olm_pickle_outbound_group_session_length(sessionPtr); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + + if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + } + else + { + size_t result = olm_pickle_outbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } + } + else + { + // build success output + (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + } + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + free(pickledPtr); + } + + return pickledDataRetValue; +} + + +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +{ + OlmOutboundGroupSession* sessionPtr = NULL; + jstring errorMessageRetValue = 0; + const char *keyPtr = NULL; + const char *pickledPtr = NULL; + + LOGD("## initWithSerializedDataJni(): IN"); + + if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); + } + else if(0 == aKey) + { + LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + } + else if(0 == aSerializedData) + { + LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + } + else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); + LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + + size_t result = olm_unpickle_outbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_outbound_group_session() Msg=%s",errorMsgPtr); + errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + } + else + { + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + } + + return errorMessageRetValue; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 6e264aa..22c32a7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -38,6 +38,9 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsgPtr); +// serialization +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 3422fee..9f64d2e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -41,7 +41,6 @@ OlmSession* initializeSessionMemory() return sessionPtr; } - JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) { LOGD("## createNewSessionJni(): IN"); -- cgit v1.2.3 From 332d9d0c09c1f1f60bf970ea2b9a30cc95b9f5f5 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Sun, 23 Oct 2016 23:55:45 +0200 Subject: Add serialization for inbound group session - remove compiler warnings when logs are not enabled - new getInstanceId() function to refactor code --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 86 +++++++++- .../src/main/java/org/matrix/olm/OlmAccount.java | 15 +- .../src/main/java/org/matrix/olm/OlmException.java | 2 + .../org/matrix/olm/OlmInboundGroupSession.java | 159 +++++++++++++++--- .../org/matrix/olm/OlmOutboundGroupSession.java | 30 ++-- .../src/main/java/org/matrix/olm/OlmSession.java | 14 +- .../src/main/java/org/matrix/olm/OlmUtility.java | 15 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 21 +-- .../src/main/jni/olm_inbound_group_session.cpp | 182 ++++++++++++++++++-- .../src/main/jni/olm_inbound_group_session.h | 6 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 7 +- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 186 ++++----------------- .../src/main/jni/olm_outbound_group_session.cpp | 24 ++- .../src/main/jni/olm_outbound_group_session.h | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 30 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 3 +- 16 files changed, 490 insertions(+), 292 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index d49ebd4..c2a266b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -28,7 +28,8 @@ import static org.junit.Assert.assertTrue; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class OlmGroupSessionTest { private static final String LOG_TAG = "OlmSessionTest"; - private final String FILE_NAME_SERIAL_SESSION = "SerialGroupSession"; + private final String FILE_NAME_SERIAL_OUT_SESSION = "SerialOutGroupSession"; + private final String FILE_NAME_SERIAL_IN_SESSION = "SerialInGroupSession"; private static OlmManager mOlmManager; private static OlmOutboundGroupSession mAliceOutboundGroupSession; @@ -158,27 +159,26 @@ public class OlmGroupSessionTest { OlmOutboundGroupSession outboundGroupSessionRef=null; OlmOutboundGroupSession outboundGroupSessionSerial=null; - // alice creates OUTBOUND GROUP SESSION + // create one OUTBOUND GROUP SESSION try { outboundGroupSessionRef = new OlmOutboundGroupSession(); } catch (OlmException e) { assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); } - assertNotNull(outboundGroupSessionRef); // serialize alice session Context context = getInstrumentation().getContext(); try { - FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE); + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_OUT_SESSION, Context.MODE_PRIVATE); ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); objectOutput.writeObject(outboundGroupSessionRef); objectOutput.flush(); objectOutput.close(); // deserialize session - FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION); + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_OUT_SESSION); ObjectInputStream objectInput = new ObjectInputStream(fileInput); outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject(); objectInput.close(); @@ -204,6 +204,9 @@ public class OlmGroupSessionTest { // session IDs comparison assertTrue(sessionIdRef.equals(sessionIdSerial)); + + outboundGroupSessionRef.releaseSession(); + outboundGroupSessionSerial.releaseSession(); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); @@ -223,5 +226,78 @@ public class OlmGroupSessionTest { } + @Test + public void test15SerializeInboundSession() { + OlmOutboundGroupSession aliceOutboundGroupSession=null; + OlmInboundGroupSession bobInboundGroupSessionRef=null; + OlmInboundGroupSession bobInboundGroupSessionSerial=null; + + // alice creates OUTBOUND GROUP SESSION + try { + aliceOutboundGroupSession = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + assertNotNull(aliceOutboundGroupSession); + + // get the session key from the outbound group session + String sessionKeyRef = aliceOutboundGroupSession.sessionKey(); + assertNotNull(sessionKeyRef); + + // bob creates INBOUND GROUP SESSION + try { + bobInboundGroupSessionRef = new OlmInboundGroupSession(sessionKeyRef); + } catch (OlmException e) { + assertTrue("Exception in OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + assertNotNull(bobInboundGroupSessionRef); + + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_IN_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(bobInboundGroupSessionRef); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_OUT_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + bobInboundGroupSessionSerial = (OlmInboundGroupSession)objectInput.readObject(); + objectInput.close(); + + // get sessions IDs + String aliceSessionId = aliceOutboundGroupSession.sessionIdentifier(); + String sessionIdRef = bobInboundGroupSessionRef.sessionIdentifier(); + String sessionIdSerial = bobInboundGroupSessionSerial.sessionIdentifier(); + + // session ID sanity check + assertFalse(TextUtils.isEmpty(aliceSessionId)); + assertFalse(TextUtils.isEmpty(sessionIdRef)); + assertFalse(TextUtils.isEmpty(sessionIdSerial)); + + // session IDs comparison + assertTrue(aliceSessionId.equals(sessionIdSerial)); + assertTrue(sessionIdRef.equals(sessionIdSerial)); + } + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + } + + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 8d19a0c..2381585 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -26,7 +26,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.Random; public class OlmAccount implements Serializable { private static final long serialVersionUID = 3497486121598434824L; @@ -52,7 +51,7 @@ public class OlmAccount implements Serializable { /** account raw pointer value (OlmAccount*) returned by JNI. * this value identifies uniquely the native account instance. */ - private transient long mNativeOlmAccountId; + private transient long mNativeId; public OlmAccount() throws OlmException { @@ -179,7 +178,7 @@ public class OlmAccount implements Serializable { * @return native account ID */ public long getOlmAccountId(){ - return mNativeOlmAccountId; + return mNativeId; } /** @@ -189,7 +188,7 @@ public class OlmAccount implements Serializable { public void releaseAccount(){ releaseAccountJni(); - mNativeOlmAccountId = 0; + mNativeId = 0; } /** @@ -208,7 +207,7 @@ public class OlmAccount implements Serializable { */ private boolean initNewAccount() { boolean retCode = false; - if(0 != (mNativeOlmAccountId = initNewAccountJni())){ + if(0 != (mNativeId = initNewAccountJni())){ retCode = true; } return retCode; @@ -217,7 +216,7 @@ public class OlmAccount implements Serializable { /** * Create and initialize an OLM account in native side.
* Do not forget to call {@link #releaseAccount()} when JAVA side is done. - * @return native account instance identifier (see {@link #mNativeOlmAccountId}) + * @return native account instance identifier (see {@link #mNativeId}) */ private native long initNewAccountJni(); @@ -230,7 +229,7 @@ public class OlmAccount implements Serializable { */ private boolean createNewAccount() { boolean retCode = false; - if(0 != (mNativeOlmAccountId = createNewAccountJni())){ + if(0 != (mNativeId = createNewAccountJni())){ retCode = true; } return retCode; @@ -239,7 +238,7 @@ public class OlmAccount implements Serializable { /** * Create an OLM account in native side.
* Do not forget to call {@link #releaseAccount()} when JAVA side is done. - * @return native account instance identifier (see {@link #mNativeOlmAccountId}) + * @return native account instance identifier (see {@link #mNativeId}) */ private native long createNewAccountJni(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index d74f6e3..fe43f94 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -33,6 +33,8 @@ public class OlmException extends Exception { public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 9; public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION = 10; public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION = 11; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION = 12; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION = 13; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index e78e259..8d33b2c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -23,6 +23,9 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; public class OlmInboundGroupSession implements Serializable { @@ -32,26 +35,18 @@ public class OlmInboundGroupSession implements Serializable { /** session raw pointer value returned by JNI.
* this value uniquely identifies the native inbound group session instance. */ - private long mNativeOlmInboundGroupSessionId; - - /** - * Getter on the native inbound group session ID. - * @return native inbound group session ID - */ - public long getOlmInboundGroupSessionId() { - return mNativeOlmInboundGroupSessionId; - } + private transient long mNativeId; /** * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. * The session key parameter is retrieved from an outbound group session - * See {@link #initNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)} + * See {@link #createNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)} * @param aSessionKey session key * @throws OlmException constructor failure */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { - if(initNewSession()) { + if(createNewSession()) { if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { releaseSession();// prevent memory leak before throwing throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION,OlmException.EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION); @@ -68,14 +63,14 @@ public class OlmInboundGroupSession implements Serializable { public void releaseSession(){ releaseSessionJni(); - mNativeOlmInboundGroupSessionId = 0; + mNativeId = 0; } /** * Destroy the corresponding OLM inbound group session native object.
* This method must ALWAYS be called when this JAVA instance * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #initNewSessionJni()}. + * See {@link #createNewSessionJni()}. */ private native void releaseSessionJni(); @@ -84,9 +79,9 @@ public class OlmInboundGroupSession implements Serializable { * To be called before any other API call. * @return true if init succeed, false otherwise. */ - private boolean initNewSession() { + private boolean createNewSession() { boolean retCode = false; - if(0 != (mNativeOlmInboundGroupSessionId = initNewSessionJni())){ + if(0 != (mNativeId = createNewSessionJni())){ retCode = true; } return retCode; @@ -95,13 +90,13 @@ public class OlmInboundGroupSession implements Serializable { /** * Create the corresponding OLM inbound group session in native side.
* Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native session instance identifier (see {@link #mNativeOlmInboundGroupSessionId}) + * @return native session instance identifier (see {@link #mNativeId}) */ - private native long initNewSessionJni(); + private native long createNewSessionJni(); /** * Start a new inbound group session.
- * The session key parameter is retrieved from a outbound group session + * The session key parameter is retrieved from an outbound group session * see {@link OlmOutboundGroupSession#sessionKey()} * @param aSessionKey session key * @return 0 if operation succeed, -1 otherwise @@ -132,8 +127,128 @@ public class OlmInboundGroupSession implements Serializable { private native String decryptMessageJni(String aEncryptedMsg); - // TODO missing API: initWithSerializedData - // TODO missing API: serializeDataWithKey - // TODO missing API: initWithCoder - // TODO missing API: encodeWithCoder + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException + * @throws OlmException + */ + private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + aOutStream.defaultWriteObject(); + + // generate serialization key + String key = OlmUtility.getRandomKey(); + + // compute pickle string + StringBuffer errorMsg = new StringBuffer(); + String pickledData = serializeDataWithKey(key, errorMsg); + + if(null == pickledData) { + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg)); + } else { + aOutStream.writeObject(key); + aOutStream.writeObject(pickledData); + } + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream + * @throws IOException + * @throws ClassNotFoundException + * @throws OlmException + */ + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + aInStream.defaultReadObject(); + StringBuffer errorMsg = new StringBuffer(); + + String key = (String) aInStream.readObject(); + String pickledData = (String) aInStream.readObject(); + + if(TextUtils.isEmpty(key)) { + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); + + } else if(TextUtils.isEmpty(pickledData)) { + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); + + } else if(!createNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + + } else if(!initWithSerializedData(pickledData, key, errorMsg)) { + releaseSession(); // prevent memory leak + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg)); + + } else { + Log.d(LOG_TAG,"## readObject(): success"); + } + } + + /** + * Return a session as a base64 string.
+ * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + } + + return pickleRetValue; + } + /** + * JNI counter part of {@link #serializeDataWithKey(String, StringBuffer)}. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serializeDataWithKey(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + * @param aErrorMsg error message description + * @return true if operation succeed, false otherwise + */ + private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + boolean retCode = false; + String jniError; + + if(null == aErrorMsg) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); + } else { + aErrorMsg.setLength(0); + + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } + + return retCode; + } + /** + * JNI counter part of {@link #initWithSerializedData(String, String, StringBuffer)}. + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + * @return null if operation succeed, an error message if operation failed + */ + private native String initWithSerializedDataJni(String aSerializedData, String aKey); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 7fdf405..94acbd0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -32,25 +32,17 @@ public class OlmOutboundGroupSession implements Serializable { /** session raw pointer value returned by JNI.
* this value uniquely identifies the native inbound group session instance. */ - private long mNativeOlmOutboundGroupSessionId; - - /** - * Getter on the native outbound group session ID. - * @return native outbound group session ID - */ - public long getOlmInboundGroupSessionId(){ - return mNativeOlmOutboundGroupSessionId; - } + private transient long mNativeId; /** * Constructor.
* Create and save a new session native instance ID and * initialise a new outbound group session.
- * See {@link #initNewSession()} and {@link #initOutboundGroupSession()} + * See {@link #createNewSession()} and {@link #initOutboundGroupSession()} * @throws OlmException constructor failure */ public OlmOutboundGroupSession() throws OlmException { - if(initNewSession()) { + if(createNewSession()) { if( 0 != initOutboundGroupSession()) { releaseSession();// prevent memory leak before throwing throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION); @@ -104,7 +96,7 @@ public class OlmOutboundGroupSession implements Serializable { } else if(TextUtils.isEmpty(pickledData)) { throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); - } else if(!initNewSession()) { + } else if(!createNewSession()) { throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); } else if(!initWithSerializedData(pickledData, key, errorMsg)) { @@ -180,26 +172,26 @@ public class OlmOutboundGroupSession implements Serializable { */ public void releaseSession() { releaseSessionJni(); - mNativeOlmOutboundGroupSessionId = 0; + mNativeId = 0; } /** * Destroy the corresponding OLM outbound group session native object.
* This method must ALWAYS be called when this JAVA instance * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #initNewSessionJni()}. + * See {@link #createNewSessionJni()}. */ private native void releaseSessionJni(); /** * Create and save the session native instance ID. - * Wrapper for {@link #initNewSessionJni()}.
+ * Wrapper for {@link #createNewSessionJni()}.
* To be called before any other API call. * @return true if init succeed, false otherwise. */ - private boolean initNewSession() { + private boolean createNewSession() { boolean retCode = false; - if(0 != (mNativeOlmOutboundGroupSessionId = initNewSessionJni())){ + if(0 != (mNativeId = createNewSessionJni())){ retCode = true; } return retCode; @@ -208,9 +200,9 @@ public class OlmOutboundGroupSession implements Serializable { /** * Create the corresponding OLM outbound group session in native side.
* Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native session instance identifier (see {@link #mNativeOlmOutboundGroupSessionId}) + * @return native session instance identifier (see {@link #mNativeId}) */ - private native long initNewSessionJni(); + private native long createNewSessionJni(); /** * Start a new outbound group session.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index eaf6110..5877d24 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -31,7 +31,7 @@ public class OlmSession implements Serializable { /** session raw pointer value (OlmSession*) returned by JNI. * this value uniquely identifies the native session instance. **/ - private transient long mNativeOlmSessionId; + private transient long mNativeId; public OlmSession() throws OlmException { @@ -158,7 +158,7 @@ public class OlmSession implements Serializable { * @return native session ID */ public long getOlmSessionId(){ - return mNativeOlmSessionId; + return mNativeId; } /** @@ -176,7 +176,7 @@ public class OlmSession implements Serializable { public void releaseSession(){ releaseSessionJni(); - mNativeOlmSessionId = 0; + mNativeId = 0; } /** @@ -187,7 +187,7 @@ public class OlmSession implements Serializable { */ private boolean initNewSession() { boolean retCode = false; - if(0 != (mNativeOlmSessionId = initNewSessionJni())){ + if(0 != (mNativeId = initNewSessionJni())){ retCode = true; } return retCode; @@ -196,7 +196,7 @@ public class OlmSession implements Serializable { /** * Create the corresponding OLM session in native side.
* Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native session instance identifier (see {@link #mNativeOlmSessionId}) + * @return native session instance identifier (see {@link #mNativeId}) */ private native long initNewSessionJni(); @@ -210,7 +210,7 @@ public class OlmSession implements Serializable { */ private boolean createNewSession() { boolean retCode = false; - if(0 != (mNativeOlmSessionId = createNewSessionJni())){ + if(0 != (mNativeId = createNewSessionJni())){ retCode = true; } return retCode; @@ -219,7 +219,7 @@ public class OlmSession implements Serializable { /** * Create an OLM account in native side.
* Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native account instance identifier (see {@link #mNativeOlmSessionId}) + * @return native account instance identifier (see {@link #mNativeId}) */ private native long createNewSessionJni(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 342d8eb..3bf65a8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -19,7 +19,6 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; -import java.io.Serializable; import java.util.Random; public class OlmUtility { @@ -31,20 +30,12 @@ public class OlmUtility { /** raw pointer value returned by JNI. * this value uniquely identifies this utility instance. **/ - private long mNativeOlmUtilityId; + private long mNativeId; public OlmUtility() { initUtility(); } - /** - * Getter on the session ID. - * @return native session ID - */ - public long getOlmUtilityId(){ - return mNativeOlmUtilityId; - } - /** * Create a native utility instance. * To be called before any other API call. @@ -52,7 +43,7 @@ public class OlmUtility { */ private boolean initUtility() { boolean retCode = false; - if(0 != (mNativeOlmUtilityId = initUtilityJni())){ + if(0 != (mNativeId = initUtilityJni())){ retCode = true; } return retCode; @@ -65,7 +56,7 @@ public class OlmUtility { */ public void releaseUtility(){ releaseUtilityJni(); - mNativeOlmUtilityId = 0; + mNativeId = 0; } private native void releaseUtilityJni(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 1a1b360..baa7939 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -119,8 +119,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi // create account accountRetCode = olm_create_account(accountPtr, (void*)randomBuffPtr, randomSize); if(accountRetCode == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE("## initNewAccount(): failure - account creation failed Msg=%s", errorMsgPtr); + LOGE("## initNewAccount(): failure - account creation failed Msg=%s", (const char *)olm_account_last_error(accountPtr)); } LOGD("## initNewAccount(): success - OLM account created"); @@ -171,8 +170,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject { // retrieve key pairs in identityKeysBytesPtr keysResult = olm_account_identity_keys(accountPtr, identityKeysBytesPtr, identityKeysLength); if(keysResult == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE("## identityKeys(): failure - error getting identity keys Msg=%s",errorMsgPtr); + LOGE("## identityKeys(): failure - error getting identity keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else { // allocate the byte array to be returned to java @@ -253,8 +251,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th // retrieve key pairs in keysBytesPtr result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); if(result == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE("## generateOneTimeKeys(): failure - error generating one time keys Msg=%s",errorMsgPtr); + LOGE("## generateOneTimeKeys(): failure - error generating one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else { @@ -302,8 +299,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t { // retrieve key pairs in keysBytesPtr keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); if(keysResult == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",errorMsgPtr); + LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else { // allocate the byte array to be returned to java @@ -351,8 +347,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, result = olm_remove_one_time_keys(accountPtr, sessionPtr); if(result == olm_error()) { // the account doesn't have any matching "one time keys".. - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGW("## removeOneTimeKeysForSessionJni(): failure - removing one time keys Msg=%s",errorMsgPtr); + LOGW("## removeOneTimeKeysForSessionJni(): failure - removing one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); retCode = ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS; } @@ -386,8 +381,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, result = olm_account_mark_keys_as_published(accountPtr); if(result == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",errorMsgPtr); + LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",(const char *)olm_account_last_error(accountPtr)); retCode = ERROR_CODE_KO; } else @@ -448,8 +442,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz signatureLength); if(resultSign == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE("## signMessageJni(): failure - error signing message Msg=%s",errorMsgPtr); + LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index d10a05b..810d62c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -38,7 +38,7 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); size_t retCode = olm_clear_inbound_group_session(sessionPtr); - LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); + LOGI(" ## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); @@ -52,26 +52,26 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env * to make the cast (OlmInboundGroupSession* => jlong) platform independent. * @return the initialized OlmInboundGroupSession* instance if init succeed, NULL otherwise **/ -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) { OlmInboundGroupSession* sessionPtr = NULL; size_t sessionSize = 0; - LOGD("## initNewSessionJni(): inbound group session IN"); + LOGD("## createNewSessionJni(): inbound group session IN"); sessionSize = olm_inbound_group_session_size(); if(0 == sessionSize) { - LOGE(" ## initNewSessionJni(): failure - inbound group session size = 0"); + LOGE(" ## createNewSessionJni(): failure - inbound group session size = 0"); } else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize))) { sessionPtr = olm_inbound_group_session(sessionPtr); - LOGD(" ## initNewSessionJni(): success - inbound group session size=%lu",sessionSize); + LOGD(" ## createNewSessionJni(): success - inbound group session size=%lu",sessionSize); } else { - LOGE(" ## initNewSessionJni(): failure - inbound group session OOM"); + LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); } return (jlong)(intptr_t)sessionPtr; @@ -160,8 +160,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); if (result == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",errorMsgPtr); + LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); } else { @@ -221,8 +220,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * encryptedMsgLength); if(maxPlainTextLength == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); } else { @@ -240,8 +238,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * maxPlainTextLength); if(plaintextLength == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); } else { @@ -275,4 +272,165 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * } +/** +* Serialize and encrypt session instance into a base64 string.
+* @param aKey key used to encrypt the serialized session data +* @param[out] aErrorMsg error message set if operation failed +* @return a base64 string if operation succeed, null otherwise +**/ +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +{ + jstring pickledDataRetValue = 0; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *keyPtr = NULL; + void *pickledPtr = NULL; + OlmInboundGroupSession* sessionPtr = NULL; + + LOGD("## inbound group session serializeDataWithKeyJni(): IN"); + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); + } + else if(0 == aKey) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + } + else if(0 == aErrorMsg) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = olm_pickle_inbound_group_session_length(sessionPtr); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + + if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + } + else + { + size_t result = olm_pickle_inbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } + } + else + { + // build success output + (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + } + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + free(pickledPtr); + } + + return pickledDataRetValue; +} + + +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +{ + OlmInboundGroupSession* sessionPtr = NULL; + jstring errorMessageRetValue = 0; + const char *keyPtr = NULL; + const char *pickledPtr = NULL; + LOGD("## initWithSerializedDataJni(): IN"); + + if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); + } + else if(0 == aKey) + { + LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + } + else if(0 == aSerializedData) + { + LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + } + else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); + LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + + size_t result = olm_unpickle_inbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_inbound_group_session() Msg=%s",errorMsgPtr); + errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + } + else + { + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + } + + return errorMessageRetValue; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 1eb8238..897ef46 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -29,12 +29,16 @@ extern "C" { // session creation/destruction JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg); +// serialization +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); + #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 2e31bff..bb718b6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -30,16 +30,15 @@ /* logging macros */ #define ENABLE_LOGS +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) +#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) + #ifdef ENABLE_LOGS - #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) - #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) #else - #define LOGV(...) #define LOGD(...) #define LOGW(...) - #define LOGE(...) #endif #define FUNC_DEF(class_name,func_name) JNICALL Java_org_matrix_olm_##class_name##_##func_name diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 174739c..1f0c0df 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -63,12 +63,13 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) /** -* Read the account instance ID of the calling object. +* Read the instance ID of the calling object. * @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked +* @param aCallingClass java calling clas name * @return the instance ID if operation succeed, -1 if instance ID was not found. **/ -jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass) { jlong instanceId = 0; jfieldID instanceIdField; @@ -77,7 +78,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) if(NULL!=aJniEnv) { - requiredClass = aJniEnv->FindClass(CLASS_OLM_ACCOUNT); + requiredClass = aJniEnv->FindClass(aCallingClass); if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) { @@ -85,78 +86,56 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) } else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J"))) + if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeId", "J"))) { instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); aJniEnv->DeleteLocalRef(loaderClass); - LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId); + LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId); } else { - LOGE("## getAccountInstanceId() ERROR! GetFieldID=null"); + LOGE("## getInstanceId() ERROR! GetFieldID=null"); } } else { - LOGE("## getAccountInstanceId() ERROR! GetObjectClass=null"); + LOGE("## getInstanceId() ERROR! GetObjectClass=null"); } } else { - LOGE("## getAccountInstanceId() ERROR! aJniEnv=NULL"); + LOGE("## getInstanceId() ERROR! aJniEnv=NULL"); } - LOGD("## getAccountInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); + LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); return instanceId; } /** -* Read the session instance ID of the calling object (aJavaObject).
+* Read the account instance ID of the calling object. * @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. +* @return the instance ID if operation succeed, -1 if instance ID was not found. **/ -jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = 0; - jfieldID instanceIdField; - jclass loaderClass; - jclass requiredClass = 0; + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT); + return instanceId; +} - if(NULL!=aJniEnv) - { - requiredClass = aJniEnv->FindClass(CLASS_OLM_SESSION); - if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) - { - LOGE("## getSessionInstanceId() failure - invalid instance of"); - } - else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGE("## getSessionInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGE("## getSessionInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGE("## getSessionInstanceId() ERROR! aJniEnv=NULL"); - } - //LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId); +/** +* Read the session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ +jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION); return instanceId; } - /** * Read the inbound group session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table @@ -165,41 +144,7 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = 0; - jfieldID instanceIdField; - jclass loaderClass; - jclass requiredClass = 0; - - if(NULL!=aJniEnv) - { - requiredClass = aJniEnv->FindClass(CLASS_OLM_INBOUND_GROUP_SESSION); - - if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) - { - LOGE("## getInboundGroupSessionInstanceId() failure - invalid instance of"); - } - else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGE("## getInboundGroupSessionInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGE("## getInboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGE("## getInboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); - } - + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION); return instanceId; } @@ -212,84 +157,23 @@ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = 0; - jfieldID instanceIdField; - jclass loaderClass; - jclass requiredClass = 0; - - if(NULL!=aJniEnv) - { - requiredClass = aJniEnv->FindClass(CLASS_OLM_OUTBOUND_GROUP_SESSION); - - if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) - { - LOGE("## getOutboundGroupSessionInstanceId() failure - invalid instance of"); - } - else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGE("## getOutboundGroupSessionInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGE("## getOutboundGroupSessionInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGE("## getOutboundGroupSessionInstanceId() ERROR! aJniEnv=NULL"); - } - + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION); return instanceId; } +/** +* Read the utility instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the instance ID if read succeed, -1 otherwise. +**/ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = 0; - jfieldID instanceIdField; - jclass loaderClass; - jclass requiredClass = 0; - - if(NULL!=aJniEnv) - { - requiredClass = aJniEnv->FindClass(CLASS_OLM_UTILITY); - - if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) - { - LOGE("## getUtilityInstanceId() failure - invalid instance of"); - } - else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) - { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmUtilityId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGE("## getUtilityInstanceId() ERROR! GetFieldID=null"); - } - } - else - { - LOGE("## getUtilityInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGE("## getUtilityInstanceId() ERROR! aJniEnv=NULL"); - } - + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); return instanceId; } + template jstring serializeDataWithKey(JNIEnv *env, jobject thiz, jstring aKey, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 67bf8bd..8ccd78e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -38,7 +38,7 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); size_t retCode = olm_clear_outbound_group_session(sessionPtr); - LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",retCode); + LOGI(" ## releaseSessionJni(): clear_outbound_group_session=%lu",retCode); LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); @@ -52,26 +52,26 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en * to make the cast (OlmOutboundGroupSession* => jlong) platform independent. * @return the initialized OlmOutboundGroupSession* instance if init succeed, NULL otherwise **/ -JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) { OlmOutboundGroupSession* sessionPtr = NULL; size_t sessionSize = 0; - LOGD("## initNewSessionJni(): outbound group session IN"); + LOGD("## createNewSessionJni(): outbound group session IN"); sessionSize = olm_outbound_group_session_size(); if(0 == sessionSize) { - LOGE(" ## initNewSessionJni(): failure - outbound group session size = 0"); + LOGE(" ## createNewSessionJni(): failure - outbound group session size = 0"); } else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize))) { sessionPtr = olm_outbound_group_session(sessionPtr); - LOGD(" ## initNewSessionJni(): success - outbound group session size=%lu",sessionSize); + LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",sessionSize); } else { - LOGE(" ## initNewSessionJni(): failure - outbound group session OOM"); + LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); } return (jlong)(intptr_t)sessionPtr; @@ -111,8 +111,7 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); if(sessionResult == olm_error()) { - const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s",errorMsgPtr); + LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); } else { @@ -160,8 +159,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE size_t result = olm_outbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); if (result == olm_error()) { - const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",errorMsgPtr); + LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); } else { @@ -237,8 +235,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env size_t result = olm_outbound_group_session_key(sessionPtr, sessionKeyPtr, sessionKeyLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s",errorMsgPtr); + LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); } else { @@ -301,8 +298,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv encryptedMsgLength); if(encryptedLength == olm_error()) { - const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## encryptMessageJni(): failure - olm_group_encrypt Msg=%s",errorMsgPtr); + LOGE(" ## encryptMessageJni(): failure - olm_group_encrypt Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); } else { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 22c32a7..4b59b93 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -29,7 +29,7 @@ extern "C" { // session creation/destruction JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 9f64d2e..cfa132c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -161,8 +161,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject (void*)randomBuffPtr, randomSize); if(sessionResult == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s",errorMsgPtr); + LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -236,8 +235,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); if(sessionResult == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -302,8 +300,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); if(sessionResult == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -355,8 +352,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); if(matchResult == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## matchesInboundSessionJni(): failure - no match Msg=%s",errorMsgPtr); + LOGE("## matchesInboundSessionJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -416,8 +412,7 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); if(matchResult == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## matchesInboundSessionFromIdKeyJni(): failure - no match Msg=%s",errorMsgPtr); + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -529,8 +524,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz encryptedMsgLength); if(result == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## encryptMessageJni(): failure - Msg=%s",errorMsgPtr); + LOGE("## encryptMessageJni(): failure - Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -542,11 +536,10 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // update message: encryptedMsgPtr => encryptedJstring jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr); - size_t encryptedUtfMsgLength = (size_t)env->GetStringUTFLength(encryptedJstring); env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring); retCode = ERROR_CODE_OK; - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", result, messageType, encryptedUtfMsgLength, (const char*)encryptedMsgPtr); + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", result, messageType, (size_t)env->GetStringUTFLength(encryptedJstring), (const char*)encryptedMsgPtr); } } } @@ -642,8 +635,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t if(maxPlainTextLength == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -662,8 +654,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t maxPlainTextLength); if(plaintextLength == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",errorMsgPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { @@ -728,8 +719,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job if (result == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr); + LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 6248d34..e11f7eb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -203,8 +203,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst hashLength); if(result == olm_error()) { - const char *errorMsgPtr = olm_utility_last_error(utilityPtr); - LOGE("## sha256Jni(): failure - hash creation Msg=%s",errorMsgPtr); + LOGE("## sha256Jni(): failure - hash creation Msg=%s",(const char *)olm_utility_last_error(utilityPtr)); } else { -- cgit v1.2.3 From 3f60e62827871169ae56d209056b725f692d9930 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 24 Oct 2016 15:30:55 +0200 Subject: Add missing account releaseAccount for test01VerifyEd25519Signing() --- .../src/androidTest/java/org/matrix/olm/OlmUtilityTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 030bea7..12aff1f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -61,7 +61,7 @@ public class OlmUtilityTest { String messageSignature = account.signMessage(message); assertNotNull(messageSignature); - // get identity key + // get identities key (finger print key) JSONObject identityKeysJson = account.identityKeys(); assertNotNull(identityKeysJson); try { @@ -82,12 +82,13 @@ public class OlmUtilityTest { assertTrue(String.valueOf(errorMsg).isEmpty()); // check a bad signature is detected and the error message is not empty - messageSignature = "Bad signature Bad signature Bad signature.."; - isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message, errorMsg); + String badSignature = "Bad signature Bad signature Bad signature.."; + isVerified = utility.verifyEd25519Signature(badSignature, fingerPrintKey, message, errorMsg); assertFalse(isVerified); assertFalse(String.valueOf(errorMsg).isEmpty()); utility.releaseUtility(); + account.releaseAccount(); } -- cgit v1.2.3 From c485bf1d53217f99d4bab53cfabb0a56943bc897 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 24 Oct 2016 15:31:59 +0200 Subject: Update comments --- .../olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 8fd2744..caa1e46 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -58,8 +58,8 @@ public class OlmSessionTest { String bobOneTimeKey=null; OlmAccount bobAccount = null; OlmAccount aliceAccount = null; - // creates alice & bob accounts + // ALICE & BOB ACCOUNTS CREATION try { aliceAccount = new OlmAccount(); bobAccount = new OlmAccount(); -- cgit v1.2.3 From 3ec91b849b5de58c4006b78a40b338e866edd12a Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 24 Oct 2016 16:51:03 +0200 Subject: Add possibility to define NDK_DEBUG flag --- java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 2 ++ 1 file changed, 2 insertions(+) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index 7a8f20b..2695cab 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -18,6 +18,8 @@ LOCAL_CFLAGS+= -DOLMLIB_VERSION_MAJOR=$(MAJOR) \ -DOLMLIB_VERSION_MINOR=$(MINOR) \ -DOLMLIB_VERSION_PATCH=$(PATCH) +#LOCAL_CFLAGS+= -DNDK_DEBUG=1 + LOCAL_C_INCLUDES+= $(LOCAL_PATH)/$(SRC_ROOT_DIR)/include/ \ $(LOCAL_PATH)/$(SRC_ROOT_DIR)/lib -- cgit v1.2.3 From acafa69c671907f31fb783e3e09c7cc662e779af Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 24 Oct 2016 17:14:35 +0200 Subject: Add possibility to define NDK_DEBUG flag --- java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index 2695cab..2d94676 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -18,7 +18,7 @@ LOCAL_CFLAGS+= -DOLMLIB_VERSION_MAJOR=$(MAJOR) \ -DOLMLIB_VERSION_MINOR=$(MINOR) \ -DOLMLIB_VERSION_PATCH=$(PATCH) -#LOCAL_CFLAGS+= -DNDK_DEBUG=1 +#LOCAL_CFLAGS+= -DNDK_DEBUG LOCAL_C_INCLUDES+= $(LOCAL_PATH)/$(SRC_ROOT_DIR)/include/ \ $(LOCAL_PATH)/$(SRC_ROOT_DIR)/lib -- cgit v1.2.3 From 6b3cb69ded8ac1ec228b1d631b0d78d5c1c06e93 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 24 Oct 2016 17:21:28 +0200 Subject: Fix compiler warnings - for 32bits platform target - when debug flag is not defined --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 29 +++++++------- .../src/main/jni/olm_inbound_group_session.cpp | 28 ++++++------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 10 ++++- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 9 ++--- .../src/main/jni/olm_outbound_group_session.cpp | 34 ++++++++-------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 46 +++++++++++----------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 10 +++-- 7 files changed, 86 insertions(+), 80 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index baa7939..c68e390 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -37,7 +37,7 @@ OlmAccount* initializeAccountMemory() if(NULL != (accountPtr=(OlmAccount*)malloc(accountSize))) { // init account object accountPtr = olm_account(accountPtr); - LOGD("## initializeAccountMemory(): success - OLM account size=%lu",accountSize); + LOGD("## initializeAccountMemory(): success - OLM account size=%lu",static_cast(accountSize)); } else { @@ -107,7 +107,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi { // get random buffer size randomSize = olm_create_account_random_length(accountPtr); - LOGD("## initNewAccount(): randomSize=%lu", randomSize); + LOGD("## initNewAccount(): randomSize=%lu", static_cast(randomSize)); // allocate random buffer if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize)) @@ -181,7 +181,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject else { env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, identityKeysLength, (const jbyte*)identityKeysBytesPtr); - LOGD("## identityKeys(): success - result=%ld", keysResult); + LOGD("## identityKeys(): success - result=%lu", static_cast(keysResult)); } } @@ -212,7 +212,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz) { maxKeys = olm_account_max_number_of_one_time_keys(accountPtr); } - LOGD("## maxOneTimeKey(): Max keys=%ld", maxKeys); + LOGD("## maxOneTimeKey(): Max keys=%lu", static_cast(maxKeys)); return (jlong)maxKeys; } @@ -238,7 +238,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th else { // keys memory allocation randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); - LOGD("## generateOneTimeKeys(): randomLength=%ld", randomLength); + LOGD("## generateOneTimeKeys(): randomLength=%lu", static_cast(randomLength)); if((0!=randomLength) && !setRandomInBuffer(&randomBufferPtr, randomLength)) { @@ -256,7 +256,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th else { retCode = ERROR_CODE_OK; - LOGD("## generateOneTimeKeys(): success - result=%ld", result); + LOGD("## generateOneTimeKeys(): success - result=%lu", static_cast(result)); } } } @@ -386,7 +386,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, } else { - LOGD("## markOneTimeKeysAsPublishedJni(): success - retCode=%ld",result); + LOGD("## markOneTimeKeysAsPublishedJni(): success - retCode=%lu",static_cast(result)); } } @@ -429,7 +429,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz // signature memory allocation signatureLength = olm_account_signature_length(accountPtr); - if(NULL == (signedMsgPtr = (void*)malloc(signatureLength*sizeof(uint8_t)))) + if(NULL == (signedMsgPtr = (void*)malloc((signatureLength+1)*sizeof(uint8_t)))) { LOGE("## signMessageJni(): failure - signature allocation OOM"); } @@ -446,10 +446,11 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz } else { - // TODO check if signedMsgPtr needs to be null ended: signedMsgPtr[resultSign]='\0' + // info: signatureLength is always equal to resultSign + (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); // convert to jstring signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 - LOGD("## signMessageJni(): success - retCode=%ld",resultSign); + LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); } free(signedMsgPtr); @@ -533,7 +534,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job { size_t pickledLength = olm_pickle_account_length(accountPtr); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) @@ -562,7 +563,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } } } @@ -616,7 +617,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j { size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -633,7 +634,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 810d62c..20d8cb0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -27,7 +27,7 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env { OlmInboundGroupSession* sessionPtr = NULL; - LOGD("## releaseSessionJni(): intbound group session"); + LOGD("## releaseSessionJni(): InBound group session IN"); if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { @@ -38,7 +38,7 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); size_t retCode = olm_clear_inbound_group_session(sessionPtr); - LOGI(" ## releaseSessionJni(): clear_inbound_group_session=%lu",retCode); + LOGI(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); @@ -67,7 +67,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize))) { sessionPtr = olm_inbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - inbound group session size=%lu",sessionSize); + LOGD(" ## createNewSessionJni(): success - inbound group session size=%lu",static_cast(sessionSize)); } else { @@ -106,7 +106,7 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes else { size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey); - LOGD(" ## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength); + LOGD(" ## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); if(sessionResult == olm_error()) { @@ -116,7 +116,7 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes else { retCode = ERROR_CODE_OK; - LOGD(" ## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult); + LOGD(" ## initInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(sessionResult)); } } @@ -149,7 +149,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn { // get the size to alloc size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); - LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId); + LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); if(NULL == (sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) { @@ -166,7 +166,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn { // update length sessionIdPtr[result] = static_cast('\0'); - LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",result, (char*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); } free(sessionIdPtr); @@ -212,7 +212,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * else { memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr); + LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",static_cast(encryptedMsgLength),encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, @@ -224,7 +224,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * } else { - LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); + LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); // allocate output decrypted message plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); @@ -245,7 +245,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * // update decrypted buffer size plainTextMsgPtr[plaintextLength] = static_cast('\0'); - LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr); + LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), (char*)plainTextMsgPtr); decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); } } @@ -318,7 +318,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN { size_t pickledLength = olm_pickle_inbound_group_session_length(sessionPtr); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) @@ -347,7 +347,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } } } @@ -400,7 +400,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( { size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -417,7 +417,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index bb718b6..16eb8b2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -28,12 +28,18 @@ #define TAG "OlmJniNative" /* logging macros */ -#define ENABLE_LOGS +//#define ENABLE_LOGS + +#ifdef NDK_DEBUG + #warning "NDK_DEBUG is defined" +#else + #warning "NDK_DEBUG not defined" +#endif #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) -#ifdef ENABLE_LOGS +#ifdef NDK_DEBUG #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) #else diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 1f0c0df..5910c42 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -45,15 +45,12 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) } else { - LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize); + LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); srand(time(NULL)); // init seed for(size_t i=0;iGetStringUTFLength(aKey); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) @@ -249,7 +246,7 @@ jstring serializeDataWithKey(JNIEnv *env, jobject thiz, // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 8ccd78e..f7e6754 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -27,7 +27,7 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en { OlmOutboundGroupSession* sessionPtr = NULL; - LOGD("## releaseSessionJni(): outbound group session"); + LOGD("## releaseSessionJni(): OutBound group session IN"); if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { @@ -38,7 +38,7 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); size_t retCode = olm_clear_outbound_group_session(sessionPtr); - LOGI(" ## releaseSessionJni(): clear_outbound_group_session=%lu",retCode); + LOGI(" ## releaseSessionJni(): clear_outbound_group_session=%lu",static_cast(retCode)); LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); @@ -67,7 +67,7 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize))) { sessionPtr = olm_outbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",sessionSize); + LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); } else { @@ -97,7 +97,7 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( { // compute random buffer size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); - LOGW(" ## initOutboundGroupSessionJni(): randomLength=%lu",randomLength); + LOGW(" ## initOutboundGroupSessionJni(): randomLength=%lu",static_cast(randomLength)); if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) { LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init"); @@ -116,7 +116,7 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( else { retCode = ERROR_CODE_OK; - LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", sessionResult); + LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); } } } @@ -148,7 +148,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE { // get the size to alloc size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); - LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",lengthSessionId); + LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); if(NULL == (sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) { @@ -159,13 +159,13 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE size_t result = olm_outbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); if (result == olm_error()) { - LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); + LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",reinterpret_cast(olm_outbound_group_session_last_error(sessionPtr))); } else { // update length sessionIdPtr[result] = static_cast('\0'); - LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",result, (char*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",static_cast(result), reinterpret_cast(sessionIdPtr)); returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); } @@ -224,7 +224,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env { // get the size to alloc size_t sessionKeyLength = olm_outbound_group_session_key_length(sessionPtr); - LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",sessionKeyLength); + LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); if(NULL == (sessionKeyPtr = (uint8_t*)malloc((sessionKeyLength+1)*sizeof(uint8_t)))) { @@ -241,7 +241,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env { // update length sessionKeyPtr[result] = static_cast('\0'); - LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%s",result, (char*)sessionKeyPtr); + LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%s",static_cast(result), reinterpret_cast(sessionKeyPtr)); returnValueStr = env->NewStringUTF((const char*)sessionKeyPtr); } @@ -279,7 +279,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv { // get clear message length size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg); - LOGD(" ## encryptMessageJni(): clearMsgLength=%lu",clearMsgLength); + LOGD(" ## encryptMessageJni(): clearMsgLength=%lu",static_cast(clearMsgLength)); // compute max encrypted length size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); @@ -289,7 +289,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv } else { - LOGD(" ## encryptMessageJni(): estimated encryptedMsgLength=%lu",encryptedMsgLength); + LOGD(" ## encryptMessageJni(): estimated encryptedMsgLength=%lu",static_cast(encryptedMsgLength)); size_t encryptedLength = olm_group_encrypt(sessionPtr, (uint8_t*)clearMsgPtr, @@ -305,7 +305,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv // update decrypted buffer size encryptedMsgPtr[encryptedLength] = static_cast('\0'); - LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%s",encryptedLength, (char*)encryptedMsgPtr); + LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); encryptedMsgRetValue = env->NewStringUTF((const char*)encryptedMsgPtr); } } @@ -372,7 +372,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J { size_t pickledLength = olm_pickle_outbound_group_session_length(sessionPtr); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) @@ -401,7 +401,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } } } @@ -454,7 +454,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) { size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -471,7 +471,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index cfa132c..c4460b3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -31,7 +31,7 @@ OlmSession* initializeSessionMemory() if(NULL != (sessionPtr=(OlmSession*)malloc(sessionSize))) { // init session object sessionPtr = olm_session(sessionPtr); - LOGD("## initializeSessionMemory(): success - OLM session size=%lu",sessionSize); + LOGD("## initializeSessionMemory(): success - OLM session size=%lu",static_cast(sessionSize)); } else { @@ -54,6 +54,8 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz { OlmSession* sessionPtr = NULL; + LOGD("## releaseSessionJni(): IN"); + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); @@ -62,10 +64,8 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz { olm_clear_session(sessionPtr); - LOGD("## releaseSessionJni(): IN"); // even if free(NULL) does not crash, logs are performed for debug purpose free(sessionPtr); - LOGD("## releaseSessionJni(): OUT"); } } @@ -131,7 +131,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject else { // allocate random buffer size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); - LOGD("## initOutboundSessionJni(): randomSize=%lu",randomSize); + LOGD("## initOutboundSessionJni(): randomSize=%lu",static_cast(randomSize)); if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize)) { LOGE("## initOutboundSessionJni(): failure - random buffer init"); @@ -166,7 +166,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject else { retCode = ERROR_CODE_OK; - LOGD("## initOutboundSessionJni(): success - result=%ld", sessionResult); + LOGD("## initOutboundSessionJni(): success - result=%lu", static_cast(sessionResult)); } } } @@ -231,7 +231,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject else { size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); - LOGD("## initInboundSessionJni(): messageLength=%lu message=%s", messageLength, messagePtr); + LOGD("## initInboundSessionJni(): messageLength=%lu message=%s", static_cast(messageLength), messagePtr); sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); if(sessionResult == olm_error()) { @@ -240,7 +240,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject else { retCode = ERROR_CODE_OK; - LOGD("## initInboundSessionJni(): success - result=%ld", sessionResult); + LOGD("## initInboundSessionJni(): success - result=%lu", static_cast(sessionResult)); } // free local alloc @@ -296,7 +296,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); size_t theirIdentityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); - LOGD("## initInboundSessionFromIdKeyJni(): message=%s messageLength=%lu",messagePtr,messageLength); + LOGD("## initInboundSessionFromIdKeyJni(): message=%s messageLength=%lu",messagePtr,static_cast(messageLength)); sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); if(sessionResult == olm_error()) { @@ -305,7 +305,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, else { retCode = ERROR_CODE_OK; - LOGD("## initInboundSessionFromIdKeyJni(): success - result=%ld", sessionResult); + LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(sessionResult)); } } @@ -357,7 +357,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje else { retCode = ERROR_CODE_OK; - LOGD("## matchesInboundSessionJni(): success - result=%ld", matchResult); + LOGD("## matchesInboundSessionJni(): success - result=%lu", static_cast(matchResult)); } } @@ -417,7 +417,7 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J else { retCode = ERROR_CODE_OK; - LOGD("## matchesInboundSessionFromIdKeyJni(): success - result=%lu", matchResult); + LOGD("## matchesInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(matchResult)); } } @@ -492,7 +492,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // Note: olm_encrypt_random_length() can return 0, which means // it just does not need new random data to encrypt a new message size_t randomLength = olm_encrypt_random_length(sessionPtr); - LOGD("## encryptMessageJni(): randomLength=%lu", randomLength); + LOGD("## encryptMessageJni(): randomLength=%lu", static_cast(randomLength)); if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) { LOGE("## encryptMessageJni(): failure - random buffer init"); @@ -513,7 +513,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz LOGW("## encryptMessageJni(): random buffer is not required"); } - LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu clearMsgLength=%lu encryptedMsgLength=%lu",messageType,randomLength, clearMsgLength, encryptedMsgLength); + LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu clearMsgLength=%lu encryptedMsgLength=%lu",static_cast(messageType),static_cast(randomLength), static_cast(clearMsgLength), static_cast(encryptedMsgLength)); // encrypt message size_t result = olm_encrypt(sessionPtr, (void const *)clearMsgPtr, @@ -539,7 +539,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring); retCode = ERROR_CODE_OK; - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", result, messageType, (size_t)env->GetStringUTFLength(encryptedJstring), (const char*)encryptedMsgPtr); + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", static_cast(result), static_cast(messageType), static_cast((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr); } } } @@ -624,7 +624,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t // create a dedicated temp buffer to be used in next Olm API calls tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): MsgType=%ld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr); + LOGD("## decryptMessageJni(): MsgType=%lu encryptedMsgLength=%lu encryptedMsg=%s",static_cast(encryptedMsgType),static_cast(encryptedMsgLength),encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, @@ -639,7 +639,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } else { - LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength); + LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); // allocate output decrypted message plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); @@ -661,7 +661,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t // update decrypted buffer size (static_cast(plainTextMsgPtr))[plaintextLength] = static_cast('\0'); - LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast(plainTextMsgPtr)); + LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), static_cast(plainTextMsgPtr)); decryptedMsgRetValue = env->NewStringUTF(static_cast(plainTextMsgPtr)); } } @@ -707,7 +707,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job { // get the size to alloc to contain the id size_t lengthSessionId = olm_session_id_length(sessionPtr); - LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",lengthSessionId); + LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",static_cast(lengthSessionId)); if(NULL == (sessionIdPtr = (void*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) { @@ -726,7 +726,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job // update length (static_cast(sessionIdPtr))[result] = static_cast('\0'); - LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr); + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); } free(sessionIdPtr); @@ -783,7 +783,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job { size_t pickledLength = olm_pickle_session_length(sessionPtr); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) @@ -812,7 +812,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(pickledPtr)); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } } } @@ -865,7 +865,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j { size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -882,7 +882,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index e11f7eb..bd93de1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -26,7 +26,7 @@ OlmUtility* initializeUtilityMemory() if(NULL != (utilityPtr=(OlmUtility*)malloc(utilitySize))) { utilityPtr = olm_utility(utilityPtr); - LOGD("## initializeUtilityMemory(): success - OLM utility size=%lu",utilitySize); + LOGD("## initializeUtilityMemory(): success - OLM utility size=%lu",static_cast(utilitySize)); } else { @@ -61,6 +61,8 @@ JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz { OlmUtility* utilityPtr = NULL; + LOGD("## releaseUtilityJni(): IN"); + if(NULL == (utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) { LOGE("## releaseUtilityJni(): failure - utility ptr=NULL"); @@ -118,7 +120,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j size_t signatureLength = (size_t)env->GetStringUTFLength(aSignature); size_t keyLength = (size_t)env->GetStringUTFLength(aKey); size_t messageLength = (size_t)env->GetStringUTFLength(aMessage); - LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",signatureLength,keyLength,messageLength); + LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",static_cast(signatureLength),static_cast(keyLength),static_cast(messageLength)); size_t result = olm_ed25519_verify(utilityPtr, (void const *)keyPtr, @@ -134,7 +136,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j } else { - LOGD("## verifyEd25519SignatureJni(): success - result=%ld", result); + LOGD("## verifyEd25519SignatureJni(): success - result=%lu", static_cast(result)); } } @@ -210,7 +212,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst // update length (static_cast(hashValuePtr))[result] = static_cast('\0'); - LOGD("## sha256Jni(): success - result=%lu hashValue=%s",result, (char*)hashValuePtr); + LOGD("## sha256Jni(): success - result=%lu hashValue=%s",static_cast(result), (char*)hashValuePtr); sha256RetValue = env->NewStringUTF((const char*)hashValuePtr); } } -- cgit v1.2.3 From 1af282fb3793bd56d6a6a5c60e9f6914c6df643e Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 25 Oct 2016 10:21:15 +0200 Subject: Add new file: test helper methods --- .../java/org/matrix/olm/TestHelper.java | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java new file mode 100644 index 0000000..fbb9e24 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java @@ -0,0 +1,85 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Iterator; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Helper class providing helper methods used in the Olm Android SDK unit tests. + */ +public class TestHelper { + + /** + * Return the identity key {@link OlmAccount#JSON_KEY_IDENTITY_KEY} from the JSON object. + * @param aIdentityKeysObj JSON result of {@link OlmAccount#identityKeys()} + * @return identity key string if operation succeed, null otherwise + */ + static public String getIdentityKey(JSONObject aIdentityKeysObj){ + String idKey = null; + + try { + idKey = aIdentityKeysObj.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); + } catch (JSONException e) { + assertTrue("Exception MSg=" + e.getMessage(), false); + } + return idKey; + } + + /** + * Return the fingerprint key {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} from the JSON object. + * @param aIdentityKeysObj JSON result of {@link OlmAccount#identityKeys()} + * @return fingerprint key string if operation succeed, null otherwise + */ + static public String getFingerprintKey(JSONObject aIdentityKeysObj){ + String fingerprintKey = null; + + try { + fingerprintKey = aIdentityKeysObj.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); + } catch (JSONException e) { + assertTrue("Exception MSg=" + e.getMessage(), false); + } + return fingerprintKey; + } + + /** + * Return the first one time key from the JSON object. + * @param aIdentityKeysObj JSON result of {@link OlmAccount#oneTimeKeys()} + * @return one time key string if operation succeed, null otherwise + */ + static public String getFirstOneTimeKey(JSONObject aIdentityKeysObj) { + String firstOneTimeKey = null; + + try { + JSONObject generatedKeys = aIdentityKeysObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY + " object is missing", generatedKeys); + + Iterator generatedKeysIt = generatedKeys.keys(); + if (generatedKeysIt.hasNext()) { + firstOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); + } + } catch (JSONException e) { + assertTrue("Exception Msg=" + e.getMessage(), false); + } + return firstOneTimeKey; + } +} -- cgit v1.2.3 From f3d4789b588bfc8af2135c2b2caafbc7d76d4feb Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 25 Oct 2016 18:13:44 +0200 Subject: Renaming: - generateOneTimeKeys => generateOneTimeKeysJni - maxOneTimeKeys => maxOneTimeKeysJni --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 16 ++++++++-------- .../android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index c68e390..07446b0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -199,7 +199,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject * Get the maximum number of "one time keys" the account can store. * **/ -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz) { OlmAccount* accountPtr = NULL; size_t maxKeys = -1; @@ -222,7 +222,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz) * @param aNumberOfKeys number of keys to generate * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) { OlmAccount *accountPtr = NULL; uint8_t *randomBufferPtr = NULL; @@ -233,30 +233,30 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE("## generateOneTimeKeys(): failure - invalid Account ptr"); + LOGE("## generateOneTimeKeysJni(): failure - invalid Account ptr"); } else { // keys memory allocation randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); - LOGD("## generateOneTimeKeys(): randomLength=%lu", static_cast(randomLength)); + LOGD("## generateOneTimeKeysJni(): randomLength=%lu", static_cast(randomLength)); if((0!=randomLength) && !setRandomInBuffer(&randomBufferPtr, randomLength)) { - LOGE("## generateOneTimeKeys(): failure - random buffer init"); + LOGE("## generateOneTimeKeysJni(): failure - random buffer init"); } else { - LOGD("## generateOneTimeKeys(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); + LOGD("## generateOneTimeKeysJni(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); // retrieve key pairs in keysBytesPtr result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); if(result == olm_error()) { - LOGE("## generateOneTimeKeys(): failure - error generating one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + LOGE("## generateOneTimeKeysJni(): failure - error generating one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else { retCode = ERROR_CODE_OK; - LOGD("## generateOneTimeKeys(): success - result=%lu", static_cast(result)); + LOGD("## generateOneTimeKeysJni(): success - result=%lu", static_cast(result)); } } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 1c8fb96..2aa5f93 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -39,8 +39,8 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject // one time keys JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); -- cgit v1.2.3 From a6401c72e6c382b906850d8975331df25439db00 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 25 Oct 2016 18:14:39 +0200 Subject: Update olm_matches_inbound_session_(from)() return code processing --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index c4460b3..a31d48f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -351,7 +351,9 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); - if(matchResult == olm_error()) { + //if(matchResult == olm_error()) { + // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 + if(matchResult != 1) { LOGE("## matchesInboundSessionJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else @@ -411,7 +413,9 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); - if(matchResult == olm_error()) { + //if(matchResult == olm_error()) { + // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 + if(matchResult != 1) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else -- cgit v1.2.3 From eb2052ba057f4e0de58adea6c69eba9062e096b6 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 25 Oct 2016 18:16:19 +0200 Subject: Update due to renaming in olm_account.cpp (maxOneTimeKeysJni() & generateOneTimeKeysJni()) Fix removeOneTimeKeysForSession() default return code --- .../olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 2381585..116d435 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -282,7 +282,10 @@ public class OlmAccount implements Serializable { * Return the largest number of "one time keys" this account can store. * @return the max number of "one time keys", -1 otherwise */ - public native long maxOneTimeKeys(); + public long maxOneTimeKeys() { + return maxOneTimeKeysJni(); + } + private native long maxOneTimeKeysJni(); /** * Generate a number of new one time keys.
If total number of keys stored @@ -291,7 +294,10 @@ public class OlmAccount implements Serializable { * @param aNumberOfKeys number of keys to generate * @return 0 if operation succeed, -1 otherwise */ - public native int generateOneTimeKeys(int aNumberOfKeys); + public int generateOneTimeKeys(int aNumberOfKeys) { + return generateOneTimeKeysJni(aNumberOfKeys); + } + private native int generateOneTimeKeysJni(int aNumberOfKeys); /** * Return the "one time keys" in a JSON array.
@@ -341,7 +347,7 @@ public class OlmAccount implements Serializable { * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed */ public int removeOneTimeKeysForSession(OlmSession aSession) { - int retCode = 0; + int retCode = -1; if(null != aSession) { retCode = removeOneTimeKeysForSessionJni(aSession.getOlmSessionId()); -- cgit v1.2.3 From 232de794f2109e468d33225610cc0b6e4e22ed12 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 25 Oct 2016 18:18:40 +0200 Subject: Update return code for initOutboundSessionWithAccount() and initInboundSessionWithAccount(): An error code is now returned, no utility to return the object itself (initial implementation matching iOS) --- .../src/main/java/org/matrix/olm/OlmSession.java | 26 +++++++++------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 5877d24..867cef9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -231,20 +231,18 @@ public class OlmSession implements Serializable { * @param aAccount the account to associate with this session * @param aTheirIdentityKey the identity key of the recipient * @param aTheirOneTimeKey the one time key of the recipient - * @return this if operation succeed, null otherwise + * @return 0 if operation succeed, -1 otherwise */ - public OlmSession initOutboundSessionWithAccount(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) { - OlmSession retObj=null; + public int initOutboundSessionWithAccount(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) { + int retCode=-1; if((null==aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)){ Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); } else { - if(0 == initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey)) { - retObj = this; - } + retCode = initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey); } - return retObj; + return retCode; } private native int initOutboundSessionJni(long aOlmAccountId, String aTheirIdentityKey, String aTheirOneTimeKey); @@ -252,25 +250,23 @@ public class OlmSession implements Serializable { /** * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY ({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message.
+ * incoming PRE_KEY message ({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}).
* Public API for {@link #initInboundSessionJni(long, String)}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session * @param aPreKeyMsg PRE KEY message - * @return this if operation succeed, null otherwise + * @return 0 if operation succeed, -1 otherwise */ - public OlmSession initInboundSessionWithAccount(OlmAccount aAccount, String aPreKeyMsg) { - OlmSession retObj=null; + public int initInboundSessionWithAccount(OlmAccount aAccount, String aPreKeyMsg) { + int retCode=-1; if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - if( 0 == initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg)) { - retObj = this; - } + retCode = initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg); } - return retObj; + return retCode; } private native int initInboundSessionJni(long aOlmAccountId, String aOneTimeKeyMsg); -- cgit v1.2.3 From b140e481830a2d82152801724b004251f502d60e Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 25 Oct 2016 18:21:50 +0200 Subject: Add missing copyright header Add sanity tests for OlmAccount and OlmSession Add a first version of MatchInboundSession --- .../java/org/matrix/olm/OlmAccountTest.java | 102 ++++++-- .../java/org/matrix/olm/OlmGroupSessionTest.java | 16 ++ .../java/org/matrix/olm/OlmSessionTest.java | 279 +++++++++++++++------ .../java/org/matrix/olm/OlmUtilityTest.java | 31 ++- .../java/org/matrix/olm/TestHelper.java | 11 +- 5 files changed, 327 insertions(+), 112 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 6c1cbf3..838fba2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -1,8 +1,22 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.matrix.olm; -import android.accounts.Account; import android.content.Context; -import android.content.SharedPreferences; import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import android.util.Log; @@ -18,7 +32,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; -import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; @@ -28,7 +41,6 @@ import java.io.ObjectOutputStream; import java.util.Iterator; import static android.support.test.InstrumentationRegistry.getInstrumentation; -import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -71,6 +83,9 @@ public class OlmAccountTest { // TBD } + /** + * Basic test: creation and release. + */ @Test public void test01CreateReleaseAccount() { try { @@ -102,12 +117,18 @@ public class OlmAccountTest { assertTrue(0!=olmNativeInstance); } + /** + * Test if {@link OlmAccount#identityKeys()} returns a JSON object + * that contains the following keys: {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} + * and {@link OlmAccount#JSON_KEY_IDENTITY_KEY} + */ @Test public void test05IdentityKeys() { JSONObject identityKeysJson = mOlmAccount.identityKeys(); assertNotNull(identityKeysJson); Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson); + // is JSON_KEY_FINGER_PRINT_KEY present? try { String fingerPrintKey = identityKeysJson.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); @@ -116,6 +137,7 @@ public class OlmAccountTest { assertTrue("Exception MSg="+e.getMessage(), false); } + // is JSON_KEY_IDENTITY_KEY present? try { String identityKey = identityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); assertTrue("identity key missing",!TextUtils.isEmpty(identityKey)); @@ -138,12 +160,18 @@ public class OlmAccountTest { assertTrue(maxOneTimeKeys>0); } + /** + * Test one time keys generation. + */ @Test public void test07GenerateOneTimeKeys() { int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); assertTrue(0==retValue); } + /** + * Test the generated amount of one time keys = GENERATION_ONE_TIME_KEYS_NUMBER. + */ @Test public void test08OneTimeKeysJsonFormat() { int oneTimeKeysCount = 0; @@ -227,11 +255,8 @@ public class OlmAccountTest { // get keys references JSONObject identityKeysRef = accountRef.identityKeys(); JSONObject oneTimeKeysRef = accountRef.oneTimeKeys(); - - /*Context context = getInstrumentation().getContext(); - SharedPreferences sharedPref = context.getSharedPreferences("TestPref",Context.MODE_PRIVATE); - SharedPreferences.Editor editPref = sharedPref.edit(); - editPref.putLong();*/ + assertNotNull(identityKeysRef); + assertNotNull(oneTimeKeysRef); try { Context context = getInstrumentation().getContext(); @@ -249,20 +274,19 @@ public class OlmAccountTest { ObjectInputStream objectInput = new ObjectInputStream(fileInput); accountDeserial = (OlmAccount) objectInput.readObject(); objectInput.close(); - assertNotNull(accountDeserial); // get de-serialized keys - JSONObject identityKeys2 = accountDeserial.identityKeys(); - assertNotNull(identityKeys2); - JSONObject oneTimeKeys2 = accountDeserial.oneTimeKeys(); - assertNotNull(oneTimeKeys2); + JSONObject identityKeysDeserial = accountDeserial.identityKeys(); + JSONObject oneTimeKeysDeserial = accountDeserial.oneTimeKeys(); + assertNotNull(identityKeysDeserial); + assertNotNull(oneTimeKeysDeserial); // compare identity keys - assertTrue(identityKeys2.toString().equals(identityKeysRef.toString())); + assertTrue(identityKeysDeserial.toString().equals(identityKeysRef.toString())); // compare onetime keys - assertTrue(oneTimeKeys2.toString().equals(oneTimeKeysRef.toString())); + assertTrue(oneTimeKeysDeserial.toString().equals(oneTimeKeysRef.toString())); accountRef.releaseAccount(); accountDeserial.releaseAccount(); @@ -285,4 +309,50 @@ public class OlmAccountTest { } + // **************************************************** + // *************** SANITY CHECK TESTS ***************** + // **************************************************** + + @Test + public void test14GenerateOneTimeKeysError() { + // keys number = 0 => no error + int retValue = mOlmAccount.generateOneTimeKeys(0); + assertTrue(0==retValue); + + // keys number = negative value + retValue = mOlmAccount.generateOneTimeKeys(-50); + assertTrue(-1==retValue); + } + + @Test + public void test15RemoveOneTimeKeysForSessionError() { + OlmAccount olmAccount = null; + try { + olmAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + int sessionRetCode = olmAccount.removeOneTimeKeysForSession(null); + // test against no matching keys + assertTrue(-1 == sessionRetCode); + + olmAccount.releaseAccount(); + } + + @Test + public void test16SignMessageError() { + OlmAccount olmAccount = null; + try { + olmAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + String clearMsg = null; + String signedMsg = olmAccount.signMessage(clearMsg); + assertNull(signedMsg); + + olmAccount.releaseAccount(); + } + } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index c2a266b..64eb7ce 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -1,3 +1,19 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.matrix.olm; import android.content.Context; diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index caa1e46..f8519d1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -1,10 +1,25 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.matrix.olm; import android.content.Context; import android.support.test.runner.AndroidJUnit4; import android.util.Log; -import org.json.JSONException; import org.json.JSONObject; import org.junit.BeforeClass; import org.junit.FixMethodOrder; @@ -18,7 +33,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.Iterator; import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertNotNull; @@ -28,7 +42,9 @@ import static org.junit.Assert.assertTrue; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class OlmSessionTest { private static final String LOG_TAG = "OlmSessionTest"; + private final String INVALID_PRE_KEY = "invalid PRE KEY hu hu!"; private final String FILE_NAME_SERIAL_SESSION = "SerialSession"; + private final int ONE_TIME_KEYS_NUMBER = 4; private static OlmManager mOlmManager; @@ -73,30 +89,14 @@ public class OlmSessionTest { // get bob identity key JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - assertNotNull(bobIdentityKeysJson); - try { - bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); - assertTrue(null!=bobIdentityKey); - } catch (JSONException e) { - assertTrue("Exception MSg="+e.getMessage(), false); - } + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + assertTrue(null!=bobIdentityKey); // get bob one time keys assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - assertNotNull(bobOneTimeKeysJsonObj); - try { - JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); - assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys); - - Iterator generatedKeysIt = generatedKeys.keys(); - if(generatedKeysIt.hasNext()) { - bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); - } - assertNotNull(bobOneTimeKey); - } catch (JSONException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + assertNotNull(bobOneTimeKey); // CREATE ALICE SESSION OlmSession aliceSession = null; @@ -112,6 +112,7 @@ public class OlmSessionTest { String clearMsg = "Heloo bob , this is alice!"; OlmMessage encryptedMsgToBob = aliceSession.encryptMessage(clearMsg); assertNotNull(encryptedMsgToBob); + assertNotNull(encryptedMsgToBob.mCipherText); Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText); // CREATE BOB INBOUND SESSION and decrypt message from alice @@ -122,7 +123,7 @@ public class OlmSessionTest { assertTrue("Exception Msg="+e.getMessage(), false); } assertTrue(0!=bobSession.getOlmSessionId()); - assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); + assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); assertNotNull(decryptedMsg); @@ -131,6 +132,7 @@ public class OlmSessionTest { // clean objects.. assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + // release accounts bobAccount.releaseAccount(); aliceAccount.releaseAccount(); @@ -154,9 +156,8 @@ public class OlmSessionTest { */ @Test public void test02AliceToBobBackAndForth() { - final int ONE_TIME_KEYS_NUMBER = 1; - String bobIdentityKey = null; - String bobOneTimeKey=null; + String bobIdentityKey; + String bobOneTimeKey; OlmAccount aliceAccount = null; OlmAccount bobAccount = null; @@ -174,31 +175,14 @@ public class OlmSessionTest { // get bob identity key JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - assertNotNull(bobIdentityKeysJson); - try { - bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); - assertTrue(null!=bobIdentityKey); - } catch (JSONException e) { - assertTrue("Exception MSg="+e.getMessage(), false); - } + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + assertTrue(null!=bobIdentityKey); // get bob one time keys assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - assertNotNull(bobOneTimeKeysJsonObj); - try { - JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); - assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys); - - Iterator generatedKeysIt = generatedKeys.keys(); - if(generatedKeysIt.hasNext()) { - // return first otk - bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); - } - assertNotNull(bobOneTimeKey); - } catch (JSONException e) { - assertTrue("Exception MSg="+e.getMessage(), false); - } + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + assertNotNull(bobOneTimeKey); // CREATE ALICE SESSION OlmSession aliceSession = null; @@ -215,6 +199,7 @@ public class OlmSessionTest { OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); assertNotNull(encryptedAliceToBobMsg1); + assertNotNull(encryptedAliceToBobMsg1.mCipherText); // CREATE BOB INBOUND SESSION and decrypt message from alice OlmSession bobSession = null; @@ -224,7 +209,7 @@ public class OlmSessionTest { assertTrue("Exception Msg="+e.getMessage(), false); } assertTrue(0!=bobSession.getOlmSessionId()); - assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); // DECRYPT MESSAGE FROM ALICE String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); @@ -233,8 +218,6 @@ public class OlmSessionTest { // MESSAGE COMPARISON: decrypted vs encrypted assertTrue(helloClearMsg.equals(decryptedMsg01)); - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); - // BACK/FORTH MESSAGE COMPARISON String clearMsg1 = "Hello I'm Bob!"; String clearMsg2 = "Isn't life grand?"; @@ -256,15 +239,19 @@ public class OlmSessionTest { String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); assertNotNull(decryptedMsg3); + // and one more form alice.. + encryptedMsg1 = aliceSession.encryptMessage(clearMsg1); + // comparison tests assertTrue(clearMsg1.equals(decryptedMsg1)); assertTrue(clearMsg2.equals(decryptedMsg2)); assertTrue(clearMsg3.equals(decryptedMsg3)); // clean objects.. + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); bobAccount.releaseAccount(); - aliceAccount.releaseAccount(); bobSession.releaseSession(); + aliceAccount.releaseAccount(); aliceSession.releaseSession(); } @@ -312,24 +299,86 @@ public class OlmSessionTest { // must be the same for both ends of the conversation assertTrue(aliceSessionId.equals(bobSessionId)); + + aliceAccount.releaseAccount(); + aliceSession.releaseSession(); + bobAccount.releaseAccount(); + bobSession.releaseSession(); + } + + @Test + public void test04MatchInboundSession() { + OlmAccount aliceAccount=null, bobAccount=null; + OlmSession aliceSession = null, bobSession = null; + + // ACCOUNTS CREATION + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(), false); + } + + // CREATE ALICE SESSION + try { + aliceSession = new OlmSession(); + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg=" + e.getMessage(), false); + } + + // get bob/luke identity key + JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); + JSONObject aliceIdentityKeysJson = aliceAccount.identityKeys(); + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + String aliceIdentityKey = TestHelper.getIdentityKey(aliceIdentityKeysJson); + + // get bob/luke one time keys + assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); + assertTrue(0 == aliceAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); + JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); + String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj, 1); + + // create alice inbound session for bob + assertTrue(0==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey1)); + + String aliceClearMsg = "hello helooo to bob!"; + OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg); + assertTrue(false==bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); + + // init bob session with alice PRE KEY + assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + + // test matchesInboundSession() and matchesInboundSessionFrom() + assertTrue(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); + assertTrue(bobSession.matchesInboundSessionFrom(aliceIdentityKey, encryptedAliceToBobMsg1.mCipherText)); + // following requires olm native lib new version with https://github.com/matrix-org/olm-backup/commit/7e9f3bebb8390f975a76c0188ce4cb460fe6692e + //assertTrue(false==bobSession.matchesInboundSessionFrom(bobIdentityKey, encryptedAliceToBobMsg1.mCipherText)); + + // release objects + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + aliceAccount.releaseAccount(); + bobAccount.releaseAccount(); + aliceSession.releaseSession(); + bobSession.releaseSession(); } // ******************************************************** // ************* SERIALIZATION TEST *********************** // ******************************************************** /** - * Same as test02AliceToBobBackAndForth() but alice's session + * Same as {@link #test02AliceToBobBackAndForth()}, but alice's session * is serialized and de-serialized before performing the final * comparison (encrypt vs ) */ @Test - public void test03SessionSerialization() { + public void test05SessionSerialization() { final int ONE_TIME_KEYS_NUMBER = 1; - String bobIdentityKey = null; - String bobOneTimeKey=null; + String bobIdentityKey; + String bobOneTimeKey; OlmAccount aliceAccount = null; OlmAccount bobAccount = null; - OlmSession aliceSessionDeserial; + OlmSession aliceSessionDeserial = null; // creates alice & bob accounts try { @@ -345,31 +394,14 @@ public class OlmSessionTest { // get bob identity key JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - assertNotNull(bobIdentityKeysJson); - try { - bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); - assertTrue(null!=bobIdentityKey); - } catch (JSONException e) { - assertTrue("Exception MSg="+e.getMessage(), false); - } + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + assertTrue(null!=bobIdentityKey); // get bob one time keys assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - assertNotNull(bobOneTimeKeysJsonObj); - try { - JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); - assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys); - - Iterator generatedKeysIt = generatedKeys.keys(); - if(generatedKeysIt.hasNext()) { - // return first otk - bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); - } - assertNotNull(bobOneTimeKey); - } catch (JSONException e) { - assertTrue("Exception MSg="+e.getMessage(), false); - } + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + assertNotNull(bobOneTimeKey); // CREATE ALICE SESSION OlmSession aliceSession = null; @@ -386,6 +418,7 @@ public class OlmSessionTest { OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); assertNotNull(encryptedAliceToBobMsg1); + assertNotNull(encryptedAliceToBobMsg1.mCipherText); // CREATE BOB INBOUND SESSION and decrypt message from alice OlmSession bobSession = null; @@ -395,7 +428,7 @@ public class OlmSessionTest { assertTrue("Exception Msg="+e.getMessage(), false); } assertTrue(0!=bobSession.getOlmSessionId()); - assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); // DECRYPT MESSAGE FROM ALICE String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); @@ -404,8 +437,6 @@ public class OlmSessionTest { // MESSAGE COMPARISON: decrypted vs encrypted assertTrue(helloClearMsg.equals(decryptedMsg01)); - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); - // BACK/FORTH MESSAGE COMPARISON String clearMsg1 = "Hello I'm Bob!"; String clearMsg2 = "Isn't life grand?"; @@ -451,6 +482,7 @@ public class OlmSessionTest { assertTrue(clearMsg3.equals(decryptedMsg3)); // clean objects.. + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); bobAccount.releaseAccount(); aliceAccount.releaseAccount(); bobSession.releaseSession(); @@ -473,4 +505,91 @@ public class OlmSessionTest { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); } } + + + // **************************************************** + // *************** SANITY CHECK TESTS ***************** + // **************************************************** + + @Test + public void test06SanityCheckErrors() { + final int ONE_TIME_KEYS_NUMBER = 5; + OlmAccount bobAccount = null; + OlmAccount aliceAccount = null; + + // ALICE & BOB ACCOUNTS CREATION + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(), false); + } + + // get bob identity key + JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + assertTrue(null != bobIdentityKey); + + // get bob one time keys + assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); + JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); + assertNotNull(bobOneTimeKeysJsonObj); + String bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + assertNotNull(bobOneTimeKey); + + // CREATE ALICE SESSION + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg=" + e.getMessage(), false); + } + + // SANITY CHECK TESTS FOR: initOutboundSessionWithAccount() + assertTrue(-1==aliceSession.initOutboundSessionWithAccount(null, bobIdentityKey, bobOneTimeKey)); + assertTrue(-1==aliceSession.initOutboundSessionWithAccount(aliceAccount, null, bobOneTimeKey)); + assertTrue(-1==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, null)); + assertTrue(-1==aliceSession.initOutboundSessionWithAccount(null, null, null)); + + // init properly + assertTrue(0==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + + // SANITY CHECK TESTS FOR: encryptMessage() + assertTrue(null==aliceSession.encryptMessage(null)); + + // encrypt properly + OlmMessage encryptedMsgToBob = aliceSession.encryptMessage("A message for bob"); + assertNotNull(encryptedMsgToBob); + + // SANITY CHECK TESTS FOR: initInboundSessionWithAccount() + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + assertTrue(-1==bobSession.initInboundSessionWithAccount(null, encryptedMsgToBob.mCipherText)); + assertTrue(-1==bobSession.initInboundSessionWithAccount(bobAccount, null)); + assertTrue(-1==bobSession.initInboundSessionWithAccount(bobAccount, INVALID_PRE_KEY)); + // init properly + assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + + // SANITY CHECK TESTS FOR: decryptMessage() + String decryptedMsg = aliceSession.decryptMessage(null); + assertTrue(null==decryptedMsg); + + // SANITY CHECK TESTS FOR: matchesInboundSession() + assertTrue(!aliceSession.matchesInboundSession(null)); + + // SANITY CHECK TESTS FOR: matchesInboundSessionFrom() + assertTrue(!aliceSession.matchesInboundSessionFrom(null,null)); + + // release objects + assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + aliceAccount.releaseAccount(); + bobAccount.releaseAccount(); + aliceSession.releaseSession(); + bobSession.releaseSession(); + } + } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 12aff1f..e483d71 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -1,22 +1,32 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package org.matrix.olm; import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import android.util.Log; -import org.json.JSONException; import org.json.JSONObject; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; -import java.util.Iterator; - import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -64,13 +74,8 @@ public class OlmUtilityTest { // get identities key (finger print key) JSONObject identityKeysJson = account.identityKeys(); assertNotNull(identityKeysJson); - try { - fingerPrintKey = identityKeysJson.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); - assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); - } catch (JSONException e) { - e.printStackTrace(); - assertTrue("Exception MSg="+e.getMessage(), false); - } + fingerPrintKey = TestHelper.getFingerprintKey(identityKeysJson); + assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); // instantiate utility object OlmUtility utility = new OlmUtility(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java index fbb9e24..88b54e6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java @@ -64,18 +64,23 @@ public class TestHelper { /** * Return the first one time key from the JSON object. * @param aIdentityKeysObj JSON result of {@link OlmAccount#oneTimeKeys()} + * @param aKeyPosition the poistion of the key to be retrieved * @return one time key string if operation succeed, null otherwise */ - static public String getFirstOneTimeKey(JSONObject aIdentityKeysObj) { + static public String getOneTimeKey(JSONObject aIdentityKeysObj, int aKeyPosition) { String firstOneTimeKey = null; + int i=0; try { JSONObject generatedKeys = aIdentityKeysObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY + " object is missing", generatedKeys); Iterator generatedKeysIt = generatedKeys.keys(); - if (generatedKeysIt.hasNext()) { - firstOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); + while(i errorMsg = INVALID_BASE64 + String badSizeFingerPrintKey = fingerPrintKey.substring(fingerPrintKey.length()/2); + isVerified = utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message, errorMsg); + assertFalse(isVerified); + assertFalse(String.valueOf(errorMsg).isEmpty()); + utility.releaseUtility(); account.releaseAccount(); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index bd93de1..19a045b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -121,6 +121,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j size_t keyLength = (size_t)env->GetStringUTFLength(aKey); size_t messageLength = (size_t)env->GetStringUTFLength(aMessage); LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",static_cast(signatureLength),static_cast(keyLength),static_cast(messageLength)); + LOGD(" ## verifyEd25519SignatureJni(): key=%s",keyPtr); size_t result = olm_ed25519_verify(utilityPtr, (void const *)keyPtr, @@ -132,7 +133,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j if(result == olm_error()) { const char *errorMsgPtr = olm_utility_last_error(utilityPtr); errorMessageRetValue = env->NewStringUTF(errorMsgPtr); - LOGE("## verifyEd25519SignatureJni(): failure - session creation Msg=%s",errorMsgPtr); + LOGE("## verifyEd25519SignatureJni(): failure - olm_ed25519_verify Msg=%s",errorMsgPtr); } else { -- cgit v1.2.3 From d6824a4f499e83a31181b22b8be1e31ce1670277 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 26 Oct 2016 18:12:38 +0200 Subject: Revert loadLibrary as static. --- .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 403b4b3..21734dc 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -16,13 +16,16 @@ package org.matrix.olm; - import android.util.Log; +/** + * Olm SDK entry point class.
An OlmManager instance must be created at first to enable native library load. + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ public class OlmManager { private static final String LOG_TAG = "OlmManager"; - public OlmManager() { + static { try { java.lang.System.loadLibrary("olm"); } catch(UnsatisfiedLinkError e) { -- cgit v1.2.3 From 6204fcd128279f876723eb2afefb6d278830465f Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 26 Oct 2016 18:15:37 +0200 Subject: Add javadoc auto generation: - add a buildJavaDoc task in build.gradle - update classes javadoc headers --- java/android/OlmLibSdk/olm-sdk/build.gradle | 10 ++++++++-- .../java/org/matrix/olm/OlmGroupSessionTest.java | 1 - .../java/org/matrix/olm/OlmSessionTest.java | 3 ++- .../src/main/java/org/matrix/olm/OlmAccount.java | 19 ++++++++++++------- .../src/main/java/org/matrix/olm/OlmException.java | 2 +- .../java/org/matrix/olm/OlmInboundGroupSession.java | 18 ++++++++++++------ .../src/main/java/org/matrix/olm/OlmMessage.java | 5 +++++ .../java/org/matrix/olm/OlmOutboundGroupSession.java | 19 +++++++++++++------ .../src/main/java/org/matrix/olm/OlmSession.java | 20 ++++++++++++++------ .../src/main/java/org/matrix/olm/OlmUtility.java | 3 +++ 10 files changed, 70 insertions(+), 30 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle index 2f92151..393342b 100644 --- a/java/android/OlmLibSdk/olm-sdk/build.gradle +++ b/java/android/OlmLibSdk/olm-sdk/build.gradle @@ -24,6 +24,13 @@ android { jni.srcDirs = [] } + task buildJavaDoc(type: Javadoc) { + source = android.sourceSets.main.java.srcDirs + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + destinationDir = file("./doc/") + failOnError false + } + task ndkBuildNativeRelease(type: Exec, description: 'NDK building..') { println 'ndkBuildNativeRelease starts..' workingDir file('src/main') @@ -53,11 +60,10 @@ android { println 'test compile: Release' compileTask.dependsOn ndkBuildNativeRelease } + compileTask.dependsOn buildJavaDoc } - clean.dependsOn cleanNative - } def getNdkFolder() { diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 64eb7ce..5bd6838 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -148,7 +148,6 @@ public class OlmGroupSessionTest { // test decrypted message mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage); assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); - assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); } @Test diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index f8519d1..a011685 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -35,6 +35,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -344,7 +345,7 @@ public class OlmSessionTest { String aliceClearMsg = "hello helooo to bob!"; OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg); - assertTrue(false==bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); + assertFalse(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); // init bob session with alice PRE KEY assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 116d435..0202cdf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -27,6 +27,11 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +/** + * Account class used to create Olm sessions in conjunction with {@link OlmSession} class.
+ * OlmAccount provides APIs to retrieve the Olm keys. + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ public class OlmAccount implements Serializable { private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; @@ -63,8 +68,8 @@ public class OlmAccount implements Serializable { /** * Kick off the serialization mechanism. * @param aOutStream output stream for serializing - * @throws IOException - * @throws OlmException + * @throws IOException exception + * @throws OlmException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { aOutStream.defaultWriteObject(); @@ -86,10 +91,10 @@ public class OlmAccount implements Serializable { /** * Kick off the deserialization mechanism. - * @param aInStream - * @throws IOException - * @throws ClassNotFoundException - * @throws OlmException + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + * @throws OlmException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { aInStream.defaultReadObject(); @@ -243,7 +248,7 @@ public class OlmAccount implements Serializable { private native long createNewAccountJni(); /** - * Return the identity keys (identity & fingerprint keys) in a JSON array.
+ * Return the identity keys (identity and fingerprint keys) in a JSON array.
* Public API for {@link #identityKeysJni()}.
* Ex: * { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index fe43f94..d548cf7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -17,7 +17,7 @@ package org.matrix.olm; /** - * Exception class to identify specific Olm SDk exceptions. + * Exception class to identify specific Olm SDK exceptions. */ public class OlmException extends Exception { // exception codes diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 8d33b2c..7b3ae6e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -28,6 +28,12 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +/** + * Class used to create an inbound Megolm session.
+ * Counter part of the outbound group session {@link OlmOutboundGroupSession}, this class decrypts the messages sent by the outbound side. + * + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ public class OlmInboundGroupSession implements Serializable { private static final long serialVersionUID = -772028491251653253L; private static final String LOG_TAG = "OlmInboundGroupSession"; @@ -130,8 +136,8 @@ public class OlmInboundGroupSession implements Serializable { /** * Kick off the serialization mechanism. * @param aOutStream output stream for serializing - * @throws IOException - * @throws OlmException + * @throws IOException exception + * @throws OlmException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { aOutStream.defaultWriteObject(); @@ -153,10 +159,10 @@ public class OlmInboundGroupSession implements Serializable { /** * Kick off the deserialization mechanism. - * @param aInStream - * @throws IOException - * @throws ClassNotFoundException - * @throws OlmException + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + * @throws OlmException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { aInStream.defaultReadObject(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java index 047db97..5e60e1e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java @@ -16,6 +16,11 @@ package org.matrix.olm; +/** + * Message class used in Olm sessions to contain the encrypted data.
+ * See {@link OlmSession#decryptMessage(OlmMessage)} and {@link OlmSession#encryptMessage(String)}. + *
Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ public class OlmMessage { /** PRE KEY message type (used to establish new Olm session) **/ public final static int MESSAGE_TYPE_PRE_KEY = 0; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 94acbd0..67427a9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -25,6 +25,13 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +/** + * Class used to create an outbound a Megolm session.
+ * To send a first message in an encrypted room, the client should start a new outbound Megolm session. + * The session ID and the session key must be shared with each device in the room within. + * + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ public class OlmOutboundGroupSession implements Serializable { private static final long serialVersionUID = -3133097431283604416L; private static final String LOG_TAG = "OlmOutboundGroupSession"; @@ -55,8 +62,8 @@ public class OlmOutboundGroupSession implements Serializable { /** * Kick off the serialization mechanism. * @param aOutStream output stream for serializing - * @throws IOException - * @throws OlmException + * @throws IOException exception + * @throws OlmException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { aOutStream.defaultWriteObject(); @@ -78,10 +85,10 @@ public class OlmOutboundGroupSession implements Serializable { /** * Kick off the deserialization mechanism. - * @param aInStream - * @throws IOException - * @throws ClassNotFoundException - * @throws OlmException + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + * @throws OlmException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { aInStream.defaultReadObject(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 867cef9..1237efd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -24,6 +24,14 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +/** + * Session class used to create Olm sessions in conjunction with {@link OlmAccount} class.
+ * Olm session is used to encrypt data between devices, especially to create Olm group sessions (see {@link OlmOutboundGroupSession} and {@link OlmInboundGroupSession}).
+ * To establish an Olm session with Bob, Alice calls {@link #initOutboundSessionWithAccount(OlmAccount, String, String)} with Bob's identity and onetime keys. Then Alice generates an encrypted PRE_KEY message ({@link #encryptMessage(String)}) + * used by Bob to open the Olm session in his side with {@link #initOutboundSessionWithAccount(OlmAccount, String, String)}. + * From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}. + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ public class OlmSession implements Serializable { private static final long serialVersionUID = -8975488639186976419L; private static final String LOG_TAG = "OlmSession"; @@ -43,8 +51,8 @@ public class OlmSession implements Serializable { /** * Kick off the serialization mechanism. * @param aOutStream output stream for serializing - * @throws IOException - * @throws OlmException + * @throws IOException exception + * @throws OlmException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { aOutStream.defaultWriteObject(); @@ -66,10 +74,10 @@ public class OlmSession implements Serializable { /** * Kick off the deserialization mechanism. - * @param aInStream - * @throws IOException - * @throws ClassNotFoundException - * @throws OlmException + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + * @throws OlmException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { aInStream.defaultReadObject(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 3bf65a8..9bd7aaa 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -21,6 +21,9 @@ import android.util.Log; import java.util.Random; +/** + * Olm SDK helper class. + */ public class OlmUtility { private static final String LOG_TAG = "OlmUtility"; -- cgit v1.2.3 From 31f8fe23c5de0cf226f5061552c02a5bdc767b6a Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 27 Oct 2016 11:44:33 +0200 Subject: Fix random issue: increase random seed precision to micro sec - previously the random seed was seconds based, and it could originate identical identity keys for different OlmAccount --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 5910c42..239fc68 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -19,6 +19,7 @@ #include "olm_jni_helper.h" #include "olm/olm.h" +#include using namespace AndroidOlmSdk; @@ -31,6 +32,8 @@ using namespace AndroidOlmSdk; bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) { bool retCode = false; + struct timeval timeValue; + if(NULL == aBuffer2Ptr) { LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); @@ -47,10 +50,14 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) { LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); - srand(time(NULL)); // init seed + gettimeofday(&timeValue, NULL); + srand(timeValue.tv_usec); // init seed + for(size_t i=0;i Date: Thu, 27 Oct 2016 17:24:16 +0200 Subject: Update test01VerifyEd25519Signing() with a real message --- .../olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index d4c3382..d40c35a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -56,7 +56,7 @@ public class OlmUtilityTest { public void test01VerifyEd25519Signing() { String fingerPrintKey = null; StringBuffer errorMsg = new StringBuffer(); - String message = "{\"key1\":\"value1\",\"key2\":\"value2\"};"; + String message = "{\"algorithms\":[\"m.megolm.v1.aes-sha2\",\"m.olm.v1.curve25519-aes-sha2\"],\"device_id\":\"YMBYCWTWCG\",\"keys\":{\"curve25519:YMBYCWTWCG\":\"KZFa5YUXV2EOdhK8dcGMMHWB67stdgAP4+xwiS69mCU\",\"ed25519:YMBYCWTWCG\":\"0cEgQJJqjgtXUGp4ZXQQmh36RAxwxr8HJw2E9v1gvA0\"},\"user_id\":\"@mxBob14774891254276b253f42-f267-43ec-bad9-767142bfea30:localhost:8480\"}"; OlmAccount account = null; // create account -- cgit v1.2.3 From 8dbc2b50d523f17ce8c10fddb8e22c35dfe57e82 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 27 Oct 2016 17:54:30 +0200 Subject: Remove unsecure logs (keys value were printed) Rename local parameter properly --- .../olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 0202cdf..321e194 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -264,7 +264,7 @@ public class OlmAccount implements Serializable { if( null != (identityKeysBuffer = identityKeysJni())) { try { identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); - Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); + //Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); } catch (JSONException e) { identityKeysJsonObj = null; Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); @@ -321,21 +321,21 @@ public class OlmAccount implements Serializable { */ public JSONObject oneTimeKeys() { byte identityKeysBuffer[]; - JSONObject identityKeysJsonObj = null; + JSONObject oneTimeKeysJsonObj = null; if( null != (identityKeysBuffer = oneTimeKeysJni())) { try { - identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); - Log.d(LOG_TAG, "## oneTimeKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); + oneTimeKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); + //Log.d(LOG_TAG, "## oneTimeKeys(): OneTime Json keys=" + oneTimeKeysJsonObj.toString()); } catch (JSONException e) { - identityKeysJsonObj = null; + oneTimeKeysJsonObj = null; Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); } } else { Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); } - return identityKeysJsonObj; + return oneTimeKeysJsonObj; } /** * Get the public parts of the unpublished "one time keys" for the account.
-- cgit v1.2.3 From 6348a45515943f5ec2347c6a5d7b9dd613ddb163 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 27 Oct 2016 18:02:38 +0200 Subject: Introduce a new log file (ENABLE_JNI_LOG) to disable/enable logs in JNI side --- .../olm-sdk/src/main/jni/olm_inbound_group_session.cpp | 9 ++++++--- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 13 +++++++------ .../olm-sdk/src/main/jni/olm_outbound_group_session.cpp | 6 +++++- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 20d8cb0..05df22b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -36,9 +36,12 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env else { LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); - +#ifdef ENABLE_JNI_LOG size_t retCode = olm_clear_inbound_group_session(sessionPtr); - LOGI(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); + LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); +#else + olm_clear_inbound_group_session(sessionPtr); +#endif LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); @@ -111,7 +114,7 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); if(sessionResult == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + LOGE(" ## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); } else { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 16eb8b2..29f0310 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -28,18 +28,19 @@ #define TAG "OlmJniNative" /* logging macros */ -//#define ENABLE_LOGS +//#define ENABLE_JNI_LOG #ifdef NDK_DEBUG - #warning "NDK_DEBUG is defined" -#else - #warning "NDK_DEBUG not defined" + #warning NDK_DEBUG is defined! +#endif + +#ifdef ENABLE_JNI_LOG + #warning ENABLE_JNI_LOG is defined! #endif #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) -#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) -#ifdef NDK_DEBUG +#ifdef ENABLE_JNI_LOG #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) #else diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index f7e6754..59327b4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -37,8 +37,12 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en { LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); +#ifdef ENABLE_JNI_LOG size_t retCode = olm_clear_outbound_group_session(sessionPtr); - LOGI(" ## releaseSessionJni(): clear_outbound_group_session=%lu",static_cast(retCode)); + LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",static_cast(retCode)); +#else + olm_clear_outbound_group_session(sessionPtr); +#endif LOGD(" ## releaseSessionJni(): free IN"); free(sessionPtr); -- cgit v1.2.3 From 1f1cbf2b3edff5b2f358e9170350566a564f80f4 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 27 Oct 2016 18:14:04 +0200 Subject: Add new tests for multiple creations of account and outbound group sessions: check random generation function in JNI works properly --- .../java/org/matrix/olm/OlmAccountTest.java | 82 +++++++++++++++++++-- .../java/org/matrix/olm/OlmGroupSessionTest.java | 86 ++++++++++++++++++++-- 2 files changed, 156 insertions(+), 12 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 838fba2..a5cde5e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -41,6 +41,7 @@ import java.io.ObjectOutputStream; import java.util.Iterator; import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -238,10 +239,10 @@ public class OlmAccountTest { @Test public void test13Serialization() { - FileOutputStream fileOutput = null; - ObjectOutputStream objectOutput = null; + FileOutputStream fileOutput; + ObjectOutputStream objectOutput; OlmAccount accountRef = null; - OlmAccount accountDeserial = null; + OlmAccount accountDeserial; try { accountRef = new OlmAccount(); @@ -348,11 +349,82 @@ public class OlmAccountTest { } catch (OlmException e) { assertTrue(e.getMessage(),false); } - String clearMsg = null; - String signedMsg = olmAccount.signMessage(clearMsg); + String signedMsg = olmAccount.signMessage(null); assertNull(signedMsg); olmAccount.releaseAccount(); } + /** + * Create multiple accounts and check that identity keys are still different. + * This test validates random series are provide enough random values. + */ + @Test + public void test17MultipleAccountCreation() { + try { + OlmAccount account1 = new OlmAccount(); + OlmAccount account2 = new OlmAccount(); + OlmAccount account3 = new OlmAccount(); + OlmAccount account4 = new OlmAccount(); + OlmAccount account5 = new OlmAccount(); + OlmAccount account6 = new OlmAccount(); + OlmAccount account7 = new OlmAccount(); + OlmAccount account8 = new OlmAccount(); + OlmAccount account9 = new OlmAccount(); + OlmAccount account10 = new OlmAccount(); + + JSONObject identityKeysJson1 = account1.identityKeys(); + JSONObject identityKeysJson2 = account2.identityKeys(); + JSONObject identityKeysJson3 = account3.identityKeys(); + JSONObject identityKeysJson4 = account4.identityKeys(); + JSONObject identityKeysJson5 = account5.identityKeys(); + JSONObject identityKeysJson6 = account6.identityKeys(); + JSONObject identityKeysJson7 = account7.identityKeys(); + JSONObject identityKeysJson8 = account8.identityKeys(); + JSONObject identityKeysJson9 = account9.identityKeys(); + JSONObject identityKeysJson10 = account10.identityKeys(); + + String identityKey1 = TestHelper.getIdentityKey(identityKeysJson1); + String identityKey2 = TestHelper.getIdentityKey(identityKeysJson2); + assertFalse(identityKey1.equals(identityKey2)); + + String identityKey3 = TestHelper.getIdentityKey(identityKeysJson3); + assertFalse(identityKey2.equals(identityKey3)); + + String identityKey4 = TestHelper.getIdentityKey(identityKeysJson4); + assertFalse(identityKey3.equals(identityKey4)); + + String identityKey5 = TestHelper.getIdentityKey(identityKeysJson5); + assertFalse(identityKey4.equals(identityKey5)); + + String identityKey6 = TestHelper.getIdentityKey(identityKeysJson6); + assertFalse(identityKey5.equals(identityKey6)); + + String identityKey7 = TestHelper.getIdentityKey(identityKeysJson7); + assertFalse(identityKey6.equals(identityKey7)); + + String identityKey8 = TestHelper.getIdentityKey(identityKeysJson8); + assertFalse(identityKey7.equals(identityKey8)); + + String identityKey9 = TestHelper.getIdentityKey(identityKeysJson9); + assertFalse(identityKey8.equals(identityKey9)); + + String identityKey10 = TestHelper.getIdentityKey(identityKeysJson10); + assertFalse(identityKey9.equals(identityKey10)); + + account1.releaseAccount(); + account2.releaseAccount(); + account3.releaseAccount(); + account4.releaseAccount(); + account5.releaseAccount(); + account6.releaseAccount(); + account7.releaseAccount(); + account8.releaseAccount(); + account9.releaseAccount(); + account10.releaseAccount(); + + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 5bd6838..eca070f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -51,7 +51,7 @@ public class OlmGroupSessionTest { private static OlmOutboundGroupSession mAliceOutboundGroupSession; private static String mAliceSessionIdentifier; private static long mAliceMessageIndex; - public static final String CLEAR_MESSAGE1 = "Hello!"; + private static final String CLEAR_MESSAGE1 = "Hello!"; private static String mAliceToBobMessage; private static OlmInboundGroupSession mBobInboundGroupSession; private static String mAliceOutboundSessionKey; @@ -172,7 +172,7 @@ public class OlmGroupSessionTest { @Test public void test14SerializeOutboundSession() { OlmOutboundGroupSession outboundGroupSessionRef=null; - OlmOutboundGroupSession outboundGroupSessionSerial=null; + OlmOutboundGroupSession outboundGroupSessionSerial; // create one OUTBOUND GROUP SESSION try { @@ -238,14 +238,13 @@ public class OlmGroupSessionTest { catch (Exception e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); } - } @Test public void test15SerializeInboundSession() { OlmOutboundGroupSession aliceOutboundGroupSession=null; OlmInboundGroupSession bobInboundGroupSessionRef=null; - OlmInboundGroupSession bobInboundGroupSessionSerial=null; + OlmInboundGroupSession bobInboundGroupSessionSerial; // alice creates OUTBOUND GROUP SESSION try { @@ -306,13 +305,86 @@ public class OlmGroupSessionTest { catch (IOException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); } - /*catch (OlmException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); - }*/ catch (Exception e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); } + } + + /** + * Create multiple outbound group sessions and check that session Keys are different. + * This test validates random series are provide enough random values. + */ + @Test + public void test16MultipleOutboundSession() { + OlmOutboundGroupSession outboundGroupSession1; + OlmOutboundGroupSession outboundGroupSession2; + OlmOutboundGroupSession outboundGroupSession3; + OlmOutboundGroupSession outboundGroupSession4; + OlmOutboundGroupSession outboundGroupSession5; + OlmOutboundGroupSession outboundGroupSession6; + OlmOutboundGroupSession outboundGroupSession7; + OlmOutboundGroupSession outboundGroupSession8; + + try { + outboundGroupSession1 = new OlmOutboundGroupSession(); + outboundGroupSession2 = new OlmOutboundGroupSession(); + outboundGroupSession3 = new OlmOutboundGroupSession(); + outboundGroupSession4 = new OlmOutboundGroupSession(); + outboundGroupSession5 = new OlmOutboundGroupSession(); + outboundGroupSession6 = new OlmOutboundGroupSession(); + outboundGroupSession7 = new OlmOutboundGroupSession(); + outboundGroupSession8 = new OlmOutboundGroupSession(); + + // get the session key from the outbound group sessions + String sessionKey1 = outboundGroupSession1.sessionKey(); + String sessionKey2 = outboundGroupSession2.sessionKey(); + assertFalse(sessionKey1.equals(sessionKey2)); + + String sessionKey3 = outboundGroupSession3.sessionKey(); + assertFalse(sessionKey2.equals(sessionKey3)); + + String sessionKey4 = outboundGroupSession4.sessionKey(); + assertFalse(sessionKey3.equals(sessionKey4)); + + String sessionKey5 = outboundGroupSession5.sessionKey(); + assertFalse(sessionKey4.equals(sessionKey5)); + String sessionKey6 = outboundGroupSession6.sessionKey(); + assertFalse(sessionKey5.equals(sessionKey6)); + + String sessionKey7 = outboundGroupSession7.sessionKey(); + assertFalse(sessionKey6.equals(sessionKey7)); + + String sessionKey8 = outboundGroupSession8.sessionKey(); + assertFalse(sessionKey7.equals(sessionKey8)); + + // get the session IDs from the outbound group sessions + String sessionId1 = outboundGroupSession1.sessionIdentifier(); + String sessionId2 = outboundGroupSession2.sessionIdentifier(); + assertFalse(sessionId1.equals(sessionId2)); + + String sessionId3 = outboundGroupSession3.sessionKey(); + assertFalse(sessionId2.equals(sessionId3)); + + String sessionId4 = outboundGroupSession4.sessionKey(); + assertFalse(sessionId3.equals(sessionId4)); + + String sessionId5 = outboundGroupSession5.sessionKey(); + assertFalse(sessionId4.equals(sessionId5)); + + String sessionId6 = outboundGroupSession6.sessionKey(); + assertFalse(sessionId5.equals(sessionId6)); + + String sessionId7 = outboundGroupSession7.sessionKey(); + assertFalse(sessionId6.equals(sessionId7)); + + String sessionId8 = outboundGroupSession8.sessionKey(); + assertFalse(sessionId7.equals(sessionId8)); + + + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } } } -- cgit v1.2.3 From 724d9ea20b938630b81bbdfe5d0ce36d86cbd09e Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 27 Oct 2016 18:47:14 +0200 Subject: Add new API to provide the SDK version --- .../src/androidTest/java/org/matrix/olm/OlmAccountTest.java | 8 +++++--- .../olm-sdk/src/main/java/org/matrix/olm/OlmManager.java | 7 +++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index a5cde5e..3b6101b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -62,9 +62,11 @@ public class OlmAccountTest { // load native lib mOlmManager = new OlmManager(); - String version = mOlmManager.getOlmLibVersion(); - assertNotNull(version); - Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + String olmLibVersion = mOlmManager.getOlmLibVersion(); + assertNotNull(olmLibVersion); + String olmSdkVersion = mOlmManager.getSdkOlmVersion(); + assertNotNull(olmLibVersion); + Log.d(LOG_TAG, "## setUpClass(): Versions - Android Olm SDK = "+olmSdkVersion+" Olm lib ="+olmLibVersion); } @AfterClass diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 21734dc..92fbe2b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -24,6 +24,7 @@ import android.util.Log; */ public class OlmManager { private static final String LOG_TAG = "OlmManager"; + private static final String SDK_OLM_VERSION = "V0.1.0_1"; static { try { @@ -33,6 +34,12 @@ public class OlmManager { } } + public String getSdkOlmVersion() { + //Date currentDate = Calendar.getInstance().getTime(); + //String retVal = new SimpleDateFormat("yyyyMMdd_HH:mm:ss").format(currentDate); + return SDK_OLM_VERSION; + } + /** * Get the OLM lib version. * @return the lib version as a string -- cgit v1.2.3 From 0d3c1a2a46589b004231b92f44d3bc8e327e0097 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 28 Oct 2016 10:02:06 +0200 Subject: Fix javadoc header comments --- .../main/java/org/matrix/olm/OlmInboundGroupSession.java | 14 +++++++------- .../main/java/org/matrix/olm/OlmOutboundGroupSession.java | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 7b3ae6e..f7e1812 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -190,8 +190,8 @@ public class OlmInboundGroupSession implements Serializable { } /** - * Return a session as a base64 string.
- * The account is serialized and encrypted with aKey. + * Return the current inbound group session as a base64 serialized string.
+ * The session is serialized and encrypted with aKey. * In case of failure, an error human readable * description is provide in aErrorMsg. * @param aKey encryption key @@ -223,10 +223,10 @@ public class OlmInboundGroupSession implements Serializable { /** - * Loads an account from a pickled base64 string.
+ * Load an inbound group session from a pickled base64 string.
* See {@link #serializeDataWithKey(String, StringBuffer)} - * @param aSerializedData pickled account in a base64 string format - * @param aKey key used to encrypted + * @param aSerializedData pickled inbound group session in a base64 string format + * @param aKey encrypting key used in {@link #serializeDataWithKey(String, StringBuffer)} * @param aErrorMsg error message description * @return true if operation succeed, false otherwise */ @@ -252,8 +252,8 @@ public class OlmInboundGroupSession implements Serializable { } /** * JNI counter part of {@link #initWithSerializedData(String, String, StringBuffer)}. - * @param aSerializedData pickled account in a base64 string format - * @param aKey key used to encrypted + * @param aSerializedData pickled session in a base64 string format + * @param aKey key used to encrypted in {@link #serializeDataWithKey(String, StringBuffer)} * @return null if operation succeed, an error message if operation failed */ private native String initWithSerializedDataJni(String aSerializedData, String aKey); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 67427a9..8ba3bcb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -116,8 +116,8 @@ public class OlmOutboundGroupSession implements Serializable { } /** - * Return a session as a base64 string.
- * The account is serialized and encrypted with aKey. + * Return the current outbound group session as a base64 serialized string.
+ * The session is serialized and encrypted with aKey. * In case of failure, an error human readable * description is provide in aErrorMsg. * @param aKey encryption key @@ -143,10 +143,10 @@ public class OlmOutboundGroupSession implements Serializable { /** - * Loads an account from a pickled base64 string.
+ * Load an outbound group session from a pickled base64 string.
* See {@link #serializeDataWithKey(String, StringBuffer)} - * @param aSerializedData pickled account in a base64 string format - * @param aKey key used to encrypted + * @param aSerializedData pickled outbound group session in a base64 string format + * @param aKey encrypting key used in {@link #serializeDataWithKey(String, StringBuffer)} * @param aErrorMsg error message description * @return true if operation succeed, false otherwise */ -- cgit v1.2.3 From 7a0d7cc36dfb2c1d7649af181160767a844e81f6 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 28 Oct 2016 10:49:04 +0200 Subject: Fix OlmException cast issue - OlmException class extends now from IOException - update corresponding serializing unit tests - update --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 61 ++++++++++------------ .../src/main/java/org/matrix/olm/OlmAccount.java | 6 +-- .../src/main/java/org/matrix/olm/OlmException.java | 21 ++++---- .../org/matrix/olm/OlmInboundGroupSession.java | 6 +-- .../org/matrix/olm/OlmOutboundGroupSession.java | 6 +-- .../src/main/java/org/matrix/olm/OlmSession.java | 6 +-- 6 files changed, 46 insertions(+), 60 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index eca070f..ac369e2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -196,13 +196,12 @@ public class OlmGroupSessionTest { FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_OUT_SESSION); ObjectInputStream objectInput = new ObjectInputStream(fileInput); outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject(); + assertNotNull(outboundGroupSessionSerial); objectInput.close(); // get sessions keys String sessionKeyRef = outboundGroupSessionRef.sessionKey(); String sessionKeySerial = outboundGroupSessionSerial.sessionKey(); - - // session keys sanity check assertFalse(TextUtils.isEmpty(sessionKeyRef)); assertFalse(TextUtils.isEmpty(sessionKeySerial)); @@ -212,8 +211,6 @@ public class OlmGroupSessionTest { // get sessions IDs String sessionIdRef = outboundGroupSessionRef.sessionIdentifier(); String sessionIdSerial = outboundGroupSessionSerial.sessionIdentifier(); - - // session ID sanity check assertFalse(TextUtils.isEmpty(sessionIdRef)); assertFalse(TextUtils.isEmpty(sessionIdSerial)); @@ -222,21 +219,16 @@ public class OlmGroupSessionTest { outboundGroupSessionRef.releaseSession(); outboundGroupSessionSerial.releaseSession(); - } - catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); - } - catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); - } - catch (IOException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); - } - /*catch (OlmException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); - }*/ - catch (Exception e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + } catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } catch (OlmException e) { + Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception OlmException Msg==" + e.getMessage()); + } catch (IOException e) { + Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception IOException Msg==" + e.getMessage()); + } catch (Exception e) { + Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception Msg==" + e.getMessage()); } } @@ -277,17 +269,16 @@ public class OlmGroupSessionTest { objectOutput.close(); // deserialize session - FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_OUT_SESSION); + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_IN_SESSION); ObjectInputStream objectInput = new ObjectInputStream(fileInput); bobInboundGroupSessionSerial = (OlmInboundGroupSession)objectInput.readObject(); + assertNotNull(bobInboundGroupSessionSerial); objectInput.close(); // get sessions IDs String aliceSessionId = aliceOutboundGroupSession.sessionIdentifier(); String sessionIdRef = bobInboundGroupSessionRef.sessionIdentifier(); String sessionIdSerial = bobInboundGroupSessionSerial.sessionIdentifier(); - - // session ID sanity check assertFalse(TextUtils.isEmpty(aliceSessionId)); assertFalse(TextUtils.isEmpty(sessionIdRef)); assertFalse(TextUtils.isEmpty(sessionIdSerial)); @@ -295,18 +286,20 @@ public class OlmGroupSessionTest { // session IDs comparison assertTrue(aliceSessionId.equals(sessionIdSerial)); assertTrue(sessionIdRef.equals(sessionIdSerial)); - } - catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); - } - catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); - } - catch (IOException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); - } - catch (Exception e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + + aliceOutboundGroupSession.releaseSession(); + bobInboundGroupSessionRef.releaseSession(); + bobInboundGroupSessionSerial.releaseSession(); + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + } catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } catch (OlmException e) { + Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception OlmException Msg==" + e.getMessage()); + } catch (IOException e) { + Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception IOException Msg==" + e.getMessage()); + } catch (Exception e) { + Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception Msg==" + e.getMessage()); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 321e194..876e651 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -69,9 +69,8 @@ public class OlmAccount implements Serializable { * Kick off the serialization mechanism. * @param aOutStream output stream for serializing * @throws IOException exception - * @throws OlmException exception */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + private void writeObject(ObjectOutputStream aOutStream) throws IOException { aOutStream.defaultWriteObject(); // generate serialization key @@ -94,9 +93,8 @@ public class OlmAccount implements Serializable { * @param aInStream input stream * @throws IOException exception * @throws ClassNotFoundException exception - * @throws OlmException exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { aInStream.defaultReadObject(); StringBuffer errorMsg = new StringBuffer(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index d548cf7..bac49f4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -16,10 +16,12 @@ package org.matrix.olm; +import java.io.IOException; + /** * Exception class to identify specific Olm SDK exceptions. */ -public class OlmException extends Exception { +public class OlmException extends IOException { // exception codes public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 0; public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 1; @@ -37,18 +39,17 @@ public class OlmException extends Exception { public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION = 13; // exception human readable messages - public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; - public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "failed to create a new inbound group Session"; - public static final String EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION = "failed to initialize a new outbound group Session"; - public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = "failed to initialize a new inbound group Session"; + public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed"; + public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "createNewSession() failed"; + public static final String EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION = "initOutboundGroupSession() failed"; + public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = " initInboundGroupSessionWithSessionKey() failed"; public static final String EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION = "initNewAccount() failure"; - public static final String EXCEPTION_MSG_INIT_ACCOUNT_DESERIALIZATION = "initWithSerializedData() failure"; public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters"; - public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "Account constructor failure"; - public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "Session constructor failure"; + public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "initNewAccount() failed"; + public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "initNewSession() failed"; - /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION} - * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}**/ + /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION}, + * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}..**/ private final int mCode; /** Human readable message description **/ diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index f7e1812..501d660 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -137,9 +137,8 @@ public class OlmInboundGroupSession implements Serializable { * Kick off the serialization mechanism. * @param aOutStream output stream for serializing * @throws IOException exception - * @throws OlmException exception */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + private void writeObject(ObjectOutputStream aOutStream) throws IOException { aOutStream.defaultWriteObject(); // generate serialization key @@ -162,9 +161,8 @@ public class OlmInboundGroupSession implements Serializable { * @param aInStream input stream * @throws IOException exception * @throws ClassNotFoundException exception - * @throws OlmException exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { aInStream.defaultReadObject(); StringBuffer errorMsg = new StringBuffer(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 8ba3bcb..37f89ea 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -63,9 +63,8 @@ public class OlmOutboundGroupSession implements Serializable { * Kick off the serialization mechanism. * @param aOutStream output stream for serializing * @throws IOException exception - * @throws OlmException exception */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + private void writeObject(ObjectOutputStream aOutStream) throws IOException { aOutStream.defaultWriteObject(); // generate serialization key @@ -88,9 +87,8 @@ public class OlmOutboundGroupSession implements Serializable { * @param aInStream input stream * @throws IOException exception * @throws ClassNotFoundException exception - * @throws OlmException exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { aInStream.defaultReadObject(); StringBuffer errorMsg = new StringBuffer(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 1237efd..9377838 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -52,9 +52,8 @@ public class OlmSession implements Serializable { * Kick off the serialization mechanism. * @param aOutStream output stream for serializing * @throws IOException exception - * @throws OlmException exception */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + private void writeObject(ObjectOutputStream aOutStream) throws IOException { aOutStream.defaultWriteObject(); // generate serialization key @@ -77,9 +76,8 @@ public class OlmSession implements Serializable { * @param aInStream input stream * @throws IOException exception * @throws ClassNotFoundException exception - * @throws OlmException exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { aInStream.defaultReadObject(); StringBuffer errorMsg = new StringBuffer(); -- cgit v1.2.3 From 8041a7e0efcf8d1f274868542dc8d6552b5e4630 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 31 Oct 2016 12:09:06 +0100 Subject: Refactoring serialization flow: - New class CommonSerializeUtils: helper class dedicated to serialization, to contain common code to all the OlmXXX classes that require to be serialized - make OlmXXX classes extending CommonSerializeUtils --- .../java/org/matrix/olm/CommonSerializeUtils.java | 90 ++++++++++++++++++++++ .../src/main/java/org/matrix/olm/OlmAccount.java | 53 ++++--------- .../org/matrix/olm/OlmInboundGroupSession.java | 53 ++++--------- .../org/matrix/olm/OlmOutboundGroupSession.java | 53 ++++--------- .../src/main/java/org/matrix/olm/OlmSession.java | 53 ++++--------- 5 files changed, 150 insertions(+), 152 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java new file mode 100644 index 0000000..bd0fda4 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.text.TextUtils; +import android.util.Log; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Helper class dedicated to serialization mechanism (template method pattern). + */ +abstract class CommonSerializeUtils { + private static final String LOG_TAG = "CommonSerializeUtils"; + + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception + */ + protected void serializeObject(ObjectOutputStream aOutStream) throws IOException { + aOutStream.defaultWriteObject(); + + // generate serialization key + String key = OlmUtility.getRandomKey(); + + // compute pickle string + StringBuffer errorMsg = new StringBuffer(); + String pickledData = serializeDataWithKey(key, errorMsg); + + if(null == pickledData) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg)); + } else { + aOutStream.writeObject(key); + aOutStream.writeObject(pickledData); + } + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + */ + protected void deserializeObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + aInStream.defaultReadObject(); + StringBuffer errorMsg = new StringBuffer(); + + String key = (String) aInStream.readObject(); + String pickledData = (String) aInStream.readObject(); + + if(TextUtils.isEmpty(key)) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); + + } else if(TextUtils.isEmpty(pickledData)) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); + + } else if(!createNewObjectFromSerialization()) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + + } else if(!initWithSerializedData(pickledData, key, errorMsg)) { + releaseObjectFromSerialization(); // prevent memory leak + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + + } else { + Log.d(LOG_TAG,"## readObject(): success"); + } + } + + protected abstract String serializeDataWithKey(String aKey, StringBuffer aErrorMsg); + protected abstract boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg); + protected abstract boolean createNewObjectFromSerialization(); + protected abstract void releaseObjectFromSerialization(); +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 876e651..1345a50 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -32,7 +32,7 @@ import java.io.Serializable; * OlmAccount provides APIs to retrieve the Olm keys. *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. */ -public class OlmAccount implements Serializable { +public class OlmAccount extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; @@ -71,21 +71,7 @@ public class OlmAccount implements Serializable { * @throws IOException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException { - aOutStream.defaultWriteObject(); - - // generate serialization key - String key = OlmUtility.getRandomKey(); - - // compute pickle string - StringBuffer errorMsg = new StringBuffer(); - String pickledData = serializeDataWithKey(key, errorMsg); - - if(null == pickledData) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg)); - } else { - aOutStream.writeObject(key); - aOutStream.writeObject(pickledData); - } + serializeObject(aOutStream); } /** @@ -95,28 +81,17 @@ public class OlmAccount implements Serializable { * @throws ClassNotFoundException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - aInStream.defaultReadObject(); - StringBuffer errorMsg = new StringBuffer(); - - String key = (String) aInStream.readObject(); - String pickledData = (String) aInStream.readObject(); - - if(TextUtils.isEmpty(key)) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); - - } else if(TextUtils.isEmpty(pickledData)) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); - - } else if(!createNewAccount()) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + deserializeObject(aInStream); + } - } else if(!initWithSerializedData(pickledData, key, errorMsg)) { - releaseAccount(); // prevent memory leak - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + @Override + protected boolean createNewObjectFromSerialization() { + return createNewAccount(); + } - } else { - Log.d(LOG_TAG,"## readObject(): success"); - } + @Override + protected void releaseObjectFromSerialization() { + releaseAccount(); } /** @@ -128,7 +103,8 @@ public class OlmAccount implements Serializable { * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + @Override + protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { String pickleRetValue = null; // sanity check @@ -154,7 +130,8 @@ public class OlmAccount implements Serializable { * @param aErrorMsg error message description * @return true if operation succeed, false otherwise */ - private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + @Override + protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { boolean retCode = false; String jniError; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 501d660..6f27507 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -34,7 +34,7 @@ import java.io.Serializable; * *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. */ -public class OlmInboundGroupSession implements Serializable { +public class OlmInboundGroupSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -772028491251653253L; private static final String LOG_TAG = "OlmInboundGroupSession"; @@ -139,21 +139,7 @@ public class OlmInboundGroupSession implements Serializable { * @throws IOException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException { - aOutStream.defaultWriteObject(); - - // generate serialization key - String key = OlmUtility.getRandomKey(); - - // compute pickle string - StringBuffer errorMsg = new StringBuffer(); - String pickledData = serializeDataWithKey(key, errorMsg); - - if(null == pickledData) { - throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg)); - } else { - aOutStream.writeObject(key); - aOutStream.writeObject(pickledData); - } + serializeObject(aOutStream); } /** @@ -163,28 +149,17 @@ public class OlmInboundGroupSession implements Serializable { * @throws ClassNotFoundException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - aInStream.defaultReadObject(); - StringBuffer errorMsg = new StringBuffer(); - - String key = (String) aInStream.readObject(); - String pickledData = (String) aInStream.readObject(); - - if(TextUtils.isEmpty(key)) { - throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); - - } else if(TextUtils.isEmpty(pickledData)) { - throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); - - } else if(!createNewSession()) { - throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + deserializeObject(aInStream); + } - } else if(!initWithSerializedData(pickledData, key, errorMsg)) { - releaseSession(); // prevent memory leak - throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg)); + @Override + protected boolean createNewObjectFromSerialization() { + return createNewSession(); + } - } else { - Log.d(LOG_TAG,"## readObject(): success"); - } + @Override + protected void releaseObjectFromSerialization() { + releaseSession(); } /** @@ -196,7 +171,8 @@ public class OlmInboundGroupSession implements Serializable { * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + @Override + protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { String pickleRetValue = null; // sanity check @@ -228,7 +204,8 @@ public class OlmInboundGroupSession implements Serializable { * @param aErrorMsg error message description * @return true if operation succeed, false otherwise */ - private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + @Override + protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { boolean retCode = false; String jniError; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 37f89ea..5b59362 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -32,7 +32,7 @@ import java.io.Serializable; * *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. */ -public class OlmOutboundGroupSession implements Serializable { +public class OlmOutboundGroupSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -3133097431283604416L; private static final String LOG_TAG = "OlmOutboundGroupSession"; @@ -65,21 +65,7 @@ public class OlmOutboundGroupSession implements Serializable { * @throws IOException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException { - aOutStream.defaultWriteObject(); - - // generate serialization key - String key = OlmUtility.getRandomKey(); - - // compute pickle string - StringBuffer errorMsg = new StringBuffer(); - String pickledData = serializeDataWithKey(key, errorMsg); - - if(null == pickledData) { - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION, String.valueOf(errorMsg)); - } else { - aOutStream.writeObject(key); - aOutStream.writeObject(pickledData); - } + serializeObject(aOutStream); } /** @@ -89,28 +75,17 @@ public class OlmOutboundGroupSession implements Serializable { * @throws ClassNotFoundException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - aInStream.defaultReadObject(); - StringBuffer errorMsg = new StringBuffer(); - - String key = (String) aInStream.readObject(); - String pickledData = (String) aInStream.readObject(); - - if(TextUtils.isEmpty(key)) { - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); - - } else if(TextUtils.isEmpty(pickledData)) { - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); - - } else if(!createNewSession()) { - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + deserializeObject(aInStream); + } - } else if(!initWithSerializedData(pickledData, key, errorMsg)) { - releaseSession(); // prevent memory leak - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION, String.valueOf(errorMsg)); + @Override + protected boolean createNewObjectFromSerialization() { + return createNewSession(); + } - } else { - Log.d(LOG_TAG,"## readObject(): success"); - } + @Override + protected void releaseObjectFromSerialization() { + releaseSession(); } /** @@ -122,7 +97,8 @@ public class OlmOutboundGroupSession implements Serializable { * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + @Override + protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { String pickleRetValue = null; // sanity check @@ -148,7 +124,8 @@ public class OlmOutboundGroupSession implements Serializable { * @param aErrorMsg error message description * @return true if operation succeed, false otherwise */ - private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + @Override + protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { boolean retCode = false; String jniError; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 9377838..ffc899a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -32,7 +32,7 @@ import java.io.Serializable; * From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}. *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. */ -public class OlmSession implements Serializable { +public class OlmSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -8975488639186976419L; private static final String LOG_TAG = "OlmSession"; @@ -54,21 +54,7 @@ public class OlmSession implements Serializable { * @throws IOException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException { - aOutStream.defaultWriteObject(); - - // generate serialization key - String key = OlmUtility.getRandomKey(); - - // compute pickle string - StringBuffer errorMsg = new StringBuffer(); - String pickledData = serializeDataWithKey(key, errorMsg); - - if(null == pickledData) { - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SERIALIZATION, String.valueOf(errorMsg)); - } else { - aOutStream.writeObject(key); - aOutStream.writeObject(pickledData); - } + serializeObject(aOutStream); } /** @@ -78,28 +64,17 @@ public class OlmSession implements Serializable { * @throws ClassNotFoundException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - aInStream.defaultReadObject(); - StringBuffer errorMsg = new StringBuffer(); - - String key = (String) aInStream.readObject(); - String pickledData = (String) aInStream.readObject(); - - if(TextUtils.isEmpty(key)) { - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); - - } else if(TextUtils.isEmpty(pickledData)) { - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); - - } else if(!createNewSession()) { - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + deserializeObject(aInStream); + } - } else if(!initWithSerializedData(pickledData, key, errorMsg)) { - releaseSession(); // prevent memory leak - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, String.valueOf(errorMsg)); + @Override + protected boolean createNewObjectFromSerialization() { + return createNewSession(); + } - } else { - Log.d(LOG_TAG,"## readObject(): success"); - } + @Override + protected void releaseObjectFromSerialization() { + releaseSession(); } /** @@ -111,7 +86,8 @@ public class OlmSession implements Serializable { * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + @Override + protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { String pickleRetValue = null; // sanity check @@ -137,7 +113,8 @@ public class OlmSession implements Serializable { * @param aErrorMsg error message description * @return true if operation succeed, false otherwise */ - private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + @Override + protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { boolean retCode = false; String jniError; -- cgit v1.2.3 From e71013b005681bac96eca5f3921534f9f602b641 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 7 Nov 2016 11:00:01 +0100 Subject: Set javadoc level to private --- java/android/OlmLibSdk/olm-sdk/build.gradle | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle index 393342b..8138617 100644 --- a/java/android/OlmLibSdk/olm-sdk/build.gradle +++ b/java/android/OlmLibSdk/olm-sdk/build.gradle @@ -28,6 +28,7 @@ android { source = android.sourceSets.main.java.srcDirs classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) destinationDir = file("./doc/") + options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PRIVATE failOnError false } @@ -48,10 +49,6 @@ android { commandLine getNdkBuildCmd(), 'clean' } - /*tasks.withType(JavaCompile) { - compileTask -> compileTask.dependsOn ndkBuildNative - }*/ - tasks.withType(JavaCompile) { compileTask -> if (compileTask.name.startsWith('compileDebugJava')) { println 'test compile: Debug' -- cgit v1.2.3 From c71235d508db25bdca1921e9bcddbbe9f3ed1b83 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 7 Nov 2016 11:01:03 +0100 Subject: Fix javadoc header --- .../olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java index 88b54e6..363ab7a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java @@ -64,7 +64,7 @@ public class TestHelper { /** * Return the first one time key from the JSON object. * @param aIdentityKeysObj JSON result of {@link OlmAccount#oneTimeKeys()} - * @param aKeyPosition the poistion of the key to be retrieved + * @param aKeyPosition the position of the key to be retrieved * @return one time key string if operation succeed, null otherwise */ static public String getOneTimeKey(JSONObject aIdentityKeysObj, int aKeyPosition) { -- cgit v1.2.3 From 59bb145ceb0b703e8124fb44b75e85a48a2caed3 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 7 Nov 2016 11:06:26 +0100 Subject: Add new API to verify object release --- .../java/org/matrix/olm/OlmAccountTest.java | 7 +-- .../java/org/matrix/olm/OlmGroupSessionTest.java | 56 ++++++++++++++++------ .../java/org/matrix/olm/OlmSessionTest.java | 35 +++++++++++++- .../java/org/matrix/olm/OlmUtilityTest.java | 4 ++ .../src/main/java/org/matrix/olm/OlmAccount.java | 19 ++++++-- .../org/matrix/olm/OlmInboundGroupSession.java | 16 +++++-- .../org/matrix/olm/OlmOutboundGroupSession.java | 18 +++++-- .../src/main/java/org/matrix/olm/OlmSession.java | 17 +++++-- .../src/main/java/org/matrix/olm/OlmUtility.java | 19 +++++++- 9 files changed, 155 insertions(+), 36 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 3b6101b..7a6233d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -187,11 +187,8 @@ public class OlmAccountTest { assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=generatedKeysJsonObj); // test the count of the generated one time keys: - Iterator generatedKeysIt = generatedKeysJsonObj.keys(); - while(generatedKeysIt.hasNext()){ - generatedKeysIt.next(); - oneTimeKeysCount++; - } + oneTimeKeysCount = generatedKeysJsonObj.length(); + assertTrue("Expected count="+GENERATION_ONE_TIME_KEYS_NUMBER+" found="+oneTimeKeysCount,GENERATION_ONE_TIME_KEYS_NUMBER==oneTimeKeysCount); } catch (JSONException e) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index ac369e2..8fc0694 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -168,9 +168,14 @@ public class OlmGroupSessionTest { mBobInboundGroupSession.releaseSession(); } + @Test + public void test14CheckUnreleaseedCount() { + assertTrue(0==mAliceOutboundGroupSession.getUnreleasedCount()); + assertTrue(0==mBobInboundGroupSession.getUnreleasedCount()); + } @Test - public void test14SerializeOutboundSession() { + public void test15SerializeOutboundSession() { OlmOutboundGroupSession outboundGroupSessionRef=null; OlmOutboundGroupSession outboundGroupSessionSerial; @@ -219,21 +224,24 @@ public class OlmGroupSessionTest { outboundGroupSessionRef.releaseSession(); outboundGroupSessionSerial.releaseSession(); + + assertTrue(0==outboundGroupSessionRef.getUnreleasedCount()); + assertTrue(0==outboundGroupSessionSerial.getUnreleasedCount()); } catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); } catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); } catch (OlmException e) { - Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception OlmException Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception OlmException Msg==" + e.getMessage()); } catch (IOException e) { - Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception IOException Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception IOException Msg==" + e.getMessage()); } catch (Exception e) { - Log.e(LOG_TAG, "## test14SerializeOutboundSession(): Exception Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception Msg==" + e.getMessage()); } } @Test - public void test15SerializeInboundSession() { + public void test16SerializeInboundSession() { OlmOutboundGroupSession aliceOutboundGroupSession=null; OlmInboundGroupSession bobInboundGroupSessionRef=null; OlmInboundGroupSession bobInboundGroupSessionSerial; @@ -290,16 +298,20 @@ public class OlmGroupSessionTest { aliceOutboundGroupSession.releaseSession(); bobInboundGroupSessionRef.releaseSession(); bobInboundGroupSessionSerial.releaseSession(); + + assertTrue(0==aliceOutboundGroupSession.getUnreleasedCount()); + assertTrue(0==bobInboundGroupSessionRef.getUnreleasedCount()); + assertTrue(0==bobInboundGroupSessionSerial.getUnreleasedCount()); } catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); } catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); } catch (OlmException e) { - Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception OlmException Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception OlmException Msg==" + e.getMessage()); } catch (IOException e) { - Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception IOException Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception IOException Msg==" + e.getMessage()); } catch (Exception e) { - Log.e(LOG_TAG, "## test15SerializeInboundSession(): Exception Msg==" + e.getMessage()); + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception Msg==" + e.getMessage()); } } @@ -308,7 +320,7 @@ public class OlmGroupSessionTest { * This test validates random series are provide enough random values. */ @Test - public void test16MultipleOutboundSession() { + public void test17MultipleOutboundSession() { OlmOutboundGroupSession outboundGroupSession1; OlmOutboundGroupSession outboundGroupSession2; OlmOutboundGroupSession outboundGroupSession3; @@ -374,7 +386,23 @@ public class OlmGroupSessionTest { String sessionId8 = outboundGroupSession8.sessionKey(); assertFalse(sessionId7.equals(sessionId8)); - + outboundGroupSession1.releaseSession(); + outboundGroupSession2.releaseSession(); + outboundGroupSession3.releaseSession(); + outboundGroupSession4.releaseSession(); + outboundGroupSession5.releaseSession(); + outboundGroupSession6.releaseSession(); + outboundGroupSession7.releaseSession(); + outboundGroupSession8.releaseSession(); + + assertTrue(0==outboundGroupSession1.getUnreleasedCount()); + assertTrue(0==outboundGroupSession2.getUnreleasedCount()); + assertTrue(0==outboundGroupSession3.getUnreleasedCount()); + assertTrue(0==outboundGroupSession4.getUnreleasedCount()); + assertTrue(0==outboundGroupSession5.getUnreleasedCount()); + assertTrue(0==outboundGroupSession6.getUnreleasedCount()); + assertTrue(0==outboundGroupSession7.getUnreleasedCount()); + assertTrue(0==outboundGroupSession8.getUnreleasedCount()); } catch (OlmException e) { assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index a011685..99127e1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -137,9 +137,14 @@ public class OlmSessionTest { // release accounts bobAccount.releaseAccount(); aliceAccount.releaseAccount(); + assertTrue(0==bobAccount.getUnreleasedCount()); + assertTrue(0==aliceAccount.getUnreleasedCount()); + // release sessions bobSession.releaseSession(); aliceSession.releaseSession(); + assertTrue(0==bobSession.getUnreleasedCount()); + assertTrue(0==aliceSession.getUnreleasedCount()); } @@ -251,9 +256,14 @@ public class OlmSessionTest { // clean objects.. assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); bobAccount.releaseAccount(); - bobSession.releaseSession(); aliceAccount.releaseAccount(); + assertTrue(0==bobAccount.getUnreleasedCount()); + assertTrue(0==aliceAccount.getUnreleasedCount()); + + bobSession.releaseSession(); aliceSession.releaseSession(); + assertTrue(0==bobSession.getUnreleasedCount()); + assertTrue(0==aliceSession.getUnreleasedCount()); } @@ -302,9 +312,14 @@ public class OlmSessionTest { assertTrue(aliceSessionId.equals(bobSessionId)); aliceAccount.releaseAccount(); - aliceSession.releaseSession(); bobAccount.releaseAccount(); + assertTrue(0==aliceAccount.getUnreleasedCount()); + assertTrue(0==bobAccount.getUnreleasedCount()); + bobSession.releaseSession(); + aliceSession.releaseSession(); + assertTrue(0==bobSession.getUnreleasedCount()); + assertTrue(0==aliceSession.getUnreleasedCount()); } @Test @@ -360,8 +375,13 @@ public class OlmSessionTest { assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); aliceAccount.releaseAccount(); bobAccount.releaseAccount(); + assertTrue(0==aliceAccount.getUnreleasedCount()); + assertTrue(0==bobAccount.getUnreleasedCount()); + aliceSession.releaseSession(); bobSession.releaseSession(); + assertTrue(0==aliceSession.getUnreleasedCount()); + assertTrue(0==bobSession.getUnreleasedCount()); } // ******************************************************** @@ -486,9 +506,15 @@ public class OlmSessionTest { assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); bobAccount.releaseAccount(); aliceAccount.releaseAccount(); + assertTrue(0==bobAccount.getUnreleasedCount()); + assertTrue(0==aliceAccount.getUnreleasedCount()); + bobSession.releaseSession(); aliceSession.releaseSession(); aliceSessionDeserial.releaseSession(); + assertTrue(0==bobSession.getUnreleasedCount()); + assertTrue(0==aliceSession.getUnreleasedCount()); + assertTrue(0==aliceSessionDeserial.getUnreleasedCount()); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); @@ -589,8 +615,13 @@ public class OlmSessionTest { assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); aliceAccount.releaseAccount(); bobAccount.releaseAccount(); + assertTrue(0==aliceAccount.getUnreleasedCount()); + assertTrue(0==bobAccount.getUnreleasedCount()); + aliceSession.releaseSession(); bobSession.releaseSession(); + assertTrue(0==aliceSession.getUnreleasedCount()); + assertTrue(0==bobSession.getUnreleasedCount()); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index d40c35a..9e03453 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -99,7 +99,10 @@ public class OlmUtilityTest { assertFalse(String.valueOf(errorMsg).isEmpty()); utility.releaseUtility(); + assertTrue(0==utility.getUnreleasedCount()); + account.releaseAccount(); + assertTrue(0==account.getUnreleasedCount()); } @@ -112,5 +115,6 @@ public class OlmUtilityTest { assertFalse(TextUtils.isEmpty(hashResult)); utility.releaseUtility(); + assertTrue(0==utility.getUnreleasedCount()); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 1345a50..aeeaebc 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -35,6 +35,7 @@ import java.io.Serializable; public class OlmAccount extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; + private transient int mUnreleasedCount; // JSON keys used in the JSON objects returned by JNI /** As well as the identity key, each device creates a number of Curve25519 key pairs which are @@ -53,8 +54,8 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { never leave the device, but the public part is published to the Matrix network. **/ public static final String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; - /** account raw pointer value (OlmAccount*) returned by JNI. - * this value identifies uniquely the native account instance. + /** Account Id returned by JNI. + * This value identifies uniquely the native account instance. */ private transient long mNativeId; @@ -167,7 +168,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ public void releaseAccount(){ releaseAccountJni(); - + mUnreleasedCount--; mNativeId = 0; } @@ -188,6 +189,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private boolean initNewAccount() { boolean retCode = false; if(0 != (mNativeId = initNewAccountJni())){ + mUnreleasedCount++; retCode = true; } return retCode; @@ -210,6 +212,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private boolean createNewAccount() { boolean retCode = false; if(0 != (mNativeId = createNewAccountJni())){ + mUnreleasedCount++; retCode = true; } return retCode; @@ -353,7 +356,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private native int markOneTimeKeysAsPublishedJni(); /** - * Sign a message with the ed25519 fingerprint key for this account. + * Sign a message with the ed25519 fingerprint key for this account.
* The signed message is returned by the method. * @param aMessage message to sign * @return the signed message if operation succeed, null otherwise @@ -362,4 +365,12 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return signMessageJni(aMessage); } private native String signMessageJni(String aMessage); + + /** + * Return the number of unreleased OlmAccount instances.
+ * @return number of unreleased instances + */ + public int getUnreleasedCount() { + return mUnreleasedCount; + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 6f27507..50e77f7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -37,9 +37,10 @@ import java.io.Serializable; public class OlmInboundGroupSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -772028491251653253L; private static final String LOG_TAG = "OlmInboundGroupSession"; + private transient int mUnreleasedCount; - /** session raw pointer value returned by JNI.
- * this value uniquely identifies the native inbound group session instance. + /** Session Id returned by JNI.
+ * This value uniquely identifies the native inbound group session instance. */ private transient long mNativeId; @@ -68,7 +69,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ public void releaseSession(){ releaseSessionJni(); - + mUnreleasedCount--; mNativeId = 0; } @@ -88,6 +89,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri private boolean createNewSession() { boolean retCode = false; if(0 != (mNativeId = createNewSessionJni())){ + mUnreleasedCount++; retCode = true; } return retCode; @@ -232,4 +234,12 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @return null if operation succeed, an error message if operation failed */ private native String initWithSerializedDataJni(String aSerializedData, String aKey); + + /** + * Return the number of unreleased OlmInboundGroupSession instances.
+ * @return number of unreleased instances + */ + public int getUnreleasedCount() { + return mUnreleasedCount; + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 5b59362..f7d5f17 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -35,9 +35,10 @@ import java.io.Serializable; public class OlmOutboundGroupSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -3133097431283604416L; private static final String LOG_TAG = "OlmOutboundGroupSession"; + private transient int mUnreleasedCount; - /** session raw pointer value returned by JNI.
- * this value uniquely identifies the native inbound group session instance. + /** Session Id returned by JNI.
+ * This value uniquely identifies the native outbound group session instance. */ private transient long mNativeId; @@ -153,7 +154,8 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * Public API for {@link #releaseSessionJni()}. */ public void releaseSession() { - releaseSessionJni(); + releaseSessionJni(); + mUnreleasedCount--; mNativeId = 0; } @@ -174,6 +176,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser private boolean createNewSession() { boolean retCode = false; if(0 != (mNativeId = createNewSessionJni())){ + mUnreleasedCount++; retCode = true; } return retCode; @@ -237,6 +240,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser /** * Encrypt some plain-text message.
+ * The message given as parameter is encrypted and returned as the return value. * @param aClearMsg message to be encrypted * @return the encrypted message if operation succeed, null otherwise */ @@ -250,4 +254,12 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return retValue; } private native String encryptMessageJni(String aClearMsg); + + /** + * Return the number of unreleased OlmOutboundGroupSession instances.
+ * @return number of unreleased instances + */ + public int getUnreleasedCount() { + return mUnreleasedCount; + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index ffc899a..38e8c89 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -35,9 +35,10 @@ import java.io.Serializable; public class OlmSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -8975488639186976419L; private static final String LOG_TAG = "OlmSession"; + private transient int mUnreleasedCount; - /** session raw pointer value (OlmSession*) returned by JNI. - * this value uniquely identifies the native session instance. + /** Session Id returned by JNI. + * This value uniquely identifies the native session instance. **/ private transient long mNativeId; @@ -158,7 +159,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { */ public void releaseSession(){ releaseSessionJni(); - + mUnreleasedCount--; mNativeId = 0; } @@ -171,6 +172,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { private boolean initNewSession() { boolean retCode = false; if(0 != (mNativeId = initNewSessionJni())){ + mUnreleasedCount++; retCode = true; } return retCode; @@ -194,6 +196,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { private boolean createNewSession() { boolean retCode = false; if(0 != (mNativeId = createNewSessionJni())){ + mUnreleasedCount++; retCode = true; } return retCode; @@ -367,5 +370,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } private native String decryptMessageJni(OlmMessage aEncryptedMsg); + + /** + * Return the number of unreleased OlmSession instances.
+ * @return number of unreleased instances + */ + public int getUnreleasedCount() { + return mUnreleasedCount; + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 9bd7aaa..8cc14c0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -29,9 +29,10 @@ public class OlmUtility { public static final int RANDOM_KEY_SIZE = 32; public static final int RANDOM_RANGE = 256; + private transient int mUnreleasedCount; - /** raw pointer value returned by JNI. - * this value uniquely identifies this utility instance. + /** Instance Id returned by JNI. + * This value uniquely identifies this utility instance. **/ private long mNativeId; @@ -47,6 +48,7 @@ public class OlmUtility { private boolean initUtility() { boolean retCode = false; if(0 != (mNativeId = initUtilityJni())){ + mUnreleasedCount++; retCode = true; } return retCode; @@ -59,6 +61,7 @@ public class OlmUtility { */ public void releaseUtility(){ releaseUtilityJni(); + mUnreleasedCount--; mNativeId = 0; } private native void releaseUtilityJni(); @@ -126,6 +129,10 @@ public class OlmUtility { private native String sha256Jni(String aMessage); + /** + * Helper method to compute a string based on random integers. + * @return string containing randoms integer values + */ public static String getRandomKey() { String keyRetValue; Random rand = new Random(); @@ -138,5 +145,13 @@ public class OlmUtility { return keyRetValue; } + + /** + * Return the number of unreleased OlmUtility instances.
+ * @return number of unreleased instances + */ + public int getUnreleasedCount() { + return mUnreleasedCount; + } } -- cgit v1.2.3 From c144d3fec5f135319a6b46bc5645f7e70eecc1da Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 7 Nov 2016 11:40:23 +0100 Subject: Update test02AliceToBobBackAndForth() with a last sequence where Alice encrypts and Bob decrypts --- .../androidTest/java/org/matrix/olm/OlmSessionTest.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 99127e1..2494c80 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -159,6 +159,8 @@ public class OlmSessionTest { * - bob decrypts the encrypted message with its own session * - bob encrypts messages with its own session * - alice decrypts bob's messages with its own message + * - alice encrypts a message + * - bob decrypts the encrypted message */ @Test public void test02AliceToBobBackAndForth() { @@ -245,14 +247,22 @@ public class OlmSessionTest { String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); assertNotNull(decryptedMsg3); - // and one more form alice.. - encryptedMsg1 = aliceSession.encryptMessage(clearMsg1); - // comparison tests assertTrue(clearMsg1.equals(decryptedMsg1)); assertTrue(clearMsg2.equals(decryptedMsg2)); assertTrue(clearMsg3.equals(decryptedMsg3)); + // and one more from alice to bob + clearMsg1 = "another message from Alice to Bob!!"; + encryptedMsg1 = aliceSession.encryptMessage(clearMsg1); + assertNotNull(encryptedMsg1); + decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1); + assertNotNull(decryptedMsg1); + assertTrue(clearMsg1.equals(decryptedMsg1)); + + // comparison test + assertTrue(clearMsg1.equals(decryptedMsg1)); + // clean objects.. assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); bobAccount.releaseAccount(); -- cgit v1.2.3 From 1fd908c72ab5227e7c9d8bfaaba7781ec1067aee Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 8 Nov 2016 11:21:45 +0100 Subject: Light refactoring by using test helper methods getFingerprintKey() and getIdentityKey() --- .../java/org/matrix/olm/OlmAccountTest.java | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 7a6233d..dc47d51 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -132,24 +132,12 @@ public class OlmAccountTest { Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson); // is JSON_KEY_FINGER_PRINT_KEY present? - try { - String fingerPrintKey = identityKeysJson.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); - assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); - } catch (JSONException e) { - e.printStackTrace(); - assertTrue("Exception MSg="+e.getMessage(), false); - } + String fingerPrintKey = TestHelper.getFingerprintKey(identityKeysJson); + assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); // is JSON_KEY_IDENTITY_KEY present? - try { - String identityKey = identityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); - assertTrue("identity key missing",!TextUtils.isEmpty(identityKey)); - } catch (JSONException e) { - e.printStackTrace(); - assertTrue("Exception MSg="+e.getMessage(), false); - } - - + String identityKey = TestHelper.getIdentityKey(identityKeysJson); + assertTrue("identity key missing",!TextUtils.isEmpty(identityKey)); } //**************************************************** -- cgit v1.2.3 From d944d5fad70283e4cc095802fd893b87309f341d Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Tue, 8 Nov 2016 11:25:10 +0100 Subject: Update initInboundSessionWithAccountFrom() return code: - return code is a basic error code (0 OK, -1 KO) Remove TODO comments --- .../olm-sdk/src/main/java/org/matrix/olm/OlmSession.java | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 38e8c89..6d570d1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -267,21 +267,18 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aAccount the account to associate with this session * @param aTheirIdentityKey the sender identity key * @param aPreKeyMsg PRE KEY message - * @return this if operation succeed, null otherwise - * TODO unit test missing: initInboundSessionWithAccountFrom + * @return 0 if operation succeed, -1 otherwise */ - public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) { - OlmSession retObj=null; + public int initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) { + int retCode=-1; if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - if(0 == initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg)){ - retObj = this; - } + retCode = initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg); } - return retObj; + return retCode; } private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, String aTheirIdentityKey, String aOneTimeKeyMsg); @@ -305,7 +302,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * Public API for {@link #matchesInboundSessionJni(String)}. * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise - * TODO unit test missing: matchesInboundSession */ public boolean matchesInboundSession(String aOneTimeKeyMsg) { boolean retCode = false; @@ -326,7 +322,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aTheirIdentityKey the sender identity key * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise - * TODO unit test missing: matchesInboundSessionFrom */ public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) { boolean retCode = false; -- cgit v1.2.3 From 04fd4c5a1301545419fb72533c57e4253085bdc0 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 14 Nov 2016 11:56:37 +0100 Subject: Fix the decrypt issue (crash on V5.1.1) when the message to decrypt contains emojis: - add an internal specific JNI function (javaCStringToUtf8()) to perform the UTF-8 conversion - the SDK is configured to enable/disable the use of javaCStringToUtf8() --- .../java/org/matrix/olm/OlmAccountTest.java | 7 +++- .../java/org/matrix/olm/OlmGroupSessionTest.java | 34 +++++++++++++++- .../java/org/matrix/olm/OlmSessionTest.java | 6 ++- .../java/org/matrix/olm/OlmUtilityTest.java | 6 ++- .../org/matrix/olm/OlmInboundGroupSession.java | 14 ++++++- .../src/main/java/org/matrix/olm/OlmManager.java | 12 ++++++ .../src/main/java/org/matrix/olm/OlmSession.java | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/Application.mk | 2 +- .../src/main/jni/olm_inbound_group_session.cpp | 28 +++++++++++--- .../src/main/jni/olm_inbound_group_session.h | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 1 + .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 45 +++++++++++++++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 32 +++++++++++---- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 2 +- 14 files changed, 168 insertions(+), 27 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index dc47d51..2c2711d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -38,7 +38,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.util.Iterator; import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertFalse; @@ -59,8 +58,12 @@ public class OlmAccountTest { @BeforeClass public static void setUpClass(){ + // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, + // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 + boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; + // load native lib - mOlmManager = new OlmManager(); + mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); String olmLibVersion = mOlmManager.getOlmLibVersion(); assertNotNull(olmLibVersion); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 8fc0694..6e12463 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -60,8 +60,13 @@ public class OlmGroupSessionTest { @BeforeClass public static void setUpClass(){ + + // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, + // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 + boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; + // load native lib - mOlmManager = new OlmManager(); + mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); String version = mOlmManager.getOlmLibVersion(); assertNotNull(version); @@ -408,4 +413,31 @@ public class OlmGroupSessionTest { } } + /** + * Specific test for the following run time error: + * "JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0 in call to NewStringUTF".
+ * When the msg to decrypt contain emojis, depending on the android platform, the NewStringUTF() behaves differently and + * can even crash. + * This issue is described in details here: https://github.com/eclipsesource/J2V8/issues/142 + */ + @Test + public void test18TestBadCharacterCrashInDecrypt() { + OlmInboundGroupSession bobInboundGroupSession=null; + + // values taken from a "real life" crash case + String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; + String msgToDecryptWithEmoji = "AwgNEpABpjs+tYF+0y8bWtzAgYAC3N55p5cPJEEiGPU1kxIHSY7f2aG5Fj4wmcsXUkhDv0UePj922kgf+Q4dFsPHKq2aVA93n8DJAQ/FRfcM98B9E6sKCZ/PsCF78uBvF12Aaq9D3pUHBopdd7llUfVq29d5y6ZwX5VDoqV2utsATkKjXYV9CbfZuvvBMQ30ZLjEtyUUBJDY9K4FxEFcULytA/IkVnATTG9ERuLF/yB6ukSFR+iUWRYAmtuOuU0k9BvaqezbGqNoK5Grlkes+dYX6/0yUObumcw9/iAI"; + + // bob creates INBOUND GROUP SESSION + try { + bobInboundGroupSession = new OlmInboundGroupSession(sessionKeyRef); + } catch (OlmException e) { + assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false); + } + + String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji); + assertNotNull(decryptedMessage); + } + } + diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 2494c80..1aeb3fb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -51,8 +51,12 @@ public class OlmSessionTest { @BeforeClass public static void setUpClass(){ + // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, + // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 + boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; + // load native lib - mOlmManager = new OlmManager(); + mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); String version = mOlmManager.getOlmLibVersion(); assertNotNull(version); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 9e03453..3006344 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -41,8 +41,12 @@ public class OlmUtilityTest { @BeforeClass public static void setUpClass(){ + // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, + // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 + boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; + // load native lib - mOlmManager = new OlmManager(); + mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); String version = mOlmManager.getOlmLibVersion(); assertNotNull(version); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 50e77f7..fa4ca1d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -123,16 +123,26 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri private native int initInboundGroupSessionWithSessionKeyJni(String aSessionKey); + /** + * Retrieve the base64-encoded identifier for this inbound group session. + * @return the session ID if operation succeed, null otherwise + */ public String sessionIdentifier() { return sessionIdentifierJni(); } private native String sessionIdentifierJni(); + /** + * Decrypt the message passed in parameter. + * @param aEncryptedMsg the message to be decrypted + * @return the decrypted message if operation succeed, null otherwise. + */ public String decryptMessage(String aEncryptedMsg) { - return decryptMessageJni(aEncryptedMsg); + String decryptedMessage = decryptMessageJni(aEncryptedMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); + return decryptedMessage; } - private native String decryptMessageJni(String aEncryptedMsg); + private native String decryptMessageJni(String aEncryptedMsg, boolean aIsUtf8ConversionRequired); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 92fbe2b..5170ee9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -25,6 +25,18 @@ import android.util.Log; public class OlmManager { private static final String LOG_TAG = "OlmManager"; private static final String SDK_OLM_VERSION = "V0.1.0_1"; + /** specific flag to enable UTF-8 specific conversion for pre Marshmallow(23) android versions.
+ * NDK NewStringUTF() UTF8 issue + **/ + public static boolean ENABLE_STRING_UTF8_SPECIFIC_CONVERSION; + + /** + * Constructor. + * @param aIsUtf8SpecificConversionEnabled true to enable JNI specific UTF-8 conversion, false otherwie + */ + public OlmManager(boolean aIsUtf8SpecificConversionEnabled) { + ENABLE_STRING_UTF8_SPECIFIC_CONVERSION = aIsUtf8SpecificConversionEnabled; + } static { try { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 6d570d1..dddc588 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -361,10 +361,10 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @return the decrypted message if operation succeed, null otherwise */ public String decryptMessage(OlmMessage aEncryptedMsg) { - return decryptMessageJni(aEncryptedMsg); + return decryptMessageJni(aEncryptedMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); } - private native String decryptMessageJni(OlmMessage aEncryptedMsg); + private native String decryptMessageJni(OlmMessage aEncryptedMsg, boolean aIsUtf8ConversionRequired); /** * Return the number of unreleased OlmSession instances.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk index adff86a..6516f5e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk @@ -1,3 +1,3 @@ APP_PLATFORM := android-16 -APP_ABI := arm64-v8a armeabi-v7a x86 x86_64 armeabi +APP_ABI := arm64-v8a armeabi-v7a armeabi x86_64 x86 APP_STL := gnustl_static \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 05df22b..a78c2cf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -180,7 +180,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jboolean aIsUtf8ConversionRequired) { jstring decryptedMsgRetValue = 0; OlmInboundGroupSession *sessionPtr = NULL; @@ -245,11 +245,27 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * } else { - // update decrypted buffer size - plainTextMsgPtr[plaintextLength] = static_cast('\0'); - - LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), (char*)plainTextMsgPtr); - decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); + // UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) + if(aIsUtf8ConversionRequired) + { + decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); + if(0 == decryptedMsgRetValue) + { + LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); + } + else + { + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); + } + } + else + { + // update decrypted buffer size + plainTextMsgPtr[plaintextLength] = static_cast('\0'); + + LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), (char*)plainTextMsgPtr); + decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); + } } } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 897ef46..ec402fd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -33,7 +33,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jboolean aIsUtf8ConversionRequired); // serialization JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 29f0310..a5cae46 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -86,6 +86,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +jstring javaCStringToUtf8(JNIEnv *env, uint8_t *aCStringMsgPtr, size_t aMsgLength); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 239fc68..561010d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -270,4 +270,47 @@ jstring serializeDataWithKey(JNIEnv *env, jobject thiz, } return pickledDataRetValue; -} \ No newline at end of file +} + + +/** +* Convert a C string into a UTF-8 format string. +* The conversion is performed in JAVA side to workaround the issue in NewStringUTF(). +* The problem is described here: https://github.com/eclipsesource/J2V8/issues/142 +*/ +jstring javaCStringToUtf8(JNIEnv *env, uint8_t *aCStringMsgPtr, size_t aMsgLength) +{ + jstring convertedRetValue = 0; + jbyteArray tempByteArray = NULL; + + if((NULL == aCStringMsgPtr) || (NULL == env)) + { + LOGE("## javaCStringToUtf8(): failure - invalid parameters (null)"); + } + else if(NULL == (tempByteArray=env->NewByteArray(aMsgLength))) + { + LOGE("## javaCStringToUtf8(): failure - return byte array OOM"); + } + else + { + env->SetByteArrayRegion(tempByteArray, 0, aMsgLength, (const jbyte*)aCStringMsgPtr); + + // UTF-8 conversion from JAVA + jstring strEncode = (env)->NewStringUTF("UTF-8"); + jclass jClass = env->FindClass("java/lang/String"); + jmethodID cstor = env->GetMethodID(jClass, "", "([BLjava/lang/String;)V"); + + if((0!=jClass) && (0!=jClass) && (0!=strEncode)) + { + convertedRetValue = (jstring) env->NewObject(jClass, cstor, tempByteArray, strEncode); + LOGD(" ## javaCStringToUtf8(): succeed"); + env->DeleteLocalRef(tempByteArray); + } + else + { + LOGE(" ## javaCStringToUtf8(): failure - invalid Java references"); + } + } + + return convertedRetValue; +} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index a31d48f..011ad44 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -574,7 +574,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz * @param aEncryptedMsg message to decrypt * @return decrypted message if operation succeed, null otherwise */ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg, jboolean aIsUtf8ConversionRequired) { jstring decryptedMsgRetValue = 0; jclass encryptedMsgJClass = 0; @@ -585,10 +585,10 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t // ptrs OlmSession *sessionPtr = NULL; const char *encryptedMsgPtr = NULL; // <= obtained from encryptedMsgJstring - void *plainTextMsgPtr = NULL; + uint8_t *plainTextMsgPtr = NULL; char *tempEncryptedPtr = NULL; - LOGD("## decryptMessageJni(): IN "); + LOGD("## decryptMessageJni(): IN - OlmSession"); if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { @@ -646,7 +646,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); // allocate output decrypted message - plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); + plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); // decrypt, but before reload encrypted buffer (previous one was destroyed) memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); @@ -662,11 +662,27 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } else { - // update decrypted buffer size - (static_cast(plainTextMsgPtr))[plaintextLength] = static_cast('\0'); + // UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) + if(aIsUtf8ConversionRequired) + { + decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); + if(0 == decryptedMsgRetValue) + { + LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); + } + else + { + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); + } + } + else + { + // update decrypted buffer size + plainTextMsgPtr[plaintextLength] = static_cast('\0'); - LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), static_cast(plainTextMsgPtr)); - decryptedMsgRetValue = env->NewStringUTF(static_cast(plainTextMsgPtr)); + LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), (char*)(plainTextMsgPtr)); + decryptedMsgRetValue = env->NewStringUTF((const char*)(plainTextMsgPtr)); + } } } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index a08b775..e5bea92 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -44,7 +44,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *e // encrypt/decrypt JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg, jboolean aIsUtf8ConversionRequired); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); -- cgit v1.2.3 From c725a561a283f508e68516ded86d141214f5ea06 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 23 Nov 2016 00:01:34 +0100 Subject: Add lib version as sufix in the aar file name --- java/android/OlmLibSdk/olm-sdk/build.gradle | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle index 8138617..b02ca0c 100644 --- a/java/android/OlmLibSdk/olm-sdk/build.gradle +++ b/java/android/OlmLibSdk/olm-sdk/build.gradle @@ -11,6 +11,7 @@ android { targetSdkVersion 21 versionCode 1 versionName "1.0" + version "0.3.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { @@ -61,6 +62,17 @@ android { } clean.dependsOn cleanNative + + + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = outputFile.name.replace(".aar", "-${version}.aar") + output.outputFile = new File(outputFile.parent, fileName) + } + } + } } def getNdkFolder() { -- cgit v1.2.3 From e63be9777453d6bc18fe70c68839bb91406ffcd0 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 23 Nov 2016 01:20:47 +0100 Subject: Update with master branch => OLM V2.0.0 --- java/android/OlmLibSdk/olm-sdk/build.gradle | 2 +- .../java/org/matrix/olm/OlmGroupSessionTest.java | 8 ++++++-- .../org/matrix/olm/OlmInboundGroupSession.java | 15 +++++++++++--- .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 4 ++-- .../src/main/jni/olm_inbound_group_session.cpp | 23 ++++++++++++++++++++-- .../src/main/jni/olm_inbound_group_session.h | 2 +- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle index b02ca0c..188acb6 100644 --- a/java/android/OlmLibSdk/olm-sdk/build.gradle +++ b/java/android/OlmLibSdk/olm-sdk/build.gradle @@ -11,7 +11,7 @@ android { targetSdkVersion 21 versionCode 1 versionName "1.0" - version "0.3.0" + version "0.2.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 6e12463..7e0324b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -151,8 +151,10 @@ public class OlmGroupSessionTest { @Test public void test10InboundDecryptMessage() { // test decrypted message - mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage); + OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); + mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage, index); assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); + assertTrue(0==index.mIndex); } @Test @@ -435,8 +437,10 @@ public class OlmGroupSessionTest { assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false); } - String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji); + OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); + String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji, index); assertNotNull(decryptedMessage); + assertTrue(13==index.mIndex); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index fa4ca1d..664b22e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -44,6 +44,14 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ private transient long mNativeId; + /** + * Wrapper class to be used in {@link #decryptMessage(String, DecryptIndex)} + */ + static public class DecryptIndex { + /** decrypt index **/ + public long mIndex; + } + /** * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. @@ -136,13 +144,14 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Decrypt the message passed in parameter. * @param aEncryptedMsg the message to be decrypted + * @param aDecryptIndex_out decrypted message index * @return the decrypted message if operation succeed, null otherwise. */ - public String decryptMessage(String aEncryptedMsg) { - String decryptedMessage = decryptMessageJni(aEncryptedMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); + public String decryptMessage(String aEncryptedMsg, DecryptIndex aDecryptIndex_out) { + String decryptedMessage = decryptMessageJni(aEncryptedMsg, aDecryptIndex_out, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); return decryptedMessage; } - private native String decryptMessageJni(String aEncryptedMsg, boolean aIsUtf8ConversionRequired); + private native String decryptMessageJni(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, boolean aIsUtf8ConversionRequired); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index 2d94676..2a7d216 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -2,8 +2,8 @@ LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := olm -MAJOR := 1 -MINOR := 3 +MAJOR := 2 +MINOR := 0 PATCH := 0 OLM_VERSION := $(MAJOR).$(MINOR).$(PATCH) SRC_ROOT_DIR := ../../../../../../.. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index a78c2cf..e450a4c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -180,13 +180,16 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jboolean aIsUtf8ConversionRequired) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jboolean aIsUtf8ConversionRequired) { jstring decryptedMsgRetValue = 0; OlmInboundGroupSession *sessionPtr = NULL; const char *encryptedMsgPtr = NULL; uint8_t *plainTextMsgPtr = NULL; uint8_t *tempEncryptedPtr = NULL; + uint32_t messageIndex = 0; + jclass indexObjJClass = 0; + jfieldID indexMsgFieldId; LOGD("## decryptMessageJni(): inbound group session IN"); @@ -198,10 +201,22 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); } + else if(0 == aDecryptIndex) + { + LOGE(" ## decryptMessageJni(): failure - invalid index object"); + } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) { LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } + else if(0 == (indexObjJClass = env->GetObjectClass(aDecryptIndex))) + { + LOGE("## decryptMessageJni(): failure - unable to get index class"); + } + else if(0 == (indexMsgFieldId = env->GetFieldID(indexObjJClass,"mIndex","J"))) + { + LOGE("## decryptMessageJni(): failure - unable to get index type field"); + } else { // get encrypted message length @@ -238,13 +253,17 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * tempEncryptedPtr, encryptedMsgLength, plainTextMsgPtr, - maxPlainTextLength); + maxPlainTextLength, + &messageIndex); if(plaintextLength == olm_error()) { LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); } else { + // update index + env->SetLongField(aDecryptIndex, indexMsgFieldId, (jlong)messageIndex); + // UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) if(aIsUtf8ConversionRequired) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index ec402fd..7d6fb5e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -33,7 +33,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jboolean aIsUtf8ConversionRequired); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jboolean aIsUtf8ConversionRequired); // serialization JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -- cgit v1.2.3 From b3c20156165962df72e1b6ae31a86e7e73d0794a Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Wed, 23 Nov 2016 09:36:46 +0100 Subject: Rename JNI API: getOlmLibVersion() => getOlmLibVersionJni() --- .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java | 5 ++++- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 4 ++-- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 5170ee9..765de5e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -56,6 +56,9 @@ public class OlmManager { * Get the OLM lib version. * @return the lib version as a string */ - public native String getOlmLibVersion(); + public String getOlmLibVersion(){ + return getOlmLibVersionJni(); + } + public native String getOlmLibVersionJni(); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 07446b0..9e6ed2a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -465,14 +465,14 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz } -JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv* env, jobject thiz) +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) { uint8_t majorVer=0, minorVer=0, patchVer=0; jstring returnValueStr=0; char buff[150]; olm_get_library_version(&majorVer, &minorVer, &patchVer); - LOGD("## getOlmLibVersion(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); + LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); snprintf(buff, sizeof(buff), " V%d.%d.%d", majorVer, minorVer, patchVer); returnValueStr = env->NewStringUTF((const char*)buff); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 2aa5f93..b4bf0ef 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -27,7 +27,7 @@ extern "C" { #endif -JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); // account creation/destruction JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz); -- cgit v1.2.3 From d3d3024ea29384093bb91d530fa5ff98002e642b Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Thu, 24 Nov 2016 10:21:12 +0100 Subject: Add missing gradle folder --- .../android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes .../OlmLibSdk/gradle/wrapper/gradle-wrapper.properties | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar create mode 100644 java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties diff --git a/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar b/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..13372ae Binary files /dev/null and b/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar differ diff --git a/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties b/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..4ba4622 --- /dev/null +++ b/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Oct 13 09:38:01 CEST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip -- cgit v1.2.3 From 0263cd3039568bd5e5b374451efc0e37c2629592 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 28 Nov 2016 11:53:54 +0100 Subject: Remove un used code --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 6 -- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 13 --- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 95 ---------------------- 3 files changed, 114 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 9e6ed2a..c8c6e8a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -18,12 +18,6 @@ using namespace AndroidOlmSdk; -/*jstring serializeDataWithKey(JNIEnv *env, jobject thiz, - jstring aKey, - jobject aErrorMsg, - olmPickleLengthFuncPtr aGetLengthFunc, - olmPickleFuncPtr aGetPickleFunc, - olmLastErrorFuncPtr aGetLastErrorFunc);*/ /** * Init memory allocation for account creation. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index a5cae46..d70dc58 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -62,19 +62,6 @@ namespace AndroidOlmSdk } -// function pointer templates -template using olmPickleLengthFuncPtr = size_t (*)(T); -template using olmPickleFuncPtr = size_t (*)(T, void const *, size_t, void *, size_t); -template using olmLastErrorFuncPtr = const char* (*)(T); - -template -jstring serializeDataWithKey(JNIEnv *env, jobject thiz, - jstring aKey, - jobject aErrorMsg, - olmPickleLengthFuncPtr aGetLengthFunc, - olmPickleFuncPtr aGetPickleFunc, - olmLastErrorFuncPtr aGetLastErrorFunc); - #ifdef __cplusplus extern "C" { #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 561010d..a0525dc 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -178,101 +178,6 @@ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) } -template -jstring serializeDataWithKey(JNIEnv *env, jobject thiz, - jstring aKey, - jobject aErrorMsg, - olmPickleLengthFuncPtr aGetLengthFunc, - olmPickleFuncPtr aGetPickleFunc, - olmLastErrorFuncPtr aGetLastErrorFunc) -{ - jstring pickledDataRetValue = 0; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; - jstring errorJstring = 0; - const char *keyPtr = NULL; - void *pickledPtr = NULL; - T accountPtr = NULL; - - LOGD("## serializeDataWithKeyJni(): IN"); - - if(NULL == (accountPtr = (T)getAccountInstanceId(env,thiz))) - { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); - } - else if(0 == aKey) - { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); - } - else if(0 == aErrorMsg) - { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); - } - else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); - } - else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); - } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) - { - LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); - } - else - { - size_t pickledLength = aGetLengthFunc(accountPtr); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); - - if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) - { - LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); - } - else - { - size_t result = aGetPickleFunc(accountPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if(result == olm_error()) - { - const char *errorMsgPtr = aGetLastErrorFunc(accountPtr); - LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); - - if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } - } - else - { - // build success output - (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); - } - } - } - - // free alloc - if(NULL != keyPtr) - { - env->ReleaseStringUTFChars(aKey, keyPtr); - } - - if(NULL != pickledPtr) - { - free(pickledPtr); - } - - return pickledDataRetValue; -} - - /** * Convert a C string into a UTF-8 format string. * The conversion is performed in JAVA side to workaround the issue in NewStringUTF(). -- cgit v1.2.3 From ac0ccb224dfac108276f30606e5cd114db3c5691 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Mon, 28 Nov 2016 11:56:20 +0100 Subject: Update decryptMessage() API with the error message as an output parameter --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 38 ++++++++++++++++++++-- .../org/matrix/olm/OlmInboundGroupSession.java | 20 +++++++++--- .../src/main/jni/olm_inbound_group_session.cpp | 33 +++++++++++++++++-- .../src/main/jni/olm_inbound_group_session.h | 2 +- 4 files changed, 82 insertions(+), 11 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 7e0324b..fe36858 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -151,8 +151,10 @@ public class OlmGroupSessionTest { @Test public void test10InboundDecryptMessage() { // test decrypted message + StringBuffer errorMsg = new StringBuffer(); OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); - mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage, index); + + mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage, index, errorMsg); assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); assertTrue(0==index.mIndex); } @@ -437,11 +439,43 @@ public class OlmGroupSessionTest { assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false); } + StringBuffer errorMsg = new StringBuffer(); OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); - String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji, index); + + String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji, index, errorMsg); assertNotNull(decryptedMessage); assertTrue(13==index.mIndex); } + + /** + * Specific test to check an error message is returned by decryptMessage() API.
+ * A corrupted encrypted message is passed, and a INVALID_BASE64 is + * espexted. + **/ + @Test + public void test19TestErrorMessageReturnedInDecrypt() { + OlmInboundGroupSession bobInboundGroupSession=null; + final String EXPECTED_ERROR_MESSAGE= "INVALID_BASE64"; + StringBuffer errorMsg = new StringBuffer(); + OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); + + String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; + String corruptedEncryptedMsg = "AwgANYTHINGf87ge45ge7gr*/rg5ganything4gr41rrgr4re55tanythingmcsXUkhDv0UePj922kgf+"; + + // valid INBOUND GROUP SESSION + try { + bobInboundGroupSession = new OlmInboundGroupSession(sessionKeyRef); + } catch (OlmException e) { + assertTrue("Exception in test19TestErrorMessageReturnedInDecrypt, Exception code=" + e.getExceptionCode(), false); + } + + String decryptedMessage = bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg, index, errorMsg); + assertTrue(0!=EXPECTED_ERROR_MESSAGE.length()); + assertTrue(EXPECTED_ERROR_MESSAGE.equals(errorMsg.toString())); + assertTrue(null==decryptedMessage); + assertTrue(0==index.mIndex); + } + } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 664b22e..073058a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -45,7 +45,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri private transient long mNativeId; /** - * Wrapper class to be used in {@link #decryptMessage(String, DecryptIndex)} + * Wrapper class to be used in {@link #decryptMessage(String, DecryptIndex, StringBuffer)} */ static public class DecryptIndex { /** decrypt index **/ @@ -142,16 +142,26 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** - * Decrypt the message passed in parameter. + * Decrypt the message passed in parameter.
+ * In case of error, null is returned and an error message description is provided in aErrorMsg. * @param aEncryptedMsg the message to be decrypted * @param aDecryptIndex_out decrypted message index + * @param aErrorMsg error message description * @return the decrypted message if operation succeed, null otherwise. */ - public String decryptMessage(String aEncryptedMsg, DecryptIndex aDecryptIndex_out) { - String decryptedMessage = decryptMessageJni(aEncryptedMsg, aDecryptIndex_out, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); + public String decryptMessage(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, StringBuffer aErrorMsg) { + String decryptedMessage = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## decryptMessage(): invalid parameter - aErrorMsg=null"); + } else { + aErrorMsg.setLength(0); + decryptedMessage = decryptMessageJni(aEncryptedMsg, aDecryptIndex_out, aErrorMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); + } return decryptedMessage; } - private native String decryptMessageJni(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, boolean aIsUtf8ConversionRequired); + private native String decryptMessageJni(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, StringBuffer aErrorMsg, boolean aIsUtf8ConversionRequired); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index e450a4c..6d11b38 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -180,7 +180,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jboolean aIsUtf8ConversionRequired) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg, jboolean aIsUtf8ConversionRequired) { jstring decryptedMsgRetValue = 0; OlmInboundGroupSession *sessionPtr = NULL; @@ -190,6 +190,10 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * uint32_t messageIndex = 0; jclass indexObjJClass = 0; jfieldID indexMsgFieldId; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *errorMsgPtr = NULL; LOGD("## decryptMessageJni(): inbound group session IN"); @@ -205,6 +209,18 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { LOGE(" ## decryptMessageJni(): failure - invalid index object"); } + else if(0 == aErrorMsg) + { + LOGE(" ## decryptMessageJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## decryptMessageJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## decryptMessageJni(): failure - unable to get error method ID"); + } else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) { LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); @@ -238,7 +254,12 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * encryptedMsgLength); if(maxPlainTextLength == olm_error()) { - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); + errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } } else { @@ -257,7 +278,13 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * &messageIndex); if(plaintextLength == olm_error()) { - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); + errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } } else { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 7d6fb5e..65ba670 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -33,7 +33,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jboolean aIsUtf8ConversionRequired); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg, jboolean aIsUtf8ConversionRequired); // serialization JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -- cgit v1.2.3 From 2fab6f946e2e46b35e050d12729525ceb40b1796 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 20 Dec 2016 10:10:52 +0100 Subject: Update the execution mode --- java/android/OlmLibSdk/gradlew | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 java/android/OlmLibSdk/gradlew diff --git a/java/android/OlmLibSdk/gradlew b/java/android/OlmLibSdk/gradlew old mode 100644 new mode 100755 -- cgit v1.2.3 From c553d18a9a7e70b1e08bf5e919243c8c0303890e Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 20 Dec 2016 10:42:06 +0100 Subject: Update the readme files. --- README.rst | 6 ++++++ java/android/OlmLibSdk/README.rst | 26 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 java/android/OlmLibSdk/README.rst diff --git a/README.rst b/README.rst index be1fb1a..3287dbd 100644 --- a/README.rst +++ b/README.rst @@ -32,6 +32,12 @@ To build the javascript bindings, install emscripten from http://kripken.github. .. code:: bash make js + +To build the android project for Android bindings, run: + + .. code:: bash + cd java/android/OlmLibSdk/OlmLibSdk + ./gradlew clean assembleRelease Release process --------------- diff --git a/java/android/OlmLibSdk/README.rst b/java/android/OlmLibSdk/README.rst new file mode 100644 index 0000000..049eed8 --- /dev/null +++ b/java/android/OlmLibSdk/README.rst @@ -0,0 +1,26 @@ +OlmLibSdk +========= + +OlmLibSdk exposes An android wrapper to libolm. + + +Installation +------------ + Create a libs directory in your project directory + Copy the olm-sdk.aar into it. + In your build.gradle file, add in the android section + repositories { + flatDir { + dir 'libs' + } + } + Add in the dependencies category + compile(name: 'olm-sdk', ext: 'aar') + +Development +----------- +import the project from the /java/android/OlmLibSdk path. + +The project contains some JNI files and some Java wraper files. + +The project contains some tests under AndroidTests package. \ No newline at end of file -- cgit v1.2.3 From d741c012f303f7d430af013be456d5221f1d29c0 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 12:58:00 +0100 Subject: identityKeys and oneTimeKeys return Map instead of JSON. --- .../java/org/matrix/olm/OlmAccountTest.java | 72 +++++++++---------- .../java/org/matrix/olm/OlmSessionTest.java | 47 ++++++------- .../java/org/matrix/olm/OlmUtilityTest.java | 8 ++- .../java/org/matrix/olm/TestHelper.java | 35 ++++------ .../src/main/java/org/matrix/olm/OlmAccount.java | 80 +++++++++++++++++++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 2 +- 6 files changed, 153 insertions(+), 91 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 2c2711d..024b44b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -38,6 +38,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.Map; import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertFalse; @@ -130,16 +131,16 @@ public class OlmAccountTest { */ @Test public void test05IdentityKeys() { - JSONObject identityKeysJson = mOlmAccount.identityKeys(); - assertNotNull(identityKeysJson); - Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson); + Map identityKeys = mOlmAccount.identityKeys(); + assertNotNull(identityKeys); + Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeys); // is JSON_KEY_FINGER_PRINT_KEY present? - String fingerPrintKey = TestHelper.getFingerprintKey(identityKeysJson); + String fingerPrintKey = TestHelper.getFingerprintKey(identityKeys); assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); // is JSON_KEY_IDENTITY_KEY present? - String identityKey = TestHelper.getIdentityKey(identityKeysJson); + String identityKey = TestHelper.getIdentityKey(identityKeys); assertTrue("identity key missing",!TextUtils.isEmpty(identityKey)); } @@ -169,20 +170,19 @@ public class OlmAccountTest { @Test public void test08OneTimeKeysJsonFormat() { int oneTimeKeysCount = 0; - JSONObject generatedKeysJsonObj; - JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys(); + Map> oneTimeKeysJson = mOlmAccount.oneTimeKeys(); assertNotNull(oneTimeKeysJson); try { - generatedKeysJsonObj = oneTimeKeysJson.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); - assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=generatedKeysJsonObj); + Map map = oneTimeKeysJson.get(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=map); // test the count of the generated one time keys: - oneTimeKeysCount = generatedKeysJsonObj.length(); + oneTimeKeysCount = map.size(); assertTrue("Expected count="+GENERATION_ONE_TIME_KEYS_NUMBER+" found="+oneTimeKeysCount,GENERATION_ONE_TIME_KEYS_NUMBER==oneTimeKeysCount); - } catch (JSONException e) { + } catch (Exception e) { assertTrue("Exception MSg="+e.getMessage(), false); } } @@ -244,8 +244,8 @@ public class OlmAccountTest { assertTrue(0==retValue); // get keys references - JSONObject identityKeysRef = accountRef.identityKeys(); - JSONObject oneTimeKeysRef = accountRef.oneTimeKeys(); + Map identityKeysRef = accountRef.identityKeys(); + Map> oneTimeKeysRef = accountRef.oneTimeKeys(); assertNotNull(identityKeysRef); assertNotNull(oneTimeKeysRef); @@ -268,8 +268,8 @@ public class OlmAccountTest { assertNotNull(accountDeserial); // get de-serialized keys - JSONObject identityKeysDeserial = accountDeserial.identityKeys(); - JSONObject oneTimeKeysDeserial = accountDeserial.oneTimeKeys(); + Map identityKeysDeserial = accountDeserial.identityKeys(); + Map> oneTimeKeysDeserial = accountDeserial.oneTimeKeys(); assertNotNull(identityKeysDeserial); assertNotNull(oneTimeKeysDeserial); @@ -363,43 +363,43 @@ public class OlmAccountTest { OlmAccount account9 = new OlmAccount(); OlmAccount account10 = new OlmAccount(); - JSONObject identityKeysJson1 = account1.identityKeys(); - JSONObject identityKeysJson2 = account2.identityKeys(); - JSONObject identityKeysJson3 = account3.identityKeys(); - JSONObject identityKeysJson4 = account4.identityKeys(); - JSONObject identityKeysJson5 = account5.identityKeys(); - JSONObject identityKeysJson6 = account6.identityKeys(); - JSONObject identityKeysJson7 = account7.identityKeys(); - JSONObject identityKeysJson8 = account8.identityKeys(); - JSONObject identityKeysJson9 = account9.identityKeys(); - JSONObject identityKeysJson10 = account10.identityKeys(); - - String identityKey1 = TestHelper.getIdentityKey(identityKeysJson1); - String identityKey2 = TestHelper.getIdentityKey(identityKeysJson2); + Map identityKeys1 = account1.identityKeys(); + Map identityKeys2 = account2.identityKeys(); + Map identityKeys3 = account3.identityKeys(); + Map identityKeys4 = account4.identityKeys(); + Map identityKeys5 = account5.identityKeys(); + Map identityKeys6 = account6.identityKeys(); + Map identityKeys7 = account7.identityKeys(); + Map identityKeys8 = account8.identityKeys(); + Map identityKeys9 = account9.identityKeys(); + Map identityKeys10 = account10.identityKeys(); + + String identityKey1 = TestHelper.getIdentityKey(identityKeys1); + String identityKey2 = TestHelper.getIdentityKey(identityKeys2); assertFalse(identityKey1.equals(identityKey2)); - String identityKey3 = TestHelper.getIdentityKey(identityKeysJson3); + String identityKey3 = TestHelper.getIdentityKey(identityKeys3); assertFalse(identityKey2.equals(identityKey3)); - String identityKey4 = TestHelper.getIdentityKey(identityKeysJson4); + String identityKey4 = TestHelper.getIdentityKey(identityKeys4); assertFalse(identityKey3.equals(identityKey4)); - String identityKey5 = TestHelper.getIdentityKey(identityKeysJson5); + String identityKey5 = TestHelper.getIdentityKey(identityKeys5); assertFalse(identityKey4.equals(identityKey5)); - String identityKey6 = TestHelper.getIdentityKey(identityKeysJson6); + String identityKey6 = TestHelper.getIdentityKey(identityKeys6); assertFalse(identityKey5.equals(identityKey6)); - String identityKey7 = TestHelper.getIdentityKey(identityKeysJson7); + String identityKey7 = TestHelper.getIdentityKey(identityKeys7); assertFalse(identityKey6.equals(identityKey7)); - String identityKey8 = TestHelper.getIdentityKey(identityKeysJson8); + String identityKey8 = TestHelper.getIdentityKey(identityKeys8); assertFalse(identityKey7.equals(identityKey8)); - String identityKey9 = TestHelper.getIdentityKey(identityKeysJson9); + String identityKey9 = TestHelper.getIdentityKey(identityKeys9); assertFalse(identityKey8.equals(identityKey9)); - String identityKey10 = TestHelper.getIdentityKey(identityKeysJson10); + String identityKey10 = TestHelper.getIdentityKey(identityKeys10); assertFalse(identityKey9.equals(identityKey10)); account1.releaseAccount(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 1aeb3fb..98e5b90 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -33,6 +33,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; +import java.util.Map; import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertFalse; @@ -93,14 +94,14 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // get bob identity key - JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + Map bobIdentityKeys = bobAccount.identityKeys(); + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null!=bobIdentityKey); // get bob one time keys assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); // CREATE ALICE SESSION @@ -186,14 +187,14 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // get bob identity key - JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + Map bobIdentityKeys = bobAccount.identityKeys(); + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null!=bobIdentityKey); // get bob one time keys assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); // CREATE ALICE SESSION @@ -358,16 +359,16 @@ public class OlmSessionTest { } // get bob/luke identity key - JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - JSONObject aliceIdentityKeysJson = aliceAccount.identityKeys(); - String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); - String aliceIdentityKey = TestHelper.getIdentityKey(aliceIdentityKeysJson); + Map bobIdentityKeys = bobAccount.identityKeys(); + Map aliceIdentityKeys = aliceAccount.identityKeys(); + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); + String aliceIdentityKey = TestHelper.getIdentityKey(aliceIdentityKeys); // get bob/luke one time keys assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); assertTrue(0 == aliceAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj, 1); + Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeys, 1); // create alice inbound session for bob assertTrue(0==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey1)); @@ -428,14 +429,14 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // get bob identity key - JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + Map bobIdentityKeys = bobAccount.identityKeys(); + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null!=bobIdentityKey); // get bob one time keys assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); // CREATE ALICE SESSION @@ -567,15 +568,15 @@ public class OlmSessionTest { } // get bob identity key - JSONObject bobIdentityKeysJson = bobAccount.identityKeys(); - String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeysJson); + Map bobIdentityKeys = bobAccount.identityKeys(); + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null != bobIdentityKey); // get bob one time keys assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys(); - assertNotNull(bobOneTimeKeysJsonObj); - String bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeysJsonObj,1); + Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + assertNotNull(bobOneTimeKeys); + String bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); // CREATE ALICE SESSION diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 3006344..6296a31 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -27,6 +27,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.util.Map; + import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -76,9 +78,9 @@ public class OlmUtilityTest { assertNotNull(messageSignature); // get identities key (finger print key) - JSONObject identityKeysJson = account.identityKeys(); - assertNotNull(identityKeysJson); - fingerPrintKey = TestHelper.getFingerprintKey(identityKeysJson); + Map identityKeys = account.identityKeys(); + assertNotNull(identityKeys); + fingerPrintKey = TestHelper.getFingerprintKey(identityKeys); assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); // instantiate utility object diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java index 363ab7a..3adb63c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java @@ -19,7 +19,9 @@ package org.matrix.olm; import org.json.JSONException; import org.json.JSONObject; +import java.util.ArrayList; import java.util.Iterator; +import java.util.Map; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -31,15 +33,15 @@ public class TestHelper { /** * Return the identity key {@link OlmAccount#JSON_KEY_IDENTITY_KEY} from the JSON object. - * @param aIdentityKeysObj JSON result of {@link OlmAccount#identityKeys()} + * @param aIdentityKeysMap result of {@link OlmAccount#identityKeys()} * @return identity key string if operation succeed, null otherwise */ - static public String getIdentityKey(JSONObject aIdentityKeysObj){ + static public String getIdentityKey(Map aIdentityKeysMap){ String idKey = null; try { - idKey = aIdentityKeysObj.getString(OlmAccount.JSON_KEY_IDENTITY_KEY); - } catch (JSONException e) { + idKey = aIdentityKeysMap.get(OlmAccount.JSON_KEY_IDENTITY_KEY); + } catch (Exception e) { assertTrue("Exception MSg=" + e.getMessage(), false); } return idKey; @@ -47,15 +49,15 @@ public class TestHelper { /** * Return the fingerprint key {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} from the JSON object. - * @param aIdentityKeysObj JSON result of {@link OlmAccount#identityKeys()} + * @param aIdentityKeysMap result of {@link OlmAccount#identityKeys()} * @return fingerprint key string if operation succeed, null otherwise */ - static public String getFingerprintKey(JSONObject aIdentityKeysObj){ + static public String getFingerprintKey(Map aIdentityKeysMap) { String fingerprintKey = null; try { - fingerprintKey = aIdentityKeysObj.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); - } catch (JSONException e) { + fingerprintKey = aIdentityKeysMap.get(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); + } catch (Exception e) { assertTrue("Exception MSg=" + e.getMessage(), false); } return fingerprintKey; @@ -63,26 +65,19 @@ public class TestHelper { /** * Return the first one time key from the JSON object. - * @param aIdentityKeysObj JSON result of {@link OlmAccount#oneTimeKeys()} + * @param aIdentityKeysMap result of {@link OlmAccount#oneTimeKeys()} * @param aKeyPosition the position of the key to be retrieved * @return one time key string if operation succeed, null otherwise */ - static public String getOneTimeKey(JSONObject aIdentityKeysObj, int aKeyPosition) { + static public String getOneTimeKey(Map> aIdentityKeysMap, int aKeyPosition) { String firstOneTimeKey = null; - int i=0; try { - JSONObject generatedKeys = aIdentityKeysObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY); + Map generatedKeys = aIdentityKeysMap.get(OlmAccount.JSON_KEY_ONE_TIME_KEY); assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY + " object is missing", generatedKeys); - Iterator generatedKeysIt = generatedKeys.keys(); - while(i(generatedKeys.values())).get(aKeyPosition - 1); + } catch (Exception e) { assertTrue("Exception Msg=" + e.getMessage(), false); } return firstOneTimeKey; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index aeeaebc..4863a06 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -26,6 +26,9 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; /** * Account class used to create Olm sessions in conjunction with {@link OlmSession} class.
@@ -226,16 +229,16 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private native long createNewAccountJni(); /** - * Return the identity keys (identity and fingerprint keys) in a JSON array.
+ * Return the identity keys (identity and fingerprint keys) in a dictionary.
* Public API for {@link #identityKeysJni()}.
* Ex: * { * "curve25519":"Vam++zZPMqDQM6ANKpO/uAl5ViJSHxV9hd+b0/fwRAg", * "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I" * } - * @return identity keys in JSON array if operation succeed, null otherwise + * @return identity keys dictionary if operation succeeds, null otherwise */ - public JSONObject identityKeys() { + public Map identityKeys() { JSONObject identityKeysJsonObj = null; byte identityKeysBuffer[]; @@ -251,7 +254,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); } - return identityKeysJsonObj; + return toStringMap(identityKeysJsonObj); } /** * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
@@ -283,7 +286,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private native int generateOneTimeKeysJni(int aNumberOfKeys); /** - * Return the "one time keys" in a JSON array.
+ * Return the "one time keys" in a dictionary.
* The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}
* Ex: * { "curve25519": @@ -295,9 +298,9 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * }
* Public API for {@link #oneTimeKeysJni()}.
* Note: these keys are to be published on the server. - * @return one time keys in JSON array format if operation succeed, null otherwise + * @return one time keys in string dictionary if operation succeed, null otherwise */ - public JSONObject oneTimeKeys() { + public Map> oneTimeKeys() { byte identityKeysBuffer[]; JSONObject oneTimeKeysJsonObj = null; @@ -313,7 +316,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); } - return oneTimeKeysJsonObj; + return toStringMapMap(oneTimeKeysJsonObj); } /** * Get the public parts of the unpublished "one time keys" for the account.
@@ -373,4 +376,65 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { public int getUnreleasedCount() { return mUnreleasedCount; } + + /** + * Build a string-string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + private static Map toStringMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap map = new HashMap<>(); + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof String) { + map.put(key, (String) value); + } else { + Log.e(LOG_TAG, "## toStringMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } + + /** + * Build a string-string dictionary of string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + private static Map> toStringMapMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap> map = new HashMap<>(); + + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof JSONObject) { + map.put(key, toStringMap((JSONObject) value)); + } else { + Log.e(LOG_TAG, "## toStringMapMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMapMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index c8c6e8a..00c8a8e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -468,7 +468,7 @@ JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject olm_get_library_version(&majorVer, &minorVer, &patchVer); LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); - snprintf(buff, sizeof(buff), " V%d.%d.%d", majorVer, minorVer, patchVer); + snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); returnValueStr = env->NewStringUTF((const char*)buff); return returnValueStr; -- cgit v1.2.3 From 1c067b1cb64ee4d12d71a6c254d631aebd72ceb9 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 13:01:12 +0100 Subject: remove the RTL support by default. --- java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml b/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml index 8a8747f..902f2e3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml +++ b/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml @@ -3,9 +3,6 @@ - + android:label="@string/app_name"> - -- cgit v1.2.3 From bacdc3c539b91ffdfb53f4f106747eb89e555400 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 13:06:51 +0100 Subject: Add an encoding type while converting byte[] to string --- .../src/main/java/org/matrix/olm/OlmAccount.java | 26 ++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 4863a06..82533c2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -244,7 +244,16 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if( null != (identityKeysBuffer = identityKeysJni())) { try { - identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); + String identityKeysString; + + try { + identityKeysString = new String(identityKeysBuffer, "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## identityKeys(): Exception : cannot convert with utf-8 charset " + e.getMessage()); + identityKeysString = new String(identityKeysBuffer); + } + + identityKeysJsonObj = new JSONObject(identityKeysString); //Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); } catch (JSONException e) { identityKeysJsonObj = null; @@ -301,12 +310,21 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * @return one time keys in string dictionary if operation succeed, null otherwise */ public Map> oneTimeKeys() { - byte identityKeysBuffer[]; + byte oneTimeKeysBuffer[]; JSONObject oneTimeKeysJsonObj = null; - if( null != (identityKeysBuffer = oneTimeKeysJni())) { + if( null != (oneTimeKeysBuffer = oneTimeKeysJni())) { try { - oneTimeKeysJsonObj = new JSONObject(new String(identityKeysBuffer)); + String oneTimeKeysString; + + try { + oneTimeKeysString = new String(oneTimeKeysBuffer, "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## oneTimeKeys(): Exception : cannot convert with utf-8 charset " + e.getMessage()); + oneTimeKeysString = new String(oneTimeKeysBuffer); + } + + oneTimeKeysJsonObj = new JSONObject(new String(oneTimeKeysString)); //Log.d(LOG_TAG, "## oneTimeKeys(): OneTime Json keys=" + oneTimeKeysJsonObj.toString()); } catch (JSONException e) { oneTimeKeysJsonObj = null; -- cgit v1.2.3 From 643165067f4140d7cb3cba88f21b3fc8dd2d244f Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 15:10:54 +0100 Subject: setRandomInBuffer uses java.lang.SecureRandom. --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 2 +- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 70 +++++++++++++++++++--- .../src/main/jni/olm_outbound_group_session.cpp | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 4 +- 5 files changed, 68 insertions(+), 14 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 00c8a8e..68dcc0b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -104,7 +104,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi LOGD("## initNewAccount(): randomSize=%lu", static_cast(randomSize)); // allocate random buffer - if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize)) + if((0!=randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) { LOGE("## initNewAccount(): failure - random buffer init"); } @@ -234,7 +234,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); LOGD("## generateOneTimeKeysJni(): randomLength=%lu", static_cast(randomLength)); - if((0!=randomLength) && !setRandomInBuffer(&randomBufferPtr, randomLength)) + if((0!=randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) { LOGE("## generateOneTimeKeysJni(): failure - random buffer init"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index d70dc58..2c8430c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -67,7 +67,7 @@ extern "C" { #endif // internal helper functions -bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize); +bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize); jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index a0525dc..b52ac30 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -29,10 +29,11 @@ using namespace AndroidOlmSdk; * @param aRandomSize the number of random values to apply * @return true if operation succeed, false otherwise **/ -bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) +bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) { bool retCode = false; struct timeval timeValue; + int bufferLen = aRandomSize*sizeof(uint8_t); if(NULL == aBuffer2Ptr) { @@ -42,7 +43,7 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) { LOGE("## setRandomInBuffer(): failure - random size=0"); } - else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t)))) + else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(bufferLen))) { LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); } @@ -50,16 +51,69 @@ bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize) { LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); - gettimeofday(&timeValue, NULL); - srand(timeValue.tv_usec); // init seed + bool secureRandomSucceeds = false; - for(size_t i=0;iFindClass("java/security/SecureRandom"); + + if (cls) { - (*aBuffer2Ptr)[i] = (uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO); - // debug purpose - //LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]); + jobject newObj = 0; + jmethodID constructor = env->GetMethodID(cls, "", "()V"); + jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V"); + + if (constructor) + { + newObj = env->NewObject(cls, constructor); + jbyteArray tempByteArray = env->NewByteArray(bufferLen); + + if (newObj && tempByteArray) + { + env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); + + jbyte* buffer = env->GetByteArrayElements(tempByteArray,0); + + if (buffer) + { + memcpy(*aBuffer2Ptr, buffer, bufferLen); + secureRandomSucceeds = true; + } + } + + if (tempByteArray) + { + env->DeleteLocalRef(tempByteArray); + } + + if (newObj) + { + env->DeleteLocalRef(newObj); + } + } } + if (!secureRandomSucceeds) + { + LOGE("## setRandomInBuffer(): SecureRandom failed, use a fallback"); + + gettimeofday(&timeValue, NULL); + srand(timeValue.tv_usec); // init seed + + for(size_t i=0;i(randomLength)); - if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) + if((0!=randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 011ad44..98897cb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -132,7 +132,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject { // allocate random buffer size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); LOGD("## initOutboundSessionJni(): randomSize=%lu",static_cast(randomSize)); - if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize)) + if((0!=randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) { LOGE("## initOutboundSessionJni(): failure - random buffer init"); } @@ -497,7 +497,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // it just does not need new random data to encrypt a new message size_t randomLength = olm_encrypt_random_length(sessionPtr); LOGD("## encryptMessageJni(): randomLength=%lu", static_cast(randomLength)); - if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength)) + if((0!=randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { LOGE("## encryptMessageJni(): failure - random buffer init"); } -- cgit v1.2.3 From ffb40326ff41985904ba74cf83a1b6b71e457626 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 15:17:53 +0100 Subject: Fix a potential memory leak. --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index b52ac30..82c3e28 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -130,8 +130,8 @@ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass) { jlong instanceId = 0; - jfieldID instanceIdField; - jclass loaderClass; + jfieldID instanceIdField = 0; + jclass loaderClass = 0; jclass requiredClass = 0; if(NULL!=aJniEnv) @@ -147,7 +147,6 @@ jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingCl if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeId", "J"))) { instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - aJniEnv->DeleteLocalRef(loaderClass); LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId); } else @@ -164,7 +163,14 @@ jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingCl { LOGE("## getInstanceId() ERROR! aJniEnv=NULL"); } + LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); + + if (loaderClass) + { + aJniEnv->DeleteLocalRef(loaderClass); + } + return instanceId; } -- cgit v1.2.3 From 2e77e3957945b52f92e4b72a8be90202ef7b7d69 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 16:26:07 +0100 Subject: move getOlmLibVersionJni --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 23 +++++----------------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 2 -- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 3 +-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 14 +++++++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 4 +++- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 68dcc0b..5d79ecb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -113,7 +113,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi // create account accountRetCode = olm_create_account(accountPtr, (void*)randomBuffPtr, randomSize); if(accountRetCode == olm_error()) { - LOGE("## initNewAccount(): failure - account creation failed Msg=%s", (const char *)olm_account_last_error(accountPtr)); + LOGE("## initNewAccount(): failure - account creation failed Msg=%s", olm_account_last_error(accountPtr)); } LOGD("## initNewAccount(): success - OLM account created"); @@ -147,16 +147,16 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject size_t keysResult; jbyteArray byteArrayRetValue = NULL; - LOGD("## identityKeys(): accountPtr =%p",accountPtr); - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { LOGE("## identityKeys(): failure - invalid Account ptr=NULL"); } else - { // identity keys allocation + { + LOGD("## identityKeys(): accountPtr =%p", accountPtr); + // identity keys allocation identityKeysLength = olm_account_identity_keys_length(accountPtr); - if(NULL == (identityKeysBytesPtr=(uint8_t*)malloc(identityKeysLength*sizeof(uint8_t)))) + if(NULL == (identityKeysBytesPtr=(uint8_t*)malloc(identityKeysLength))) { LOGE("## identityKeys(): failure - identity keys array OOM"); } @@ -459,20 +459,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz } -JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) -{ - uint8_t majorVer=0, minorVer=0, patchVer=0; - jstring returnValueStr=0; - char buff[150]; - - olm_get_library_version(&majorVer, &minorVer, &patchVer); - LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); - - snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); - returnValueStr = env->NewStringUTF((const char*)buff); - return returnValueStr; -} /** * Serialize and encrypt account instance into a base64 string.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index b4bf0ef..d57c7d9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -27,8 +27,6 @@ extern "C" { #endif -JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); - // account creation/destruction JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 82c3e28..25f3193 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -32,7 +32,6 @@ using namespace AndroidOlmSdk; bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) { bool retCode = false; - struct timeval timeValue; int bufferLen = aRandomSize*sizeof(uint8_t); if(NULL == aBuffer2Ptr) @@ -98,7 +97,7 @@ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) if (!secureRandomSucceeds) { LOGE("## setRandomInBuffer(): SecureRandom failed, use a fallback"); - + struct timeval timeValue; gettimeofday(&timeValue, NULL); srand(timeValue.tv_usec); // init seed diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 19a045b..0e51940 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -36,6 +36,20 @@ OlmUtility* initializeUtilityMemory() return utilityPtr; } +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) +{ + uint8_t majorVer=0, minorVer=0, patchVer=0; + jstring returnValueStr=0; + char buff[150]; + + olm_get_library_version(&majorVer, &minorVer, &patchVer); + LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); + + snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); + returnValueStr = env->NewStringUTF((const char*)buff); + + return returnValueStr; +} JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index 0bbbb52..b807c6d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -26,8 +26,10 @@ #ifdef __cplusplus extern "C" { #endif - JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz); + +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); + JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jstring aMessageToHash); -- cgit v1.2.3 From e6d634f9dbbdebfa548e23a8631241acfb286526 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 16:31:56 +0100 Subject: move getOlmLibVersionJni to the bottom --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 30 +++++++++++----------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 5 +--- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 0e51940..3e5dbe1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -36,21 +36,6 @@ OlmUtility* initializeUtilityMemory() return utilityPtr; } -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) -{ - uint8_t majorVer=0, minorVer=0, patchVer=0; - jstring returnValueStr=0; - char buff[150]; - - olm_get_library_version(&majorVer, &minorVer, &patchVer); - LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); - - snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); - returnValueStr = env->NewStringUTF((const char*)buff); - - return returnValueStr; -} - JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz) { OlmUtility* utilityPtr = NULL; @@ -245,4 +230,19 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst } return sha256RetValue; +} + +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) +{ + uint8_t majorVer=0, minorVer=0, patchVer=0; + jstring returnValueStr=0; + char buff[150]; + + olm_get_library_version(&majorVer, &minorVer, &patchVer); + LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); + + snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); + returnValueStr = env->NewStringUTF((const char*)buff); + + return returnValueStr; } \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index b807c6d..691bcf9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -27,13 +27,10 @@ extern "C" { #endif JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz); - -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); - JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jstring aMessageToHash); - +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); #ifdef __cplusplus } #endif -- cgit v1.2.3 From e17eb690487e9cf0062a9da3a91afeae80bc43eb Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 17:47:21 +0100 Subject: create a dedicated file for olm_manager. --- .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 3 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp | 34 +++++++++++++++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h | 35 ++++++++++++++++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 15 ---------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 1 - 5 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk index 2a7d216..ffe1f67 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk @@ -50,7 +50,8 @@ olm_session.cpp \ olm_jni_helper.cpp \ olm_inbound_group_session.cpp \ olm_outbound_group_session.cpp \ -olm_utility.cpp +olm_utility.cpp \ +olm_manager.cpp LOCAL_LDLIBS := -llog diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp new file mode 100644 index 0000000..2ae05aa --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp @@ -0,0 +1,34 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_manager.h" + +using namespace AndroidOlmSdk; + +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) +{ + uint8_t majorVer=0, minorVer=0, patchVer=0; + jstring returnValueStr=0; + char buff[150]; + + olm_get_library_version(&majorVer, &minorVer, &patchVer); + LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); + + snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); + returnValueStr = env->NewStringUTF((const char*)buff); + + return returnValueStr; +} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h new file mode 100644 index 0000000..20f7112 --- /dev/null +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h @@ -0,0 +1,35 @@ +/* + * Copyright 2016 OpenMarket Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLMANAGER_H +#define _OMLMANAGER_H + +#include "olm_jni.h" +#include "olm/olm.h" + +#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 3e5dbe1..d84ee0c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -230,19 +230,4 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst } return sha256RetValue; -} - -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) -{ - uint8_t majorVer=0, minorVer=0, patchVer=0; - jstring returnValueStr=0; - char buff[150]; - - olm_get_library_version(&majorVer, &minorVer, &patchVer); - LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); - - snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); - returnValueStr = env->NewStringUTF((const char*)buff); - - return returnValueStr; } \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index 691bcf9..da973de 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -30,7 +30,6 @@ JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jstring aMessageToHash); -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); #ifdef __cplusplus } #endif -- cgit v1.2.3 From c3eb050be23b1c17897a0899016f152e669bbda4 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 21 Dec 2016 18:37:34 +0100 Subject: signMessage : the utf8 conversion is done on Java side. --- .../src/main/java/org/matrix/olm/OlmAccount.java | 20 ++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 61 ++++++++++------------ .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 2 +- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 82533c2..984ef57 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -383,9 +383,25 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * @return the signed message if operation succeed, null otherwise */ public String signMessage(String aMessage) { - return signMessageJni(aMessage); + if (null == aMessage) { + return null; + } + + byte[] utf8String = null; + + try { + utf8String = aMessage.getBytes("UTF-8"); + } catch (Exception e) { + Log.d(LOG_TAG,"## signMessage(): failed ="+e.getMessage()); + } + + if (null == utf8String) { + return null; + } + + return signMessageJni(utf8String); } - private native String signMessageJni(String aMessage); + private native String signMessageJni(byte[] aMessage); /** * Return the number of unreleased OlmAccount instances.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 5d79ecb..6fc1227 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -393,7 +393,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, * @param aMessage message to sign * @return the signed message, null otherwise **/ -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage) +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) { OlmAccount* accountPtr = NULL; size_t signatureLength; @@ -411,48 +411,41 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz } else { - // convert message from JAVA to C string - const char* messageToSign = env->GetStringUTFChars(aMessage, 0); - if(NULL == messageToSign) + int messageLength = env->GetArrayLength(aMessage); + unsigned char* messageToSign = new unsigned char[messageLength]; + env->GetByteArrayRegion(aMessage, 0, messageLength, reinterpret_cast(messageToSign)); + + // signature memory allocation + signatureLength = olm_account_signature_length(accountPtr); + if(NULL == (signedMsgPtr = (void*)malloc((signatureLength+1)*sizeof(uint8_t)))) { - LOGE("## signMessageJni(): failure - message JNI allocation OOM"); + LOGE("## signMessageJni(): failure - signature allocation OOM"); } else - { - int messageLength = env->GetStringUTFLength(aMessage); - - // signature memory allocation - signatureLength = olm_account_signature_length(accountPtr); - if(NULL == (signedMsgPtr = (void*)malloc((signatureLength+1)*sizeof(uint8_t)))) + { // sign message + resultSign = olm_account_sign(accountPtr, + (void*)messageToSign, + (size_t)messageLength, + signedMsgPtr, + signatureLength); + if(resultSign == olm_error()) { - LOGE("## signMessageJni(): failure - signature allocation OOM"); + LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else - { // sign message - resultSign = olm_account_sign(accountPtr, - (void*)messageToSign, - (size_t)messageLength, - signedMsgPtr, - signatureLength); - if(resultSign == olm_error()) - { - LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); - } - else - { - // info: signatureLength is always equal to resultSign - (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); - // convert to jstring - signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 - LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); - } - - free(signedMsgPtr); + { + // info: signatureLength is always equal to resultSign + (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); + // convert to jstring + signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 + LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); } - // release messageToSign - env->ReleaseStringUTFChars(aMessage, messageToSign); + free(signedMsgPtr); } + + // release messageToSign + free(messageToSign); } return signedMsgRetValue; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index d57c7d9..04f3718 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -43,7 +43,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); // signing -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage); +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); // serialization JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -- cgit v1.2.3 From 2593c69a8acb035099d6b692941bc3cf8d597bfa Mon Sep 17 00:00:00 2001 From: ylecollen Date: Thu, 22 Dec 2016 11:12:41 +0100 Subject: Update the copyrights --- .../olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java | 1 + .../src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java | 1 + .../olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java | 1 + .../olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java | 1 + .../olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java | 5 +---- .../olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java | 1 + .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java | 1 + .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java | 1 + .../olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java | 4 +--- .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java | 1 + .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java | 1 + .../src/main/java/org/matrix/olm/OlmOutboundGroupSession.java | 1 + .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java | 1 + .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp | 4 +--- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h | 4 +--- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 1 + java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 1 + 29 files changed, 29 insertions(+), 13 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 024b44b..12bc424 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index fe36858..c5122b2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 98e5b90..df8dadb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 6296a31..a1b3f81 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java index 3adb63c..4451f7a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,11 +17,7 @@ package org.matrix.olm; -import org.json.JSONException; -import org.json.JSONObject; - import java.util.ArrayList; -import java.util.Iterator; import java.util.Map; import static org.junit.Assert.assertNotNull; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java index bd0fda4..c3f9757 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 984ef57..3f65c97 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index bac49f4..0cb06fa 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 073058a..ee5a20a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -1,8 +1,6 @@ -/** - * Created by pedrocon on 13/10/2016. - */ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 765de5e..57170c4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java index 5e60e1e..e005fcf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index f7d5f17..4aa07b4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index dddc588..374659d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 8cc14c0..c90e552 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 6fc1227..121dccd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 04f3718..7e09403 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 6d11b38..e78d583 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 65ba670..132af43 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 2c8430c..7fea2f1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 25f3193..d2ecce3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -1,8 +1,6 @@ -/** - * Created by pedrocon on 06/10/2016. - */ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h index 986a5a2..a181b32 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h @@ -1,8 +1,6 @@ -/** - * Created by pedrocon on 06/10/2016. - */ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp index 2ae05aa..e72824f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h index 20f7112..5fb6da2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index ca8f9ea..91504de 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 4b59b93..2fc44f8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 98897cb..7ec46df 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index e5bea92..a43ce3a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index d84ee0c..4770280 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index da973de..2a534a3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -1,5 +1,6 @@ /* * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. -- cgit v1.2.3 From da2e1c59026a9fac2ec025d9c0303e268c0ff146 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 14:01:45 +0100 Subject: setRandomInBuffer : clear tempByteArray content --- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 199 +++++++++++---------- 1 file changed, 102 insertions(+), 97 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index d2ecce3..3fddf62 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -29,91 +29,96 @@ using namespace AndroidOlmSdk; **/ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) { - bool retCode = false; - int bufferLen = aRandomSize*sizeof(uint8_t); + bool retCode = false; + int bufferLen = aRandomSize*sizeof(uint8_t); - if(NULL == aBuffer2Ptr) - { - LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); - } - else if(0 == aRandomSize) - { - LOGE("## setRandomInBuffer(): failure - random size=0"); - } - else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(bufferLen))) - { - LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); - } - else - { - LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); + if(NULL == aBuffer2Ptr) + { + LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); + } + else if(0 == aRandomSize) + { + LOGE("## setRandomInBuffer(): failure - random size=0"); + } + else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(bufferLen))) + { + LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); + } + else + { + LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); - bool secureRandomSucceeds = false; + bool secureRandomSucceeds = false; - // clear the buffer - memset(*aBuffer2Ptr, 0, bufferLen); + // use the secureRandom class + jclass cls = env->FindClass("java/security/SecureRandom"); - // use the secureRandom class - jclass cls = env->FindClass("java/security/SecureRandom"); + if (cls) + { + jobject newObj = 0; + jmethodID constructor = env->GetMethodID(cls, "", "()V"); + jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V"); - if (cls) + if (constructor) + { + newObj = env->NewObject(cls, constructor); + jbyteArray tempByteArray = env->NewByteArray(bufferLen); + + if (newObj && tempByteArray) { - jobject newObj = 0; - jmethodID constructor = env->GetMethodID(cls, "", "()V"); - jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V"); - - if (constructor) - { - newObj = env->NewObject(cls, constructor); - jbyteArray tempByteArray = env->NewByteArray(bufferLen); - - if (newObj && tempByteArray) - { - env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); - - jbyte* buffer = env->GetByteArrayElements(tempByteArray,0); - - if (buffer) - { - memcpy(*aBuffer2Ptr, buffer, bufferLen); - secureRandomSucceeds = true; - } - } - - if (tempByteArray) - { - env->DeleteLocalRef(tempByteArray); - } - - if (newObj) - { - env->DeleteLocalRef(newObj); - } - } + env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); + + jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); + + if (buffer) + { + memcpy(*aBuffer2Ptr, buffer, bufferLen); + secureRandomSucceeds = true; + + // clear tempByteArray to hide sensitive data. + memset(buffer, 0, bufferLen); + env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer); + + // ensure that the buffer is released + env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT); + } } - if (!secureRandomSucceeds) + if (tempByteArray) { - LOGE("## setRandomInBuffer(): SecureRandom failed, use a fallback"); - struct timeval timeValue; - gettimeofday(&timeValue, NULL); - srand(timeValue.tv_usec); // init seed - - for(size_t i=0;iDeleteLocalRef(tempByteArray); } - // debug purpose - /*for(int i = 0; i < aRandomSize; i++) + if (newObj) { - LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]); - }*/ + env->DeleteLocalRef(newObj); + } + } + } - retCode = true; + if (!secureRandomSucceeds) + { + LOGE("## setRandomInBuffer(): SecureRandom failed, use a fallback"); + struct timeval timeValue; + gettimeofday(&timeValue, NULL); + srand(timeValue.tv_usec); // init seed + + for(size_t i=0;iNewByteArray(aMsgLength))) + if((NULL == aCStringMsgPtr) || (NULL == env)) + { + LOGE("## javaCStringToUtf8(): failure - invalid parameters (null)"); + } + else if(NULL == (tempByteArray=env->NewByteArray(aMsgLength))) + { + LOGE("## javaCStringToUtf8(): failure - return byte array OOM"); + } + else + { + env->SetByteArrayRegion(tempByteArray, 0, aMsgLength, (const jbyte*)aCStringMsgPtr); + + // UTF-8 conversion from JAVA + jstring strEncode = (env)->NewStringUTF("UTF-8"); + jclass jClass = env->FindClass("java/lang/String"); + jmethodID cstor = env->GetMethodID(jClass, "", "([BLjava/lang/String;)V"); + + if((0!=jClass) && (0!=jClass) && (0!=strEncode)) { - LOGE("## javaCStringToUtf8(): failure - return byte array OOM"); + convertedRetValue = (jstring) env->NewObject(jClass, cstor, tempByteArray, strEncode); + LOGD(" ## javaCStringToUtf8(): succeed"); + env->DeleteLocalRef(tempByteArray); } else { - env->SetByteArrayRegion(tempByteArray, 0, aMsgLength, (const jbyte*)aCStringMsgPtr); - - // UTF-8 conversion from JAVA - jstring strEncode = (env)->NewStringUTF("UTF-8"); - jclass jClass = env->FindClass("java/lang/String"); - jmethodID cstor = env->GetMethodID(jClass, "", "([BLjava/lang/String;)V"); - - if((0!=jClass) && (0!=jClass) && (0!=strEncode)) - { - convertedRetValue = (jstring) env->NewObject(jClass, cstor, tempByteArray, strEncode); - LOGD(" ## javaCStringToUtf8(): succeed"); - env->DeleteLocalRef(tempByteArray); - } - else - { - LOGE(" ## javaCStringToUtf8(): failure - invalid Java references"); - } + LOGE(" ## javaCStringToUtf8(): failure - invalid Java references"); } + } - return convertedRetValue; + return convertedRetValue; } -- cgit v1.2.3 From b2b182161e489ba2db871472ffdb136f56b48054 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 14:04:53 +0100 Subject: Update the README files. --- README.rst | 2 +- java/android/OlmLibSdk/README.rst | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.rst b/README.rst index 3287dbd..6a509d4 100644 --- a/README.rst +++ b/README.rst @@ -36,7 +36,7 @@ To build the javascript bindings, install emscripten from http://kripken.github. To build the android project for Android bindings, run: .. code:: bash - cd java/android/OlmLibSdk/OlmLibSdk + cd java/android/OlmLibSdk ./gradlew clean assembleRelease Release process diff --git a/java/android/OlmLibSdk/README.rst b/java/android/OlmLibSdk/README.rst index 049eed8..7729506 100644 --- a/java/android/OlmLibSdk/README.rst +++ b/java/android/OlmLibSdk/README.rst @@ -10,10 +10,10 @@ Installation Copy the olm-sdk.aar into it. In your build.gradle file, add in the android section repositories { - flatDir { + flatDir { dir 'libs' - } - } + } + } Add in the dependencies category compile(name: 'olm-sdk', ext: 'aar') -- cgit v1.2.3 From 2a7c191d843e96704202b4804acdc870bf090082 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 14:18:12 +0100 Subject: identityKeys / oneTimeKeys : remove useless try/catch blocks --- .../src/main/java/org/matrix/olm/OlmAccount.java | 36 +++++----------------- 1 file changed, 8 insertions(+), 28 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 3f65c97..d229535 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -241,23 +241,13 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ public Map identityKeys() { JSONObject identityKeysJsonObj = null; - byte identityKeysBuffer[]; + byte[] identityKeysBuffer = identityKeysJni(); - if( null != (identityKeysBuffer = identityKeysJni())) { + if (null != identityKeysBuffer) { try { - String identityKeysString; - - try { - identityKeysString = new String(identityKeysBuffer, "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## identityKeys(): Exception : cannot convert with utf-8 charset " + e.getMessage()); - identityKeysString = new String(identityKeysBuffer); - } - - identityKeysJsonObj = new JSONObject(identityKeysString); + identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer, "UTF-8")); //Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); - } catch (JSONException e) { - identityKeysJsonObj = null; + } catch (Exception e) { Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); } } else { @@ -311,24 +301,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * @return one time keys in string dictionary if operation succeed, null otherwise */ public Map> oneTimeKeys() { - byte oneTimeKeysBuffer[]; JSONObject oneTimeKeysJsonObj = null; + byte[] oneTimeKeysBuffer = oneTimeKeysJni(); - if( null != (oneTimeKeysBuffer = oneTimeKeysJni())) { + if( null != oneTimeKeysBuffer) { try { - String oneTimeKeysString; - - try { - oneTimeKeysString = new String(oneTimeKeysBuffer, "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## oneTimeKeys(): Exception : cannot convert with utf-8 charset " + e.getMessage()); - oneTimeKeysString = new String(oneTimeKeysBuffer); - } - - oneTimeKeysJsonObj = new JSONObject(new String(oneTimeKeysString)); + oneTimeKeysJsonObj = new JSONObject(new String(new String(oneTimeKeysBuffer, "UTF-8"))); //Log.d(LOG_TAG, "## oneTimeKeys(): OneTime Json keys=" + oneTimeKeysJsonObj.toString()); - } catch (JSONException e) { - oneTimeKeysJsonObj = null; + } catch (Exception e) { Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); } } else { -- cgit v1.2.3 From 60bcf865d0c83655288f94ffa3b927a73652a7d1 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 14:19:22 +0100 Subject: remove useless "new string" --- .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index d229535..70ecd2a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -306,7 +306,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if( null != oneTimeKeysBuffer) { try { - oneTimeKeysJsonObj = new JSONObject(new String(new String(oneTimeKeysBuffer, "UTF-8"))); + oneTimeKeysJsonObj = new JSONObject(new String(oneTimeKeysBuffer, "UTF-8")); //Log.d(LOG_TAG, "## oneTimeKeys(): OneTime Json keys=" + oneTimeKeysJsonObj.toString()); } catch (Exception e) { Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); -- cgit v1.2.3 From b893b81c8242b9838700ec5c8cb1be088263d8d9 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 14:41:54 +0100 Subject: Simplify signMessageJni --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 101 +++++++++++---------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 121dccd..9c572e5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -396,65 +396,66 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, **/ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) { - OlmAccount* accountPtr = NULL; - size_t signatureLength; - void* signedMsgPtr; - size_t resultSign; - jstring signedMsgRetValue = NULL; + OlmAccount* accountPtr = NULL; + size_t signatureLength; + void* signedMsgPtr; + size_t resultSign; + jstring signedMsgRetValue = NULL; - if(NULL == aMessage) - { - LOGE("## signMessageJni(): failure - invalid aMessage param"); - } - else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + if(NULL == aMessage) + { + LOGE("## signMessageJni(): failure - invalid aMessage param"); + } + else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## signMessageJni(): failure - invalid account ptr"); + } + else + { + int messageLength = env->GetArrayLength(aMessage); + jbyte* messageToSign = env->GetByteArrayElements(aMessage, NULL); + + // signature memory allocation + signatureLength = olm_account_signature_length(accountPtr); + + if(NULL == (signedMsgPtr = (void*)malloc((signatureLength+1)*sizeof(uint8_t)))) { - LOGE("## signMessageJni(): failure - invalid account ptr"); + LOGE("## signMessageJni(): failure - signature allocation OOM"); } else { - int messageLength = env->GetArrayLength(aMessage); - unsigned char* messageToSign = new unsigned char[messageLength]; - env->GetByteArrayRegion(aMessage, 0, messageLength, reinterpret_cast(messageToSign)); - - // signature memory allocation - signatureLength = olm_account_signature_length(accountPtr); - if(NULL == (signedMsgPtr = (void*)malloc((signatureLength+1)*sizeof(uint8_t)))) - { - LOGE("## signMessageJni(): failure - signature allocation OOM"); - } - else - { // sign message - resultSign = olm_account_sign(accountPtr, - (void*)messageToSign, - (size_t)messageLength, - signedMsgPtr, - signatureLength); - if(resultSign == olm_error()) - { - LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); - } - else - { - // info: signatureLength is always equal to resultSign - (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); - // convert to jstring - signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 - LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); - } - - free(signedMsgPtr); - } - - // release messageToSign - free(messageToSign); + // sign message + resultSign = olm_account_sign(accountPtr, + (void*)messageToSign, + (size_t)messageLength, + signedMsgPtr, + signatureLength); + if(resultSign == olm_error()) + { + LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); + } + else + { + // info: signatureLength is always equal to resultSign + (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); + // convert to jstring + signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 + LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); + } + + free(signedMsgPtr); + } + + // release messageToSign + if (messageToSign) + { + env->ReleaseByteArrayElements(aMessage, messageToSign, JNI_ABORT); } + } - return signedMsgRetValue; + return signedMsgRetValue; } - - - /** * Serialize and encrypt account instance into a base64 string.
* @param aKey key used to encrypt the serialized account data -- cgit v1.2.3 From f4ae0d86c9bd8d4ae74ecf1b17c33d427628ca34 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 15:28:42 +0100 Subject: getOlmAccountId is aonly public in the OLM SDK package --- .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 70ecd2a..0aa2c3d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -63,7 +63,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ private transient long mNativeId; - public OlmAccount() throws OlmException { if(!initNewAccount()) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); @@ -162,7 +161,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * Getter on the account ID. * @return native account ID */ - public long getOlmAccountId(){ + long getOlmAccountId(){ return mNativeId; } -- cgit v1.2.3 From 8f3d5bed728bf3c2a0275bd6a13178b7b9f9521d Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 15:32:14 +0100 Subject: Fix tabulations mix and split block of variables when it is possible. --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 350 +++++++++++---------- 1 file changed, 176 insertions(+), 174 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 9c572e5..47c616d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -26,17 +26,18 @@ using namespace AndroidOlmSdk; **/ OlmAccount* initializeAccountMemory() { - OlmAccount* accountPtr = NULL; size_t accountSize = olm_account_size(); + OlmAccount* accountPtr = (OlmAccount*)malloc(accountSize); - if(NULL != (accountPtr=(OlmAccount*)malloc(accountSize))) - { // init account object - accountPtr = olm_account(accountPtr); - LOGD("## initializeAccountMemory(): success - OLM account size=%lu",static_cast(accountSize)); + if (accountPtr) + { + // init account object + accountPtr = olm_account(accountPtr); + LOGD("## initializeAccountMemory(): success - OLM account size=%lu",static_cast(accountSize)); } else { - LOGE("## initializeAccountMemory(): failure - OOM"); + LOGE("## initializeAccountMemory(): failure - OOM"); } return accountPtr; @@ -60,24 +61,24 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject t */ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) { - OlmAccount* accountPtr = NULL; - - LOGD("## releaseAccountJni(): IN"); - - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) - { - LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); - } - else - { - LOGD(" ## releaseAccountJni(): accountPtr=%p",accountPtr); - olm_clear_account(accountPtr); - - LOGD(" ## releaseAccountJni(): IN"); - // even if free(NULL) does not crash, logs are performed for debug purpose - free(accountPtr); - LOGD(" ## releaseAccountJni(): OUT"); - } + LOGD("## releaseAccountJni(): IN"); + + OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); + + if(!accountPtr) + { + LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); + } + else + { + LOGD(" ## releaseAccountJni(): accountPtr=%p",accountPtr); + olm_clear_account(accountPtr); + + LOGD(" ## releaseAccountJni(): IN"); + // even if free(NULL) does not crash, logs are performed for debug purpose + free(accountPtr); + LOGD(" ## releaseAccountJni(): OUT"); + } } /** @@ -88,24 +89,25 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz **/ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz) { - OlmAccount *accountPtr = NULL; - uint8_t *randomBuffPtr = NULL; - size_t accountRetCode; - size_t randomSize; + OlmAccount *accountPtr = initializeAccountMemory(); // init account memory allocation - if(NULL == (accountPtr = initializeAccountMemory())) + if (!accountPtr) { LOGE("## initNewAccount(): failure - init account OOM"); } else { // get random buffer size - randomSize = olm_create_account_random_length(accountPtr); + size_t randomSize = olm_create_account_random_length(accountPtr); + LOGD("## initNewAccount(): randomSize=%lu", static_cast(randomSize)); + uint8_t *randomBuffPtr = NULL; + size_t accountRetCode; + // allocate random buffer - if((0!=randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) + if ((0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) { LOGE("## initNewAccount(): failure - random buffer init"); } @@ -113,25 +115,25 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi { // create account accountRetCode = olm_create_account(accountPtr, (void*)randomBuffPtr, randomSize); - if(accountRetCode == olm_error()) { + + if (accountRetCode == olm_error()) + { LOGE("## initNewAccount(): failure - account creation failed Msg=%s", olm_account_last_error(accountPtr)); - } + } LOGD("## initNewAccount(): success - OLM account created"); LOGD("## initNewAccount(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); } - } - if(NULL != randomBuffPtr) - { - free(randomBuffPtr); + if (randomBuffPtr) + { + free(randomBuffPtr); + } } return (jlong)(intptr_t)accountPtr; } - - // ********************************************************************* // ************************* IDENTITY KEYS API ************************* // ********************************************************************* @@ -142,34 +144,40 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz) { - OlmAccount* accountPtr = NULL; - size_t identityKeysLength; - uint8_t *identityKeysBytesPtr; - size_t keysResult; jbyteArray byteArrayRetValue = NULL; + OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + if (NULL == accountPtr) { LOGE("## identityKeys(): failure - invalid Account ptr=NULL"); } else { LOGD("## identityKeys(): accountPtr =%p", accountPtr); + // identity keys allocation - identityKeysLength = olm_account_identity_keys_length(accountPtr); - if(NULL == (identityKeysBytesPtr=(uint8_t*)malloc(identityKeysLength))) + size_t identityKeysLength = olm_account_identity_keys_length(accountPtr); + uint8_t *identityKeysBytesPtr = (uint8_t*)malloc(identityKeysLength); + + if (!identityKeysBytesPtr) { LOGE("## identityKeys(): failure - identity keys array OOM"); } else - { // retrieve key pairs in identityKeysBytesPtr - keysResult = olm_account_identity_keys(accountPtr, identityKeysBytesPtr, identityKeysLength); - if(keysResult == olm_error()) { + { + // retrieve key pairs in identityKeysBytesPtr + size_t keysResult = olm_account_identity_keys(accountPtr, identityKeysBytesPtr, identityKeysLength); + + if(keysResult == olm_error()) + { LOGE("## identityKeys(): failure - error getting identity keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else - { // allocate the byte array to be returned to java - if(NULL == (byteArrayRetValue=env->NewByteArray(identityKeysLength))) + { + // allocate the byte array to be returned to java + byteArrayRetValue = env->NewByteArray(identityKeysLength); + + if(NULL == byteArrayRetValue) { LOGE("## identityKeys(): failure - return byte array OOM"); } @@ -196,10 +204,10 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject **/ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz) { - OlmAccount* accountPtr = NULL; + OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); size_t maxKeys = -1; - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + if (!accountPtr) { LOGE("## maxOneTimeKey(): failure - invalid Account ptr=NULL"); } @@ -207,6 +215,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thi { maxKeys = olm_account_max_number_of_one_time_keys(accountPtr); } + LOGD("## maxOneTimeKey(): Max keys=%lu", static_cast(maxKeys)); return (jlong)maxKeys; @@ -219,23 +228,22 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thi **/ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) { - OlmAccount *accountPtr = NULL; - uint8_t *randomBufferPtr = NULL; + OlmAccount *accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); jint retCode = ERROR_CODE_KO; - size_t randomLength; - size_t result; - - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + if (!accountPtr) { LOGE("## generateOneTimeKeysJni(): failure - invalid Account ptr"); } else - { // keys memory allocation - randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); + { + // keys memory allocation + size_t randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); LOGD("## generateOneTimeKeysJni(): randomLength=%lu", static_cast(randomLength)); - if((0!=randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) + uint8_t *randomBufferPtr = NULL; + + if ( (0!=randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) { LOGE("## generateOneTimeKeysJni(): failure - random buffer init"); } @@ -244,8 +252,9 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject LOGD("## generateOneTimeKeysJni(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); // retrieve key pairs in keysBytesPtr - result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); - if(result == olm_error()) { + size_t result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); + + if (result == olm_error()) { LOGE("## generateOneTimeKeysJni(): failure - error generating one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else @@ -254,11 +263,12 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject LOGD("## generateOneTimeKeysJni(): success - result=%lu", static_cast(result)); } } - } - if(NULL != randomBufferPtr) - { - free(randomBufferPtr); + + if (randomBufferPtr) + { + free(randomBufferPtr); + } } return retCode; @@ -271,34 +281,38 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz) { - OlmAccount* accountPtr = NULL; - size_t keysLength; - uint8_t *keysBytesPtr; - size_t keysResult; jbyteArray byteArrayRetValue = NULL; + OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); LOGD("## oneTimeKeysJni(): IN"); - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + if (!accountPtr) { LOGE("## oneTimeKeysJni(): failure - invalid Account ptr"); } else - { // keys memory allocation - keysLength = olm_account_one_time_keys_length(accountPtr); - if(NULL == (keysBytesPtr=(uint8_t *)malloc(keysLength*sizeof(uint8_t)))) + { + // keys memory allocation + size_t keysLength = olm_account_one_time_keys_length(accountPtr); + uint8_t *keysBytesPtr = (uint8_t *)malloc(keysLength*sizeof(uint8_t)); + + if (!keysBytesPtr) { LOGE("## oneTimeKeysJni(): failure - one time keys array OOM"); } else - { // retrieve key pairs in keysBytesPtr - keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); + { + // retrieve key pairs in keysBytesPtr + size_t keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); if(keysResult == olm_error()) { LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else - { // allocate the byte array to be returned to java - if(NULL == (byteArrayRetValue=env->NewByteArray(keysLength))) + { + // allocate the byte array to be returned to java + byteArrayRetValue = env->NewByteArray(keysLength); + + if (!byteArrayRetValue) { LOGE("## oneTimeKeysJni(): failure - return byte array OOM"); } @@ -327,20 +341,20 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jint retCode = ERROR_CODE_KO; OlmAccount* accountPtr = NULL; OlmSession* sessionPtr = (OlmSession*)aNativeOlmSessionId; - size_t result; - if(NULL == sessionPtr) + if (!sessionPtr) { LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid session ptr"); } - else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid account ptr"); } else { - result = olm_remove_one_time_keys(accountPtr, sessionPtr); - if(result == olm_error()) + size_t result = olm_remove_one_time_keys(accountPtr, sessionPtr); + + if (result == olm_error()) { // the account doesn't have any matching "one time keys".. LOGW("## removeOneTimeKeysForSessionJni(): failure - removing one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); @@ -363,17 +377,17 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) { jint retCode = ERROR_CODE_OK; - OlmAccount* accountPtr = NULL; - size_t result; + OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + if (!accountPtr) { LOGE("## markOneTimeKeysAsPublishedJni(): failure - invalid account ptr"); retCode = ERROR_CODE_KO; } else { - result = olm_account_mark_keys_as_published(accountPtr); + size_t result = olm_account_mark_keys_as_published(accountPtr); + if(result == olm_error()) { LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",(const char *)olm_account_last_error(accountPtr)); @@ -396,64 +410,63 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, **/ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) { - OlmAccount* accountPtr = NULL; - size_t signatureLength; - void* signedMsgPtr; - size_t resultSign; - jstring signedMsgRetValue = NULL; - - if(NULL == aMessage) - { - LOGE("## signMessageJni(): failure - invalid aMessage param"); - } - else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) - { - LOGE("## signMessageJni(): failure - invalid account ptr"); - } - else - { - int messageLength = env->GetArrayLength(aMessage); - jbyte* messageToSign = env->GetByteArrayElements(aMessage, NULL); - - // signature memory allocation - signatureLength = olm_account_signature_length(accountPtr); - - if(NULL == (signedMsgPtr = (void*)malloc((signatureLength+1)*sizeof(uint8_t)))) - { - LOGE("## signMessageJni(): failure - signature allocation OOM"); + OlmAccount* accountPtr = NULL; + jstring signedMsgRetValue = NULL; + + if (!aMessage) + { + LOGE("## signMessageJni(): failure - invalid aMessage param"); + } + else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE("## signMessageJni(): failure - invalid account ptr"); } else { - // sign message - resultSign = olm_account_sign(accountPtr, + int messageLength = env->GetArrayLength(aMessage); + jbyte* messageToSign = env->GetByteArrayElements(aMessage, NULL); + + // signature memory allocation + size_t signatureLength = olm_account_signature_length(accountPtr); + void* signedMsgPtr = malloc((signatureLength+1)*sizeof(uint8_t)); + + if (!signedMsgPtr) + { + LOGE("## signMessageJni(): failure - signature allocation OOM"); + } + else + { + // sign message + size_t resultSign = olm_account_sign(accountPtr, (void*)messageToSign, (size_t)messageLength, signedMsgPtr, signatureLength); - if(resultSign == olm_error()) - { - LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); - } - else - { - // info: signatureLength is always equal to resultSign - (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); - // convert to jstring - signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 - LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); - } - free(signedMsgPtr); - } + if (resultSign == olm_error()) + { + LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); + } + else + { + // info: signatureLength is always equal to resultSign + (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); + // convert to jstring + signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 + LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); + } - // release messageToSign - if (messageToSign) - { - env->ReleaseByteArrayElements(aMessage, messageToSign, JNI_ABORT); + free(signedMsgPtr); + } + + // release messageToSign + if (messageToSign) + { + env->ReleaseByteArrayElements(aMessage, messageToSign, JNI_ABORT); + } } - } - return signedMsgRetValue; + return signedMsgRetValue; } /** @@ -464,45 +477,36 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz **/ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) { - /*jstring pickledDataRetValue = serializeDataWithKey(env,thiz, - aKey, - aErrorMsg, - olm_pickle_account_length, - olm_pickle_account, - olm_account_last_error); - return pickledDataRetValue;*/ - jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; jstring errorJstring = 0; const char *keyPtr = NULL; - void *pickledPtr = NULL; OlmAccount* accountPtr = NULL; LOGD("## serializeDataWithKeyJni(): IN"); - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) - { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); - } - else if(0 == aKey) + if (!aKey) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } - else if(0 == aErrorMsg) + else if(!aErrorMsg) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); } - else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); + } + else if(!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); } - else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + else if(!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if(!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } @@ -513,7 +517,9 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); - if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + + if (!pickledPtr) { LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); } @@ -524,7 +530,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); @@ -541,18 +547,15 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } + + free(pickledPtr); } } // free alloc - if(NULL != keyPtr) - { - env->ReleaseStringUTFChars(aKey, keyPtr); - } - - if(NULL != pickledPtr) + if (keyPtr) { - free(pickledPtr); + env->ReleaseStringUTFChars(aKey, keyPtr); } return pickledDataRetValue; @@ -568,24 +571,23 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j LOGD("## initWithSerializedDataJni(): IN"); - if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) - //if(NULL == (accountPtr = initializeAccountMemory())) - { - LOGE(" ## initWithSerializedDataJni(): failure - account failure OOM"); - } - else if(0 == aKey) + if (!aKey) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if(0 == aSerializedData) + else if (!aSerializedData) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + { + LOGE(" ## initWithSerializedDataJni(): failure - account failure OOM"); + } + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } @@ -615,12 +617,12 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j } // free alloc - if(NULL != keyPtr) + if (keyPtr) { env->ReleaseStringUTFChars(aKey, keyPtr); } - if(NULL != pickledPtr) + if (pickledPtr) { env->ReleaseStringUTFChars(aSerializedData, pickledPtr); } -- cgit v1.2.3 From 47a52dcf4170fb7c121467a683d85059efa3c2dc Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 16:02:17 +0100 Subject: Use a 4 spaces tabulation --- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 287 ++++++++++----------- 1 file changed, 130 insertions(+), 157 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 3fddf62..eaa7edf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -29,99 +29,80 @@ using namespace AndroidOlmSdk; **/ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) { - bool retCode = false; - int bufferLen = aRandomSize*sizeof(uint8_t); + bool retCode = false; + int bufferLen = aRandomSize*sizeof(uint8_t); - if(NULL == aBuffer2Ptr) - { - LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); - } - else if(0 == aRandomSize) - { - LOGE("## setRandomInBuffer(): failure - random size=0"); - } - else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(bufferLen))) - { - LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); - } - else - { - LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); - - bool secureRandomSucceeds = false; - - // use the secureRandom class - jclass cls = env->FindClass("java/security/SecureRandom"); - - if (cls) + if (!aBuffer2Ptr) { - jobject newObj = 0; - jmethodID constructor = env->GetMethodID(cls, "", "()V"); - jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V"); - - if (constructor) - { - newObj = env->NewObject(cls, constructor); - jbyteArray tempByteArray = env->NewByteArray(bufferLen); - - if (newObj && tempByteArray) - { - env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); - - jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); - - if (buffer) - { - memcpy(*aBuffer2Ptr, buffer, bufferLen); - secureRandomSucceeds = true; - - // clear tempByteArray to hide sensitive data. - memset(buffer, 0, bufferLen); - env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer); + LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); + } + else if(!aRandomSize) + { + LOGE("## setRandomInBuffer(): failure - random size=0"); + } + else if (!(*aBuffer2Ptr = (uint8_t*)malloc(bufferLen))) + { + LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); + } + else + { + LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); - // ensure that the buffer is released - env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT); - } - } + // use the secureRandom class + jclass cls = env->FindClass("java/security/SecureRandom"); - if (tempByteArray) + if (cls) { - env->DeleteLocalRef(tempByteArray); + jobject newObj = 0; + jmethodID constructor = env->GetMethodID(cls, "", "()V"); + jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V"); + + if (constructor) + { + newObj = env->NewObject(cls, constructor); + jbyteArray tempByteArray = env->NewByteArray(bufferLen); + + if (newObj && tempByteArray) + { + env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); + jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); + + if (buffer) + { + memcpy(*aBuffer2Ptr, buffer, bufferLen); + retCode = true; + + // clear tempByteArray to hide sensitive data. + memset(buffer, 0, bufferLen); + env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer); + + // ensure that the buffer is released + env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT); + } + } + + if (tempByteArray) + { + env->DeleteLocalRef(tempByteArray); + } + + if (newObj) + { + env->DeleteLocalRef(newObj); + } + } } - if (newObj) + // debug purpose + /*for(int i = 0; i < aRandomSize; i++) { - env->DeleteLocalRef(newObj); - } - } + LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]); + }*/ } - if (!secureRandomSucceeds) - { - LOGE("## setRandomInBuffer(): SecureRandom failed, use a fallback"); - struct timeval timeValue; - gettimeofday(&timeValue, NULL); - srand(timeValue.tv_usec); // init seed - - for(size_t i=0;iFindClass(aCallingClass); - - if((0 != requiredClass) && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) - { - LOGE("## getAccountInstanceId() failure - invalid instance of"); - } - else if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject))) + jlong instanceId = 0; + if (aJniEnv) { - if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeId", "J"))) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId); - } - else - { - LOGE("## getInstanceId() ERROR! GetFieldID=null"); - } + jclass requiredClass = aJniEnv->FindClass(aCallingClass); + jclass loaderClass = 0; + + if (requiredClass && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) + { + LOGE("## getAccountInstanceId() failure - invalid instance of"); + } + else if (loaderClass = aJniEnv->GetObjectClass(aJavaObject)) + { + jfieldID instanceIdField = aJniEnv->GetFieldID(loaderClass, "mNativeId", "J"); + + if (instanceIdField) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId); + } + else + { + LOGE("## getInstanceId() ERROR! GetFieldID=null"); + } + + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGE("## getInstanceId() ERROR! GetObjectClass=null"); + } } else { - LOGE("## getInstanceId() ERROR! GetObjectClass=null"); + LOGE("## getInstanceId() ERROR! aJniEnv=NULL"); } - } - else - { - LOGE("## getInstanceId() ERROR! aJniEnv=NULL"); - } - - LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); - if (loaderClass) - { - aJniEnv->DeleteLocalRef(loaderClass); - } + LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); - return instanceId; + return instanceId; } /** @@ -184,12 +161,10 @@ jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingCl **/ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT); - return instanceId; + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT); + return instanceId; } - - /** * Read the session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table @@ -198,8 +173,8 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION); - return instanceId; + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION); + return instanceId; } /** @@ -210,11 +185,10 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION); - return instanceId; + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION); + return instanceId; } - /** * Read the outbound group session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table @@ -223,8 +197,8 @@ jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION); - return instanceId; + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION); + return instanceId; } /** @@ -235,11 +209,10 @@ jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) **/ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); - return instanceId; + jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); + return instanceId; } - /** * Convert a C string into a UTF-8 format string. * The conversion is performed in JAVA side to workaround the issue in NewStringUTF(). @@ -247,37 +220,37 @@ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) */ jstring javaCStringToUtf8(JNIEnv *env, uint8_t *aCStringMsgPtr, size_t aMsgLength) { - jstring convertedRetValue = 0; - jbyteArray tempByteArray = NULL; - - if((NULL == aCStringMsgPtr) || (NULL == env)) - { - LOGE("## javaCStringToUtf8(): failure - invalid parameters (null)"); - } - else if(NULL == (tempByteArray=env->NewByteArray(aMsgLength))) - { - LOGE("## javaCStringToUtf8(): failure - return byte array OOM"); - } - else - { - env->SetByteArrayRegion(tempByteArray, 0, aMsgLength, (const jbyte*)aCStringMsgPtr); + jstring convertedRetValue = 0; + jbyteArray tempByteArray = NULL; - // UTF-8 conversion from JAVA - jstring strEncode = (env)->NewStringUTF("UTF-8"); - jclass jClass = env->FindClass("java/lang/String"); - jmethodID cstor = env->GetMethodID(jClass, "", "([BLjava/lang/String;)V"); - - if((0!=jClass) && (0!=jClass) && (0!=strEncode)) + if (!aCStringMsgPtr || !env) + { + LOGE("## javaCStringToUtf8(): failure - invalid parameters (null)"); + } + else if (!(tempByteArray=env->NewByteArray(aMsgLength))) { - convertedRetValue = (jstring) env->NewObject(jClass, cstor, tempByteArray, strEncode); - LOGD(" ## javaCStringToUtf8(): succeed"); - env->DeleteLocalRef(tempByteArray); + LOGE("## javaCStringToUtf8(): failure - return byte array OOM"); } else { - LOGE(" ## javaCStringToUtf8(): failure - invalid Java references"); + env->SetByteArrayRegion(tempByteArray, 0, aMsgLength, (const jbyte*)aCStringMsgPtr); + + // UTF-8 conversion from JAVA + jstring strEncode = (env)->NewStringUTF("UTF-8"); + jclass jClass = env->FindClass("java/lang/String"); + jmethodID cstor = env->GetMethodID(jClass, "", "([BLjava/lang/String;)V"); + + if (jClass && strEncode) + { + convertedRetValue = (jstring) env->NewObject(jClass, cstor, tempByteArray, strEncode); + LOGD(" ## javaCStringToUtf8(): succeed"); + env->DeleteLocalRef(tempByteArray); + } + else + { + LOGE(" ## javaCStringToUtf8(): failure - invalid Java references"); + } } - } - return convertedRetValue; + return convertedRetValue; } -- cgit v1.2.3 From 5e0bbe770292d679f8bbc80134fdf1704b207571 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 16:29:44 +0100 Subject: Rename getUnreleasedCount to isReleased. --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 30 ++++++------- .../java/org/matrix/olm/OlmSessionTest.java | 50 +++++++++++----------- .../java/org/matrix/olm/OlmUtilityTest.java | 7 ++- .../src/main/java/org/matrix/olm/OlmAccount.java | 26 ++++------- .../org/matrix/olm/OlmInboundGroupSession.java | 18 +++----- .../org/matrix/olm/OlmOutboundGroupSession.java | 34 +++++---------- .../src/main/java/org/matrix/olm/OlmSession.java | 27 ++++-------- .../src/main/java/org/matrix/olm/OlmUtility.java | 19 +++----- 8 files changed, 82 insertions(+), 129 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index c5122b2..2152a8d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -180,8 +180,8 @@ public class OlmGroupSessionTest { @Test public void test14CheckUnreleaseedCount() { - assertTrue(0==mAliceOutboundGroupSession.getUnreleasedCount()); - assertTrue(0==mBobInboundGroupSession.getUnreleasedCount()); + assertTrue(mAliceOutboundGroupSession.isReleased()); + assertTrue(mBobInboundGroupSession.isReleased()); } @Test @@ -235,8 +235,8 @@ public class OlmGroupSessionTest { outboundGroupSessionRef.releaseSession(); outboundGroupSessionSerial.releaseSession(); - assertTrue(0==outboundGroupSessionRef.getUnreleasedCount()); - assertTrue(0==outboundGroupSessionSerial.getUnreleasedCount()); + assertTrue(outboundGroupSessionRef.isReleased()); + assertTrue(outboundGroupSessionSerial.isReleased()); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); } catch (ClassNotFoundException e) { @@ -309,9 +309,9 @@ public class OlmGroupSessionTest { bobInboundGroupSessionRef.releaseSession(); bobInboundGroupSessionSerial.releaseSession(); - assertTrue(0==aliceOutboundGroupSession.getUnreleasedCount()); - assertTrue(0==bobInboundGroupSessionRef.getUnreleasedCount()); - assertTrue(0==bobInboundGroupSessionSerial.getUnreleasedCount()); + assertTrue(aliceOutboundGroupSession.isReleased()); + assertTrue(bobInboundGroupSessionRef.isReleased()); + assertTrue(bobInboundGroupSessionSerial.isReleased()); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); } catch (ClassNotFoundException e) { @@ -405,14 +405,14 @@ public class OlmGroupSessionTest { outboundGroupSession7.releaseSession(); outboundGroupSession8.releaseSession(); - assertTrue(0==outboundGroupSession1.getUnreleasedCount()); - assertTrue(0==outboundGroupSession2.getUnreleasedCount()); - assertTrue(0==outboundGroupSession3.getUnreleasedCount()); - assertTrue(0==outboundGroupSession4.getUnreleasedCount()); - assertTrue(0==outboundGroupSession5.getUnreleasedCount()); - assertTrue(0==outboundGroupSession6.getUnreleasedCount()); - assertTrue(0==outboundGroupSession7.getUnreleasedCount()); - assertTrue(0==outboundGroupSession8.getUnreleasedCount()); + assertTrue(outboundGroupSession1.isReleased()); + assertTrue(outboundGroupSession2.isReleased()); + assertTrue(outboundGroupSession3.isReleased()); + assertTrue(outboundGroupSession4.isReleased()); + assertTrue(outboundGroupSession5.isReleased()); + assertTrue(outboundGroupSession6.isReleased()); + assertTrue(outboundGroupSession7.isReleased()); + assertTrue(outboundGroupSession8.isReleased()); } catch (OlmException e) { assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index df8dadb..b25d865 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -143,14 +143,14 @@ public class OlmSessionTest { // release accounts bobAccount.releaseAccount(); aliceAccount.releaseAccount(); - assertTrue(0==bobAccount.getUnreleasedCount()); - assertTrue(0==aliceAccount.getUnreleasedCount()); + assertTrue(bobAccount.isReleased()); + assertTrue(aliceAccount.isReleased()); // release sessions bobSession.releaseSession(); aliceSession.releaseSession(); - assertTrue(0==bobSession.getUnreleasedCount()); - assertTrue(0==aliceSession.getUnreleasedCount()); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); } @@ -273,13 +273,13 @@ public class OlmSessionTest { assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); bobAccount.releaseAccount(); aliceAccount.releaseAccount(); - assertTrue(0==bobAccount.getUnreleasedCount()); - assertTrue(0==aliceAccount.getUnreleasedCount()); + assertTrue(bobAccount.isReleased()); + assertTrue(aliceAccount.isReleased()); bobSession.releaseSession(); aliceSession.releaseSession(); - assertTrue(0==bobSession.getUnreleasedCount()); - assertTrue(0==aliceSession.getUnreleasedCount()); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); } @@ -329,13 +329,13 @@ public class OlmSessionTest { aliceAccount.releaseAccount(); bobAccount.releaseAccount(); - assertTrue(0==aliceAccount.getUnreleasedCount()); - assertTrue(0==bobAccount.getUnreleasedCount()); + assertTrue(aliceAccount.isReleased()); + assertTrue(bobAccount.isReleased()); bobSession.releaseSession(); aliceSession.releaseSession(); - assertTrue(0==bobSession.getUnreleasedCount()); - assertTrue(0==aliceSession.getUnreleasedCount()); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); } @Test @@ -391,13 +391,13 @@ public class OlmSessionTest { assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); aliceAccount.releaseAccount(); bobAccount.releaseAccount(); - assertTrue(0==aliceAccount.getUnreleasedCount()); - assertTrue(0==bobAccount.getUnreleasedCount()); + assertTrue(aliceAccount.isReleased()); + assertTrue(bobAccount.isReleased()); aliceSession.releaseSession(); bobSession.releaseSession(); - assertTrue(0==aliceSession.getUnreleasedCount()); - assertTrue(0==bobSession.getUnreleasedCount()); + assertTrue(aliceSession.isReleased()); + assertTrue(bobSession.isReleased()); } // ******************************************************** @@ -522,15 +522,15 @@ public class OlmSessionTest { assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); bobAccount.releaseAccount(); aliceAccount.releaseAccount(); - assertTrue(0==bobAccount.getUnreleasedCount()); - assertTrue(0==aliceAccount.getUnreleasedCount()); + assertTrue(bobAccount.isReleased()); + assertTrue(aliceAccount.isReleased()); bobSession.releaseSession(); aliceSession.releaseSession(); aliceSessionDeserial.releaseSession(); - assertTrue(0==bobSession.getUnreleasedCount()); - assertTrue(0==aliceSession.getUnreleasedCount()); - assertTrue(0==aliceSessionDeserial.getUnreleasedCount()); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); + assertTrue(aliceSessionDeserial.isReleased()); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); @@ -631,13 +631,13 @@ public class OlmSessionTest { assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); aliceAccount.releaseAccount(); bobAccount.releaseAccount(); - assertTrue(0==aliceAccount.getUnreleasedCount()); - assertTrue(0==bobAccount.getUnreleasedCount()); + assertTrue(aliceAccount.isReleased()); + assertTrue(bobAccount.isReleased()); aliceSession.releaseSession(); bobSession.releaseSession(); - assertTrue(0==aliceSession.getUnreleasedCount()); - assertTrue(0==bobSession.getUnreleasedCount()); + assertTrue(aliceSession.isReleased()); + assertTrue(bobSession.isReleased()); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index a1b3f81..9a97205 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -106,13 +106,12 @@ public class OlmUtilityTest { assertFalse(String.valueOf(errorMsg).isEmpty()); utility.releaseUtility(); - assertTrue(0==utility.getUnreleasedCount()); + assertTrue(utility.isReleased()); account.releaseAccount(); - assertTrue(0==account.getUnreleasedCount()); + assertTrue(account.isReleased()); } - @Test public void test02sha256() { OlmUtility utility = new OlmUtility(); @@ -122,6 +121,6 @@ public class OlmUtilityTest { assertFalse(TextUtils.isEmpty(hashResult)); utility.releaseUtility(); - assertTrue(0==utility.getUnreleasedCount()); + assertTrue(utility.isReleased()); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 0aa2c3d..2d91634 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -39,7 +39,6 @@ import java.util.Map; public class OlmAccount extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; - private transient int mUnreleasedCount; // JSON keys used in the JSON objects returned by JNI /** As well as the identity key, each device creates a number of Curve25519 key pairs which are @@ -171,7 +170,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ public void releaseAccount(){ releaseAccountJni(); - mUnreleasedCount--; mNativeId = 0; } @@ -190,12 +188,8 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * @return true if init succeed, false otherwise. */ private boolean initNewAccount() { - boolean retCode = false; - if(0 != (mNativeId = initNewAccountJni())){ - mUnreleasedCount++; - retCode = true; - } - return retCode; + mNativeId = initNewAccountJni(); + return (0 != mNativeId); } /** @@ -213,12 +207,8 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * @return true if init succeed, false otherwise. */ private boolean createNewAccount() { - boolean retCode = false; - if(0 != (mNativeId = createNewAccountJni())){ - mUnreleasedCount++; - retCode = true; - } - return retCode; + mNativeId = initNewAccountJni(); + return (0 != mNativeId); } /** @@ -384,11 +374,11 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private native String signMessageJni(byte[] aMessage); /** - * Return the number of unreleased OlmAccount instances.
- * @return number of unreleased instances + * Return true the object resources have been released.
+ * @return true the object resources have been released */ - public int getUnreleasedCount() { - return mUnreleasedCount; + public boolean isReleased() { + return (0 == mNativeId); } /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index ee5a20a..2e32a30 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -35,7 +35,6 @@ import java.io.Serializable; public class OlmInboundGroupSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -772028491251653253L; private static final String LOG_TAG = "OlmInboundGroupSession"; - private transient int mUnreleasedCount; /** Session Id returned by JNI.
* This value uniquely identifies the native inbound group session instance. @@ -75,7 +74,6 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ public void releaseSession(){ releaseSessionJni(); - mUnreleasedCount--; mNativeId = 0; } @@ -93,12 +91,8 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @return true if init succeed, false otherwise. */ private boolean createNewSession() { - boolean retCode = false; - if(0 != (mNativeId = createNewSessionJni())){ - mUnreleasedCount++; - retCode = true; - } - return retCode; + mNativeId = createNewSessionJni(); + return (0 != mNativeId); } /** @@ -263,10 +257,10 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri private native String initWithSerializedDataJni(String aSerializedData, String aKey); /** - * Return the number of unreleased OlmInboundGroupSession instances.
- * @return number of unreleased instances + * Return true the object resources have been released.
+ * @return true the object resources have been released */ - public int getUnreleasedCount() { - return mUnreleasedCount; + public boolean isReleased() { + return (0 == mNativeId); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 4aa07b4..4c09313 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -36,7 +36,6 @@ import java.io.Serializable; public class OlmOutboundGroupSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -3133097431283604416L; private static final String LOG_TAG = "OlmOutboundGroupSession"; - private transient int mUnreleasedCount; /** Session Id returned by JNI.
* This value uniquely identifies the native outbound group session instance. @@ -156,7 +155,6 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ public void releaseSession() { releaseSessionJni(); - mUnreleasedCount--; mNativeId = 0; } @@ -175,12 +173,8 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * @return true if init succeed, false otherwise. */ private boolean createNewSession() { - boolean retCode = false; - if(0 != (mNativeId = createNewSessionJni())){ - mUnreleasedCount++; - retCode = true; - } - return retCode; + mNativeId = createNewSessionJni(); + return (0 != mNativeId); } /** @@ -204,11 +198,9 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * @return session identifier if operation succeed, null otherwise. */ public String sessionIdentifier() { - String retValue = null; - retValue = sessionIdentifierJni(); - - return retValue; + return sessionIdentifierJni(); } + private native String sessionIdentifierJni(); /** @@ -218,10 +210,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * @return current session index */ public int messageIndex() { - int retValue =0; - retValue = messageIndexJni(); - - return retValue; + return messageIndexJni(); } private native int messageIndexJni(); @@ -232,10 +221,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * @return outbound session key */ public String sessionKey() { - String retValue = null; - retValue = sessionKeyJni(); - - return retValue; + return sessionKeyJni(); } private native String sessionKeyJni(); @@ -257,10 +243,10 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser private native String encryptMessageJni(String aClearMsg); /** - * Return the number of unreleased OlmOutboundGroupSession instances.
- * @return number of unreleased instances + * Return true the object resources have been released.
+ * @return true the object resources have been released */ - public int getUnreleasedCount() { - return mUnreleasedCount; + public boolean isReleased() { + return (0 == mNativeId); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 374659d..139cbb6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -36,14 +36,12 @@ import java.io.Serializable; public class OlmSession extends CommonSerializeUtils implements Serializable { private static final long serialVersionUID = -8975488639186976419L; private static final String LOG_TAG = "OlmSession"; - private transient int mUnreleasedCount; /** Session Id returned by JNI. * This value uniquely identifies the native session instance. **/ private transient long mNativeId; - public OlmSession() throws OlmException { if(!initNewSession()) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, OlmException.EXCEPTION_MSG_INIT_SESSION_CREATION); @@ -160,7 +158,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { */ public void releaseSession(){ releaseSessionJni(); - mUnreleasedCount--; mNativeId = 0; } @@ -171,12 +168,8 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @return true if init succeed, false otherwise. */ private boolean initNewSession() { - boolean retCode = false; - if(0 != (mNativeId = initNewSessionJni())){ - mUnreleasedCount++; - retCode = true; - } - return retCode; + mNativeId = initNewSessionJni(); + return (0 != mNativeId); } /** @@ -195,12 +188,8 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @return true if init succeed, false otherwise. */ private boolean createNewSession() { - boolean retCode = false; - if(0 != (mNativeId = createNewSessionJni())){ - mUnreleasedCount++; - retCode = true; - } - return retCode; + mNativeId = initNewSessionJni(); + return (0 != mNativeId); } /** @@ -368,11 +357,11 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { private native String decryptMessageJni(OlmMessage aEncryptedMsg, boolean aIsUtf8ConversionRequired); /** - * Return the number of unreleased OlmSession instances.
- * @return number of unreleased instances + * Return true the object resources have been released.
+ * @return true the object resources have been released */ - public int getUnreleasedCount() { - return mUnreleasedCount; + public boolean isReleased() { + return (0 == mNativeId); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index c90e552..8db9dca 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -30,7 +30,6 @@ public class OlmUtility { public static final int RANDOM_KEY_SIZE = 32; public static final int RANDOM_RANGE = 256; - private transient int mUnreleasedCount; /** Instance Id returned by JNI. * This value uniquely identifies this utility instance. @@ -47,13 +46,10 @@ public class OlmUtility { * @return true if init succeed, false otherwise. */ private boolean initUtility() { - boolean retCode = false; - if(0 != (mNativeId = initUtilityJni())){ - mUnreleasedCount++; - retCode = true; - } - return retCode; + mNativeId = initUtilityJni(); + return (0 != mNativeId); } + private native long initUtilityJni(); /** @@ -62,7 +58,6 @@ public class OlmUtility { */ public void releaseUtility(){ releaseUtilityJni(); - mUnreleasedCount--; mNativeId = 0; } private native void releaseUtilityJni(); @@ -148,11 +143,11 @@ public class OlmUtility { } /** - * Return the number of unreleased OlmUtility instances.
- * @return number of unreleased instances + * Return true the object resources have been released.
+ * @return true the object resources have been released */ - public int getUnreleasedCount() { - return mUnreleasedCount; + public boolean isReleased() { + return (0 == mNativeId); } } -- cgit v1.2.3 From b03cdebfb58b9d35c12c83a3c804b1317ad5f104 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 2 Jan 2017 17:10:59 +0100 Subject: Update the tab size to 4 spaces --- .../src/main/jni/olm_inbound_group_session.cpp | 115 +++++++++++---------- 1 file changed, 59 insertions(+), 56 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index e78d583..4ccb571 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -186,51 +186,47 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * jstring decryptedMsgRetValue = 0; OlmInboundGroupSession *sessionPtr = NULL; const char *encryptedMsgPtr = NULL; - uint8_t *plainTextMsgPtr = NULL; - uint8_t *tempEncryptedPtr = NULL; - uint32_t messageIndex = 0; jclass indexObjJClass = 0; jfieldID indexMsgFieldId; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; - jstring errorJstring = 0; const char *errorMsgPtr = NULL; LOGD("## decryptMessageJni(): inbound group session IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); } - else if(0 == aEncryptedMsg) + else if (!aEncryptedMsg) { LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); } - else if(0 == aDecryptIndex) + else if (!aDecryptIndex) { LOGE(" ## decryptMessageJni(): failure - invalid index object"); } - else if(0 == aErrorMsg) + else if (!aErrorMsg) { LOGE(" ## decryptMessageJni(): failure - invalid error object"); } - else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { LOGE(" ## decryptMessageJni(): failure - unable to get error class"); } - else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { LOGE(" ## decryptMessageJni(): failure - unable to get error method ID"); } - else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) + else if (!(encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) { LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } - else if(0 == (indexObjJClass = env->GetObjectClass(aDecryptIndex))) + else if (!(indexObjJClass = env->GetObjectClass(aDecryptIndex))) { LOGE("## decryptMessageJni(): failure - unable to get index class"); } - else if(0 == (indexMsgFieldId = env->GetFieldID(indexObjJClass,"mIndex","J"))) + else if (!(indexMsgFieldId = env->GetFieldID(indexObjJClass,"mIndex","J"))) { LOGE("## decryptMessageJni(): failure - unable to get index type field"); } @@ -238,9 +234,10 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { // get encrypted message length size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg); + uint8_t *tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); // create a dedicated temp buffer to be used in next Olm API calls - if(NULL == (tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))))) + if (!tempEncryptedPtr) { LOGE(" ## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); } @@ -253,11 +250,14 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, tempEncryptedPtr, encryptedMsgLength); - if(maxPlainTextLength == olm_error()) + if (maxPlainTextLength == olm_error()) { errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); - if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + + jstring errorJstring = env->NewStringUTF(errorMsgPtr); + + if (errorJstring) { env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); } @@ -266,8 +266,10 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); + uint32_t messageIndex = 0; + // allocate output decrypted message - plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); + uint8_t *plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); // decrypt, but before reload encrypted buffer (previous one was destroyed) memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); @@ -277,12 +279,14 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * plainTextMsgPtr, maxPlainTextLength, &messageIndex); - if(plaintextLength == olm_error()) + if (plaintextLength == olm_error()) { errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); - if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + jstring errorJstring = env->NewStringUTF(errorMsgPtr); + + if (errorJstring) { env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); } @@ -293,7 +297,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * env->SetLongField(aDecryptIndex, indexMsgFieldId, (jlong)messageIndex); // UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) - if(aIsUtf8ConversionRequired) + if (aIsUtf8ConversionRequired) { decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); if(0 == decryptedMsgRetValue) @@ -314,26 +318,26 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); } } + + if (plainTextMsgPtr) + { + free(plainTextMsgPtr); + } + } + + if (tempEncryptedPtr) + { + free(tempEncryptedPtr); } } } // free alloc - if(NULL != encryptedMsgPtr) + if (encryptedMsgPtr) { env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr); } - if(NULL != tempEncryptedPtr) - { - free(tempEncryptedPtr); - } - - if(NULL != plainTextMsgPtr) - { - free(plainTextMsgPtr); - } - return decryptedMsgRetValue; } @@ -349,34 +353,32 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; - jstring errorJstring = 0; const char *keyPtr = NULL; - void *pickledPtr = NULL; OlmInboundGroupSession* sessionPtr = NULL; LOGD("## inbound group session serializeDataWithKeyJni(): IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); } - else if(0 == aKey) + else if (!aKey) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } - else if(0 == aErrorMsg) + else if (!aErrorMsg) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); } - else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); } - else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } @@ -387,7 +389,9 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); - if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + + if (!pickledPtr) { LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); } @@ -403,7 +407,9 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); - if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + jstring errorJstring = env->NewStringUTF(errorMsgPtr); + + if (errorJstring) { env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); } @@ -415,18 +421,15 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } + + free(pickledPtr); } } // free alloc - if(NULL != keyPtr) - { - env->ReleaseStringUTFChars(aKey, keyPtr); - } - - if(NULL != pickledPtr) + if (keyPtr) { - free(pickledPtr); + env->ReleaseStringUTFChars(aKey, keyPtr); } return pickledDataRetValue; @@ -442,23 +445,23 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( LOGD("## initWithSerializedDataJni(): IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); } - else if(0 == aKey) + else if (!aKey) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if(0 == aSerializedData) + else if (!aSerializedData) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } @@ -475,7 +478,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_inbound_group_session() Msg=%s",errorMsgPtr); @@ -488,12 +491,12 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( } // free alloc - if(NULL != keyPtr) + if (keyPtr) { env->ReleaseStringUTFChars(aKey, keyPtr); } - if(NULL != pickledPtr) + if (pickledPtr) { env->ReleaseStringUTFChars(aSerializedData, pickledPtr); } -- cgit v1.2.3 From 65352d05aa1c9cc607a1bc2c560ac3c6e6ebf22e Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 09:32:59 +0100 Subject: ->Replace 2 spaces tabs by 4 spaces. ->fix the NULL and 0 pointer comparisons mixes --- .../src/main/java/org/matrix/olm/OlmSession.java | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 31 +- .../src/main/jni/olm_inbound_group_session.cpp | 62 ++-- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 7 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp | 16 +- .../src/main/jni/olm_outbound_group_session.cpp | 171 +++++----- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 375 +++++++++++---------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 80 +++-- 8 files changed, 372 insertions(+), 372 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 139cbb6..23b2091 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -335,7 +335,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { public OlmMessage encryptMessage(String aClearMsg) { OlmMessage encryptedMsgRetValue = new OlmMessage(); - if(0 != encryptMessageJni(aClearMsg, encryptedMsgRetValue)){ + if (0 != encryptMessageJni(aClearMsg, encryptedMsgRetValue)){ encryptedMsgRetValue = null; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 47c616d..a44d9db 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -19,7 +19,6 @@ using namespace AndroidOlmSdk; - /** * Init memory allocation for account creation. * @return valid memory allocation, NULL otherwise @@ -43,7 +42,6 @@ OlmAccount* initializeAccountMemory() return accountPtr; } - JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) { LOGD("## createNewAccountJni(): IN"); @@ -53,7 +51,6 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject t return (jlong)(intptr_t)accountPtr; } - /** * Release the account allocation made by initializeAccountMemory().
* This method MUST be called when java counter part account instance is done. @@ -65,7 +62,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); - if(!accountPtr) + if (!accountPtr) { LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); } @@ -147,7 +144,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject jbyteArray byteArrayRetValue = NULL; OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); - if (NULL == accountPtr) + if (!accountPtr) { LOGE("## identityKeys(): failure - invalid Account ptr=NULL"); } @@ -168,7 +165,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject // retrieve key pairs in identityKeysBytesPtr size_t keysResult = olm_account_identity_keys(accountPtr, identityKeysBytesPtr, identityKeysLength); - if(keysResult == olm_error()) + if (keysResult == olm_error()) { LOGE("## identityKeys(): failure - error getting identity keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } @@ -177,7 +174,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject // allocate the byte array to be returned to java byteArrayRetValue = env->NewByteArray(identityKeysLength); - if(NULL == byteArrayRetValue) + if (!byteArrayRetValue) { LOGE("## identityKeys(): failure - return byte array OOM"); } @@ -243,7 +240,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject uint8_t *randomBufferPtr = NULL; - if ( (0!=randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) + if ((0 != randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) { LOGE("## generateOneTimeKeysJni(): failure - random buffer init"); } @@ -304,7 +301,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t { // retrieve key pairs in keysBytesPtr size_t keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); - if(keysResult == olm_error()) { + if (keysResult == olm_error()) { LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); } else @@ -388,7 +385,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, { size_t result = olm_account_mark_keys_as_published(accountPtr); - if(result == olm_error()) + if (result == olm_error()) { LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",(const char *)olm_account_last_error(accountPtr)); retCode = ERROR_CODE_KO; @@ -417,7 +414,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz { LOGE("## signMessageJni(): failure - invalid aMessage param"); } - else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { LOGE("## signMessageJni(): failure - invalid account ptr"); } @@ -490,23 +487,23 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } - else if(!aErrorMsg) + else if (!aErrorMsg) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); } - else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + else if (!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); } - else if(!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) + else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); } - else if(!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if(!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } @@ -604,7 +601,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 4ccb571..535fd48 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -26,28 +26,28 @@ using namespace AndroidOlmSdk; */ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { - OlmInboundGroupSession* sessionPtr = NULL; + OlmInboundGroupSession* sessionPtr = NULL; - LOGD("## releaseSessionJni(): InBound group session IN"); + LOGD("## releaseSessionJni(): InBound group session IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) - { - LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); - } - else - { - LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); + if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + { + LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); + } + else + { + LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); #ifdef ENABLE_JNI_LOG - size_t retCode = olm_clear_inbound_group_session(sessionPtr); - LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); + size_t retCode = olm_clear_inbound_group_session(sessionPtr); + LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); #else - olm_clear_inbound_group_session(sessionPtr); + olm_clear_inbound_group_session(sessionPtr); #endif - LOGD(" ## releaseSessionJni(): free IN"); - free(sessionPtr); - LOGD(" ## releaseSessionJni(): free OUT"); - } + LOGD(" ## releaseSessionJni(): free IN"); + free(sessionPtr); + LOGD(" ## releaseSessionJni(): free OUT"); + } } /** @@ -64,18 +64,18 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * LOGD("## createNewSessionJni(): inbound group session IN"); sessionSize = olm_inbound_group_session_size(); - if(0 == sessionSize) + if (!sessionSize) { LOGE(" ## createNewSessionJni(): failure - inbound group session size = 0"); } - else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize))) + else if ((sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) { - sessionPtr = olm_inbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - inbound group session size=%lu",static_cast(sessionSize)); + sessionPtr = olm_inbound_group_session(sessionPtr); + LOGD(" ## createNewSessionJni(): success - inbound group session size=%lu",static_cast(sessionSize)); } else { - LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); + LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); } return (jlong)(intptr_t)sessionPtr; @@ -95,15 +95,15 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes LOGD("## initInboundGroupSessionWithSessionKeyJni(): inbound group session IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance"); } - else if(0 == aSessionKey) + else if (!aSessionKey) { LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); } - else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0))) + else if (!(sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0))) { LOGE(" ## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); } @@ -113,7 +113,7 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes LOGD(" ## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); - if(sessionResult == olm_error()) { + if (sessionResult == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); } @@ -125,7 +125,7 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes } // free local alloc - if(NULL!= sessionKeyPtr) + if (sessionKeyPtr) { env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr); } @@ -140,12 +140,11 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { OlmInboundGroupSession *sessionPtr = NULL; - uint8_t *sessionIdPtr = NULL; jstring returnValueStr=0; LOGD("## sessionIdentifierJni(): inbound group session IN"); - if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## sessionIdentifierJni(): failure - invalid inbound group session instance"); } @@ -155,13 +154,16 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); - if(NULL == (sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) + uint8_t *sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)); + + if (!sessionIdPtr) { LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); } else { size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + if (result == olm_error()) { LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); @@ -402,7 +404,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index eaa7edf..767fad4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -36,7 +36,7 @@ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) { LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); } - else if(!aRandomSize) + else if (!aRandomSize) { LOGE("## setRandomInBuffer(): failure - random size=0"); } @@ -113,7 +113,8 @@ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass) { jlong instanceId = 0; - if (aJniEnv) + + if (aJniEnv) { jclass requiredClass = aJniEnv->FindClass(aCallingClass); jclass loaderClass = 0; @@ -227,7 +228,7 @@ jstring javaCStringToUtf8(JNIEnv *env, uint8_t *aCStringMsgPtr, size_t aMsgLengt { LOGE("## javaCStringToUtf8(): failure - invalid parameters (null)"); } - else if (!(tempByteArray=env->NewByteArray(aMsgLength))) + else if (!(tempByteArray = env->NewByteArray(aMsgLength))) { LOGE("## javaCStringToUtf8(): failure - return byte array OOM"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp index e72824f..8ee0df7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp @@ -21,15 +21,15 @@ using namespace AndroidOlmSdk; JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) { - uint8_t majorVer=0, minorVer=0, patchVer=0; - jstring returnValueStr=0; - char buff[150]; + uint8_t majorVer=0, minorVer=0, patchVer=0; + jstring returnValueStr=0; + char buff[150]; - olm_get_library_version(&majorVer, &minorVer, &patchVer); - LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); + olm_get_library_version(&majorVer, &minorVer, &patchVer); + LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); - snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); - returnValueStr = env->NewStringUTF((const char*)buff); + snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); + returnValueStr = env->NewStringUTF((const char*)buff); - return returnValueStr; + return returnValueStr; } \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 91504de..2dad00a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -26,29 +26,29 @@ using namespace AndroidOlmSdk; */ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { - OlmOutboundGroupSession* sessionPtr = NULL; + LOGD("## releaseSessionJni(): OutBound group session IN"); - LOGD("## releaseSessionJni(): OutBound group session IN"); + OlmOutboundGroupSession* sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) - { - LOGE(" ## releaseSessionJni(): failure - invalid outbound group session instance"); - } - else - { - LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); + if (!sessionPtr) + { + LOGE(" ## releaseSessionJni(): failure - invalid outbound group session instance"); + } + else + { + LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); #ifdef ENABLE_JNI_LOG - size_t retCode = olm_clear_outbound_group_session(sessionPtr); - LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",static_cast(retCode)); + size_t retCode = olm_clear_outbound_group_session(sessionPtr); + LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",static_cast(retCode)); #else - olm_clear_outbound_group_session(sessionPtr); + olm_clear_outbound_group_session(sessionPtr); #endif - LOGD(" ## releaseSessionJni(): free IN"); - free(sessionPtr); - LOGD(" ## releaseSessionJni(): free OUT"); - } + LOGD(" ## releaseSessionJni(): free IN"); + free(sessionPtr); + LOGD(" ## releaseSessionJni(): free OUT"); + } } /** @@ -65,18 +65,18 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv LOGD("## createNewSessionJni(): outbound group session IN"); sessionSize = olm_outbound_group_session_size(); - if(0 == sessionSize) + if (0 == sessionSize) { LOGE(" ## createNewSessionJni(): failure - outbound group session size = 0"); } - else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize))) + else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) { - sessionPtr = olm_outbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); + sessionPtr = olm_outbound_group_session(sessionPtr); + LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); } else { - LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); + LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); } return (jlong)(intptr_t)sessionPtr; @@ -89,12 +89,12 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) { jint retCode = ERROR_CODE_KO; - OlmOutboundGroupSession *sessionPtr = NULL; - uint8_t *randomBuffPtr = NULL; LOGD("## initOutboundGroupSessionJni(): IN"); - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); + + if (!sessionPtr) { LOGE(" ## initOutboundGroupSessionJni(): failure - invalid outbound group session instance"); } @@ -102,20 +102,24 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( { // compute random buffer size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); + uint8_t *randomBuffPtr = NULL; + LOGW(" ## initOutboundGroupSessionJni(): randomLength=%lu",static_cast(randomLength)); - if((0!=randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) + + if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init"); } else { - if(0==randomLength) + if (0 == randomLength) { LOGW(" ## initOutboundGroupSessionJni(): random buffer is not required"); } size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); - if(sessionResult == olm_error()) { + + if (sessionResult == olm_error()) { LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); } else @@ -123,12 +127,9 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( retCode = ERROR_CODE_OK; LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); } - } - } - if(NULL != randomBuffPtr) - { - free(randomBuffPtr); + free(randomBuffPtr); + } } return retCode; @@ -139,13 +140,11 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( */ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { - OlmOutboundGroupSession *sessionPtr = NULL; - uint8_t *sessionIdPtr = NULL; - jstring returnValueStr=0; - LOGD("## sessionIdentifierJni(): outbound group session IN"); + OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); + jstring returnValueStr=0; - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## sessionIdentifierJni(): failure - invalid outbound group session instance"); } @@ -155,13 +154,16 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); - if(NULL == (sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) + uint8_t *sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)); + + if (!sessionIdPtr) { LOGE(" ## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); } else { size_t result = olm_outbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + if (result == olm_error()) { LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",reinterpret_cast(olm_outbound_group_session_last_error(sessionPtr))); @@ -196,7 +198,7 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, LOGD("## messageIndexJni(): IN"); - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## messageIndexJni(): failure - invalid outbound group session instance"); } @@ -204,24 +206,22 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, { indexRetValue = static_cast(olm_outbound_group_session_message_index(sessionPtr)); } + LOGD(" ## messageIndexJni(): success - index=%d",indexRetValue); return indexRetValue; } - /** * Get the base64-encoded current ratchet key for this session.
*/ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) { - OlmOutboundGroupSession *sessionPtr = NULL; - uint8_t *sessionKeyPtr = NULL; - jstring returnValueStr=0; - LOGD("## sessionKeyJni(): outbound group session IN"); + OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); + jstring returnValueStr = 0; - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## sessionKeyJni(): failure - invalid outbound group session instance"); } @@ -231,13 +231,16 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env size_t sessionKeyLength = olm_outbound_group_session_key_length(sessionPtr); LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); - if(NULL == (sessionKeyPtr = (uint8_t*)malloc((sessionKeyLength+1)*sizeof(uint8_t)))) + uint8_t *sessionKeyPtr = (uint8_t*)malloc((sessionKeyLength+1)*sizeof(uint8_t)); + + if (!sessionKeyPtr) { LOGE(" ## sessionKeyJni(): failure - session key allocation OOM"); } else { size_t result = olm_outbound_group_session_key(sessionPtr, sessionKeyPtr, sessionKeyLength); + if (result == olm_error()) { LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); @@ -261,22 +264,21 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg) { + LOGD("## encryptMessageJni(): IN"); + jstring encryptedMsgRetValue = 0; OlmOutboundGroupSession *sessionPtr = NULL; const char *clearMsgPtr = NULL; - uint8_t *encryptedMsgPtr = NULL; - LOGD("## encryptMessageJni(): IN"); - - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## encryptMessageJni(): failure - invalid outbound group session ptr=NULL"); } - else if(0 == aClearMsg) + else if (!aClearMsg) { LOGE(" ## encryptMessageJni(): failure - invalid clear message"); } - else if(0 == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) + else if (!(clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) { LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM"); } @@ -288,7 +290,9 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv // compute max encrypted length size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); - if(NULL == (encryptedMsgPtr = (uint8_t*)malloc((encryptedMsgLength+1)*sizeof(uint8_t)))) + uint8_t *encryptedMsgPtr = (uint8_t*)malloc((encryptedMsgLength+1)*sizeof(uint8_t)); + + if (!encryptedMsgPtr) { LOGE(" ## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); } @@ -301,7 +305,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv clearMsgLength, encryptedMsgPtr, encryptedMsgLength); - if(encryptedLength == olm_error()) + if (encryptedLength == olm_error()) { LOGE(" ## encryptMessageJni(): failure - olm_group_encrypt Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); } @@ -313,20 +317,17 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); encryptedMsgRetValue = env->NewStringUTF((const char*)encryptedMsgPtr); } - } + + free(encryptedMsgPtr); + } } // free alloc - if(NULL != clearMsgPtr) + if (clearMsgPtr) { env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr); } - if(NULL != encryptedMsgPtr) - { - free(encryptedMsgPtr); - } - return encryptedMsgRetValue; } @@ -344,32 +345,31 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J jmethodID errorMsgMethodId = 0; jstring errorJstring = 0; const char *keyPtr = NULL; - void *pickledPtr = NULL; OlmOutboundGroupSession* sessionPtr = NULL; LOGD("## outbound group session serializeDataWithKeyJni(): IN"); - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); } - else if(0 == aKey) + else if (!aKey) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } - else if(0 == aErrorMsg) + else if (!aErrorMsg) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); } - else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); } - else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } @@ -380,7 +380,9 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); - if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + + if(!pickledPtr) { LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); } @@ -391,12 +393,12 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); - if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + if (!(errorJstring = env->NewStringUTF(errorMsgPtr))) { env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); } @@ -409,17 +411,14 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } } - } - // free alloc - if(NULL != keyPtr) - { - env->ReleaseStringUTFChars(aKey, keyPtr); + free(pickledPtr); } - if(NULL != pickledPtr) + // free alloc + if (keyPtr) { - free(pickledPtr); + env->ReleaseStringUTFChars(aKey, keyPtr); } return pickledDataRetValue; @@ -435,23 +434,23 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) LOGD("## initWithSerializedDataJni(): IN"); - if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); } - else if(0 == aKey) + else if (!aKey) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if(0 == aSerializedData) + else if (!aSerializedData) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } @@ -468,7 +467,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_outbound_group_session() Msg=%s",errorMsgPtr); @@ -481,12 +480,12 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) } // free alloc - if(NULL != keyPtr) + if (keyPtr) { env->ReleaseStringUTFChars(aKey, keyPtr); } - if(NULL != pickledPtr) + if (pickledPtr) { env->ReleaseStringUTFChars(aSerializedData, pickledPtr); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 7ec46df..28edae1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -26,17 +26,18 @@ using namespace AndroidOlmSdk; **/ OlmSession* initializeSessionMemory() { - OlmSession* sessionPtr = NULL; size_t sessionSize = olm_session_size(); + OlmSession* sessionPtr = (OlmSession*)malloc(sessionSize); - if(NULL != (sessionPtr=(OlmSession*)malloc(sessionSize))) - { // init session object - sessionPtr = olm_session(sessionPtr); - LOGD("## initializeSessionMemory(): success - OLM session size=%lu",static_cast(sessionSize)); + if (sessionPtr) + { + // init session object + sessionPtr = olm_session(sessionPtr); + LOGD("## initializeSessionMemory(): success - OLM session size=%lu",static_cast(sessionSize)); } else { - LOGE("## initializeSessionMemory(): failure - OOM"); + LOGE("## initializeSessionMemory(): failure - OOM"); } return sessionPtr; @@ -53,21 +54,20 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject t JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { - OlmSession* sessionPtr = NULL; - - LOGD("## releaseSessionJni(): IN"); + LOGD("## releaseSessionJni(): IN"); + OlmSession* sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz); - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) - { - LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); - } - else - { - olm_clear_session(sessionPtr); + if (!sessionPtr) + { + LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); + } + else + { + olm_clear_session(sessionPtr); - // even if free(NULL) does not crash, logs are performed for debug purpose - free(sessionPtr); - } + // even if free(NULL) does not crash, logs are performed for debug purpose + free(sessionPtr); + } } /** @@ -78,18 +78,18 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz **/ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) { - OlmSession* sessionPtr = NULL; - LOGD("## initNewSessionJni(): OlmSession IN"); + OlmSession* sessionPtr = initializeSessionMemory(); + // init account memory allocation - if(NULL == (sessionPtr = initializeSessionMemory())) + if (!sessionPtr) { LOGE(" ## initNewSessionJni(): failure - init session OOM"); } else { - LOGD(" ## initNewSessionJni(): success - OLM session created"); + LOGD(" ## initNewSessionJni(): success - OLM session created"); } return (jlong)(intptr_t)sessionPtr; @@ -112,38 +112,41 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject jint retCode = ERROR_CODE_KO; OlmSession* sessionPtr = NULL; OlmAccount* accountPtr = NULL; - const char* theirIdentityKeyPtr = NULL; - const char* theirOneTimeKeyPtr = NULL; - uint8_t *randomBuffPtr = NULL; - size_t sessionResult; - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## initOutboundSessionJni(): failure - invalid Session ptr=NULL"); } - else if(NULL == (accountPtr = (OlmAccount*)aOlmAccountId)) + else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) { LOGE("## initOutboundSessionJni(): failure - invalid Account ptr=NULL"); } - else if((0==aTheirIdentityKey) || (0==aTheirOneTimeKey)) + else if (!aTheirIdentityKey || !aTheirOneTimeKey) { LOGE("## initOutboundSessionJni(): failure - invalid keys"); } else - { // allocate random buffer + { size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); + uint8_t *randomBuffPtr = NULL; + LOGD("## initOutboundSessionJni(): randomSize=%lu",static_cast(randomSize)); - if((0!=randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) + + if ( (0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) { LOGE("## initOutboundSessionJni(): failure - random buffer init"); } else - { // convert identity & one time keys to C strings - if(NULL == (theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + { + const char* theirIdentityKeyPtr = NULL; + const char* theirOneTimeKeyPtr = NULL; + + // convert identity & one time keys to C strings + if (!(theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) { LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM"); } - else if(NULL == (theirOneTimeKeyPtr = env->GetStringUTFChars(aTheirOneTimeKey, 0))) + else if (!(theirOneTimeKeyPtr = env->GetStringUTFChars(aTheirOneTimeKey, 0))) { LOGE("## initOutboundSessionJni(): failure - one time Key JNI allocation OOM"); } @@ -153,7 +156,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject size_t theirOneTimeKeyLength = (size_t)env->GetStringUTFLength(aTheirOneTimeKey); LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr); - sessionResult = olm_create_outbound_session(sessionPtr, + size_t sessionResult = olm_create_outbound_session(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, @@ -161,7 +164,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject theirOneTimeKeyLength, (void*)randomBuffPtr, randomSize); - if(sessionResult == olm_error()) { + if (sessionResult == olm_error()) { LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else @@ -170,24 +173,23 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject LOGD("## initOutboundSessionJni(): success - result=%lu", static_cast(sessionResult)); } } - } - } - // **** free mem alloc *** - if(NULL!= randomBuffPtr) - { - free(randomBuffPtr); - } + if (theirIdentityKeyPtr) + { + env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + } - if(NULL!= theirIdentityKeyPtr) - { - env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); - } + if (theirOneTimeKeyPtr) + { + env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr); + } - if(NULL!= theirOneTimeKeyPtr) - { - env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr); - } + if (randomBuffPtr) + { + free(randomBuffPtr); + } + } + } return retCode; } @@ -208,24 +210,25 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; OlmAccount *accountPtr = NULL; - const char *messagePtr = NULL; size_t sessionResult; - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## initInboundSessionJni(): failure - invalid Session ptr=NULL"); } - else if(NULL == (accountPtr = (OlmAccount*)aOlmAccountId)) + else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) { LOGE("## initInboundSessionJni(): failure - invalid Account ptr=NULL"); } - else if(0==aOneTimeKeyMsg) + else if (!aOneTimeKeyMsg) { LOGE("## initInboundSessionJni(): failure - invalid message"); } else - { // convert message to C strings - if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + { + const char *messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0); + + if (!messagePtr) { LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM"); } @@ -235,7 +238,9 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject LOGD("## initInboundSessionJni(): messageLength=%lu message=%s", static_cast(messageLength), messagePtr); sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); - if(sessionResult == olm_error()) { + + if (sessionResult == olm_error()) + { LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else @@ -268,27 +273,27 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, const char *theirIdentityKeyPtr = NULL; size_t sessionResult; - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); } - else if(NULL == (accountPtr = (OlmAccount*)aOlmAccountId)) + else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Account ptr=NULL"); } - else if(0 == aTheirIdentityKey) + else if (!aTheirIdentityKey) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); } - else if(0==aOneTimeKeyMsg) + else if (!aOneTimeKeyMsg) { LOGE("## initInboundSessionJni(): failure - invalid one time key message"); } - else if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + else if (!(messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - message JNI allocation OOM"); } - else if(NULL == (theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + else if(!(theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); } @@ -300,7 +305,8 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, LOGD("## initInboundSessionFromIdKeyJni(): message=%s messageLength=%lu",messagePtr,static_cast(messageLength)); sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); - if(sessionResult == olm_error()) { + if (sessionResult == olm_error()) + { LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else @@ -311,11 +317,12 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, } // free local alloc - if(NULL!= messagePtr) + if (messagePtr) { env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); } - if(NULL!= theirIdentityKeyPtr) + + if (theirIdentityKeyPtr) { env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); } @@ -335,15 +342,15 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje OlmSession *sessionPtr = NULL; const char *messagePtr = NULL; - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## matchesInboundSessionJni(): failure - invalid Session ptr=NULL"); } - else if(0==aOneTimeKeyMsg) + else if (!aOneTimeKeyMsg) { LOGE("## matchesInboundSessionJni(): failure - invalid one time key message"); } - else if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + else if (!(messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) { LOGE("## matchesInboundSessionJni(): failure - one time key JNI allocation OOM"); } @@ -354,7 +361,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); //if(matchResult == olm_error()) { // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 - if(matchResult != 1) { + if (matchResult != 1) { LOGE("## matchesInboundSessionJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else @@ -365,9 +372,9 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje } // free local alloc - if(NULL!= messagePtr) + if (messagePtr) { - env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); } return retCode; @@ -388,23 +395,23 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J const char *messagePtr = NULL; const char *theirIdentityKeyPtr = NULL; - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); } - else if(0 == aTheirIdentityKey) + else if (!aTheirIdentityKey) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); } - else if(NULL == (theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + else if (!(theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); } - else if(0==aOneTimeKeyMsg) + else if (!aOneTimeKeyMsg) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid one time key message"); } - else if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + else if (!(messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - one time key JNI allocation OOM"); } @@ -412,11 +419,12 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J { size_t identityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); - size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); + //if(matchResult == olm_error()) { // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 - if(matchResult != 1) { + if (matchResult != 1) + { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else @@ -427,14 +435,14 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J } // free local alloc - if(NULL!= theirIdentityKeyPtr) + if (theirIdentityKeyPtr) { - env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); } - if(NULL!= messagePtr) + if (messagePtr) { - env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); } return retCode; @@ -452,39 +460,37 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; const char *clearMsgPtr = NULL; - uint8_t *randomBuffPtr = NULL; - void *encryptedMsgPtr = NULL; jclass encryptedMsgJClass = 0; jfieldID encryptedMsgFieldId; jfieldID typeMsgFieldId; LOGD("## encryptMessageJni(): IN "); - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); } - else if(0 == aClearMsg) + else if (!aClearMsg) { LOGE("## encryptMessageJni(): failure - invalid clear message"); } - else if(0 == aEncryptedMsg) + else if (!aEncryptedMsg) { LOGE("## encryptMessageJni(): failure - invalid encrypted message"); } - else if(NULL == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) + else if (!(clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) { LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM"); } - else if(0 == (encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) + else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) { LOGE("## encryptMessageJni(): failure - unable to get crypted message class"); } - else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) + else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) { LOGE("## encryptMessageJni(): failure - unable to get message field"); } - else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) + else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) { LOGE("## encryptMessageJni(): failure - unable to get message type field"); } @@ -492,13 +498,16 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz { // get message type size_t messageType = olm_encrypt_message_type(sessionPtr); + uint8_t *randomBuffPtr = NULL; // compute random buffer // Note: olm_encrypt_random_length() can return 0, which means // it just does not need new random data to encrypt a new message size_t randomLength = olm_encrypt_random_length(sessionPtr); + LOGD("## encryptMessageJni(): randomLength=%lu", static_cast(randomLength)); - if((0!=randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) + + if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { LOGE("## encryptMessageJni(): failure - random buffer init"); } @@ -507,13 +516,16 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // alloc buffer for encrypted message size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg); size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); - if(NULL == (encryptedMsgPtr = (void*)malloc((encryptedMsgLength+1)*sizeof(uint8_t)))) + + void *encryptedMsgPtr = malloc((encryptedMsgLength+1)*sizeof(uint8_t)); + + if (!encryptedMsgPtr) { LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); } else { - if(0==randomLength) + if (0 == randomLength) { LOGW("## encryptMessageJni(): random buffer is not required"); } @@ -527,7 +539,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz randomLength, encryptedMsgPtr, encryptedMsgLength); - if(result == olm_error()) + if (result == olm_error()) { LOGE("## encryptMessageJni(): failure - Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } @@ -546,30 +558,23 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz retCode = ERROR_CODE_OK; LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", static_cast(result), static_cast(messageType), static_cast((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr); } + + free(encryptedMsgPtr); } + + free(randomBuffPtr); } } // free alloc - if(NULL != clearMsgPtr) - { - env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr); - } - - if(NULL != randomBuffPtr) - { - free(randomBuffPtr); - } - - if(NULL != encryptedMsgPtr) + if (clearMsgPtr) { - free(encryptedMsgPtr); + env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr); } return retCode; } - /** * Decrypt a message using the session.
* @param aEncryptedMsg message to decrypt @@ -591,31 +596,31 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t LOGD("## decryptMessageJni(): IN - OlmSession"); - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); } - else if(0 == aEncryptedMsg) + else if (!aEncryptedMsg) { LOGE("## decryptMessageJni(): failure - invalid encrypted message"); } - else if(0 == (encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) + else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) { LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); } - else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) + else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) { LOGE("## decryptMessageJni(): failure - unable to get message field"); } - else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) + else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) { LOGE("## decryptMessageJni(): failure - unable to get message type field"); } - else if(0 == (encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) + else if (!(encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) { LOGE("## decryptMessageJni(): failure - JNI encrypted object "); } - else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) + else if (!(encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) { LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } @@ -638,7 +643,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t encryptedMsgLength); // Note: tempEncryptedPtr is destroyed by olm_decrypt_max_plaintext_length() - if(maxPlainTextLength == olm_error()) + if (maxPlainTextLength == olm_error()) { LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } @@ -657,14 +662,14 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t encryptedMsgLength, plainTextMsgPtr, maxPlainTextLength); - if(plaintextLength == olm_error()) + if (plaintextLength == olm_error()) { LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",(const char *)olm_session_last_error(sessionPtr)); } else { // UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) - if(aIsUtf8ConversionRequired) + if (aIsUtf8ConversionRequired) { decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); if(0 == decryptedMsgRetValue) @@ -689,17 +694,17 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } // free alloc - if(NULL != encryptedMsgPtr) + if (encryptedMsgPtr) { env->ReleaseStringUTFChars(encryptedMsgJstring, encryptedMsgPtr); } - if(NULL != tempEncryptedPtr) + if (tempEncryptedPtr) { free(tempEncryptedPtr); } - if(NULL != plainTextMsgPtr) + if (plainTextMsgPtr) { free(plainTextMsgPtr); } @@ -714,47 +719,49 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t */ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) { - OlmSession *sessionPtr = NULL; - void *sessionIdPtr = NULL; - jstring returnValueStr=0; + jstring returnValueStr=0; - LOGD("## getSessionIdentifierJni(): IN "); + LOGD("## getSessionIdentifierJni(): IN "); - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) - { - LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); - } - else - { - // get the size to alloc to contain the id - size_t lengthSessionId = olm_session_id_length(sessionPtr); - LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",static_cast(lengthSessionId)); + OlmSession *sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz); - if(NULL == (sessionIdPtr = (void*)malloc((lengthSessionId+1)*sizeof(uint8_t)))) - { - LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); - } - else - { - size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - - if (result == olm_error()) - { - LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",(const char *)olm_session_last_error(sessionPtr)); - } - else - { - // update length - (static_cast(sessionIdPtr))[result] = static_cast('\0'); - - LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); - returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); - } - free(sessionIdPtr); - } - } + if (!sessionPtr) + { + LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); + } + else + { + // get the size to alloc to contain the id + size_t lengthSessionId = olm_session_id_length(sessionPtr); + LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",static_cast(lengthSessionId)); + + void *sessionIdPtr = malloc((lengthSessionId+1)*sizeof(uint8_t)); + + if (!sessionIdPtr) + { + LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); + } + else + { + size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + + if (result == olm_error()) + { + LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + } + else + { + // update length + (static_cast(sessionIdPtr))[result] = static_cast('\0'); + + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); + returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + } + free(sessionIdPtr); + } + } - return returnValueStr; + return returnValueStr; } @@ -771,32 +778,31 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job jmethodID errorMsgMethodId = 0; jstring errorJstring = 0; const char *keyPtr = NULL; - void *pickledPtr = NULL; OlmSession* sessionPtr = NULL; LOGD("## serializeDataWithKeyJni(): IN"); - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); } - else if(0 == aKey) + else if (!aKey) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } - else if(0 == aErrorMsg) + else if (!aErrorMsg) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); } - else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); } - else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } @@ -807,7 +813,9 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); - if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + + if (!pickledPtr) { LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); } @@ -818,7 +826,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr); @@ -835,18 +843,15 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } + + free(pickledPtr); } } // free alloc - if(NULL != keyPtr) + if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); - } - - if(NULL != pickledPtr) - { - free(pickledPtr); + env->ReleaseStringUTFChars(aKey, keyPtr); } return pickledDataRetValue; @@ -862,23 +867,23 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j LOGD("## initWithSerializedDataJni(): IN"); - if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); } - else if(0 == aKey) + else if (!aKey) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if(0 == aSerializedData) + else if (!aSerializedData) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } - else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } @@ -895,7 +900,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j keyLength, (void*)pickledPtr, pickledLength); - if(result == olm_error()) + if (result == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); @@ -909,12 +914,12 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j } // free alloc - if(NULL != keyPtr) + if (keyPtr) { env->ReleaseStringUTFChars(aKey, keyPtr); } - if(NULL != pickledPtr) + if (pickledPtr) { env->ReleaseStringUTFChars(aSerializedData, pickledPtr); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 4770280..8a7607c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -21,17 +21,17 @@ using namespace AndroidOlmSdk; OlmUtility* initializeUtilityMemory() { - OlmUtility* utilityPtr = NULL; size_t utilitySize = olm_utility_size(); + OlmUtility* utilityPtr = (OlmUtility*)malloc(utilitySize); - if(NULL != (utilityPtr=(OlmUtility*)malloc(utilitySize))) + if (utilityPtr) { - utilityPtr = olm_utility(utilityPtr); - LOGD("## initializeUtilityMemory(): success - OLM utility size=%lu",static_cast(utilitySize)); + utilityPtr = olm_utility(utilityPtr); + LOGD("## initializeUtilityMemory(): success - OLM utility size=%lu",static_cast(utilitySize)); } else { - LOGE("## initializeUtilityMemory(): failure - OOM"); + LOGE("## initializeUtilityMemory(): failure - OOM"); } return utilityPtr; @@ -39,12 +39,12 @@ OlmUtility* initializeUtilityMemory() JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz) { - OlmUtility* utilityPtr = NULL; + OlmUtility* utilityPtr = initializeUtilityMemory(); LOGD("## initUtilityJni(): IN"); // init account memory allocation - if(NULL == (utilityPtr = initializeUtilityMemory())) + if (!utilityPtr) { LOGE(" ## initUtilityJni(): failure - init OOM"); } @@ -59,19 +59,19 @@ JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz) JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz) { - OlmUtility* utilityPtr = NULL; - - LOGD("## releaseUtilityJni(): IN"); - - if(NULL == (utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) - { - LOGE("## releaseUtilityJni(): failure - utility ptr=NULL"); - } - else - { - olm_clear_utility(utilityPtr); - free(utilityPtr); - } + OlmUtility* utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz); + + LOGD("## releaseUtilityJni(): IN"); + + if (!utilityPtr) + { + LOGE("## releaseUtilityJni(): failure - utility ptr=NULL"); + } + else + { + olm_clear_utility(utilityPtr); + free(utilityPtr); + } } @@ -95,23 +95,23 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j LOGD("## verifyEd25519SignatureJni(): IN"); - if(NULL == (utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) + if (!(utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) { LOGE(" ## verifyEd25519SignatureJni(): failure - invalid utility ptr=NULL"); } - else if((0 == aSignature) || (0 == aKey) || (0 == aMessage)) + else if (!aSignature || !aKey || !aMessage) { LOGE(" ## verifyEd25519SignatureJni(): failure - invalid input parameters "); } - else if(0 == (signaturePtr = env->GetStringUTFChars(aSignature, 0))) + else if (!(signaturePtr = env->GetStringUTFChars(aSignature, 0))) { LOGE(" ## verifyEd25519SignatureJni(): failure - signature JNI allocation OOM"); } - else if(0 == (keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) { LOGE(" ## verifyEd25519SignatureJni(): failure - key JNI allocation OOM"); } - else if(0 == (messagePtr = env->GetStringUTFChars(aMessage, 0))) + else if (!(messagePtr = env->GetStringUTFChars(aMessage, 0))) { LOGE(" ## verifyEd25519SignatureJni(): failure - message JNI allocation OOM"); } @@ -130,7 +130,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j messageLength, (void*)signaturePtr, signatureLength); - if(result == olm_error()) { + if (result == olm_error()) { const char *errorMsgPtr = olm_utility_last_error(utilityPtr); errorMessageRetValue = env->NewStringUTF(errorMsgPtr); LOGE("## verifyEd25519SignatureJni(): failure - olm_ed25519_verify Msg=%s",errorMsgPtr); @@ -142,17 +142,17 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j } // free alloc - if(NULL != signaturePtr) + if (signaturePtr) { env->ReleaseStringUTFChars(aSignature, signaturePtr); } - if(NULL != keyPtr) + if (keyPtr) { env->ReleaseStringUTFChars(aKey, keyPtr); } - if(NULL != messagePtr) + if (messagePtr) { env->ReleaseStringUTFChars(aMessage, messagePtr); } @@ -171,19 +171,18 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst jstring sha256RetValue = 0; OlmUtility* utilityPtr = NULL; const char* messagePtr = NULL; - void *hashValuePtr = NULL; LOGD("## sha256Jni(): IN"); - if(NULL == (utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) + if (!(utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) { LOGE(" ## sha256Jni(): failure - invalid utility ptr=NULL"); } - else if(0 == aMessageToHash) + else if(!aMessageToHash) { LOGE(" ## sha256Jni(): failure - invalid message parameters "); } - else if(0 == (messagePtr = env->GetStringUTFChars(aMessageToHash, 0))) + else if(!(messagePtr = env->GetStringUTFChars(aMessageToHash, 0))) { LOGE(" ## sha256Jni(): failure - message JNI allocation OOM"); } @@ -192,8 +191,9 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst // get lengths size_t messageLength = (size_t)env->GetStringUTFLength(aMessageToHash); size_t hashLength = olm_sha256_length(utilityPtr); + void* hashValuePtr = malloc((hashLength+1)*sizeof(uint8_t)); - if(NULL == (hashValuePtr = static_cast(malloc((hashLength+1)*sizeof(uint8_t))))) + if (!hashValuePtr) { LOGE("## sha256Jni(): failure - hash value allocation OOM"); } @@ -204,7 +204,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst messageLength, (void *)hashValuePtr, hashLength); - if(result == olm_error()) + if (result == olm_error()) { LOGE("## sha256Jni(): failure - hash creation Msg=%s",(const char *)olm_utility_last_error(utilityPtr)); } @@ -216,16 +216,12 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst LOGD("## sha256Jni(): success - result=%lu hashValue=%s",static_cast(result), (char*)hashValuePtr); sha256RetValue = env->NewStringUTF((const char*)hashValuePtr); } - } + free(hashValuePtr); + } } - if(NULL != hashValuePtr) - { - free(hashValuePtr); - } - - if(NULL != messagePtr) + if (messagePtr) { env->ReleaseStringUTFChars(aMessageToHash, messagePtr); } -- cgit v1.2.3 From c8c7a8ad19d3238ae3c0c7db4eaff165748a6a1e Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 10:46:56 +0100 Subject: -> simplify OlmSession.DecryptMessage -> Always use javaCStringToUtf8 to convert byte array to String --- .../java/org/matrix/olm/OlmAccountTest.java | 6 +-- .../java/org/matrix/olm/OlmGroupSessionTest.java | 52 ++++++++++++---------- .../java/org/matrix/olm/OlmSessionTest.java | 6 +-- .../java/org/matrix/olm/OlmUtilityTest.java | 6 +-- .../org/matrix/olm/OlmInboundGroupSession.java | 44 +++++++++++------- .../src/main/java/org/matrix/olm/OlmManager.java | 8 +--- .../src/main/java/org/matrix/olm/OlmSession.java | 4 +- .../src/main/jni/olm_inbound_group_session.cpp | 30 +++++-------- .../src/main/jni/olm_inbound_group_session.h | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 23 +++------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 2 +- 11 files changed, 80 insertions(+), 103 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 12bc424..b275688 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -60,12 +60,8 @@ public class OlmAccountTest { @BeforeClass public static void setUpClass(){ - // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, - // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 - boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; - // load native lib - mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); + mOlmManager = new OlmManager(); String olmLibVersion = mOlmManager.getOlmLibVersion(); assertNotNull(olmLibVersion); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 2152a8d..111032e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -61,13 +61,8 @@ public class OlmGroupSessionTest { @BeforeClass public static void setUpClass(){ - - // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, - // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 - boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; - // load native lib - mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); + mOlmManager = new OlmManager(); String version = mOlmManager.getOlmLibVersion(); assertNotNull(version); @@ -151,13 +146,18 @@ public class OlmGroupSessionTest { @Test public void test10InboundDecryptMessage() { - // test decrypted message - StringBuffer errorMsg = new StringBuffer(); - OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); + mBobDecryptedMessage = null; + OlmInboundGroupSession.DecryptMessageResult result = null; - mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage, index, errorMsg); + try { + result = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage); + } catch (Exception e) { + } + + // test decrypted message + mBobDecryptedMessage = result.mDecryptedMessage; assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); - assertTrue(0==index.mIndex); + assertTrue(0 == result.mIndex); } @Test @@ -440,14 +440,17 @@ public class OlmGroupSessionTest { assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false); } - StringBuffer errorMsg = new StringBuffer(); - OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); + OlmInboundGroupSession.DecryptMessageResult result = null; - String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji, index, errorMsg); - assertNotNull(decryptedMessage); - assertTrue(13==index.mIndex); - } + try { + result = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji); + } catch (Exception e) { + assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getMessage(), false); + } + assertNotNull(result.mDecryptedMessage); + assertTrue(13 == result.mIndex); + } /** * Specific test to check an error message is returned by decryptMessage() API.
@@ -458,8 +461,6 @@ public class OlmGroupSessionTest { public void test19TestErrorMessageReturnedInDecrypt() { OlmInboundGroupSession bobInboundGroupSession=null; final String EXPECTED_ERROR_MESSAGE= "INVALID_BASE64"; - StringBuffer errorMsg = new StringBuffer(); - OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex(); String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; String corruptedEncryptedMsg = "AwgANYTHINGf87ge45ge7gr*/rg5ganything4gr41rrgr4re55tanythingmcsXUkhDv0UePj922kgf+"; @@ -471,12 +472,15 @@ public class OlmGroupSessionTest { assertTrue("Exception in test19TestErrorMessageReturnedInDecrypt, Exception code=" + e.getExceptionCode(), false); } - String decryptedMessage = bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg, index, errorMsg); + String exceptionMessage = null; + try { + bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg); + } catch (OlmInboundGroupSession.DecryptMessageException e) { + exceptionMessage = e.getMessage(); + } + assertTrue(0!=EXPECTED_ERROR_MESSAGE.length()); - assertTrue(EXPECTED_ERROR_MESSAGE.equals(errorMsg.toString())); - assertTrue(null==decryptedMessage); - assertTrue(0==index.mIndex); + assertTrue(EXPECTED_ERROR_MESSAGE.equals(exceptionMessage)); } - } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index b25d865..099f2a5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -53,12 +53,8 @@ public class OlmSessionTest { @BeforeClass public static void setUpClass(){ - // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, - // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 - boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; - // load native lib - mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); + mOlmManager = new OlmManager(); String version = mOlmManager.getOlmLibVersion(); assertNotNull(version); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 9a97205..e3ca544 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -44,12 +44,8 @@ public class OlmUtilityTest { @BeforeClass public static void setUpClass(){ - // enable UTF-8 specific conversion for pre Marshmallow(23) android versions, - // due to issue described here: https://github.com/eclipsesource/J2V8/issues/142 - boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23; - // load native lib - mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); + mOlmManager = new OlmManager(); String version = mOlmManager.getOlmLibVersion(); assertNotNull(version); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 2e32a30..61d0ec6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -42,13 +42,25 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri private transient long mNativeId; /** - * Wrapper class to be used in {@link #decryptMessage(String, DecryptIndex, StringBuffer)} + * Result in {@link #decryptMessage(String)} */ - static public class DecryptIndex { + static class DecryptMessageResult { + /** decrypt message **/ + public String mDecryptedMessage; + /** decrypt index **/ public long mIndex; } + /** + * Exception triggered in {@link #decryptMessage(String)} + */ + static public class DecryptMessageException extends Exception { + public DecryptMessageException(String message) { + super(message); + } + } + /** * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. @@ -59,7 +71,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { if(createNewSession()) { - if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { + if (0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { releaseSession();// prevent memory leak before throwing throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION,OlmException.EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION); } @@ -137,24 +149,24 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * Decrypt the message passed in parameter.
* In case of error, null is returned and an error message description is provided in aErrorMsg. * @param aEncryptedMsg the message to be decrypted - * @param aDecryptIndex_out decrypted message index - * @param aErrorMsg error message description - * @return the decrypted message if operation succeed, null otherwise. + * @return the decrypted message information + * @exception DecryptMessageException if there is an error while */ - public String decryptMessage(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, StringBuffer aErrorMsg) { - String decryptedMessage = null; + public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws DecryptMessageException { + DecryptMessageResult result = new DecryptMessageResult(); - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## decryptMessage(): invalid parameter - aErrorMsg=null"); - } else { - aErrorMsg.setLength(0); - decryptedMessage = decryptMessageJni(aEncryptedMsg, aDecryptIndex_out, aErrorMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); + StringBuffer errorMsg = new StringBuffer(); + result.mDecryptedMessage = decryptMessageJni(aEncryptedMsg, result, errorMsg); + + // check if there is an error while decrypting + if (0 != errorMsg.length()) { + throw new DecryptMessageException(errorMsg.toString()); } - return decryptedMessage; + + return result; } - private native String decryptMessageJni(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, StringBuffer aErrorMsg, boolean aIsUtf8ConversionRequired); + private native String decryptMessageJni(String aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg); /** * Kick off the serialization mechanism. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 57170c4..1605392 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -26,17 +26,11 @@ import android.util.Log; public class OlmManager { private static final String LOG_TAG = "OlmManager"; private static final String SDK_OLM_VERSION = "V0.1.0_1"; - /** specific flag to enable UTF-8 specific conversion for pre Marshmallow(23) android versions.
- * NDK NewStringUTF() UTF8 issue - **/ - public static boolean ENABLE_STRING_UTF8_SPECIFIC_CONVERSION; /** * Constructor. - * @param aIsUtf8SpecificConversionEnabled true to enable JNI specific UTF-8 conversion, false otherwie */ - public OlmManager(boolean aIsUtf8SpecificConversionEnabled) { - ENABLE_STRING_UTF8_SPECIFIC_CONVERSION = aIsUtf8SpecificConversionEnabled; + public OlmManager() { } static { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 23b2091..faf092e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -351,10 +351,10 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @return the decrypted message if operation succeed, null otherwise */ public String decryptMessage(OlmMessage aEncryptedMsg) { - return decryptMessageJni(aEncryptedMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); + return decryptMessageJni(aEncryptedMsg); } - private native String decryptMessageJni(OlmMessage aEncryptedMsg, boolean aIsUtf8ConversionRequired); + private native String decryptMessageJni(OlmMessage aEncryptedMsg); /** * Return true the object resources have been released.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 535fd48..8a56a12 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -183,7 +183,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg, jboolean aIsUtf8ConversionRequired) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptionResult, jobject aErrorMsg) { jstring decryptedMsgRetValue = 0; OlmInboundGroupSession *sessionPtr = NULL; @@ -204,7 +204,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); } - else if (!aDecryptIndex) + else if (!aDecryptionResult) { LOGE(" ## decryptMessageJni(): failure - invalid index object"); } @@ -224,7 +224,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } - else if (!(indexObjJClass = env->GetObjectClass(aDecryptIndex))) + else if (!(indexObjJClass = env->GetObjectClass(aDecryptionResult))) { LOGE("## decryptMessageJni(): failure - unable to get index class"); } @@ -296,28 +296,18 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * else { // update index - env->SetLongField(aDecryptIndex, indexMsgFieldId, (jlong)messageIndex); + env->SetLongField(aDecryptionResult, indexMsgFieldId, (jlong)messageIndex); - // UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) - if (aIsUtf8ConversionRequired) + // convert to utf8 + decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); + + if (!decryptedMsgRetValue) { - decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); - if(0 == decryptedMsgRetValue) - { - LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); - } - else - { - LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); - } + LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); } else { - // update decrypted buffer size - plainTextMsgPtr[plaintextLength] = static_cast('\0'); - - LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), (char*)plainTextMsgPtr); - decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr); + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 132af43..7060df4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -34,7 +34,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg, jboolean aIsUtf8ConversionRequired); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg); // serialization JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 28edae1..0797ae6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -580,7 +580,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz * @param aEncryptedMsg message to decrypt * @return decrypted message if operation succeed, null otherwise */ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg, jboolean aIsUtf8ConversionRequired) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) { jstring decryptedMsgRetValue = 0; jclass encryptedMsgJClass = 0; @@ -668,26 +668,15 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } else { - // UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) - if (aIsUtf8ConversionRequired) + decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); + + if (!decryptedMsgRetValue) { - decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); - if(0 == decryptedMsgRetValue) - { - LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); - } - else - { - LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); - } + LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); } else { - // update decrypted buffer size - plainTextMsgPtr[plaintextLength] = static_cast('\0'); - - LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(plaintextLength), (char*)(plainTextMsgPtr)); - decryptedMsgRetValue = env->NewStringUTF((const char*)(plainTextMsgPtr)); + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); } } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index a43ce3a..22005d9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -45,7 +45,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *e // encrypt/decrypt JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg, jboolean aIsUtf8ConversionRequired); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); -- cgit v1.2.3 From 5e948b1ac42ad44c0207d00144d32e1611ccf7a6 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 11:04:06 +0100 Subject: Add exception checks --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 767fad4..c649d32 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -62,7 +62,7 @@ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) newObj = env->NewObject(cls, constructor); jbyteArray tempByteArray = env->NewByteArray(bufferLen); - if (newObj && tempByteArray) + if (newObj && tempByteArray && !env->ExceptionOccurred()) { env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); -- cgit v1.2.3 From e7c7d77a8a170ed9b85eb8b6ccc060ff09e63f24 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 11:04:22 +0100 Subject: Comments update --- .../OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java index e005fcf..08db993 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java @@ -28,7 +28,7 @@ public class OlmMessage { /** normal message type **/ public final static int MESSAGE_TYPE_MESSAGE = 1; - /** the encrypted message (ie. )**/ + /** the encrypted message **/ public String mCipherText; /** defined by {@link #MESSAGE_TYPE_MESSAGE} or {@link #MESSAGE_TYPE_PRE_KEY}**/ -- cgit v1.2.3 From de962ef8d7f0dd447274dc88d9630caa6614379b Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 11:38:43 +0100 Subject: encryptMessage : the UTF8 conversion is done on JAVA side. --- .../main/java/org/matrix/olm/OlmOutboundGroupSession.java | 8 ++++++-- .../olm-sdk/src/main/jni/olm_outbound_group_session.cpp | 12 ++++++------ .../olm-sdk/src/main/jni/olm_outbound_group_session.h | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 4c09313..7278d0f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -235,12 +235,16 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser String retValue = null; if(!TextUtils.isEmpty(aClearMsg)) { - retValue = encryptMessageJni(aClearMsg); + try { + retValue = encryptMessageJni(aClearMsg.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## encryptMessage() failed " + e.getMessage()); + } } return retValue; } - private native String encryptMessageJni(String aClearMsg); + private native String encryptMessageJni(byte[] aClearMsgBuffer); /** * Return true the object resources have been released.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 2dad00a..3ee3db7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -262,30 +262,30 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env } -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg) +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) { LOGD("## encryptMessageJni(): IN"); jstring encryptedMsgRetValue = 0; OlmOutboundGroupSession *sessionPtr = NULL; - const char *clearMsgPtr = NULL; + jbyte* clearMsgPtr = NULL; if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## encryptMessageJni(): failure - invalid outbound group session ptr=NULL"); } - else if (!aClearMsg) + else if (!aClearMsgBuffer) { LOGE(" ## encryptMessageJni(): failure - invalid clear message"); } - else if (!(clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) + else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, NULL))) { LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM"); } else { // get clear message length - size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg); + size_t clearMsgLength = (size_t)env->GetArrayLength(aClearMsgBuffer); LOGD(" ## encryptMessageJni(): clearMsgLength=%lu",static_cast(clearMsgLength)); // compute max encrypted length @@ -325,7 +325,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv // free alloc if (clearMsgPtr) { - env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr); + env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); } return encryptedMsgRetValue; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 2fc44f8..f7e8a21 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -37,7 +37,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsgPtr); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); // serialization JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -- cgit v1.2.3 From 765647cda501b53bac990332444aadc4404fe314 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 14:14:56 +0100 Subject: There is more GetStringUTFChars call. --- .../src/main/java/org/matrix/olm/OlmAccount.java | 30 +++-- .../org/matrix/olm/OlmInboundGroupSession.java | 44 ++++--- .../org/matrix/olm/OlmOutboundGroupSession.java | 28 +++-- .../src/main/java/org/matrix/olm/OlmSession.java | 94 ++++++++++----- .../src/main/java/org/matrix/olm/OlmUtility.java | 32 +++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 36 +++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 4 +- .../src/main/jni/olm_inbound_group_session.cpp | 62 +++++----- .../src/main/jni/olm_inbound_group_session.h | 8 +- .../src/main/jni/olm_outbound_group_session.cpp | 34 +++--- .../src/main/jni/olm_outbound_group_session.h | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 132 ++++++++++----------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 16 +-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 40 +++---- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 4 +- 15 files changed, 322 insertions(+), 246 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 2d91634..5c1ad3c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -117,12 +117,17 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); } else { aErrorMsg.setLength(0); - pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + try { + pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); + } catch (Exception e) { + Log.e(LOG_TAG, "## serializeDataWithKey() failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } } return pickleRetValue; } - private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); /** @@ -138,23 +143,28 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { boolean retCode = false; String jniError; - if(null == aErrorMsg) { + if (null == aErrorMsg) { Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); } else { aErrorMsg.setLength(0); - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { - retCode = true; - } else { - aErrorMsg.append(jniError); + try { + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## initWithSerializedData() failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); } } return retCode; } - private native String initWithSerializedDataJni(String aSerializedData, String aKey); + private native String initWithSerializedDataJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); /** * Getter on the account ID. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 61d0ec6..7ec5b2f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -127,12 +127,16 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri if(TextUtils.isEmpty(aSessionKey)){ Log.e(LOG_TAG, "## initInboundGroupSessionWithSessionKey(): invalid session key"); } else { - retCode = initInboundGroupSessionWithSessionKeyJni(aSessionKey); + try { + retCode = initInboundGroupSessionWithSessionKeyJni(aSessionKey.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## initInboundGroupSessionWithSessionKey() failed " + e.getMessage()); + } } return retCode; } - private native int initInboundGroupSessionWithSessionKeyJni(String aSessionKey); + private native int initInboundGroupSessionWithSessionKeyJni(byte[] aSessionKeyBuffer); /** @@ -156,7 +160,11 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri DecryptMessageResult result = new DecryptMessageResult(); StringBuffer errorMsg = new StringBuffer(); - result.mDecryptedMessage = decryptMessageJni(aEncryptedMsg, result, errorMsg); + try { + result.mDecryptedMessage = decryptMessageJni(aEncryptedMsg.getBytes("UTF-8"), result, errorMsg); + } catch (Exception e) { + Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage()); + } // check if there is an error while decrypting if (0 != errorMsg.length()) { @@ -166,7 +174,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return result; } - private native String decryptMessageJni(String aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg); + private native String decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg); /** * Kick off the serialization mechanism. @@ -217,7 +225,11 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); } else { aErrorMsg.setLength(0); - pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + try { + pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); + } catch (Exception e) { + Log.e(LOG_TAG, "## serializeDataWithKey() failed " + e.getMessage()); + } } return pickleRetValue; @@ -228,7 +240,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); /** @@ -248,13 +260,17 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); } else { aErrorMsg.setLength(0); - - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { - retCode = true; - } else { - aErrorMsg.append(jniError); + try { + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## initWithSerializedData() failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); } } @@ -266,7 +282,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @param aKey key used to encrypted in {@link #serializeDataWithKey(String, StringBuffer)} * @return null if operation succeed, an error message if operation failed */ - private native String initWithSerializedDataJni(String aSerializedData, String aKey); + private native String initWithSerializedDataJni(byte[] aSerializedData, byte[] aKey); /** * Return true the object resources have been released.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 7278d0f..bfb2cd1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -109,12 +109,17 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); } else { aErrorMsg.setLength(0); - pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + try { + pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); + } catch (Exception e) { + Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } } return pickleRetValue; } - private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); /** @@ -135,18 +140,23 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } else { aErrorMsg.setLength(0); - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { - retCode = true; - } else { - aErrorMsg.append(jniError); + try { + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## initWithSerializedData(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); } } return retCode; } - private native String initWithSerializedDataJni(String aSerializedData, String aKey); + private native String initWithSerializedDataJni(byte[] aSerializedData, byte[] aKey); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index faf092e..7b9b736 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -97,12 +97,17 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); } else { aErrorMsg.setLength(0); - pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + try { + pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); + } catch (Exception e) { + Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } } return pickleRetValue; } - private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); /** @@ -123,18 +128,23 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } else { aErrorMsg.setLength(0); - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { - retCode = true; - } else { - aErrorMsg.append(jniError); + try { + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## initWithSerializedData(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); } } return retCode; } - private native String initWithSerializedDataJni(String aSerializedData, String aKey); + private native String initWithSerializedDataJni(byte[] aSerializedData, byte[] aKey); /** * Getter on the session ID. @@ -215,43 +225,50 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { if((null==aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)){ Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); } else { - retCode = initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey); + try { + retCode = initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## initOutboundSessionWithAccount(): " + e.getMessage()); + } } return retCode; } - private native int initOutboundSessionJni(long aOlmAccountId, String aTheirIdentityKey, String aTheirOneTimeKey); - + private native int initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey); /** * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY message ({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}).
- * Public API for {@link #initInboundSessionJni(long, String)}. + * Public API for {@link #initInboundSessionJni(long, byte[])}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session * @param aPreKeyMsg PRE KEY message * @return 0 if operation succeed, -1 otherwise */ public int initInboundSessionWithAccount(OlmAccount aAccount, String aPreKeyMsg) { - int retCode=-1; + int retCode = -1; - if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ + if ((null == aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - retCode = initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg); + try { + retCode = initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## initInboundSessionWithAccount(): " + e.getMessage()); + } } return retCode; } - private native int initInboundSessionJni(long aOlmAccountId, String aOneTimeKeyMsg); + private native int initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg); /** * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message based on the sender identity key.
- * Public API for {@link #initInboundSessionFromIdKeyJni(long, String, String)}. + * Public API for {@link #initInboundSessionFromIdKeyJni(long, byte[], byte[])}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * This method must only be called the first time a pre-key message is received from an inbound session. * @param aAccount the account to associate with this session @@ -265,13 +282,17 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - retCode = initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg); + try { + retCode = initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## initInboundSessionWithAccountFrom(): " + e.getMessage()); + } } return retCode; } - private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, String aTheirIdentityKey, String aOneTimeKeyMsg); + private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); /** * Get the session identifier.
Will be the same for both ends of the @@ -289,26 +310,29 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { /** * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * Public API for {@link #matchesInboundSessionJni(String)}. + * Public API for {@link #matchesInboundSessionJni(byte[])}. * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise */ public boolean matchesInboundSession(String aOneTimeKeyMsg) { boolean retCode = false; - if(0 == matchesInboundSessionJni(aOneTimeKeyMsg)){ - retCode = true; + try { + retCode = (0 == matchesInboundSessionJni(aOneTimeKeyMsg.getBytes("UTF-8"))); + } catch (Exception e) { + Log.e(LOG_TAG, "## matchesInboundSession(): failed " + e.getMessage()); } + return retCode; } - private native int matchesInboundSessionJni(String aOneTimeKeyMsg); + private native int matchesInboundSessionJni(byte[] aOneTimeKeyMsg); /** * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session based on the sender identity key.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * Public API for {@link #matchesInboundSessionJni(String)}. + * Public API for {@link #matchesInboundSessionJni(byte[])}. * @param aTheirIdentityKey the sender identity key * @param aOneTimeKeyMsg PRE KEY message * @return this if operation succeed, null otherwise @@ -316,33 +340,41 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) { boolean retCode = false; - if(0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey, aOneTimeKeyMsg)){ - retCode = true; + try { + retCode = (0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey.getBytes("UTF-8"), aOneTimeKeyMsg.getBytes("UTF-8"))); + } catch (Exception e) { + Log.e(LOG_TAG, "## matchesInboundSessionFrom(): failed " + e.getMessage()); } + return retCode; } - private native int matchesInboundSessionFromIdKeyJni(String aTheirIdentityKey, String aOneTimeKeyMsg); + private native int matchesInboundSessionFromIdKeyJni(byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); /** * Encrypt a message using the session.
* The encrypted message is returned in a OlmMessage object. - * Public API for {@link #encryptMessageJni(String, OlmMessage)}. + * Public API for {@link #encryptMessageJni(byte[], OlmMessage)}. * @param aClearMsg message to encrypted * @return the encrypted message if operation succeed, null otherwise */ public OlmMessage encryptMessage(String aClearMsg) { OlmMessage encryptedMsgRetValue = new OlmMessage(); - if (0 != encryptMessageJni(aClearMsg, encryptedMsgRetValue)){ + try { + if (0 != encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue)) { + encryptedMsgRetValue = null; + } + } catch (Exception e) { + Log.e(LOG_TAG, "## encryptMessage(): failed " + e.getMessage()); encryptedMsgRetValue = null; } return encryptedMsgRetValue; } - private native int encryptMessageJni(String aClearMsg, OlmMessage aEncryptedMsg); + private native int encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); /** * Decrypt a message using the session.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 8db9dca..3d9d99d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -82,13 +82,17 @@ public class OlmUtility { } else { aError.setLength(0); - if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { - Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); - aError.append("JAVA sanity check failure - invalid input parameters"); - } else if (null == (jniError = verifyEd25519SignatureJni(aSignature, aFingerprintKey, aMessage))) { - retCode = true; - } else { - aError.append(jniError); + try { + if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); + aError.append("JAVA sanity check failure - invalid input parameters"); + } else if (null == (jniError = verifyEd25519SignatureJni(aSignature.getBytes("UTF-8"), aFingerprintKey.getBytes("UTF-8"), aMessage.getBytes("UTF-8")))) { + retCode = true; + } else { + aError.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): failed " + e.getMessage()); } } @@ -103,7 +107,7 @@ public class OlmUtility { * @param aMessage the signed message * @return null if validation succeed, the error message string if operation failed */ - private native String verifyEd25519SignatureJni(String aSignature, String aFingerprintKey, String aMessage); + private native String verifyEd25519SignatureJni(byte[] aSignature, byte[] aFingerprintKey, byte[] aMessage); /** @@ -115,14 +119,18 @@ public class OlmUtility { public String sha256(String aMessageToHash) { String hashRetValue = null; - if(null != aMessageToHash){ - hashRetValue = sha256Jni(aMessageToHash); + if (null != aMessageToHash) { + try { + hashRetValue = sha256Jni(aMessageToHash.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## sha256(): failed " + e.getMessage()); + } } return hashRetValue; - } - private native String sha256Jni(String aMessage); + + private native String sha256Jni(byte[] aMessage); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index a44d9db..87ed86a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -468,22 +468,22 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz /** * Serialize and encrypt account instance into a base64 string.
-* @param aKey key used to encrypt the serialized account data +* @param aKeyBuffer key used to encrypt the serialized account data * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; jstring errorJstring = 0; - const char *keyPtr = NULL; + jbyte* keyPtr = NULL; OlmAccount* accountPtr = NULL; LOGD("## serializeDataWithKeyJni(): IN"); - if (!aKey) + if (!aKeyBuffer) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } @@ -503,14 +503,14 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, NULL))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_account_length(accountPtr); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); @@ -552,27 +552,27 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } return pickledDataRetValue; } -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmAccount* accountPtr = NULL; jstring errorMessageRetValue = 0; - const char *keyPtr = NULL; - const char *pickledPtr = NULL; + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; LOGD("## initWithSerializedDataJni(): IN"); - if (!aKey) + if (!aKeyBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if (!aSerializedData) + else if (!aSerializedDataBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } @@ -580,18 +580,18 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j { LOGE(" ## initWithSerializedDataJni(): failure - account failure OOM"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } else { - size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -616,12 +616,12 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } if (pickledPtr) { - env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } return errorMessageRetValue; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 7e09403..88ef215 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -47,8 +47,8 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); // serialization -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg); +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 8a56a12..9eba3af 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -86,11 +86,11 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * * @param aSessionKey session key from an outbound session * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey) +JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) { jint retCode = ERROR_CODE_KO; OlmInboundGroupSession *sessionPtr = NULL; - const uint8_t *sessionKeyPtr = NULL; + jbyte* sessionKeyPtr = NULL; size_t sessionResult; LOGD("## initInboundGroupSessionWithSessionKeyJni(): inbound group session IN"); @@ -99,20 +99,20 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes { LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance"); } - else if (!aSessionKey) + else if (!aSessionKeyBuffer) { LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); } - else if (!(sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0))) + else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) { LOGE(" ## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); } else { - size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey); + size_t sessionKeyLength = (size_t)env->GetArrayLength(aSessionKeyBuffer); LOGD(" ## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); - sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength); + sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); if (sessionResult == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); @@ -127,7 +127,7 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes // free local alloc if (sessionKeyPtr) { - env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr); + env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); } return retCode; @@ -183,11 +183,11 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptionResult, jobject aErrorMsg) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult, jobject aErrorMsg) { jstring decryptedMsgRetValue = 0; OlmInboundGroupSession *sessionPtr = NULL; - const char *encryptedMsgPtr = NULL; + jbyte *encryptedMsgPtr = NULL; jclass indexObjJClass = 0; jfieldID indexMsgFieldId; jclass errorMsgJClass = 0; @@ -200,7 +200,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); } - else if (!aEncryptedMsg) + else if (!aEncryptedMsgBuffer) { LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); } @@ -220,7 +220,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * { LOGE(" ## decryptMessageJni(): failure - unable to get error method ID"); } - else if (!(encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0))) + else if (!(encryptedMsgPtr = env->GetByteArrayElements(aEncryptedMsgBuffer, 0))) { LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); } @@ -235,7 +235,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * else { // get encrypted message length - size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg); + size_t encryptedMsgLength = (size_t)env->GetArrayLength(aEncryptedMsgBuffer); uint8_t *tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); // create a dedicated temp buffer to be used in next Olm API calls @@ -327,7 +327,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * // free alloc if (encryptedMsgPtr) { - env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr); + env->ReleaseByteArrayElements(aEncryptedMsgBuffer, encryptedMsgPtr, JNI_ABORT); } return decryptedMsgRetValue; @@ -336,16 +336,16 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * /** * Serialize and encrypt session instance into a base64 string.
-* @param aKey key used to encrypt the serialized session data +* @param aKeyBuffer key used to encrypt the serialized session data * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; - const char *keyPtr = NULL; + jbyte* keyPtr = NULL; OlmInboundGroupSession* sessionPtr = NULL; LOGD("## inbound group session serializeDataWithKeyJni(): IN"); @@ -354,7 +354,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN { LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); } - else if (!aKey) + else if (!aKeyBuffer) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } @@ -370,14 +370,14 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_inbound_group_session_length(sessionPtr); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); @@ -421,19 +421,19 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } return pickledDataRetValue; } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmInboundGroupSession* sessionPtr = NULL; jstring errorMessageRetValue = 0; - const char *keyPtr = NULL; - const char *pickledPtr = NULL; + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; LOGD("## initWithSerializedDataJni(): IN"); @@ -441,26 +441,26 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( { LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); } - else if (!aKey) + else if (!aKeyBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if (!aSerializedData) + else if (!aSerializedDataBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } else { - size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -485,12 +485,12 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } if (pickledPtr) { - env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } return errorMessageRetValue; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 7060df4..af763f4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -32,13 +32,13 @@ extern "C" { JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); +JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg); // serialization -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 3ee3db7..0ccc6e8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -338,13 +338,13 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; jstring errorJstring = 0; - const char *keyPtr = NULL; + jbyte* keyPtr = NULL; OlmOutboundGroupSession* sessionPtr = NULL; LOGD("## outbound group session serializeDataWithKeyJni(): IN"); @@ -353,7 +353,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J { LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); } - else if (!aKey) + else if (!aKeyBuffer) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } @@ -369,14 +369,14 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_outbound_group_session_length(sessionPtr); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); @@ -418,19 +418,19 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } return pickledDataRetValue; } -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmOutboundGroupSession* sessionPtr = NULL; jstring errorMessageRetValue = 0; - const char *keyPtr = NULL; - const char *pickledPtr = NULL; + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; LOGD("## initWithSerializedDataJni(): IN"); @@ -438,26 +438,26 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) { LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); } - else if (!aKey) + else if (!aKeyBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if (!aSerializedData) + else if (!aSerializedDataBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } else { - size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -482,12 +482,12 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } if (pickledPtr) { - env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } return errorMessageRetValue; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index f7e8a21..43ec4f7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -40,8 +40,8 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); // serialization -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 0797ae6..491795f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -107,7 +107,7 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi * @param aTheirOneTimeKey the one time key of the recipient * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) { jint retCode = ERROR_CODE_KO; OlmSession* sessionPtr = NULL; @@ -121,7 +121,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject { LOGE("## initOutboundSessionJni(): failure - invalid Account ptr=NULL"); } - else if (!aTheirIdentityKey || !aTheirOneTimeKey) + else if (!aTheirIdentityKeyBuffer || !aTheirOneTimeKeyBuffer) { LOGE("## initOutboundSessionJni(): failure - invalid keys"); } @@ -138,22 +138,22 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject } else { - const char* theirIdentityKeyPtr = NULL; - const char* theirOneTimeKeyPtr = NULL; + jbyte* theirIdentityKeyPtr = NULL; + jbyte* theirOneTimeKeyPtr = NULL; // convert identity & one time keys to C strings - if (!(theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) { LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM"); } - else if (!(theirOneTimeKeyPtr = env->GetStringUTFChars(aTheirOneTimeKey, 0))) + else if (!(theirOneTimeKeyPtr = env->GetByteArrayElements(aTheirOneTimeKeyBuffer, 0))) { LOGE("## initOutboundSessionJni(): failure - one time Key JNI allocation OOM"); } else { - size_t theirIdentityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); - size_t theirOneTimeKeyLength = (size_t)env->GetStringUTFLength(aTheirOneTimeKey); + size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); + size_t theirOneTimeKeyLength = (size_t)env->GetArrayLength(aTheirOneTimeKeyBuffer); LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr); size_t sessionResult = olm_create_outbound_session(sessionPtr, @@ -176,12 +176,12 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject if (theirIdentityKeyPtr) { - env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); } if (theirOneTimeKeyPtr) { - env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr); + env->ReleaseByteArrayElements(aTheirOneTimeKeyBuffer, theirOneTimeKeyPtr, JNI_ABORT); } if (randomBuffPtr) @@ -205,7 +205,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject * @param aOneTimeKeyMsg PRE_KEY message * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; @@ -220,13 +220,13 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject { LOGE("## initInboundSessionJni(): failure - invalid Account ptr=NULL"); } - else if (!aOneTimeKeyMsg) + else if (!aOneTimeKeyMsgBuffer) { LOGE("## initInboundSessionJni(): failure - invalid message"); } else { - const char *messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0); + jbyte* messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0); if (!messagePtr) { @@ -234,7 +234,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject } else { - size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); LOGD("## initInboundSessionJni(): messageLength=%lu message=%s", static_cast(messageLength), messagePtr); sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); @@ -250,7 +250,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject } // free local alloc - env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); } } return retCode; @@ -264,13 +264,13 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject * @param aOneTimeKeyMsg encrypted message * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; OlmAccount *accountPtr = NULL; - const char *messagePtr = NULL; - const char *theirIdentityKeyPtr = NULL; + jbyte *messagePtr = NULL; + jbyte *theirIdentityKeyPtr = NULL; size_t sessionResult; if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) @@ -281,26 +281,26 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Account ptr=NULL"); } - else if (!aTheirIdentityKey) + else if (!aTheirIdentityKeyBuffer) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); } - else if (!aOneTimeKeyMsg) + else if (!aOneTimeKeyMsgBuffer) { LOGE("## initInboundSessionJni(): failure - invalid one time key message"); } - else if (!(messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - message JNI allocation OOM"); } - else if(!(theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + else if(!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); } else { - size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); - size_t theirIdentityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); + size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); LOGD("## initInboundSessionFromIdKeyJni(): message=%s messageLength=%lu",messagePtr,static_cast(messageLength)); @@ -319,12 +319,12 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, // free local alloc if (messagePtr) { - env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); } if (theirIdentityKeyPtr) { - env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); } return retCode; @@ -336,27 +336,27 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, * @param aOneTimeKeyMsg PRE KEY message * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; - const char *messagePtr = NULL; + jbyte *messagePtr = NULL; if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## matchesInboundSessionJni(): failure - invalid Session ptr=NULL"); } - else if (!aOneTimeKeyMsg) + else if (!aOneTimeKeyMsgBuffer) { LOGE("## matchesInboundSessionJni(): failure - invalid one time key message"); } - else if (!(messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) { LOGE("## matchesInboundSessionJni(): failure - one time key JNI allocation OOM"); } else { - size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); //if(matchResult == olm_error()) { @@ -374,7 +374,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje // free local alloc if (messagePtr) { - env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); } return retCode; @@ -388,37 +388,37 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje * @param aOneTimeKeyMsg PRE KEY message * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise */ -JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg) +JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; - const char *messagePtr = NULL; - const char *theirIdentityKeyPtr = NULL; + jbyte *messagePtr = NULL; + jbyte *theirIdentityKeyPtr = NULL; if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); } - else if (!aTheirIdentityKey) + else if (!aTheirIdentityKeyBuffer) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); } - else if (!(theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0))) + else if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); } - else if (!aOneTimeKeyMsg) + else if (!aOneTimeKeyMsgBuffer) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid one time key message"); } - else if (!(messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0))) + else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - one time key JNI allocation OOM"); } else { - size_t identityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey); - size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg); + size_t identityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); //if(matchResult == olm_error()) { @@ -437,12 +437,12 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J // free local alloc if (theirIdentityKeyPtr) { - env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr); + env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); } if (messagePtr) { - env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr); + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); } return retCode; @@ -455,11 +455,11 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J * @param [out] aEncryptedMsg ciphered message * @return ERROR_CODE_OK if encrypt operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; - const char *clearMsgPtr = NULL; + jbyte *clearMsgPtr = NULL; jclass encryptedMsgJClass = 0; jfieldID encryptedMsgFieldId; jfieldID typeMsgFieldId; @@ -470,7 +470,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz { LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); } - else if (!aClearMsg) + else if (!aClearMsgBuffer) { LOGE("## encryptMessageJni(): failure - invalid clear message"); } @@ -478,7 +478,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz { LOGE("## encryptMessageJni(): failure - invalid encrypted message"); } - else if (!(clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0))) + else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, 0))) { LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM"); } @@ -514,7 +514,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz else { // alloc buffer for encrypted message - size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg); + size_t clearMsgLength = (size_t)env->GetArrayLength(aClearMsgBuffer); size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); void *encryptedMsgPtr = malloc((encryptedMsgLength+1)*sizeof(uint8_t)); @@ -569,7 +569,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz // free alloc if (clearMsgPtr) { - env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr); + env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); } return retCode; @@ -760,13 +760,13 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; jstring errorJstring = 0; - const char *keyPtr = NULL; + jbyte* keyPtr = NULL; OlmSession* sessionPtr = NULL; LOGD("## serializeDataWithKeyJni(): IN"); @@ -775,7 +775,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job { LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); } - else if (!aKey) + else if (!aKeyBuffer) { LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); } @@ -791,14 +791,14 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job { LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_session_length(sessionPtr); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); @@ -840,19 +840,19 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } return pickledDataRetValue; } -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmSession* sessionPtr = NULL; jstring errorMessageRetValue = 0; - const char *keyPtr = NULL; - const char *pickledPtr = NULL; + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; LOGD("## initWithSerializedDataJni(): IN"); @@ -860,26 +860,26 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j { LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); } - else if (!aKey) + else if (!aKeyBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); } - else if (!aSerializedData) + else if (!aSerializedDataBuffer) { LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); } - else if (!(pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); } else { - size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); @@ -905,12 +905,12 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j // free alloc if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } if (pickledPtr) { - env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } return errorMessageRetValue; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 22005d9..b18ac86 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -33,25 +33,25 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); // outbound session -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey); // inbound sessions: establishment based on PRE KEY message -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg); -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // match inbound sessions: based on PRE KEY message -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg); -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // encrypt/decrypt -JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); // serialization -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 8a7607c..584e83e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -85,13 +85,13 @@ JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz * @param aMessage the message which was signed * @return 0 if validation succeed, an error message string if operation failed */ -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage) +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignatureBuffer, jbyteArray aKeyBuffer, jbyteArray aMessageBuffer) { jstring errorMessageRetValue = 0; OlmUtility* utilityPtr = NULL; - const char* signaturePtr = NULL; - const char* keyPtr = NULL; - const char* messagePtr = NULL; + jbyte* signaturePtr = NULL; + jbyte* keyPtr = NULL; + jbyte* messagePtr = NULL; LOGD("## verifyEd25519SignatureJni(): IN"); @@ -99,27 +99,27 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j { LOGE(" ## verifyEd25519SignatureJni(): failure - invalid utility ptr=NULL"); } - else if (!aSignature || !aKey || !aMessage) + else if (!aSignatureBuffer || !aKeyBuffer || !aMessageBuffer) { LOGE(" ## verifyEd25519SignatureJni(): failure - invalid input parameters "); } - else if (!(signaturePtr = env->GetStringUTFChars(aSignature, 0))) + else if (!(signaturePtr = env->GetByteArrayElements(aSignatureBuffer, 0))) { LOGE(" ## verifyEd25519SignatureJni(): failure - signature JNI allocation OOM"); } - else if (!(keyPtr = env->GetStringUTFChars(aKey, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## verifyEd25519SignatureJni(): failure - key JNI allocation OOM"); } - else if (!(messagePtr = env->GetStringUTFChars(aMessage, 0))) + else if (!(messagePtr = env->GetByteArrayElements(aMessageBuffer, 0))) { LOGE(" ## verifyEd25519SignatureJni(): failure - message JNI allocation OOM"); } else { - size_t signatureLength = (size_t)env->GetStringUTFLength(aSignature); - size_t keyLength = (size_t)env->GetStringUTFLength(aKey); - size_t messageLength = (size_t)env->GetStringUTFLength(aMessage); + size_t signatureLength = (size_t)env->GetArrayLength(aSignatureBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + size_t messageLength = (size_t)env->GetArrayLength(aMessageBuffer); LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",static_cast(signatureLength),static_cast(keyLength),static_cast(messageLength)); LOGD(" ## verifyEd25519SignatureJni(): key=%s",keyPtr); @@ -144,17 +144,17 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j // free alloc if (signaturePtr) { - env->ReleaseStringUTFChars(aSignature, signaturePtr); + env->ReleaseByteArrayElements(aSignatureBuffer, signaturePtr, JNI_ABORT); } if (keyPtr) { - env->ReleaseStringUTFChars(aKey, keyPtr); + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } if (messagePtr) { - env->ReleaseStringUTFChars(aMessage, messagePtr); + env->ReleaseByteArrayElements(aMessageBuffer, messagePtr, JNI_ABORT); } return errorMessageRetValue; @@ -166,11 +166,11 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j * @param aMessage * @return digest of the message if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jstring aMessageToHash) +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHashBuffer) { jstring sha256RetValue = 0; OlmUtility* utilityPtr = NULL; - const char* messagePtr = NULL; + jbyte* messagePtr = NULL; LOGD("## sha256Jni(): IN"); @@ -178,18 +178,18 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst { LOGE(" ## sha256Jni(): failure - invalid utility ptr=NULL"); } - else if(!aMessageToHash) + else if(!aMessageToHashBuffer) { LOGE(" ## sha256Jni(): failure - invalid message parameters "); } - else if(!(messagePtr = env->GetStringUTFChars(aMessageToHash, 0))) + else if(!(messagePtr = env->GetByteArrayElements(aMessageToHashBuffer, 0))) { LOGE(" ## sha256Jni(): failure - message JNI allocation OOM"); } else { // get lengths - size_t messageLength = (size_t)env->GetStringUTFLength(aMessageToHash); + size_t messageLength = (size_t)env->GetArrayLength(aMessageToHashBuffer); size_t hashLength = olm_sha256_length(utilityPtr); void* hashValuePtr = malloc((hashLength+1)*sizeof(uint8_t)); @@ -223,7 +223,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jst if (messagePtr) { - env->ReleaseStringUTFChars(aMessageToHash, messagePtr); + env->ReleaseByteArrayElements(aMessageToHashBuffer, messagePtr, JNI_ABORT); } return sha256RetValue; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index 2a534a3..7c3601d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -29,8 +29,8 @@ extern "C" { #endif JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jstring aSignature, jstring aKey, jstring aMessage); -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jstring aMessageToHash); +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignature, jbyteArray aKey, jbyteArray aMessage); +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHash); #ifdef __cplusplus } #endif -- cgit v1.2.3 From 9552e14fdadd9fadbe88970cfb8df7b697c0deb4 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 16:12:20 +0100 Subject: -> the byte[] to String conversions are done on Java level (when it is possible) -> remove javaCStringToUtf8 --- .../src/main/java/org/matrix/olm/OlmAccount.java | 40 +++++++++++------- .../org/matrix/olm/OlmInboundGroupSession.java | 24 ++++++++--- .../org/matrix/olm/OlmOutboundGroupSession.java | 25 +++++++++--- .../src/main/java/org/matrix/olm/OlmSession.java | 20 +++++++-- .../src/main/java/org/matrix/olm/OlmUtility.java | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 25 +++++++----- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 4 +- .../src/main/jni/olm_inbound_group_session.cpp | 47 +++++++++++----------- .../src/main/jni/olm_inbound_group_session.h | 6 +-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 1 - .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 42 ------------------- .../src/main/jni/olm_outbound_group_session.cpp | 37 ++++++++++------- .../src/main/jni/olm_outbound_group_session.h | 6 +-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 30 +++++++------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 12 +++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 2 +- 17 files changed, 174 insertions(+), 155 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 5c1ad3c..1e41fa1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -118,7 +118,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } else { aErrorMsg.setLength(0); try { - pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); + pickleRetValue = new String(serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## serializeDataWithKey() failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -127,7 +127,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); + private native byte[] serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); /** @@ -164,6 +164,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return retCode; } + private native String initWithSerializedDataJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); /** @@ -363,25 +364,34 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * @return the signed message if operation succeed, null otherwise */ public String signMessage(String aMessage) { - if (null == aMessage) { - return null; - } + String result = null; - byte[] utf8String = null; + if (null != aMessage) { + byte[] utf8String = null; - try { - utf8String = aMessage.getBytes("UTF-8"); - } catch (Exception e) { - Log.d(LOG_TAG,"## signMessage(): failed ="+e.getMessage()); - } + try { + utf8String = aMessage.getBytes("UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## signMessage(): failed =" + e.getMessage()); + } - if (null == utf8String) { - return null; + if (null != utf8String) { + byte[] signedMessage = signMessageJni(utf8String); + + if (null != signedMessage) { + try { + result = new String(signedMessage, "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## signMessage(): failed =" + e.getMessage()); + } + } + } } - return signMessageJni(utf8String); + return result; } - private native String signMessageJni(byte[] aMessage); + + private native byte[] signMessageJni(byte[] aMessage); /** * Return true the object resources have been released.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 7ec5b2f..bfd50fb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -144,10 +144,16 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @return the session ID if operation succeed, null otherwise */ public String sessionIdentifier() { - return sessionIdentifierJni(); + try { + return new String(sessionIdentifierJni(), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); + } + + return null; } - private native String sessionIdentifierJni(); + private native byte[] sessionIdentifierJni(); /** * Decrypt the message passed in parameter.
@@ -161,9 +167,14 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri StringBuffer errorMsg = new StringBuffer(); try { - result.mDecryptedMessage = decryptMessageJni(aEncryptedMsg.getBytes("UTF-8"), result, errorMsg); + byte[] decryptedMessageBuffer = decryptMessageJni(aEncryptedMsg.getBytes("UTF-8"), result, errorMsg); + + if (null != decryptedMessageBuffer) { + result.mDecryptedMessage = new String(decryptedMessageBuffer, "UTF-8"); + } } catch (Exception e) { Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage()); + errorMsg.append(e.getMessage()); } // check if there is an error while decrypting @@ -174,7 +185,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return result; } - private native String decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg); + private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg); /** * Kick off the serialization mechanism. @@ -226,9 +237,10 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } else { aErrorMsg.setLength(0); try { - pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); + pickleRetValue = new String(serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## serializeDataWithKey() failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); } } @@ -240,7 +252,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); + private native byte[] serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index bfb2cd1..171891c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -208,10 +208,16 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * @return session identifier if operation succeed, null otherwise. */ public String sessionIdentifier() { - return sessionIdentifierJni(); + try { + return new String(sessionIdentifierJni(), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); + } + + return null; } - private native String sessionIdentifierJni(); + private native byte[] sessionIdentifierJni(); /** * Get the current message index for this session.
@@ -231,9 +237,16 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * @return outbound session key */ public String sessionKey() { - return sessionKeyJni(); + try { + return new String(sessionKeyJni(), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionKey() failed " + e.getMessage()); + } + + return null; } - private native String sessionKeyJni(); + + private native byte[] sessionKeyJni(); /** * Encrypt some plain-text message.
@@ -246,7 +259,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser if(!TextUtils.isEmpty(aClearMsg)) { try { - retValue = encryptMessageJni(aClearMsg.getBytes("UTF-8")); + retValue = new String(encryptMessageJni(aClearMsg.getBytes("UTF-8")), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## encryptMessage() failed " + e.getMessage()); } @@ -254,7 +267,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return retValue; } - private native String encryptMessageJni(byte[] aClearMsgBuffer); + private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); /** * Return true the object resources have been released.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 7b9b736..a58036f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -302,10 +302,16 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @return the session ID as a String if operation succeed, null otherwise */ public String sessionIdentifier() { - return getSessionIdentifierJni(); + try { + return new String(getSessionIdentifierJni(), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier(): " + e.getMessage()); + } + + return null; } - private native String getSessionIdentifierJni(); + private native byte[] getSessionIdentifierJni(); /** * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.
@@ -383,10 +389,16 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @return the decrypted message if operation succeed, null otherwise */ public String decryptMessage(OlmMessage aEncryptedMsg) { - return decryptMessageJni(aEncryptedMsg); + try { + return new String(decryptMessageJni(aEncryptedMsg), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## decryptMessage(): failed " + e.getMessage()); + } + + return null; } - private native String decryptMessageJni(OlmMessage aEncryptedMsg); + private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg); /** * Return true the object resources have been released.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 3d9d99d..287a9d2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -121,7 +121,7 @@ public class OlmUtility { if (null != aMessageToHash) { try { - hashRetValue = sha256Jni(aMessageToHash.getBytes("UTF-8")); + hashRetValue = new String(sha256Jni(aMessageToHash.getBytes("UTF-8")), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## sha256(): failed " + e.getMessage()); } @@ -130,7 +130,7 @@ public class OlmUtility { return hashRetValue; } - private native String sha256Jni(byte[] aMessage); + private native byte[] sha256Jni(byte[] aMessage); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 87ed86a..06709e7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -405,10 +405,10 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, * @param aMessage message to sign * @return the signed message, null otherwise **/ -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) { OlmAccount* accountPtr = NULL; - jstring signedMsgRetValue = NULL; + jbyteArray signedMsgRetValueBuffer = NULL; if (!aMessage) { @@ -425,7 +425,8 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz // signature memory allocation size_t signatureLength = olm_account_signature_length(accountPtr); - void* signedMsgPtr = malloc((signatureLength+1)*sizeof(uint8_t)); + size_t bufferLen = signatureLength + 1; + void* signedMsgPtr = malloc(bufferLen * sizeof(uint8_t)); if (!signedMsgPtr) { @@ -448,9 +449,12 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz { // info: signatureLength is always equal to resultSign (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); - // convert to jstring - signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8 + LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); + + signedMsgRetValueBuffer = env->NewByteArray(signatureLength); + env->SetByteArrayRegion(signedMsgRetValueBuffer, 0 , signatureLength, (jbyte*)signedMsgPtr); + } free(signedMsgPtr); @@ -463,7 +467,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz } } - return signedMsgRetValue; + return signedMsgRetValueBuffer; } /** @@ -472,9 +476,9 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { - jstring pickledDataRetValue = 0; + jbyteArray pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; jstring errorJstring = 0; @@ -541,8 +545,11 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job { // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + + pickledDataRetValue = env->NewByteArray(pickledLength+1); + env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength+1, (jbyte*)pickledPtr); } free(pickledPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 88ef215..c866dbc 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -44,10 +44,10 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); // signing -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); // serialization -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg); +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg); JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); #ifdef __cplusplus diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 9eba3af..ca47dbb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -137,10 +137,10 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes /** * Get a base64-encoded identifier for this inbound group session. */ -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { OlmInboundGroupSession *sessionPtr = NULL; - jstring returnValueStr=0; + jbyteArray returnValue = 0; LOGD("## sessionIdentifierJni(): inbound group session IN"); @@ -170,22 +170,26 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn } else { - // update length + sessionIdPtr[result] = static_cast('\0'); LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); - returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); } + free(sessionIdPtr); } } - return returnValueStr; + return returnValue; } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult, jobject aErrorMsg) { - jstring decryptedMsgRetValue = 0; + jbyteArray decryptedMsgBuffer = 0; + OlmInboundGroupSession *sessionPtr = NULL; jbyte *encryptedMsgPtr = NULL; jclass indexObjJClass = 0; @@ -298,17 +302,10 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * // update index env->SetLongField(aDecryptionResult, indexMsgFieldId, (jlong)messageIndex); - // convert to utf8 - decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); + decryptedMsgBuffer = env->NewByteArray(plaintextLength); + env->SetByteArrayRegion(decryptedMsgBuffer, 0 , plaintextLength, (jbyte*)plainTextMsgPtr); - if (!decryptedMsgRetValue) - { - LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); - } - else - { - LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); - } + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); } if (plainTextMsgPtr) @@ -330,7 +327,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * env->ReleaseByteArrayElements(aEncryptedMsgBuffer, encryptedMsgPtr, JNI_ABORT); } - return decryptedMsgRetValue; + return decryptedMsgBuffer; } @@ -340,9 +337,10 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv * * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { - jstring pickledDataRetValue = 0; + jbyteArray pickledDataRet = 0; + jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; jbyte* keyPtr = NULL; @@ -408,10 +406,11 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN } else { - // build success output - (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + + pickledDataRet = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(pickledDataRet, 0 , pickledLength, (jbyte*)pickledPtr); } free(pickledPtr); @@ -424,7 +423,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JN env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } - return pickledDataRetValue; + return pickledDataRet; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index af763f4..7ed6d8b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -33,11 +33,11 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg); +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg); // serialization -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 7fea2f1..f1d124e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -74,7 +74,6 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -jstring javaCStringToUtf8(JNIEnv *env, uint8_t *aCStringMsgPtr, size_t aMsgLength); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index c649d32..9205fc0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -213,45 +213,3 @@ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); return instanceId; } - -/** -* Convert a C string into a UTF-8 format string. -* The conversion is performed in JAVA side to workaround the issue in NewStringUTF(). -* The problem is described here: https://github.com/eclipsesource/J2V8/issues/142 -*/ -jstring javaCStringToUtf8(JNIEnv *env, uint8_t *aCStringMsgPtr, size_t aMsgLength) -{ - jstring convertedRetValue = 0; - jbyteArray tempByteArray = NULL; - - if (!aCStringMsgPtr || !env) - { - LOGE("## javaCStringToUtf8(): failure - invalid parameters (null)"); - } - else if (!(tempByteArray = env->NewByteArray(aMsgLength))) - { - LOGE("## javaCStringToUtf8(): failure - return byte array OOM"); - } - else - { - env->SetByteArrayRegion(tempByteArray, 0, aMsgLength, (const jbyte*)aCStringMsgPtr); - - // UTF-8 conversion from JAVA - jstring strEncode = (env)->NewStringUTF("UTF-8"); - jclass jClass = env->FindClass("java/lang/String"); - jmethodID cstor = env->GetMethodID(jClass, "", "([BLjava/lang/String;)V"); - - if (jClass && strEncode) - { - convertedRetValue = (jstring) env->NewObject(jClass, cstor, tempByteArray, strEncode); - LOGD(" ## javaCStringToUtf8(): succeed"); - env->DeleteLocalRef(tempByteArray); - } - else - { - LOGE(" ## javaCStringToUtf8(): failure - invalid Java references"); - } - } - - return convertedRetValue; -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 0ccc6e8..211757f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -138,12 +138,13 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( /** * Get a base64-encoded identifier for this outbound group session. */ -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { LOGD("## sessionIdentifierJni(): outbound group session IN"); - OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - jstring returnValueStr=0; + OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); + jbyteArray returnValue = 0; + if (!sessionPtr) { LOGE(" ## sessionIdentifierJni(): failure - invalid outbound group session instance"); @@ -172,8 +173,11 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE { // update length sessionIdPtr[result] = static_cast('\0'); + + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",static_cast(result), reinterpret_cast(sessionIdPtr)); - returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); } // free alloc @@ -181,7 +185,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIE } } - return returnValueStr; + return returnValue; } @@ -215,11 +219,12 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, /** * Get the base64-encoded current ratchet key for this session.
*/ -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) { LOGD("## sessionKeyJni(): outbound group session IN"); + OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - jstring returnValueStr = 0; + jbyteArray returnValue = 0; if (!sessionPtr) { @@ -250,7 +255,9 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env // update length sessionKeyPtr[result] = static_cast('\0'); LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%s",static_cast(result), reinterpret_cast(sessionKeyPtr)); - returnValueStr = env->NewStringUTF((const char*)sessionKeyPtr); + + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionKeyPtr); } // free alloc @@ -258,15 +265,15 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env } } - return returnValueStr; + return returnValue; } - -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) { LOGD("## encryptMessageJni(): IN"); - jstring encryptedMsgRetValue = 0; + jbyteArray encryptedMsgRet = 0; + OlmOutboundGroupSession *sessionPtr = NULL; jbyte* clearMsgPtr = NULL; @@ -315,7 +322,9 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv encryptedMsgPtr[encryptedLength] = static_cast('\0'); LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); - encryptedMsgRetValue = env->NewStringUTF((const char*)encryptedMsgPtr); + + encryptedMsgRet = env->NewByteArray(encryptedLength); + env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedLength, (jbyte*)encryptedMsgPtr); } free(encryptedMsgPtr); @@ -328,7 +337,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); } - return encryptedMsgRetValue; + return encryptedMsgRet; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 43ec4f7..71ddb3b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -33,11 +33,11 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); // serialization JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 491795f..5ae68d0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -580,9 +580,10 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz * @param aEncryptedMsg message to decrypt * @return decrypted message if operation succeed, null otherwise */ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) { - jstring decryptedMsgRetValue = 0; + jbyteArray decryptedMsgRet = 0; + jclass encryptedMsgJClass = 0; jstring encryptedMsgJstring = 0; // <= obtained from encryptedMsgFieldId // field IDs @@ -668,16 +669,10 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } else { - decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); + decryptedMsgRet = env->NewByteArray(plaintextLength); + env->SetByteArrayRegion(decryptedMsgRet, 0 , plaintextLength, (jbyte*)plainTextMsgPtr); - if (!decryptedMsgRetValue) - { - LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null"); - } - else - { - LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); - } + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); } } } @@ -698,7 +693,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t free(plainTextMsgPtr); } - return decryptedMsgRetValue; + return decryptedMsgRet; } @@ -706,9 +701,9 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t * Get the session identifier for this session. * @return the session identifier if operation succeed, null otherwise */ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) { - jstring returnValueStr=0; + jbyteArray returnValue = 0; LOGD("## getSessionIdentifierJni(): IN "); @@ -744,13 +739,16 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job (static_cast(sessionIdPtr))[result] = static_cast('\0'); LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); - returnValueStr = env->NewStringUTF((const char*)sessionIdPtr); + + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); } + free(sessionIdPtr); } } - return returnValueStr; + return returnValue; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index b18ac86..924b439 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -45,9 +45,9 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *e // encrypt/decrypt JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); // serialization JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index 584e83e..f4a0c80 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -166,9 +166,10 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j * @param aMessage * @return digest of the message if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHashBuffer) +JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHashBuffer) { - jstring sha256RetValue = 0; + jbyteArray sha256Ret = 0; + OlmUtility* utilityPtr = NULL; jbyte* messagePtr = NULL; @@ -212,9 +213,10 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jby { // update length (static_cast(hashValuePtr))[result] = static_cast('\0'); - LOGD("## sha256Jni(): success - result=%lu hashValue=%s",static_cast(result), (char*)hashValuePtr); - sha256RetValue = env->NewStringUTF((const char*)hashValuePtr); + + sha256Ret = env->NewByteArray(result); + env->SetByteArrayRegion(sha256Ret, 0 , result, (jbyte*)hashValuePtr); } free(hashValuePtr); @@ -226,5 +228,5 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jby env->ReleaseByteArrayElements(aMessageToHashBuffer, messagePtr, JNI_ABORT); } - return sha256RetValue; + return sha256Ret; } \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index 7c3601d..16d9e7a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -30,7 +30,7 @@ extern "C" { JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignature, jbyteArray aKey, jbyteArray aMessage); -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHash); +JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHash); #ifdef __cplusplus } #endif -- cgit v1.2.3 From 45a98c20a8f0018c80b18e6bb6e04b3a6be03732 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 16:41:04 +0100 Subject: EncryptMessage triggers an exception when it fails --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 6 ++++- .../org/matrix/olm/OlmOutboundGroupSession.java | 31 ++++++++++++++++++---- .../src/main/jni/olm_outbound_group_session.cpp | 31 +++++++++++++++++++--- .../src/main/jni/olm_outbound_group_session.h | 2 +- 4 files changed, 60 insertions(+), 10 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 111032e..0f0d779 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -113,7 +113,11 @@ public class OlmGroupSessionTest { @Test public void test05OutboundGroupEncryptMessage() { // alice encrypts a message to bob - mAliceToBobMessage = mAliceOutboundGroupSession.encryptMessage(CLEAR_MESSAGE1); + try { + mAliceToBobMessage = mAliceOutboundGroupSession.encryptMessage(CLEAR_MESSAGE1); + } catch (OlmOutboundGroupSession.EncryptMessageException e) { + assertTrue("Exception in bob encryptMessage, Exception code=" + e.getMessage(), false); + } assertFalse(TextUtils.isEmpty(mAliceToBobMessage)); // test message index after encryption is incremented diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 171891c..b9c21ff 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -42,6 +42,15 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ private transient long mNativeId; + /** + * Exception triggered in {@link #encryptMessage(String)} + */ + static public class EncryptMessageException extends Exception { + public EncryptMessageException(String message) { + super(message); + } + } + /** * Constructor.
* Create and save a new session native instance ID and @@ -252,22 +261,34 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * Encrypt some plain-text message.
* The message given as parameter is encrypted and returned as the return value. * @param aClearMsg message to be encrypted - * @return the encrypted message if operation succeed, null otherwise + * @return the encrypted message + * @exception EncryptMessageException the encryption failure reason */ - public String encryptMessage(String aClearMsg) { + public String encryptMessage(String aClearMsg) throws EncryptMessageException { String retValue = null; - if(!TextUtils.isEmpty(aClearMsg)) { + if (!TextUtils.isEmpty(aClearMsg)) { + StringBuffer errorMsg = new StringBuffer(); + try { - retValue = new String(encryptMessageJni(aClearMsg.getBytes("UTF-8")), "UTF-8"); + byte[] encryptedBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8"), errorMsg); + + if (null != encryptedBuffer) { + retValue = new String(encryptedBuffer , "UTF-8"); + } } catch (Exception e) { Log.e(LOG_TAG, "## encryptMessage() failed " + e.getMessage()); + errorMsg.append(e.getMessage()); + } + + if (0 != errorMsg.length()) { + throw new EncryptMessageException(errorMsg.toString()); } } return retValue; } - private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); + private native byte[] encryptMessageJni(byte[] aClearMsgBuffer, StringBuffer aErrorMsg); /** * Return true the object resources have been released.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 211757f..aa0e5e7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -268,7 +268,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * return returnValue; } -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aErrorMsg) { LOGD("## encryptMessageJni(): IN"); @@ -277,10 +277,17 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE OlmOutboundGroupSession *sessionPtr = NULL; jbyte* clearMsgPtr = NULL; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## encryptMessageJni(): failure - invalid outbound group session ptr=NULL"); } + else if (!aErrorMsg) + { + LOGE(" ## encryptMessageJni(): failure - invalid error output"); + } else if (!aClearMsgBuffer) { LOGE(" ## encryptMessageJni(): failure - invalid clear message"); @@ -289,6 +296,14 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE { LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM"); } + else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## encryptMessageJni(): failure - unable to get error class"); + } + else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## encryptMessageJni(): failure - unable to get error method ID"); + } else { // get clear message length @@ -312,9 +327,19 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE clearMsgLength, encryptedMsgPtr, encryptedMsgLength); + + if (encryptedLength == olm_error()) { - LOGE(" ## encryptMessageJni(): failure - olm_group_encrypt Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); + const char * errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); + + jstring errorJstring = env->NewStringUTF(errorMsgPtr); + + if (errorJstring) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } } else { @@ -329,7 +354,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE free(encryptedMsgPtr); } - } + } // free alloc if (clearMsgPtr) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 71ddb3b..37f0ea6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -37,7 +37,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aErrorMsg); // serialization JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); -- cgit v1.2.3 From 2070de4fc57980527dadd2ef88340e7455269e09 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 3 Jan 2017 17:20:18 +0100 Subject: initInboundSessionWithAccount triggers an exception when it fails. --- .../java/org/matrix/olm/OlmSessionTest.java | 70 +++++++++++++++++++--- .../src/main/java/org/matrix/olm/OlmSession.java | 28 ++++----- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 28 ++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 2 +- 4 files changed, 102 insertions(+), 26 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 099f2a5..6c888d0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -19,6 +19,7 @@ package org.matrix.olm; import android.content.Context; import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; import android.util.Log; import org.json.JSONObject; @@ -126,7 +127,13 @@ public class OlmSessionTest { assertTrue("Exception Msg="+e.getMessage(), false); } assertTrue(0!=bobSession.getOlmSessionId()); - assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); + + try { + bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } + String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); assertNotNull(decryptedMsg); @@ -218,8 +225,14 @@ public class OlmSessionTest { } catch (OlmException e) { assertTrue("Exception Msg="+e.getMessage(), false); } + assertTrue(0!=bobSession.getOlmSessionId()); - assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + + try { + bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } // DECRYPT MESSAGE FROM ALICE String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); @@ -375,7 +388,11 @@ public class OlmSessionTest { assertFalse(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); // init bob session with alice PRE KEY - assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + try { + bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } // test matchesInboundSession() and matchesInboundSessionFrom() assertTrue(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); @@ -461,7 +478,13 @@ public class OlmSessionTest { assertTrue("Exception Msg="+e.getMessage(), false); } assertTrue(0!=bobSession.getOlmSessionId()); - assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); + + // init bob session with alice PRE KEY + try { + bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } // DECRYPT MESSAGE FROM ALICE String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); @@ -604,11 +627,42 @@ public class OlmSessionTest { OlmSession bobSession = null; try { bobSession = new OlmSession(); - assertTrue(-1==bobSession.initInboundSessionWithAccount(null, encryptedMsgToBob.mCipherText)); - assertTrue(-1==bobSession.initInboundSessionWithAccount(bobAccount, null)); - assertTrue(-1==bobSession.initInboundSessionWithAccount(bobAccount, INVALID_PRE_KEY)); + String errorMessage = null; + try { + bobSession.initInboundSessionWithAccount(null, encryptedMsgToBob.mCipherText); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(!TextUtils.isEmpty(errorMessage)); + + errorMessage = null; + try { + bobSession.initInboundSessionWithAccount(bobAccount, null); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(!TextUtils.isEmpty(errorMessage)); + + errorMessage = null; + try { + bobSession.initInboundSessionWithAccount(bobAccount, INVALID_PRE_KEY); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(!TextUtils.isEmpty(errorMessage)); + // init properly - assertTrue(0==bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); + errorMessage = null; + try { + bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(TextUtils.isEmpty(errorMessage)); } catch (OlmException e) { assertTrue("Exception Msg="+e.getMessage(), false); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index a58036f..85804a1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -150,7 +150,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * Getter on the session ID. * @return native session ID */ - public long getOlmSessionId(){ + long getOlmSessionId(){ return mNativeId; } @@ -209,11 +209,9 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { */ private native long createNewSessionJni(); - /** * Creates a new out-bound session for sending messages to a recipient * identified by an identity key and a one time key.
- * Public API for {@link #initOutboundSessionWithAccount(OlmAccount, String, String)}. * @param aAccount the account to associate with this session * @param aTheirIdentityKey the identity key of the recipient * @param aTheirOneTimeKey the one time key of the recipient @@ -222,7 +220,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { public int initOutboundSessionWithAccount(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) { int retCode=-1; - if((null==aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)){ + if ((null == aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)) { Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); } else { try { @@ -240,30 +238,32 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { /** * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY message ({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}).
- * Public API for {@link #initInboundSessionJni(long, byte[])}. * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session * @param aPreKeyMsg PRE KEY message - * @return 0 if operation succeed, -1 otherwise + * @exception Exception the failure reason */ - public int initInboundSessionWithAccount(OlmAccount aAccount, String aPreKeyMsg) { - int retCode = -1; - + public void initInboundSessionWithAccount(OlmAccount aAccount, String aPreKeyMsg) throws Exception { if ((null == aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); + throw new Exception("invalid input parameters"); } else { + StringBuffer errorMsg = new StringBuffer(); + try { - retCode = initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8")); + initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8"), errorMsg); } catch (Exception e) { Log.e(LOG_TAG, "## initInboundSessionWithAccount(): " + e.getMessage()); + errorMsg.append(errorMsg); } - } - return retCode; + if (errorMsg.length() != 0) { + throw new Exception(errorMsg.toString()); + } + } } - private native int initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg); - + private native int initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg, StringBuffer aErrorMsg); /** * Create a new in-bound session for sending/receiving messages from an diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 5ae68d0..3731d14 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -205,12 +205,14 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject * @param aOneTimeKeyMsg PRE_KEY message * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer) +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer, jobject aErrorMsg) { jint retCode = ERROR_CODE_KO; OlmSession *sessionPtr = NULL; OlmAccount *accountPtr = NULL; size_t sessionResult; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { @@ -224,6 +226,18 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject { LOGE("## initInboundSessionJni(): failure - invalid message"); } + else if (!aErrorMsg) + { + LOGE(" ## initInboundSessionJni(): failure - invalid error output"); + } + else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## initInboundSessionJni(): failure - unable to get error class"); + } + else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## initInboundSessionJni(): failure - unable to get error method ID"); + } else { jbyte* messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0); @@ -241,7 +255,15 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject if (sessionResult == olm_error()) { - LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s", errorMsgPtr); + + jstring errorJstring = env->NewStringUTF(errorMsgPtr); + + if (errorJstring) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } } else { @@ -818,7 +840,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job const char *errorMsgPtr = olm_session_last_error(sessionPtr); LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr); - if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + if ((errorJstring = env->NewStringUTF(errorMsgPtr))) { env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 924b439..9ce12d4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -36,7 +36,7 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject t JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey); // inbound sessions: establishment based on PRE KEY message -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg, jobject aErrorMsg); JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // match inbound sessions: based on PRE KEY message -- cgit v1.2.3 From ce9f67d5beb4cc46ded3f374afee6b737e505ff4 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 08:57:41 +0100 Subject: Simplify the serialization / deserializtion methods (CommonSerializeUtils) --- .../java/org/matrix/olm/OlmSessionTest.java | 34 ++-- .../java/org/matrix/olm/CommonSerializeUtils.java | 31 +-- .../src/main/java/org/matrix/olm/OlmAccount.java | 206 ++++++++++--------- .../org/matrix/olm/OlmInboundGroupSession.java | 119 ++++++----- .../org/matrix/olm/OlmOutboundGroupSession.java | 200 +++++++++---------- .../src/main/java/org/matrix/olm/OlmSession.java | 217 ++++++++++----------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 50 ++--- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 4 +- .../src/main/jni/olm_inbound_group_session.cpp | 66 +++---- .../src/main/jni/olm_inbound_group_session.h | 6 +- .../src/main/jni/olm_outbound_group_session.cpp | 50 ++--- .../src/main/jni/olm_outbound_group_session.h | 4 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 51 +++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 4 +- 14 files changed, 500 insertions(+), 542 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 6c888d0..675d72c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -112,7 +112,7 @@ public class OlmSessionTest { assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); String clearMsg = "Heloo bob , this is alice!"; OlmMessage encryptedMsgToBob = aliceSession.encryptMessage(clearMsg); assertNotNull(encryptedMsgToBob); @@ -129,7 +129,7 @@ public class OlmSessionTest { assertTrue(0!=bobSession.getOlmSessionId()); try { - bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText); + bobSession.initInboundSession(bobAccount, encryptedMsgToBob.mCipherText); } catch (Exception e) { assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); } @@ -211,7 +211,7 @@ public class OlmSessionTest { assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); String helloClearMsg = "Hello I'm Alice!"; OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); @@ -229,7 +229,7 @@ public class OlmSessionTest { assertTrue(0!=bobSession.getOlmSessionId()); try { - bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText); + bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); } catch (Exception e) { assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); } @@ -381,7 +381,7 @@ public class OlmSessionTest { String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeys, 1); // create alice inbound session for bob - assertTrue(0==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey1)); + assertTrue(0==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey1)); String aliceClearMsg = "hello helooo to bob!"; OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg); @@ -389,7 +389,7 @@ public class OlmSessionTest { // init bob session with alice PRE KEY try { - bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText); + bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); } catch (Exception e) { assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); } @@ -463,7 +463,7 @@ public class OlmSessionTest { assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); String helloClearMsg = "Hello I'm Alice!"; OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); @@ -481,7 +481,7 @@ public class OlmSessionTest { // init bob session with alice PRE KEY try { - bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText); + bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); } catch (Exception e) { assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); } @@ -608,13 +608,13 @@ public class OlmSessionTest { } // SANITY CHECK TESTS FOR: initOutboundSessionWithAccount() - assertTrue(-1==aliceSession.initOutboundSessionWithAccount(null, bobIdentityKey, bobOneTimeKey)); - assertTrue(-1==aliceSession.initOutboundSessionWithAccount(aliceAccount, null, bobOneTimeKey)); - assertTrue(-1==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, null)); - assertTrue(-1==aliceSession.initOutboundSessionWithAccount(null, null, null)); + assertTrue(-1==aliceSession.initOutboundSession(null, bobIdentityKey, bobOneTimeKey)); + assertTrue(-1==aliceSession.initOutboundSession(aliceAccount, null, bobOneTimeKey)); + assertTrue(-1==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, null)); + assertTrue(-1==aliceSession.initOutboundSession(null, null, null)); // init properly - assertTrue(0==aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey)); + assertTrue(0==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); // SANITY CHECK TESTS FOR: encryptMessage() assertTrue(null==aliceSession.encryptMessage(null)); @@ -629,7 +629,7 @@ public class OlmSessionTest { bobSession = new OlmSession(); String errorMessage = null; try { - bobSession.initInboundSessionWithAccount(null, encryptedMsgToBob.mCipherText); + bobSession.initInboundSession(null, encryptedMsgToBob.mCipherText); } catch (Exception e) { errorMessage = e.getMessage(); } @@ -638,7 +638,7 @@ public class OlmSessionTest { errorMessage = null; try { - bobSession.initInboundSessionWithAccount(bobAccount, null); + bobSession.initInboundSession(bobAccount, null); } catch (Exception e) { errorMessage = e.getMessage(); } @@ -647,7 +647,7 @@ public class OlmSessionTest { errorMessage = null; try { - bobSession.initInboundSessionWithAccount(bobAccount, INVALID_PRE_KEY); + bobSession.initInboundSession(bobAccount, INVALID_PRE_KEY); } catch (Exception e) { errorMessage = e.getMessage(); } @@ -657,7 +657,7 @@ public class OlmSessionTest { // init properly errorMessage = null; try { - bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText); + bobSession.initInboundSession(bobAccount, encryptedMsgToBob.mCipherText); } catch (Exception e) { errorMessage = e.getMessage(); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java index c3f9757..72437e4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -35,7 +35,7 @@ abstract class CommonSerializeUtils { * @param aOutStream output stream for serializing * @throws IOException exception */ - protected void serializeObject(ObjectOutputStream aOutStream) throws IOException { + protected void serialize(ObjectOutputStream aOutStream) throws IOException { aOutStream.defaultWriteObject(); // generate serialization key @@ -43,7 +43,7 @@ abstract class CommonSerializeUtils { // compute pickle string StringBuffer errorMsg = new StringBuffer(); - String pickledData = serializeDataWithKey(key, errorMsg); + String pickledData = serialize(key, errorMsg); if(null == pickledData) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg)); @@ -59,33 +59,22 @@ abstract class CommonSerializeUtils { * @throws IOException exception * @throws ClassNotFoundException exception */ - protected void deserializeObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + protected void deserialize(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { aInStream.defaultReadObject(); - StringBuffer errorMsg = new StringBuffer(); String key = (String) aInStream.readObject(); String pickledData = (String) aInStream.readObject(); - if(TextUtils.isEmpty(key)) { + if (TextUtils.isEmpty(key)) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); - - } else if(TextUtils.isEmpty(pickledData)) { + } else if (TextUtils.isEmpty(pickledData)) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); - - } else if(!createNewObjectFromSerialization()) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); - - } else if(!initWithSerializedData(pickledData, key, errorMsg)) { - releaseObjectFromSerialization(); // prevent memory leak - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); - - } else { - Log.d(LOG_TAG,"## readObject(): success"); } + + deserialize(pickledData, key); + Log.d(LOG_TAG,"## deserializeObject(): success"); } - protected abstract String serializeDataWithKey(String aKey, StringBuffer aErrorMsg); - protected abstract boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg); - protected abstract boolean createNewObjectFromSerialization(); - protected abstract void releaseObjectFromSerialization(); + protected abstract String serialize(String aKey, StringBuffer aErrorMsg); + protected abstract void deserialize(String aSerializedData, String aKey) throws IOException; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 1e41fa1..649085e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -68,105 +68,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serializeObject(aOutStream); - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception - */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - deserializeObject(aInStream); - } - - @Override - protected boolean createNewObjectFromSerialization() { - return createNewAccount(); - } - - @Override - protected void releaseObjectFromSerialization() { - releaseAccount(); - } - - /** - * Return an account as a base64 string.
- * The account is serialized and encrypted with aKey. - * In case of failure, an error human readable - * description is provide in aErrorMsg. - * @param aKey encryption key - * @param aErrorMsg error message description - * @return pickled base64 string if operation succeed, null otherwise - */ - @Override - protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { - String pickleRetValue = null; - - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); - } else if(TextUtils.isEmpty(aKey)) { - aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); - } else { - aErrorMsg.setLength(0); - try { - pickleRetValue = new String(serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## serializeDataWithKey() failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return pickleRetValue; - } - private native byte[] serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); - - - /** - * Loads an account from a pickled base64 string.
- * See {@link #serializeDataWithKey(String, StringBuffer)} - * @param aSerializedData pickled account in a base64 string format - * @param aKey key used to encrypted - * @param aErrorMsg error message description - * @return true if operation succeed, false otherwise - */ - @Override - protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { - boolean retCode = false; - String jniError; - - if (null == aErrorMsg) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); - } else { - aErrorMsg.setLength(0); - - try { - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { - retCode = true; - } else { - aErrorMsg.append(jniError); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## initWithSerializedData() failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return retCode; - } - - private native String initWithSerializedDataJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); - /** * Getter on the account ID. * @return native account ID @@ -229,6 +130,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ private native long createNewAccountJni(); + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + /** * Return the identity keys (identity and fingerprint keys) in a dictionary.
* Public API for {@link #identityKeysJni()}.
@@ -393,14 +302,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private native byte[] signMessageJni(byte[] aMessage); - /** - * Return true the object resources have been released.
- * @return true the object resources have been released - */ - public boolean isReleased() { - return (0 == mNativeId); - } - /** * Build a string-string dictionary from a jsonObject.
* @param jsonObject the object to parse @@ -461,4 +362,95 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return null; } + + //============================================================================================================== + // Serialization management + //============================================================================================================== + + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception + */ + private void writeObject(ObjectOutputStream aOutStream) throws IOException { + serialize(aOutStream); + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + */ + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + deserialize(aInStream); + } + + /** + * Return an account as a base64 string.
+ * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + @Override + protected String serialize(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + try { + pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } + } + + return pickleRetValue; + } + + private native byte[] serializeJni(byte[] aKey, StringBuffer aErrorMsg); + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serialize(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + */ + @Override + protected void deserialize(String aSerializedData, String aKey) throws IOException { + if (!createNewAccount()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); + } + + StringBuffer errorMsg = new StringBuffer(); + + try { + String jniError; + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg.append("invalid input parameters"); + } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + errorMsg.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg.append(e.getMessage()); + } + + if (errorMsg.length() > 0) { + releaseAccount(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + } + } + + private native String deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index bfd50fb..68878c7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -65,13 +65,13 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. * The session key parameter is retrieved from an outbound group session - * See {@link #createNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)} + * See {@link #createNewSession()} and {@link #initInboundGroupSession(String)} * @param aSessionKey session key * @throws OlmException constructor failure */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { if(createNewSession()) { - if (0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { + if (0 != initInboundGroupSession(aSessionKey)) { releaseSession();// prevent memory leak before throwing throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION,OlmException.EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION); } @@ -114,6 +114,14 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ private native long createNewSessionJni(); + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + /** * Start a new inbound group session.
* The session key parameter is retrieved from an outbound group session @@ -121,23 +129,23 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @param aSessionKey session key * @return 0 if operation succeed, -1 otherwise */ - private int initInboundGroupSessionWithSessionKey(String aSessionKey) { + private int initInboundGroupSession(String aSessionKey) { int retCode = -1; if(TextUtils.isEmpty(aSessionKey)){ - Log.e(LOG_TAG, "## initInboundGroupSessionWithSessionKey(): invalid session key"); + Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); } else { try { - retCode = initInboundGroupSessionWithSessionKeyJni(aSessionKey.getBytes("UTF-8")); + retCode = initInboundGroupSessionJni(aSessionKey.getBytes("UTF-8")); } catch (Exception e) { - Log.e(LOG_TAG, "## initInboundGroupSessionWithSessionKey() failed " + e.getMessage()); + Log.e(LOG_TAG, "## initInboundGroupSession() failed " + e.getMessage()); } } return retCode; } - private native int initInboundGroupSessionWithSessionKeyJni(byte[] aSessionKeyBuffer); + private native int initInboundGroupSessionJni(byte[] aSessionKeyBuffer); /** * Retrieve the base64-encoded identifier for this inbound group session. @@ -187,13 +195,17 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg); + //============================================================================================================== + // Serialization management + //============================================================================================================== + /** * Kick off the serialization mechanism. * @param aOutStream output stream for serializing * @throws IOException exception */ private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serializeObject(aOutStream); + serialize(aOutStream); } /** @@ -203,17 +215,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @throws ClassNotFoundException exception */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - deserializeObject(aInStream); - } - - @Override - protected boolean createNewObjectFromSerialization() { - return createNewSession(); - } - - @Override - protected void releaseObjectFromSerialization() { - releaseSession(); + deserialize(aInStream); } /** @@ -226,20 +228,20 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @return pickled base64 string if operation succeed, null otherwise */ @Override - protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + protected String serialize(String aKey, StringBuffer aErrorMsg) { String pickleRetValue = null; // sanity check if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); } else if(TextUtils.isEmpty(aKey)) { - aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + aErrorMsg.append("Invalid input parameters in serialize()"); } else { aErrorMsg.setLength(0); try { - pickleRetValue = new String(serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); + pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); } catch (Exception e) { - Log.e(LOG_TAG, "## serializeDataWithKey() failed " + e.getMessage()); + Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); } } @@ -247,60 +249,51 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return pickleRetValue; } /** - * JNI counter part of {@link #serializeDataWithKey(String, StringBuffer)}. + * JNI counter part of {@link #serialize(String, StringBuffer)}. * @param aKey encryption key * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private native byte[] serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); - + private native byte[] serializeJni(byte[] aKey, StringBuffer aErrorMsg); /** - * Load an inbound group session from a pickled base64 string.
- * See {@link #serializeDataWithKey(String, StringBuffer)} - * @param aSerializedData pickled inbound group session in a base64 string format - * @param aKey encrypting key used in {@link #serializeDataWithKey(String, StringBuffer)} - * @param aErrorMsg error message description - * @return true if operation succeed, false otherwise + * Loads an account from a pickled base64 string.
+ * See {@link #serialize(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted */ @Override - protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { - boolean retCode = false; - String jniError; + protected void deserialize(String aSerializedData, String aKey) throws IOException { + if (!createNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); + } - if(null == aErrorMsg) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); - } else { - aErrorMsg.setLength(0); - try { - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { - retCode = true; - } else { - aErrorMsg.append(jniError); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## initWithSerializedData() failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); + StringBuffer errorMsg = new StringBuffer(); + + try { + String jniError; + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg.append("invalid input parameters"); + } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + errorMsg.append(jniError); } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg.append(e.getMessage()); } - return retCode; + if (errorMsg.length() > 0) { + releaseSession(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + } } + /** - * JNI counter part of {@link #initWithSerializedData(String, String, StringBuffer)}. + * JNI counter part of {@link #deserialize(String, String)}. * @param aSerializedData pickled session in a base64 string format - * @param aKey key used to encrypted in {@link #serializeDataWithKey(String, StringBuffer)} + * @param aKey key used to encrypted in {@link #serialize(String, StringBuffer)} * @return null if operation succeed, an error message if operation failed */ - private native String initWithSerializedDataJni(byte[] aSerializedData, byte[] aKey); - - /** - * Return true the object resources have been released.
- * @return true the object resources have been released - */ - public boolean isReleased() { - return (0 == mNativeId); - } + private native String deserializeJni(byte[] aSerializedData, byte[] aKey); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index b9c21ff..66a44d2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -69,105 +69,6 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } } - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serializeObject(aOutStream); - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception - */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - deserializeObject(aInStream); - } - - @Override - protected boolean createNewObjectFromSerialization() { - return createNewSession(); - } - - @Override - protected void releaseObjectFromSerialization() { - releaseSession(); - } - - /** - * Return the current outbound group session as a base64 serialized string.
- * The session is serialized and encrypted with aKey. - * In case of failure, an error human readable - * description is provide in aErrorMsg. - * @param aKey encryption key - * @param aErrorMsg error message description - * @return pickled base64 string if operation succeed, null otherwise - */ - @Override - protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { - String pickleRetValue = null; - - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); - } else if(TextUtils.isEmpty(aKey)) { - aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); - } else { - aErrorMsg.setLength(0); - try { - pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); - } catch (Exception e) { - Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return pickleRetValue; - } - private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); - - - /** - * Load an outbound group session from a pickled base64 string.
- * See {@link #serializeDataWithKey(String, StringBuffer)} - * @param aSerializedData pickled outbound group session in a base64 string format - * @param aKey encrypting key used in {@link #serializeDataWithKey(String, StringBuffer)} - * @param aErrorMsg error message description - * @return true if operation succeed, false otherwise - */ - @Override - protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { - boolean retCode = false; - String jniError; - - if(null == aErrorMsg) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); - } else { - aErrorMsg.setLength(0); - - try { - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { - retCode = true; - } else { - aErrorMsg.append(jniError); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## initWithSerializedData(): failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return retCode; - } - private native String initWithSerializedDataJni(byte[] aSerializedData, byte[] aKey); - - /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. @@ -203,6 +104,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ private native long createNewSessionJni(); + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + /** * Start a new outbound group session.
* @return 0 if operation succeed, -1 otherwise @@ -290,11 +199,96 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } private native byte[] encryptMessageJni(byte[] aClearMsgBuffer, StringBuffer aErrorMsg); + + //============================================================================================================== + // Serialization management + //============================================================================================================== + /** - * Return true the object resources have been released.
- * @return true the object resources have been released + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception */ - public boolean isReleased() { - return (0 == mNativeId); + private void writeObject(ObjectOutputStream aOutStream) throws IOException { + serialize(aOutStream); } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + */ + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + deserialize(aInStream); + } + + /** + * Return the current outbound group session as a base64 serialized string.
+ * The session is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + @Override + protected String serialize(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serialize()"); + } else { + aErrorMsg.setLength(0); + try { + pickleRetValue = serializeJni(aKey.getBytes("UTF-8"), aErrorMsg); + } catch (Exception e) { + Log.e(LOG_TAG,"## serialize(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } + } + + return pickleRetValue; + } + private native String serializeJni(byte[] aKey, StringBuffer aErrorMsg); + + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serialize(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + */ + @Override + protected void deserialize(String aSerializedData, String aKey) throws IOException { + if (!createNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); + } + + StringBuffer errorMsg = new StringBuffer(); + + try { + String jniError; + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg.append("invalid input parameters"); + } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + errorMsg.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg.append(e.getMessage()); + } + + if (errorMsg.length() > 0) { + releaseSession(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + } + } + + private native String deserializeJni(byte[] aSerializedData, byte[] aKey); + } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 85804a1..36a95a1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -28,8 +28,8 @@ import java.io.Serializable; /** * Session class used to create Olm sessions in conjunction with {@link OlmAccount} class.
* Olm session is used to encrypt data between devices, especially to create Olm group sessions (see {@link OlmOutboundGroupSession} and {@link OlmInboundGroupSession}).
- * To establish an Olm session with Bob, Alice calls {@link #initOutboundSessionWithAccount(OlmAccount, String, String)} with Bob's identity and onetime keys. Then Alice generates an encrypted PRE_KEY message ({@link #encryptMessage(String)}) - * used by Bob to open the Olm session in his side with {@link #initOutboundSessionWithAccount(OlmAccount, String, String)}. + * To establish an Olm session with Bob, Alice calls {@link #initOutboundSession(OlmAccount, String, String)} with Bob's identity and onetime keys. Then Alice generates an encrypted PRE_KEY message ({@link #encryptMessage(String)}) + * used by Bob to open the Olm session in his side with {@link #initOutboundSession(OlmAccount, String, String)}. * From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}. *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. */ @@ -48,104 +48,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } } - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serializeObject(aOutStream); - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception - */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { - deserializeObject(aInStream); - } - - @Override - protected boolean createNewObjectFromSerialization() { - return createNewSession(); - } - - @Override - protected void releaseObjectFromSerialization() { - releaseSession(); - } - - /** - * Return a session as a base64 string.
- * The account is serialized and encrypted with aKey. - * In case of failure, an error human readable - * description is provide in aErrorMsg. - * @param aKey encryption key - * @param aErrorMsg error message description - * @return pickled base64 string if operation succeed, null otherwise - */ - @Override - protected String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { - String pickleRetValue = null; - - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); - } else if(TextUtils.isEmpty(aKey)) { - aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); - } else { - aErrorMsg.setLength(0); - try { - pickleRetValue = serializeDataWithKeyJni(aKey.getBytes("UTF-8"), aErrorMsg); - } catch (Exception e) { - Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return pickleRetValue; - } - private native String serializeDataWithKeyJni(byte[] aKey, StringBuffer aErrorMsg); - - - /** - * Loads a session from a pickled base64 string.
- * See {@link #serializeDataWithKey(String, StringBuffer)} - * @param aSerializedData pickled account in a base64 string format - * @param aKey key used to encrypted - * @param aErrorMsg error message description - * @return true if operation succeed, false otherwise - */ - @Override - protected boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { - boolean retCode = false; - String jniError; - - if(null == aErrorMsg) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); - } else { - aErrorMsg.setLength(0); - - try { - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { - Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); - } else if (null == (jniError = initWithSerializedDataJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { - retCode = true; - } else { - aErrorMsg.append(jniError); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## initWithSerializedData(): failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return retCode; - } - private native String initWithSerializedDataJni(byte[] aSerializedData, byte[] aKey); - /** * Getter on the session ID. * @return native session ID @@ -189,7 +91,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { */ private native long initNewSessionJni(); - /** * Create a native account instance without any initialization.
* Since the account is left uninitialized, this @@ -209,6 +110,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { */ private native long createNewSessionJni(); + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + /** * Creates a new out-bound session for sending messages to a recipient * identified by an identity key and a one time key.
@@ -217,7 +126,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aTheirOneTimeKey the one time key of the recipient * @return 0 if operation succeed, -1 otherwise */ - public int initOutboundSessionWithAccount(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) { + public int initOutboundSession(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) { int retCode=-1; if ((null == aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)) { @@ -226,7 +135,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { try { retCode = initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8")); } catch (Exception e) { - Log.e(LOG_TAG, "## initOutboundSessionWithAccount(): " + e.getMessage()); + Log.e(LOG_TAG, "## initOutboundSession(): " + e.getMessage()); } } @@ -243,9 +152,9 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aPreKeyMsg PRE KEY message * @exception Exception the failure reason */ - public void initInboundSessionWithAccount(OlmAccount aAccount, String aPreKeyMsg) throws Exception { + public void initInboundSession(OlmAccount aAccount, String aPreKeyMsg) throws Exception { if ((null == aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ - Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); + Log.e(LOG_TAG, "## initInboundSession(): invalid input parameters"); throw new Exception("invalid input parameters"); } else { StringBuffer errorMsg = new StringBuffer(); @@ -253,7 +162,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { try { initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8"), errorMsg); } catch (Exception e) { - Log.e(LOG_TAG, "## initInboundSessionWithAccount(): " + e.getMessage()); + Log.e(LOG_TAG, "## initInboundSession(): " + e.getMessage()); errorMsg.append(errorMsg); } @@ -276,16 +185,16 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aPreKeyMsg PRE KEY message * @return 0 if operation succeed, -1 otherwise */ - public int initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) { + public int initInboundSessionFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) { int retCode=-1; if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ - Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); + Log.e(LOG_TAG, "## initInboundSessionFrom(): invalid input parameters"); } else { try { retCode = initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8")); } catch (Exception e) { - Log.e(LOG_TAG, "## initInboundSessionWithAccountFrom(): " + e.getMessage()); + Log.e(LOG_TAG, "## initInboundSessionFrom(): " + e.getMessage()); } } @@ -400,12 +309,94 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg); + //============================================================================================================== + // Serialization management + //============================================================================================================== + /** - * Return true the object resources have been released.
- * @return true the object resources have been released + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception */ - public boolean isReleased() { - return (0 == mNativeId); + private void writeObject(ObjectOutputStream aOutStream) throws IOException { + serialize(aOutStream); } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + */ + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + deserialize(aInStream); + } + + /** + * Return a session as a base64 string.
+ * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + @Override + protected String serialize(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + try { + pickleRetValue = serializeJni(aKey.getBytes("UTF-8"), aErrorMsg); + } catch (Exception e) { + Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } + } + + return pickleRetValue; + } + private native String serializeJni(byte[] aKey, StringBuffer aErrorMsg); + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serialize(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + */ + @Override + protected void deserialize(String aSerializedData, String aKey) throws IOException { + if (!createNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); + } + + StringBuffer errorMsg = new StringBuffer(); + + try { + String jniError; + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg.append("invalid input parameters"); + } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + errorMsg.append(jniError); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg.append(e.getMessage()); + } + + if (errorMsg.length() > 0) { + releaseSession(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + } + } + + private native String deserializeJni(byte[] aSerializedData, byte[] aKey); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 06709e7..d57e55b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -476,7 +476,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jbyteArray pickledDataRetValue = 0; jclass errorMsgJClass = 0; @@ -485,44 +485,44 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jbyte* keyPtr = NULL; OlmAccount* accountPtr = NULL; - LOGD("## serializeDataWithKeyJni(): IN"); + LOGD("## serializeJni(): IN"); if (!aKeyBuffer) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + LOGE(" ## serializeJni(): failure - invalid key"); } else if (!aErrorMsg) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + LOGE(" ## serializeJni(): failure - invalid error object"); } else if (!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); + LOGE(" ## serializeJni(): failure - invalid account ptr"); } else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + LOGE(" ## serializeJni(): failure - unable to get error class"); } else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + LOGE(" ## serializeJni(): failure - unable to get error method ID"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, NULL))) { - LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_account_length(accountPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); if (!pickledPtr) { - LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); } else { @@ -534,7 +534,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, if (result == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) { @@ -546,7 +546,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); pickledDataRetValue = env->NewByteArray(pickledLength+1); env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength+1, (jbyte*)pickledPtr); @@ -566,42 +566,42 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, } -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmAccount* accountPtr = NULL; jstring errorMessageRetValue = 0; jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; - LOGD("## initWithSerializedDataJni(): IN"); + LOGD("## deserializeJni(): IN"); if (!aKeyBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + LOGE(" ## deserializeJni(): failure - invalid key"); } else if (!aSerializedDataBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + LOGE(" ## deserializeJni(): failure - serialized data"); } else if (!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE(" ## initWithSerializedDataJni(): failure - account failure OOM"); + LOGE(" ## deserializeJni(): failure - account failure OOM"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); } else { size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); - LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); + LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_account(accountPtr, (void const *)keyPtr, @@ -611,12 +611,12 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j if (result == olm_error()) { const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); errorMessageRetValue = env->NewStringUTF(errorMsgPtr); } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); + LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index c866dbc..94a0381 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -47,8 +47,8 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); // serialization -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg); -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg); +JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index ca47dbb..d396eb9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -86,41 +86,41 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * * @param aSessionKey session key from an outbound session * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) +JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) { jint retCode = ERROR_CODE_KO; OlmInboundGroupSession *sessionPtr = NULL; jbyte* sessionKeyPtr = NULL; size_t sessionResult; - LOGD("## initInboundGroupSessionWithSessionKeyJni(): inbound group session IN"); + LOGD("## initInboundGroupSessionJni(): inbound group session IN"); if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { - LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance"); + LOGE(" ## initInboundGroupSessionJni(): failure - invalid inbound group session instance"); } else if (!aSessionKeyBuffer) { - LOGE(" ## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey"); + LOGE(" ## initInboundGroupSessionJni(): failure - invalid aSessionKey"); } else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) { - LOGE(" ## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM"); + LOGE(" ## initInboundGroupSessionJni(): failure - session key JNI allocation OOM"); } else { size_t sessionKeyLength = (size_t)env->GetArrayLength(aSessionKeyBuffer); - LOGD(" ## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); + LOGD(" ## initInboundGroupSessionJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); if (sessionResult == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + LOGE(" ## initInboundGroupSessionJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); } else { retCode = ERROR_CODE_OK; - LOGD(" ## initInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(sessionResult)); + LOGD(" ## initInboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); } } @@ -337,7 +337,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jbyteArray pickledDataRet = 0; @@ -346,44 +346,44 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni) jbyte* keyPtr = NULL; OlmInboundGroupSession* sessionPtr = NULL; - LOGD("## inbound group session serializeDataWithKeyJni(): IN"); + LOGD("## inbound group session serializeJni(): IN"); if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); + LOGE(" ## serializeJni(): failure - invalid session ptr"); } else if (!aKeyBuffer) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + LOGE(" ## serializeJni(): failure - invalid key"); } else if (!aErrorMsg) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + LOGE(" ## serializeJni(): failure - invalid error object"); } else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + LOGE(" ## serializeJni(): failure - unable to get error class"); } else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + LOGE(" ## serializeJni(): failure - unable to get error method ID"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { - LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_inbound_group_session_length(sessionPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); if (!pickledPtr) { - LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); } else { @@ -395,7 +395,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni) if (result == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); jstring errorJstring = env->NewStringUTF(errorMsgPtr); @@ -407,7 +407,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni) else { (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); pickledDataRet = env->NewByteArray(pickledLength); env->SetByteArrayRegion(pickledDataRet, 0 , pickledLength, (jbyte*)pickledPtr); @@ -427,42 +427,42 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni) } -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmInboundGroupSession* sessionPtr = NULL; jstring errorMessageRetValue = 0; jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; - LOGD("## initWithSerializedDataJni(): IN"); + LOGD("## deserializeJni(): IN"); if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { - LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); + LOGE(" ## deserializeJni(): failure - session failure OOM"); } else if (!aKeyBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + LOGE(" ## deserializeJni(): failure - invalid key"); } else if (!aSerializedDataBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + LOGE(" ## deserializeJni(): failure - serialized data"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); } else { size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); - LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); + LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_inbound_group_session(sessionPtr, (void const *)keyPtr, @@ -472,12 +472,12 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)( if (result == olm_error()) { const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_inbound_group_session() Msg=%s",errorMsgPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_inbound_group_session() Msg=%s",errorMsgPtr); errorMessageRetValue = env->NewStringUTF(errorMsgPtr); } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); + LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 7ed6d8b..0ef55cf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -32,13 +32,13 @@ extern "C" { JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); +JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg); // serialization -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index aa0e5e7..4168742 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -372,7 +372,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; @@ -381,44 +381,44 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J jbyte* keyPtr = NULL; OlmOutboundGroupSession* sessionPtr = NULL; - LOGD("## outbound group session serializeDataWithKeyJni(): IN"); + LOGD("## outbound group session serializeJni(): IN"); if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); + LOGE(" ## serializeJni(): failure - invalid session ptr"); } else if (!aKeyBuffer) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + LOGE(" ## serializeJni(): failure - invalid key"); } else if (!aErrorMsg) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + LOGE(" ## serializeJni(): failure - invalid error object"); } else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + LOGE(" ## serializeJni(): failure - unable to get error class"); } else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + LOGE(" ## serializeJni(): failure - unable to get error method ID"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { - LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_outbound_group_session_length(sessionPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); if(!pickledPtr) { - LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); } else { @@ -430,7 +430,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J if (result == olm_error()) { const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); if (!(errorJstring = env->NewStringUTF(errorMsgPtr))) { @@ -442,7 +442,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } } @@ -459,42 +459,42 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(J } -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmOutboundGroupSession* sessionPtr = NULL; jstring errorMessageRetValue = 0; jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; - LOGD("## initWithSerializedDataJni(): IN"); + LOGD("## deserializeJni(): IN"); if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { - LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); + LOGE(" ## deserializeJni(): failure - session failure OOM"); } else if (!aKeyBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + LOGE(" ## deserializeJni(): failure - invalid key"); } else if (!aSerializedDataBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + LOGE(" ## deserializeJni(): failure - serialized data"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); } else { size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); - LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); + LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_outbound_group_session(sessionPtr, (void const *)keyPtr, @@ -504,12 +504,12 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni) if (result == olm_error()) { const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_outbound_group_session() Msg=%s",errorMsgPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_outbound_group_session() Msg=%s",errorMsgPtr); errorMessageRetValue = env->NewStringUTF(errorMsgPtr); } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); + LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 37f0ea6..f954bef 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -40,8 +40,8 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aErrorMsg); // serialization -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 3731d14..4a1717a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -780,7 +780,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, * @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) { jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; @@ -789,44 +789,44 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job jbyte* keyPtr = NULL; OlmSession* sessionPtr = NULL; - LOGD("## serializeDataWithKeyJni(): IN"); + LOGD("## serializeJni(): IN"); if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); + LOGE(" ## serializeJni(): failure - invalid session ptr"); } else if (!aKeyBuffer) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + LOGE(" ## serializeJni(): failure - invalid key"); } else if (!aErrorMsg) { - LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + LOGE(" ## serializeJni(): failure - invalid error object"); } else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + LOGE(" ## serializeJni(): failure - unable to get error class"); } else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) { - LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + LOGE(" ## serializeJni(): failure - unable to get error method ID"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { - LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); } else { size_t pickledLength = olm_pickle_session_length(sessionPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); if (!pickledPtr) { - LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); } else { @@ -838,7 +838,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job if (result == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr); if ((errorJstring = env->NewStringUTF(errorMsgPtr))) { @@ -850,7 +850,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); - LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); } free(pickledPtr); @@ -867,42 +867,42 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, job } -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmSession* sessionPtr = NULL; jstring errorMessageRetValue = 0; jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; - LOGD("## initWithSerializedDataJni(): IN"); + LOGD("## deserializeJni(): IN"); if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { - LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); + LOGE(" ## deserializeJni(): failure - session failure OOM"); } else if (!aKeyBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + LOGE(" ## deserializeJni(): failure - invalid key"); } else if (!aSerializedDataBuffer) { - LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + LOGE(" ## deserializeJni(): failure - serialized data"); } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { - LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); } else { size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); - LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); + LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_session(sessionPtr, (void const *)keyPtr, @@ -912,14 +912,13 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, j if (result == olm_error()) { const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); errorMessageRetValue = env->NewStringUTF(errorMsgPtr); } else { - LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", static_cast(result)); + LOGD(" ## initJni(): success - result=%lu ", static_cast(result)); } - } // free alloc diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 9ce12d4..95b421b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -50,8 +50,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); // serialization -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } -- cgit v1.2.3 From 570e8bbe939f04abc31a78eb99e5e0d3c461728f Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 09:07:12 +0100 Subject: use secureRandom in getRandomKey --- .../olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 287a9d2..d3c185f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -20,7 +20,7 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; -import java.util.Random; +import java.security.SecureRandom; /** * Olm SDK helper class. @@ -138,16 +138,10 @@ public class OlmUtility { * @return string containing randoms integer values */ public static String getRandomKey() { - String keyRetValue; - Random rand = new Random(); - StringBuilder strBuilder = new StringBuilder(); - - for(int i = 0; i< RANDOM_KEY_SIZE; i++) { - strBuilder.append(rand.nextInt(RANDOM_RANGE)); - } - keyRetValue = strBuilder.toString(); - - return keyRetValue; + SecureRandom secureRandom = new SecureRandom(); + byte[] buffer = new byte[RANDOM_KEY_SIZE]; + secureRandom.nextBytes(buffer); + return new String(buffer); } /** -- cgit v1.2.3 From 88548f687e7f6f51a48ac9cf3a342354731ad694 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 11:46:37 +0100 Subject: OlmAccount methods trigger an exception when they fail. --- .../java/org/matrix/olm/OlmAccountTest.java | 121 +++++++++++--- .../java/org/matrix/olm/OlmSessionTest.java | 185 ++++++++++++++++++--- .../java/org/matrix/olm/OlmUtilityTest.java | 18 +- .../src/main/java/org/matrix/olm/OlmAccount.java | 118 ++++++++----- .../src/main/java/org/matrix/olm/OlmException.java | 7 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 137 +++++++++------ .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 8 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 1 - 8 files changed, 452 insertions(+), 143 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index b275688..569b520 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -128,7 +128,12 @@ public class OlmAccountTest { */ @Test public void test05IdentityKeys() { - Map identityKeys = mOlmAccount.identityKeys(); + Map identityKeys = null; + try { + identityKeys = mOlmAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } assertNotNull(identityKeys); Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeys); @@ -157,8 +162,15 @@ public class OlmAccountTest { */ @Test public void test07GenerateOneTimeKeys() { - int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); - assertTrue(0==retValue); + String error = null; + + try { + mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + error = e.getMessage(); + } + + assertTrue(null == error); } /** @@ -167,7 +179,13 @@ public class OlmAccountTest { @Test public void test08OneTimeKeysJsonFormat() { int oneTimeKeysCount = 0; - Map> oneTimeKeysJson = mOlmAccount.oneTimeKeys(); + Map> oneTimeKeysJson = null; + + try { + oneTimeKeysJson = mOlmAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(oneTimeKeysJson); try { @@ -195,26 +213,40 @@ public class OlmAccountTest { long sessionId = olmSession.getOlmSessionId(); assertTrue(0 != sessionId); - int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(olmSession); - // test against no matching keys - assertTrue(1 == sessionRetCode); + String errorMessage = null; + + try { + mOlmAccount.removeOneTimeKeys(olmSession); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); olmSession.releaseSession(); sessionId = olmSession.getOlmSessionId(); - assertTrue("sessionRetCode="+sessionRetCode,0 == sessionId); + assertTrue(0 == sessionId); } @Test public void test11MarkOneTimeKeysAsPublished() { - int retCode = mOlmAccount.markOneTimeKeysAsPublished(); - // if OK => retCode=0 - assertTrue(0 == retCode); + try { + mOlmAccount.markOneTimeKeysAsPublished(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } } @Test public void test12SignMessage() { String clearMsg = "String to be signed by olm"; - String signedMsg = mOlmAccount.signMessage(clearMsg); + String signedMsg = null; + + try { + signedMsg = mOlmAccount.signMessage(clearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(signedMsg); // additional tests are performed in test01VerifyEd25519Signing() } @@ -237,12 +269,29 @@ public class OlmAccountTest { assertTrue(e.getMessage(),false); } - int retValue = accountRef.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); - assertTrue(0==retValue); + try { + accountRef.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(),false); + } // get keys references - Map identityKeysRef = accountRef.identityKeys(); - Map> oneTimeKeysRef = accountRef.oneTimeKeys(); + Map identityKeysRef = null; + + try { + identityKeysRef = accountRef.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + Map> oneTimeKeysRef = null; + + try { + oneTimeKeysRef = accountRef.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(identityKeysRef); assertNotNull(oneTimeKeysRef); @@ -304,12 +353,25 @@ public class OlmAccountTest { @Test public void test14GenerateOneTimeKeysError() { // keys number = 0 => no error - int retValue = mOlmAccount.generateOneTimeKeys(0); - assertTrue(0==retValue); + + String errorMessage = null; + try { + mOlmAccount.generateOneTimeKeys(0); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(null == errorMessage); // keys number = negative value - retValue = mOlmAccount.generateOneTimeKeys(-50); - assertTrue(-1==retValue); + errorMessage = null; + try { + mOlmAccount.generateOneTimeKeys(-50); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(null != errorMessage); } @Test @@ -321,9 +383,16 @@ public class OlmAccountTest { assertTrue(e.getMessage(),false); } - int sessionRetCode = olmAccount.removeOneTimeKeysForSession(null); + boolean sessionRetCode = true; + + try { + sessionRetCode = olmAccount.removeOneTimeKeys(null); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + // test against no matching keys - assertTrue(-1 == sessionRetCode); + assertFalse(sessionRetCode); olmAccount.releaseAccount(); } @@ -336,7 +405,13 @@ public class OlmAccountTest { } catch (OlmException e) { assertTrue(e.getMessage(),false); } - String signedMsg = olmAccount.signMessage(null); + String signedMsg = null; + + try { + signedMsg = olmAccount.signMessage(null); + } catch (Exception e) { + } + assertNull(signedMsg); olmAccount.releaseAccount(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index 675d72c..e8b2288 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -92,13 +92,32 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // get bob identity key - Map bobIdentityKeys = bobAccount.identityKeys(); + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null!=bobIdentityKey); // get bob one time keys - assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); @@ -141,7 +160,13 @@ public class OlmSessionTest { assertTrue(clearMsg.equals(decryptedMsg)); // clean objects.. - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + boolean res = false; + try { + res = bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(res); // release accounts bobAccount.releaseAccount(); @@ -191,13 +216,32 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // get bob identity key - Map bobIdentityKeys = bobAccount.identityKeys(); + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null!=bobIdentityKey); // get bob one time keys - assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); @@ -279,7 +323,14 @@ public class OlmSessionTest { assertTrue(clearMsg1.equals(decryptedMsg1)); // clean objects.. - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + boolean res = false; + try { + res = bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(res); + bobAccount.releaseAccount(); aliceAccount.releaseAccount(); assertTrue(bobAccount.isReleased()); @@ -369,15 +420,46 @@ public class OlmSessionTest { } // get bob/luke identity key - Map bobIdentityKeys = bobAccount.identityKeys(); - Map aliceIdentityKeys = aliceAccount.identityKeys(); + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + Map aliceIdentityKeys = null; + + try { + aliceIdentityKeys = aliceAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); String aliceIdentityKey = TestHelper.getIdentityKey(aliceIdentityKeys); // get bob/luke one time keys - assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - assertTrue(0 == aliceAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + try { + aliceAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeys, 1); // create alice inbound session for bob @@ -401,7 +483,14 @@ public class OlmSessionTest { //assertTrue(false==bobSession.matchesInboundSessionFrom(bobIdentityKey, encryptedAliceToBobMsg1.mCipherText)); // release objects - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + boolean res = false; + try { + res = bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(res); + aliceAccount.releaseAccount(); bobAccount.releaseAccount(); assertTrue(aliceAccount.isReleased()); @@ -443,13 +532,32 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // get bob identity key - Map bobIdentityKeys = bobAccount.identityKeys(); + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null!=bobIdentityKey); // get bob one time keys - assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); @@ -538,7 +646,14 @@ public class OlmSessionTest { assertTrue(clearMsg3.equals(decryptedMsg3)); // clean objects.. - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + boolean res = false; + try { + res = bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(res); + bobAccount.releaseAccount(); aliceAccount.releaseAccount(); assertTrue(bobAccount.isReleased()); @@ -588,13 +703,32 @@ public class OlmSessionTest { } // get bob identity key - Map bobIdentityKeys = bobAccount.identityKeys(); + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); assertTrue(null != bobIdentityKey); // get bob one time keys - assertTrue(0 == bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER)); - Map> bobOneTimeKeys = bobAccount.oneTimeKeys(); + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(bobOneTimeKeys); String bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); assertNotNull(bobOneTimeKey); @@ -678,7 +812,14 @@ public class OlmSessionTest { assertTrue(!aliceSession.matchesInboundSessionFrom(null,null)); // release objects - assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession)); + boolean res = false; + try { + res = bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(res); + aliceAccount.releaseAccount(); bobAccount.releaseAccount(); assertTrue(aliceAccount.isReleased()); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index e3ca544..4096001 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -71,11 +71,25 @@ public class OlmUtilityTest { assertNotNull(account); // sign message - String messageSignature = account.signMessage(message); + String messageSignature = null; + + try { + messageSignature = account.signMessage(message); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(messageSignature); // get identities key (finger print key) - Map identityKeys = account.identityKeys(); + Map identityKeys = null; + + try { + identityKeys = account.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + assertNotNull(identityKeys); fingerPrintKey = TestHelper.getFingerprintKey(identityKeys); assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 649085e..3107ff3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -63,9 +63,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private transient long mNativeId; public OlmAccount() throws OlmException { - if(!initNewAccount()) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); - } + initNewAccount(); } /** @@ -97,11 +95,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * Create and initialize a native account instance.
* Wrapper for {@link #initNewAccountJni()}. * To be called before any other API call. - * @return true if init succeed, false otherwise. + * @exception OlmException the failure reason */ - private boolean initNewAccount() { - mNativeId = initNewAccountJni(); - return (0 != mNativeId); + private void initNewAccount() throws OlmException { + try { + mNativeId = initNewAccountJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); + } } /** @@ -147,10 +148,19 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I" * }
* @return identity keys dictionary if operation succeeds, null otherwise + * @exception OlmException the failure reason */ - public Map identityKeys() { + public Map identityKeys() throws OlmException { JSONObject identityKeysJsonObj = null; - byte[] identityKeysBuffer = identityKeysJni(); + + byte[] identityKeysBuffer; + + try { + identityKeysBuffer = identityKeysJni(); + } catch (Exception e) { + Log.e(LOG_TAG, "## identityKeys(): Failure - " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS, e.getMessage()); + } if (null != identityKeysBuffer) { try { @@ -165,6 +175,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return toStringMap(identityKeysJsonObj); } + /** * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
* Keys are Base64 encoded. @@ -180,6 +191,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { public long maxOneTimeKeys() { return maxOneTimeKeysJni(); } + private native long maxOneTimeKeysJni(); /** @@ -187,12 +199,17 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded.
* The corresponding keys are retrieved by {@link #oneTimeKeys()}. * @param aNumberOfKeys number of keys to generate - * @return 0 if operation succeed, -1 otherwise + * @exception OlmException the failure reason */ - public int generateOneTimeKeys(int aNumberOfKeys) { - return generateOneTimeKeysJni(aNumberOfKeys); + public void generateOneTimeKeys(int aNumberOfKeys) throws OlmException { + try { + generateOneTimeKeysJni(aNumberOfKeys); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS, e.getMessage()); + } } - private native int generateOneTimeKeysJni(int aNumberOfKeys); + + private native void generateOneTimeKeysJni(int aNumberOfKeys); /** * Return the "one time keys" in a dictionary.
@@ -207,11 +224,18 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * }

* Public API for {@link #oneTimeKeysJni()}.
* Note: these keys are to be published on the server. - * @return one time keys in string dictionary if operation succeed, null otherwise + * @return one time keys in string dictionary. + * @exception OlmException the failure reason */ - public Map> oneTimeKeys() { + public Map> oneTimeKeys() throws OlmException { JSONObject oneTimeKeysJsonObj = null; - byte[] oneTimeKeysBuffer = oneTimeKeysJni(); + byte[] oneTimeKeysBuffer; + + try { + oneTimeKeysBuffer = oneTimeKeysJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS, e.getMessage()); + } if( null != oneTimeKeysBuffer) { try { @@ -226,6 +250,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return toStringMapMap(oneTimeKeysJsonObj); } + /** * Get the public parts of the unpublished "one time keys" for the account.
* The returned data is a JSON-formatted object with the single property @@ -238,62 +263,67 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { /** * Remove the "one time keys" that the session used from the account. * @param aSession session instance - * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed + * @return true if the operation succeeded. + * @throws OlmException the failure reason */ - public int removeOneTimeKeysForSession(OlmSession aSession) { - int retCode = -1; + public boolean removeOneTimeKeys(OlmSession aSession) throws OlmException { + boolean res = false; - if(null != aSession) { - retCode = removeOneTimeKeysForSessionJni(aSession.getOlmSessionId()); - Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result="+retCode); + if (null != aSession) { + try { + res = (removeOneTimeKeysJni(aSession.getOlmSessionId()) >= 0); + Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result=" + res); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS, e.getMessage()); + } } - return retCode; + return res; } + /** * Remove the "one time keys" that the session used from the account. * @param aNativeOlmSessionId native session instance identifier * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed */ - private native int removeOneTimeKeysForSessionJni(long aNativeOlmSessionId); + private native int removeOneTimeKeysJni(long aNativeOlmSessionId); /** * Marks the current set of "one time keys" as being published. - * @return 0 if operation succeed, -1 otherwise + * @exception OlmException the failure reason */ - public int markOneTimeKeysAsPublished() { - return markOneTimeKeysAsPublishedJni(); + public void markOneTimeKeysAsPublished() throws OlmException { + try { + markOneTimeKeysAsPublishedJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED, e.getMessage()); + } } - private native int markOneTimeKeysAsPublishedJni(); + + private native void markOneTimeKeysAsPublishedJni(); /** * Sign a message with the ed25519 fingerprint key for this account.
* The signed message is returned by the method. * @param aMessage message to sign - * @return the signed message if operation succeed, null otherwise + * @return the signed message */ - public String signMessage(String aMessage) { + public String signMessage(String aMessage) throws OlmException { String result = null; if (null != aMessage) { - byte[] utf8String = null; - try { - utf8String = aMessage.getBytes("UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## signMessage(): failed =" + e.getMessage()); - } + byte[] utf8String = aMessage.getBytes("UTF-8"); - if (null != utf8String) { - byte[] signedMessage = signMessageJni(utf8String); + if (null != utf8String) { + byte[] signedMessage = signMessageJni(utf8String); - if (null != signedMessage) { - try { + if (null != signedMessage) { result = new String(signedMessage, "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## signMessage(): failed =" + e.getMessage()); } } + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE, e.getMessage()); } } @@ -407,7 +437,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } else { aErrorMsg.setLength(0); try { - pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); + pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8")), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -417,7 +447,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native byte[] serializeJni(byte[] aKey, StringBuffer aErrorMsg); + private native byte[] serializeJni(byte[] aKey); /** * Loads an account from a pickled base64 string.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 0cb06fa..a04286b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -39,6 +39,13 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION = 12; public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION = 13; + public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 20; + public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 21; + public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 22; + public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 23; + public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 24; + public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 25; + // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed"; public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "createNewSession() failed"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index d57e55b..bac8b34 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -82,16 +82,18 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz * Initialize a new account and return it to JAVA side.
* Since a C prt is returned as a jlong, special care will be taken * to make the cast (OlmAccount* => jlong) platform independent. -* @return the initialized OlmAccount* instance if init succeed, NULL otherwise +* @return the initialized OlmAccount* instance **/ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; OlmAccount *accountPtr = initializeAccountMemory(); // init account memory allocation if (!accountPtr) { LOGE("## initNewAccount(): failure - init account OOM"); + errorMessage = "init account OOM"; } else { @@ -107,6 +109,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi if ((0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) { LOGE("## initNewAccount(): failure - random buffer init"); + errorMessage = "random buffer init"; } else { @@ -116,6 +119,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi if (accountRetCode == olm_error()) { LOGE("## initNewAccount(): failure - account creation failed Msg=%s", olm_account_last_error(accountPtr)); + errorMessage = olm_account_last_error(accountPtr); } LOGD("## initNewAccount(): success - OLM account created"); @@ -128,6 +132,11 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return (jlong)(intptr_t)accountPtr; } @@ -141,12 +150,14 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; jbyteArray byteArrayRetValue = NULL; OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); if (!accountPtr) { LOGE("## identityKeys(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr"; } else { @@ -159,6 +170,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject if (!identityKeysBytesPtr) { LOGE("## identityKeys(): failure - identity keys array OOM"); + errorMessage = "identity keys array OOM"; } else { @@ -167,7 +179,8 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject if (keysResult == olm_error()) { - LOGE("## identityKeys(): failure - error getting identity keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); + LOGE("## identityKeys(): failure - error getting identity keys Msg=%s", errorMessage); } else { @@ -177,6 +190,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject if (!byteArrayRetValue) { LOGE("## identityKeys(): failure - return byte array OOM"); + errorMessage = "byte array OOM"; } else { @@ -189,6 +203,11 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return byteArrayRetValue; } @@ -221,16 +240,16 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thi /** * Generate "one time keys". * @param aNumberOfKeys number of keys to generate - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) { + const char* errorMessage = NULL; OlmAccount *accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); - jint retCode = ERROR_CODE_KO; if (!accountPtr) { LOGE("## generateOneTimeKeysJni(): failure - invalid Account ptr"); + errorMessage = "invalid Account ptr"; } else { @@ -243,6 +262,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject if ((0 != randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) { LOGE("## generateOneTimeKeysJni(): failure - random buffer init"); + errorMessage = "random buffer init"; } else { @@ -251,12 +271,13 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject // retrieve key pairs in keysBytesPtr size_t result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); - if (result == olm_error()) { - LOGE("## generateOneTimeKeysJni(): failure - error generating one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + if (result == olm_error()) + { + errorMessage = olm_account_last_error(accountPtr); + LOGE("## generateOneTimeKeysJni(): failure - error generating one time keys Msg=%s", errorMessage); } else { - retCode = ERROR_CODE_OK; LOGD("## generateOneTimeKeysJni(): success - result=%lu", static_cast(result)); } } @@ -268,7 +289,10 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject } } - return retCode; + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } /** @@ -278,6 +302,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; jbyteArray byteArrayRetValue = NULL; OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); @@ -286,6 +311,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t if (!accountPtr) { LOGE("## oneTimeKeysJni(): failure - invalid Account ptr"); + errorMessage = "invalid Account ptr"; } else { @@ -296,13 +322,16 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t if (!keysBytesPtr) { LOGE("## oneTimeKeysJni(): failure - one time keys array OOM"); + errorMessage = "one time keys array OOM"; } else { // retrieve key pairs in keysBytesPtr size_t keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); + if (keysResult == olm_error()) { LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); } else { @@ -312,6 +341,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t if (!byteArrayRetValue) { LOGE("## oneTimeKeysJni(): failure - return byte array OOM"); + errorMessage = "return byte array OOM"; } else { @@ -324,6 +354,11 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return byteArrayRetValue; } @@ -331,21 +366,24 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t * Remove the "one time keys" that the session used from the account. * Return the public parts of the unpublished "one time keys" for the account * @param aNativeOlmSessionId session instance - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS if no matching keys, ERROR_CODE_KO otherwise + * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) { + const char* errorMessage = NULL; jint retCode = ERROR_CODE_KO; OlmAccount* accountPtr = NULL; OlmSession* sessionPtr = (OlmSession*)aNativeOlmSessionId; if (!sessionPtr) { - LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid session ptr"); + LOGE("## removeOneTimeKeysJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; } else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { - LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid account ptr"); + LOGE("## removeOneTimeKeysJni(): failure - invalid account ptr"); + errorMessage = "invalid account ptr"; } else { @@ -353,33 +391,36 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, if (result == olm_error()) { // the account doesn't have any matching "one time keys".. - LOGW("## removeOneTimeKeysForSessionJni(): failure - removing one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); - - retCode = ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS; + LOGW("## removeOneTimeKeysJni(): failure - removing one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); } else { retCode = ERROR_CODE_OK; - LOGD("## removeOneTimeKeysForSessionJni(): success"); + LOGD("## removeOneTimeKeysJni(): success"); } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return retCode; } /** * Mark the current set of "one time keys" as being published. - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) { - jint retCode = ERROR_CODE_OK; + const char* errorMessage = NULL; OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); if (!accountPtr) { LOGE("## markOneTimeKeysAsPublishedJni(): failure - invalid account ptr"); - retCode = ERROR_CODE_KO; + errorMessage = "invalid account ptr"; } else { @@ -388,7 +429,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, if (result == olm_error()) { LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",(const char *)olm_account_last_error(accountPtr)); - retCode = ERROR_CODE_KO; + errorMessage = (const char *)olm_account_last_error(accountPtr); } else { @@ -396,7 +437,10 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, } } - return retCode; + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } /** @@ -407,16 +451,19 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) { + const char* errorMessage = NULL; OlmAccount* accountPtr = NULL; jbyteArray signedMsgRetValueBuffer = NULL; if (!aMessage) { LOGE("## signMessageJni(): failure - invalid aMessage param"); + errorMessage = "invalid aMessage param"; } else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { LOGE("## signMessageJni(): failure - invalid account ptr"); + errorMessage = "invalid account ptr"; } else { @@ -431,6 +478,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t if (!signedMsgPtr) { LOGE("## signMessageJni(): failure - signature allocation OOM"); + errorMessage = "signature allocation OOM"; } else { @@ -444,6 +492,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t if (resultSign == olm_error()) { LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); } else { @@ -467,21 +516,23 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return signedMsgRetValueBuffer; } /** * Serialize and encrypt account instance into a base64 string.
* @param aKeyBuffer key used to encrypt the serialized account data -* @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { + const char* errorMessage = NULL; jbyteArray pickledDataRetValue = 0; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; - jstring errorJstring = 0; jbyte* keyPtr = NULL; OlmAccount* accountPtr = NULL; @@ -490,26 +541,17 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi if (!aKeyBuffer) { LOGE(" ## serializeJni(): failure - invalid key"); - } - else if (!aErrorMsg) - { - LOGE(" ## serializeJni(): failure - invalid error object"); + errorMessage = "invalid key"; } else if (!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) { LOGE(" ## serializeJni(): failure - invalid account ptr"); - } - else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## serializeJni(): failure - unable to get error class"); - } - else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## serializeJni(): failure - unable to get error method ID"); + errorMessage = "invalid account ptr"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, NULL))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else { @@ -523,6 +565,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi if (!pickledPtr) { LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; } else { @@ -533,13 +576,8 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); - - if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_account_last_error(accountPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_account() Msg=%s", errorMessage); } else { @@ -562,6 +600,11 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return pickledDataRetValue; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 94a0381..5b73acd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -39,15 +39,15 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject // one time keys JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); +JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); // signing JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); // serialization -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg); +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer); JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); #ifdef __cplusplus diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index f1d124e..1c80388 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -55,7 +55,6 @@ namespace AndroidOlmSdk { // Error codes definition static const int ERROR_CODE_OK = 0; - static const int ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS = ERROR_CODE_OK+1; static const int ERROR_CODE_KO = -1; // constants -- cgit v1.2.3 From 261c08086c0a6dc6c9f9400017a1c1a03cbece23 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 12:35:15 +0100 Subject: the OlmInboundGroupSession methods trigger an exception when they fails --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 10 +- .../src/main/java/org/matrix/olm/OlmAccount.java | 1 + .../src/main/java/org/matrix/olm/OlmException.java | 4 + .../org/matrix/olm/OlmInboundGroupSession.java | 63 ++++------- .../src/main/jni/olm_inbound_group_session.cpp | 125 +++++++++------------ .../src/main/jni/olm_inbound_group_session.h | 6 +- 6 files changed, 91 insertions(+), 118 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 0f0d779..9526410 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -138,7 +138,13 @@ public class OlmGroupSessionTest { @Test public void test08GetInboundGroupSessionIdentifier() { // check both session identifiers are equals - mBobSessionIdentifier = mBobInboundGroupSession.sessionIdentifier(); + mBobSessionIdentifier = null; + + try { + mBobSessionIdentifier = mBobInboundGroupSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertFalse(TextUtils.isEmpty(mBobSessionIdentifier)); } @@ -479,7 +485,7 @@ public class OlmGroupSessionTest { String exceptionMessage = null; try { bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg); - } catch (OlmInboundGroupSession.DecryptMessageException e) { + } catch (OlmException e) { exceptionMessage = e.getMessage(); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 3107ff3..9d8e6d6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -307,6 +307,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * The signed message is returned by the method. * @param aMessage message to sign * @return the signed message + * @exception OlmException the failure reason */ public String signMessage(String aMessage) throws OlmException { String result = null; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index a04286b..f31cab2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -46,6 +46,10 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 24; public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 25; + public static final int EXCEPTION_CODE_SESSION_IDENTIFIER = 30; + public static final int EXCEPTION_CODE_SESSION_DECRYPT_SESSION = 31; + + // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed"; public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "createNewSession() failed"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 68878c7..f0536bd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -52,15 +52,6 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri public long mIndex; } - /** - * Exception triggered in {@link #decryptMessage(String)} - */ - static public class DecryptMessageException extends Exception { - public DecryptMessageException(String message) { - super(message); - } - } - /** * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. @@ -71,10 +62,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { if(createNewSession()) { - if (0 != initInboundGroupSession(aSessionKey)) { - releaseSession();// prevent memory leak before throwing - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION,OlmException.EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION); - } + initInboundGroupSession(aSessionKey); } else { throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION); } @@ -127,38 +115,34 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * The session key parameter is retrieved from an outbound group session * see {@link OlmOutboundGroupSession#sessionKey()} * @param aSessionKey session key - * @return 0 if operation succeed, -1 otherwise + * @exception OlmException the failure reason */ - private int initInboundGroupSession(String aSessionKey) { - int retCode = -1; - - if(TextUtils.isEmpty(aSessionKey)){ + private void initInboundGroupSession(String aSessionKey) throws OlmException { + if (TextUtils.isEmpty(aSessionKey)) { Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); } else { try { - retCode = initInboundGroupSessionJni(aSessionKey.getBytes("UTF-8")); + initInboundGroupSessionJni(aSessionKey.getBytes("UTF-8")); } catch (Exception e) { - Log.e(LOG_TAG, "## initInboundGroupSession() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); } } - - return retCode; } - private native int initInboundGroupSessionJni(byte[] aSessionKeyBuffer); + private native void initInboundGroupSessionJni(byte[] aSessionKeyBuffer); /** * Retrieve the base64-encoded identifier for this inbound group session. - * @return the session ID if operation succeed, null otherwise + * @return the session ID */ - public String sessionIdentifier() { + public String sessionIdentifier() throws OlmException { try { return new String(sessionIdentifierJni(), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_IDENTIFIER, e.getMessage()); } - - return null; } private native byte[] sessionIdentifierJni(); @@ -168,32 +152,26 @@ 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 DecryptMessageException if there is an error while + * @exception OlmException teh failure reason */ - public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws DecryptMessageException { + public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws OlmException { DecryptMessageResult result = new DecryptMessageResult(); - StringBuffer errorMsg = new StringBuffer(); try { - byte[] decryptedMessageBuffer = decryptMessageJni(aEncryptedMsg.getBytes("UTF-8"), result, errorMsg); + byte[] decryptedMessageBuffer = decryptMessageJni(aEncryptedMsg.getBytes("UTF-8"), result); if (null != decryptedMessageBuffer) { result.mDecryptedMessage = new String(decryptedMessageBuffer, "UTF-8"); } } catch (Exception e) { Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage()); - errorMsg.append(e.getMessage()); - } - - // check if there is an error while decrypting - if (0 != errorMsg.length()) { - throw new DecryptMessageException(errorMsg.toString()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_SESSION, e.getMessage()); } return result; } - private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg); + private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult); //============================================================================================================== // Serialization management @@ -231,15 +209,17 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri protected String serialize(String aKey, StringBuffer aErrorMsg) { String pickleRetValue = null; + aErrorMsg.setLength(0); + // sanity check if(null == aErrorMsg) { Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); + aErrorMsg.append("aErrorMsg=null"); } else if(TextUtils.isEmpty(aKey)) { aErrorMsg.append("Invalid input parameters in serialize()"); } else { - aErrorMsg.setLength(0); try { - pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8"), aErrorMsg), "UTF-8"); + pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8")), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -251,10 +231,9 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * JNI counter part of {@link #serialize(String, StringBuffer)}. * @param aKey encryption key - * @param aErrorMsg error message description * @return pickled base64 string if operation succeed, null otherwise */ - private native byte[] serializeJni(byte[] aKey, StringBuffer aErrorMsg); + private native byte[] serializeJni(byte[] aKey); /** * Loads an account from a pickled base64 string.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index d396eb9..223b3d8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -36,7 +36,7 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env } else { - LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); + LOGD(" ## releaseSessionJni(): sessionPtr=%p", sessionPtr); #ifdef ENABLE_JNI_LOG size_t retCode = olm_clear_inbound_group_session(sessionPtr); LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); @@ -84,11 +84,10 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * /** * Create a new in-bound session.
* @param aSessionKey session key from an outbound session - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) +JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) { - jint retCode = ERROR_CODE_KO; + const char* errorMessage = NULL; OlmInboundGroupSession *sessionPtr = NULL; jbyte* sessionKeyPtr = NULL; size_t sessionResult; @@ -98,14 +97,17 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JN if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## initInboundGroupSessionJni(): failure - invalid inbound group session instance"); + errorMessage = "invalid inbound group session instance"; } else if (!aSessionKeyBuffer) { LOGE(" ## initInboundGroupSessionJni(): failure - invalid aSessionKey"); + errorMessage = "invalid aSessionKey"; } else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) { LOGE(" ## initInboundGroupSessionJni(): failure - session key JNI allocation OOM"); + errorMessage = "Session key JNI allocation OOM"; } else { @@ -114,12 +116,11 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JN sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); if (sessionResult == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## initInboundGroupSessionJni(): failure - init inbound session creation Msg=%s",errorMsgPtr); + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## initInboundGroupSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); } else { - retCode = ERROR_CODE_OK; LOGD(" ## initInboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); } } @@ -130,15 +131,18 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JN env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); } - return retCode; + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } - /** * Get a base64-encoded identifier for this inbound group session. */ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; OlmInboundGroupSession *sessionPtr = NULL; jbyteArray returnValue = 0; @@ -147,6 +151,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## sessionIdentifierJni(): failure - invalid inbound group session instance"); + errorMessage = "invalid inbound group session instance"; } else { @@ -158,7 +163,8 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN if (!sessionIdPtr) { - LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); + LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); + errorMessage = "inbound group session identifier allocation OOM"; } else { @@ -166,11 +172,11 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN if (result == olm_error()) { + errorMessage = (const char *)olm_inbound_group_session_last_error(sessionPtr); LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); } else { - sessionIdPtr[result] = static_cast('\0'); LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); @@ -182,59 +188,56 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return returnValue; } -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult) { jbyteArray decryptedMsgBuffer = 0; + const char* errorMessage = NULL; OlmInboundGroupSession *sessionPtr = NULL; jbyte *encryptedMsgPtr = NULL; jclass indexObjJClass = 0; jfieldID indexMsgFieldId; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; - const char *errorMsgPtr = NULL; LOGD("## decryptMessageJni(): inbound group session IN"); if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); + errorMessage = "invalid inbound group session ptr=NULL"; } else if (!aEncryptedMsgBuffer) { LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); + errorMessage = "invalid encrypted message"; } else if (!aDecryptionResult) { LOGE(" ## decryptMessageJni(): failure - invalid index object"); - } - else if (!aErrorMsg) - { - LOGE(" ## decryptMessageJni(): failure - invalid error object"); - } - else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## decryptMessageJni(): failure - unable to get error class"); - } - else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## decryptMessageJni(): failure - unable to get error method ID"); + errorMessage = "invalid index object"; } else if (!(encryptedMsgPtr = env->GetByteArrayElements(aEncryptedMsgBuffer, 0))) { LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + errorMessage = "encrypted message JNI allocation OOM"; } else if (!(indexObjJClass = env->GetObjectClass(aDecryptionResult))) { LOGE("## decryptMessageJni(): failure - unable to get index class"); + errorMessage = "unable to get index class"; } else if (!(indexMsgFieldId = env->GetFieldID(indexObjJClass,"mIndex","J"))) { LOGE("## decryptMessageJni(): failure - unable to get index type field"); + errorMessage = "unable to get index type field"; } else { @@ -246,6 +249,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn if (!tempEncryptedPtr) { LOGE(" ## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); + errorMessage = "tempEncryptedPtr allocation OOM"; } else { @@ -258,15 +262,8 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn encryptedMsgLength); if (maxPlainTextLength == olm_error()) { - errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); - - jstring errorJstring = env->NewStringUTF(errorMsgPtr); - - if (errorJstring) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s", errorMessage); } else { @@ -287,15 +284,8 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn &messageIndex); if (plaintextLength == olm_error()) { - errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr); - - jstring errorJstring = env->NewStringUTF(errorMsgPtr); - - if (errorJstring) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s", errorMessage); } else { @@ -327,6 +317,11 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn env->ReleaseByteArrayElements(aEncryptedMsgBuffer, encryptedMsgPtr, JNI_ABORT); } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return decryptedMsgBuffer; } @@ -334,15 +329,13 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn /** * Serialize and encrypt session instance into a base64 string.
* @param aKeyBuffer key used to encrypt the serialized session data -* @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { - jbyteArray pickledDataRet = 0; + const char* errorMessage = NULL; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; + jbyteArray pickledDataRet = 0; jbyte* keyPtr = NULL; OlmInboundGroupSession* sessionPtr = NULL; @@ -351,26 +344,17 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## serializeJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; } else if (!aKeyBuffer) { LOGE(" ## serializeJni(): failure - invalid key"); - } - else if (!aErrorMsg) - { - LOGE(" ## serializeJni(): failure - invalid error object"); - } - else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## serializeJni(): failure - unable to get error class"); - } - else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## serializeJni(): failure - unable to get error method ID"); + errorMessage = "invalid key"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else { @@ -384,6 +368,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en if (!pickledPtr) { LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; } else { @@ -394,15 +379,8 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); - - jstring errorJstring = env->NewStringUTF(errorMsgPtr); - - if (errorJstring) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s", errorMessage); } else { @@ -423,6 +401,11 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return pickledDataRet; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index 0ef55cf..a631acf 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -32,12 +32,12 @@ extern "C" { JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); +JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg); +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex); // serialization -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); -- cgit v1.2.3 From 846ea49a9839862868ff94dec2eeea0b7d52221b Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 13:13:13 +0100 Subject: the OlmOutboundGroupSession methods trigger an exception when they fail --- .../java/org/matrix/olm/OlmGroupSessionTest.java | 28 ++++- .../src/main/java/org/matrix/olm/OlmException.java | 3 + .../org/matrix/olm/OlmInboundGroupSession.java | 3 +- .../org/matrix/olm/OlmOutboundGroupSession.java | 61 +++++------ .../src/main/jni/olm_outbound_group_session.cpp | 114 ++++++++++----------- .../src/main/jni/olm_outbound_group_session.h | 6 +- 6 files changed, 110 insertions(+), 105 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index 9526410..c532179 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -90,7 +90,14 @@ public class OlmGroupSessionTest { @Test public void test02GetOutboundGroupSessionIdentifier() { // test session ID - mAliceSessionIdentifier = mAliceOutboundGroupSession.sessionIdentifier(); + mAliceSessionIdentifier = null; + + try { + mAliceSessionIdentifier = mAliceOutboundGroupSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(mAliceSessionIdentifier); assertTrue(mAliceSessionIdentifier.length() > 0); } @@ -98,7 +105,13 @@ public class OlmGroupSessionTest { @Test public void test03GetOutboundGroupSessionKey() { // test session Key - mAliceOutboundSessionKey = mAliceOutboundGroupSession.sessionKey(); + mAliceOutboundSessionKey = null; + + try { + mAliceOutboundSessionKey = mAliceOutboundGroupSession.sessionKey(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(mAliceOutboundSessionKey); assertTrue(mAliceOutboundSessionKey.length() > 0); } @@ -115,7 +128,7 @@ public class OlmGroupSessionTest { // alice encrypts a message to bob try { mAliceToBobMessage = mAliceOutboundGroupSession.encryptMessage(CLEAR_MESSAGE1); - } catch (OlmOutboundGroupSession.EncryptMessageException e) { + } catch (Exception e) { assertTrue("Exception in bob encryptMessage, Exception code=" + e.getMessage(), false); } assertFalse(TextUtils.isEmpty(mAliceToBobMessage)); @@ -275,7 +288,13 @@ public class OlmGroupSessionTest { assertNotNull(aliceOutboundGroupSession); // get the session key from the outbound group session - String sessionKeyRef = aliceOutboundGroupSession.sessionKey(); + String sessionKeyRef = null; + + try { + sessionKeyRef = aliceOutboundGroupSession.sessionKey(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(sessionKeyRef); // bob creates INBOUND GROUP SESSION @@ -286,7 +305,6 @@ public class OlmGroupSessionTest { } assertNotNull(bobInboundGroupSessionRef); - // serialize alice session Context context = getInstrumentation().getContext(); try { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index f31cab2..1a1b8ab 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -49,6 +49,9 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_SESSION_IDENTIFIER = 30; public static final int EXCEPTION_CODE_SESSION_DECRYPT_SESSION = 31; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 40; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 41; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 42; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index f0536bd..7ac38b2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -209,8 +209,6 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri protected String serialize(String aKey, StringBuffer aErrorMsg) { String pickleRetValue = null; - aErrorMsg.setLength(0); - // sanity check if(null == aErrorMsg) { Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); @@ -218,6 +216,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } else if(TextUtils.isEmpty(aKey)) { aErrorMsg.append("Invalid input parameters in serialize()"); } else { + aErrorMsg.setLength(0); try { pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8")), "UTF-8"); } catch (Exception e) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 66a44d2..c27addb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -42,15 +42,6 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ private transient long mNativeId; - /** - * Exception triggered in {@link #encryptMessage(String)} - */ - static public class EncryptMessageException extends Exception { - public EncryptMessageException(String message) { - super(message); - } - } - /** * Constructor.
* Create and save a new session native instance ID and @@ -60,10 +51,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ public OlmOutboundGroupSession() throws OlmException { if(createNewSession()) { - if( 0 != initOutboundGroupSession()) { - releaseSession();// prevent memory leak before throwing - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION); - } + initOutboundGroupSession(); } else { throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION); } @@ -114,25 +102,29 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser /** * Start a new outbound group session.
- * @return 0 if operation succeed, -1 otherwise + * @exception OlmException the failre reason */ - private int initOutboundGroupSession() { - return initOutboundGroupSessionJni(); + private void initOutboundGroupSession() throws OlmException { + try { + initOutboundGroupSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION, e.getMessage()); + } } - private native int initOutboundGroupSessionJni(); + + private native void initOutboundGroupSessionJni(); /** * Get a base64-encoded identifier for this session. - * @return session identifier if operation succeed, null otherwise. + * @return session identifier */ - public String sessionIdentifier() { + public String sessionIdentifier() throws OlmException { try { return new String(sessionIdentifierJni(), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER, e.getMessage()); } - - return null; } private native byte[] sessionIdentifierJni(); @@ -153,15 +145,15 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * Each message is sent with a different ratchet key. This method returns the * ratchet key that will be used for the next message. * @return outbound session key + * @exception OlmException the failure reason */ - public String sessionKey() { + public String sessionKey() throws OlmException { try { return new String(sessionKeyJni(), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## sessionKey() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY, e.getMessage()); } - - return null; } private native byte[] sessionKeyJni(); @@ -171,33 +163,27 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * The message given as parameter is encrypted and returned as the return value. * @param aClearMsg message to be encrypted * @return the encrypted message - * @exception EncryptMessageException the encryption failure reason + * @exception OlmException the encryption failure reason */ - public String encryptMessage(String aClearMsg) throws EncryptMessageException { + public String encryptMessage(String aClearMsg) throws OlmException { String retValue = null; if (!TextUtils.isEmpty(aClearMsg)) { - StringBuffer errorMsg = new StringBuffer(); - try { - byte[] encryptedBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8"), errorMsg); + byte[] encryptedBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8")); if (null != encryptedBuffer) { retValue = new String(encryptedBuffer , "UTF-8"); } } catch (Exception e) { Log.e(LOG_TAG, "## encryptMessage() failed " + e.getMessage()); - errorMsg.append(e.getMessage()); - } - - if (0 != errorMsg.length()) { - throw new EncryptMessageException(errorMsg.toString()); + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE, e.getMessage()); } } return retValue; } - private native byte[] encryptMessageJni(byte[] aClearMsgBuffer, StringBuffer aErrorMsg); + private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); //============================================================================================================== @@ -242,9 +228,8 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } else if(TextUtils.isEmpty(aKey)) { aErrorMsg.append("Invalid input parameters in serialize()"); } else { - aErrorMsg.setLength(0); try { - pickleRetValue = serializeJni(aKey.getBytes("UTF-8"), aErrorMsg); + pickleRetValue = serializeJni(aKey.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG,"## serialize(): failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -253,7 +238,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return pickleRetValue; } - private native String serializeJni(byte[] aKey, StringBuffer aErrorMsg); + private native String serializeJni(byte[] aKey); /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 4168742..982840c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -84,11 +84,10 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv /** * Start a new outbound session.
- * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) +JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) { - jint retCode = ERROR_CODE_KO; + const char* errorMessage = NULL; LOGD("## initOutboundGroupSessionJni(): IN"); @@ -97,6 +96,7 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( if (!sessionPtr) { LOGE(" ## initOutboundGroupSessionJni(): failure - invalid outbound group session instance"); + errorMessage = "invalid outbound group session instance"; } else { @@ -109,6 +109,7 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init"); + errorMessage = "random buffer init"; } else { @@ -120,11 +121,11 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); if (sessionResult == olm_error()) { - LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s", errorMessage); } else { - retCode = ERROR_CODE_OK; LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); } @@ -132,7 +133,10 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( } } - return retCode; + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } /** @@ -142,12 +146,14 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J { LOGD("## sessionIdentifierJni(): outbound group session IN"); + const char* errorMessage = NULL; OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); jbyteArray returnValue = 0; if (!sessionPtr) { LOGE(" ## sessionIdentifierJni(): failure - invalid outbound group session instance"); + errorMessage = "invalid outbound group session instance"; } else { @@ -160,6 +166,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J if (!sessionIdPtr) { LOGE(" ## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); + errorMessage = "outbound identifier allocation OOM"; } else { @@ -167,7 +174,8 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J if (result == olm_error()) { - LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s",reinterpret_cast(olm_outbound_group_session_last_error(sessionPtr))); + errorMessage = reinterpret_cast(olm_outbound_group_session_last_error(sessionPtr)); + LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s", errorMessage); } else { @@ -185,6 +193,11 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return returnValue; } @@ -223,12 +236,14 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * { LOGD("## sessionKeyJni(): outbound group session IN"); + const char* errorMessage = NULL; OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); jbyteArray returnValue = 0; if (!sessionPtr) { LOGE(" ## sessionKeyJni(): failure - invalid outbound group session instance"); + errorMessage = "invalid outbound group session instance"; } else { @@ -241,6 +256,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * if (!sessionKeyPtr) { LOGE(" ## sessionKeyJni(): failure - session key allocation OOM"); + errorMessage = "session key allocation OOM"; } else { @@ -248,7 +264,8 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * if (result == olm_error()) { - LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s",(const char *)olm_outbound_group_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s", errorMessage); } else { @@ -265,44 +282,38 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return returnValue; } -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aErrorMsg) +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) { LOGD("## encryptMessageJni(): IN"); + const char* errorMessage = NULL; jbyteArray encryptedMsgRet = 0; OlmOutboundGroupSession *sessionPtr = NULL; jbyte* clearMsgPtr = NULL; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; - if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## encryptMessageJni(): failure - invalid outbound group session ptr=NULL"); - } - else if (!aErrorMsg) - { - LOGE(" ## encryptMessageJni(): failure - invalid error output"); + errorMessage = "invalid outbound group session ptr=NULL"; } else if (!aClearMsgBuffer) { LOGE(" ## encryptMessageJni(): failure - invalid clear message"); + errorMessage = "invalid clear message"; } else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, NULL))) { LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM"); - } - else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## encryptMessageJni(): failure - unable to get error class"); - } - else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## encryptMessageJni(): failure - unable to get error method ID"); + errorMessage = "clear message JNI allocation OOM"; } else { @@ -317,6 +328,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE if (!encryptedMsgPtr) { LOGE(" ## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); + errorMessage = "encryptedMsgPtr buffer OOM"; } else { @@ -331,15 +343,8 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE if (encryptedLength == olm_error()) { - const char * errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr); - - jstring errorJstring = env->NewStringUTF(errorMsgPtr); - - if (errorJstring) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s", errorMessage); } else { @@ -362,6 +367,11 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return encryptedMsgRet; } @@ -369,15 +379,13 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE /** * Serialize and encrypt session instance into a base64 string.
* @param aKey key used to encrypt the serialized session data -* @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { + const char* errorMessage = NULL; + jstring pickledDataRetValue = 0; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; - jstring errorJstring = 0; jbyte* keyPtr = NULL; OlmOutboundGroupSession* sessionPtr = NULL; @@ -386,26 +394,17 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) { LOGE(" ## serializeJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; } else if (!aKeyBuffer) { LOGE(" ## serializeJni(): failure - invalid key"); - } - else if (!aErrorMsg) - { - LOGE(" ## serializeJni(): failure - invalid error object"); - } - else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## serializeJni(): failure - unable to get error class"); - } - else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## serializeJni(): failure - unable to get error method ID"); + errorMessage = "invalid key"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else { @@ -419,6 +418,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, if(!pickledPtr) { LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; } else { @@ -429,13 +429,8 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s",errorMsgPtr); - - if (!(errorJstring = env->NewStringUTF(errorMsgPtr))) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s", errorMessage); } else { @@ -455,6 +450,11 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return pickledDataRetValue; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index f954bef..1156b77 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -32,15 +32,15 @@ extern "C" { JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aErrorMsg); +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); // serialization -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus -- cgit v1.2.3 From 4ca8086a394eb403494c3411e8f61c5964ef5cda Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 14:35:08 +0100 Subject: OlmSession triggers exception when there is a failure. --- .../java/org/matrix/olm/OlmSessionTest.java | 251 ++++++++++++++++++--- .../src/main/java/org/matrix/olm/OlmException.java | 55 +++-- .../org/matrix/olm/OlmInboundGroupSession.java | 4 +- .../src/main/java/org/matrix/olm/OlmSession.java | 93 ++++---- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 176 +++++++++------ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 10 +- 6 files changed, 402 insertions(+), 187 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index e8b2288..ec2582f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -131,9 +131,18 @@ public class OlmSessionTest { assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } String clearMsg = "Heloo bob , this is alice!"; - OlmMessage encryptedMsgToBob = aliceSession.encryptMessage(clearMsg); + OlmMessage encryptedMsgToBob = null; + try { + encryptedMsgToBob = aliceSession.encryptMessage(clearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsgToBob); assertNotNull(encryptedMsgToBob.mCipherText); Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText); @@ -153,7 +162,12 @@ public class OlmSessionTest { assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); } - String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); + String decryptedMsg = null; + try { + decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(decryptedMsg); // MESSAGE COMPARISON: decrypted vs encrypted @@ -255,10 +269,22 @@ public class OlmSessionTest { assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + String helloClearMsg = "Hello I'm Alice!"; - OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + OlmMessage encryptedAliceToBobMsg1 = null; + + try { + encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedAliceToBobMsg1); assertNotNull(encryptedAliceToBobMsg1.mCipherText); @@ -279,7 +305,12 @@ public class OlmSessionTest { } // DECRYPT MESSAGE FROM ALICE - String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + String decryptedMsg01 = null; + try { + decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(decryptedMsg01); // MESSAGE COMPARISON: decrypted vs encrypted @@ -291,19 +322,54 @@ public class OlmSessionTest { String clearMsg3 = "Let's go to the opera."; // bob encrypts messages - OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + OlmMessage encryptedMsg1 = null; + try { + encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsg1); - OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + + OlmMessage encryptedMsg2 = null; + try { + encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsg2); - OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + + + OlmMessage encryptedMsg3 = null; + try { + encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsg3); // alice decrypts bob's messages - String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); + String decryptedMsg1 = null; + try { + decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(decryptedMsg1); - String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); + String decryptedMsg2 = null; + try { + decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(decryptedMsg2); - String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); + String decryptedMsg3 = null; + try { + decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(decryptedMsg3); // comparison tests @@ -313,9 +379,22 @@ public class OlmSessionTest { // and one more from alice to bob clearMsg1 = "another message from Alice to Bob!!"; - encryptedMsg1 = aliceSession.encryptMessage(clearMsg1); + encryptedMsg1 = null; + + try { + encryptedMsg1 = aliceSession.encryptMessage(clearMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsg1); - decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1); + + decryptedMsg1 = null; + try { + decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(decryptedMsg1); assertTrue(clearMsg1.equals(decryptedMsg1)); @@ -378,10 +457,21 @@ public class OlmSessionTest { } assertTrue(0!=bobSession.getOlmSessionId()); - String aliceSessionId = aliceSession.sessionIdentifier(); + String aliceSessionId = null; + try { + aliceSessionId = aliceSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(aliceSessionId); - String bobSessionId = bobSession.sessionIdentifier(); + String bobSessionId = null; + try { + bobSessionId = bobSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(bobSessionId); // must be the same for both ends of the conversation @@ -463,10 +553,21 @@ public class OlmSessionTest { String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeys, 1); // create alice inbound session for bob - assertTrue(0==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey1)); + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } String aliceClearMsg = "hello helooo to bob!"; - OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg); + OlmMessage encryptedAliceToBobMsg1 = null; + + try { + encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertFalse(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); // init bob session with alice PRE KEY @@ -571,10 +672,20 @@ public class OlmSessionTest { assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - assertNotNull(aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + String helloClearMsg = "Hello I'm Alice!"; - OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + OlmMessage encryptedAliceToBobMsg1 = null; + try { + encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedAliceToBobMsg1); assertNotNull(encryptedAliceToBobMsg1.mCipherText); @@ -595,7 +706,14 @@ public class OlmSessionTest { } // DECRYPT MESSAGE FROM ALICE - String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + String decryptedMsg01 = null; + + try { + decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(decryptedMsg01); // MESSAGE COMPARISON: decrypted vs encrypted @@ -607,11 +725,28 @@ public class OlmSessionTest { String clearMsg3 = "Let's go to the opera."; // bob encrypts messages - OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + OlmMessage encryptedMsg1 = null; + try { + encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsg1); - OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + + OlmMessage encryptedMsg2 = null; + try { + encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsg2); - OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + + OlmMessage encryptedMsg3 = null; + try { + encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsg3); // serialize alice session @@ -742,26 +877,70 @@ public class OlmSessionTest { } // SANITY CHECK TESTS FOR: initOutboundSessionWithAccount() - assertTrue(-1==aliceSession.initOutboundSession(null, bobIdentityKey, bobOneTimeKey)); - assertTrue(-1==aliceSession.initOutboundSession(aliceAccount, null, bobOneTimeKey)); - assertTrue(-1==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, null)); - assertTrue(-1==aliceSession.initOutboundSession(null, null, null)); + String errorMessage = null; + try { + aliceSession.initOutboundSession(null, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + errorMessage = null; + try { + aliceSession.initOutboundSession(aliceAccount, null, bobOneTimeKey); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + errorMessage = null; + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, null); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + errorMessage = null; + try { + aliceSession.initOutboundSession(null, null, null); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); // init properly - assertTrue(0==aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey)); + errorMessage = null; + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null == errorMessage); // SANITY CHECK TESTS FOR: encryptMessage() - assertTrue(null==aliceSession.encryptMessage(null)); + OlmMessage message = null; + try { + message = aliceSession.encryptMessage(null); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(null==message); // encrypt properly - OlmMessage encryptedMsgToBob = aliceSession.encryptMessage("A message for bob"); + OlmMessage encryptedMsgToBob = null; + try { + encryptedMsgToBob = aliceSession.encryptMessage("A message for bob"); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } assertNotNull(encryptedMsgToBob); // SANITY CHECK TESTS FOR: initInboundSessionWithAccount() OlmSession bobSession = null; try { bobSession = new OlmSession(); - String errorMessage = null; + errorMessage = null; try { bobSession.initInboundSession(null, encryptedMsgToBob.mCipherText); } catch (Exception e) { @@ -802,7 +981,13 @@ public class OlmSessionTest { } // SANITY CHECK TESTS FOR: decryptMessage() - String decryptedMsg = aliceSession.decryptMessage(null); + String decryptedMsg = null; + try { + decryptedMsg = aliceSession.decryptMessage(null); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(null==decryptedMsg); // SANITY CHECK TESTS FOR: matchesInboundSession() diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 1a1b8ab..a6f1805 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -24,41 +24,40 @@ import java.io.IOException; */ public class OlmException extends IOException { // exception codes - public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 0; - public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 1; - public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 2; - public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 3; - public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 4; - public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 5; - public static final int EXCEPTION_CODE_SESSION_SERIALIZATION = 6; - public static final int EXCEPTION_CODE_SESSION_DESERIALIZATION = 7; - public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 8; - public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 9; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_SERIALIZATION = 10; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_DESERIALIZATION = 11; - public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_SERIALIZATION = 12; - public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DESERIALIZATION = 13; - public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 20; - public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 21; - public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 22; - public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 23; - public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 24; - public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 25; + public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 10; - public static final int EXCEPTION_CODE_SESSION_IDENTIFIER = 30; - public static final int EXCEPTION_CODE_SESSION_DECRYPT_SESSION = 31; + public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 20; + public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 21; + public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 22; + public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 23; + public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 24; + public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 25; + public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 26; + public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 27; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 40; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 41; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 42; + public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 30; + public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 31; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER = 32; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION = 33; + + public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 40; + public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 41; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 42; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 43; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 44; + + public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 50; + public static final int EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION = 51; + public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION = 52; + public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM = 53; + public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 54; + public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 55; + public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 56; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed"; public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "createNewSession() failed"; - public static final String EXCEPTION_MSG_INIT_OUTBOUND_GROUP_SESSION = "initOutboundGroupSession() failed"; - public static final String EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION = " initInboundGroupSessionWithSessionKey() failed"; - public static final String EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION = "initNewAccount() failure"; public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters"; public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "initNewAccount() failed"; public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "initNewSession() failed"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 7ac38b2..41eeba1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -141,7 +141,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return new String(sessionIdentifierJni(), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_IDENTIFIER, e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER, e.getMessage()); } } @@ -165,7 +165,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } } catch (Exception e) { Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_SESSION, e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION, e.getMessage()); } return result; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 36a95a1..9138309 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -124,25 +124,23 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aAccount the account to associate with this session * @param aTheirIdentityKey the identity key of the recipient * @param aTheirOneTimeKey the one time key of the recipient - * @return 0 if operation succeed, -1 otherwise + * @exception OlmException the failure reason */ - public int initOutboundSession(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) { - int retCode=-1; - + public void initOutboundSession(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) throws OlmException { if ((null == aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)) { Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, "invalid input parameters"); } else { try { - retCode = initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8")); + initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG, "## initOutboundSession(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, e.getMessage()); } } - - return retCode; } - private native int initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey); + private native void initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey); /** * Create a new in-bound session for sending/receiving messages from an @@ -150,29 +148,23 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aAccount the account to associate with this session * @param aPreKeyMsg PRE KEY message - * @exception Exception the failure reason + * @exception OlmException the failure reason */ - public void initInboundSession(OlmAccount aAccount, String aPreKeyMsg) throws Exception { + public void initInboundSession(OlmAccount aAccount, String aPreKeyMsg) throws OlmException { if ((null == aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSession(): invalid input parameters"); - throw new Exception("invalid input parameters"); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, "invalid input parameters"); } else { - StringBuffer errorMsg = new StringBuffer(); - try { - initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8"), errorMsg); + initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG, "## initInboundSession(): " + e.getMessage()); - errorMsg.append(errorMsg); - } - - if (errorMsg.length() != 0) { - throw new Exception(errorMsg.toString()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, e.getMessage()); } } } - private native int initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg, StringBuffer aErrorMsg); + private native void initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg); /** * Create a new in-bound session for sending/receiving messages from an @@ -183,38 +175,42 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aAccount the account to associate with this session * @param aTheirIdentityKey the sender identity key * @param aPreKeyMsg PRE KEY message - * @return 0 if operation succeed, -1 otherwise + * @exception OlmException the failure reason */ - public int initInboundSessionFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) { - int retCode=-1; - - if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ + public void initInboundSessionFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) throws OlmException { + if ( (null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionFrom(): invalid input parameters"); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, "invalid input parameters"); } else { try { - retCode = initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8")); + initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG, "## initInboundSessionFrom(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, e.getMessage()); } } - - return retCode; } - private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); + private native void initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); /** * Get the session identifier.
Will be the same for both ends of the * conversation. The session identifier is returned as a String object. * Session Id sample: "session_id":"M4fOVwD6AABrkTKl" * Public API for {@link #getSessionIdentifierJni()}. - * @return the session ID as a String if operation succeed, null otherwise + * @return the session ID + * @exception OlmException the failure reason */ - public String sessionIdentifier() { + public String sessionIdentifier() throws OlmException { try { - return new String(getSessionIdentifierJni(), "UTF-8"); + byte[] buffer = getSessionIdentifierJni(); + + if (null != buffer) { + return new String(buffer, "UTF-8"); + } } catch (Exception e) { Log.e(LOG_TAG, "## sessionIdentifier(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER, e.getMessage()); } return null; @@ -272,39 +268,46 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * The encrypted message is returned in a OlmMessage object. * Public API for {@link #encryptMessageJni(byte[], OlmMessage)}. * @param aClearMsg message to encrypted - * @return the encrypted message if operation succeed, null otherwise + * @return the encrypted message + * @exception OlmException the failure reason */ - public OlmMessage encryptMessage(String aClearMsg) { + public OlmMessage encryptMessage(String aClearMsg) throws OlmException { + if (null == aClearMsg) { + return null; + } + OlmMessage encryptedMsgRetValue = new OlmMessage(); try { - if (0 != encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue)) { - encryptedMsgRetValue = null; - } + encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue); } catch (Exception e) { Log.e(LOG_TAG, "## encryptMessage(): failed " + e.getMessage()); - encryptedMsgRetValue = null; + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE, e.getMessage()); } return encryptedMsgRetValue; } - private native int encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); + private native void encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); /** * Decrypt a message using the session.
* The encrypted message is given as a OlmMessage object. * @param aEncryptedMsg message to decrypt - * @return the decrypted message if operation succeed, null otherwise + * @return the decrypted message + * @exception OlmException the failure reason */ - public String decryptMessage(OlmMessage aEncryptedMsg) { + public String decryptMessage(OlmMessage aEncryptedMsg) throws OlmException { + if (null == aEncryptedMsg) { + return null; + } + try { return new String(decryptMessageJni(aEncryptedMsg), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## decryptMessage(): failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage()); } - - return null; } private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg); @@ -353,7 +356,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } else { aErrorMsg.setLength(0); try { - pickleRetValue = serializeJni(aKey.getBytes("UTF-8"), aErrorMsg); + pickleRetValue = serializeJni(aKey.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -362,7 +365,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native String serializeJni(byte[] aKey, StringBuffer aErrorMsg); + private native String serializeJni(byte[] aKey); /** * Loads an account from a pickled base64 string.
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 4a1717a..f09ace6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -105,25 +105,27 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi * @param aOlmAccountId account instance * @param aTheirIdentityKey the identity key of the recipient * @param aTheirOneTimeKey the one time key of the recipient -* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise **/ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) +JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) { - jint retCode = ERROR_CODE_KO; + const char* errorMessage = NULL; OlmSession* sessionPtr = NULL; OlmAccount* accountPtr = NULL; if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## initOutboundSessionJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; } else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) { LOGE("## initOutboundSessionJni(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr=NULL"; } else if (!aTheirIdentityKeyBuffer || !aTheirOneTimeKeyBuffer) { LOGE("## initOutboundSessionJni(): failure - invalid keys"); + errorMessage = "invalid keys"; } else { @@ -135,6 +137,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject if ( (0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) { LOGE("## initOutboundSessionJni(): failure - random buffer init"); + errorMessage = "random buffer init"; } else { @@ -145,10 +148,12 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) { LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM"); + errorMessage = "identityKey JNI allocation OOM"; } else if (!(theirOneTimeKeyPtr = env->GetByteArrayElements(aTheirOneTimeKeyBuffer, 0))) { LOGE("## initOutboundSessionJni(): failure - one time Key JNI allocation OOM"); + errorMessage = "one time Key JNI allocation OOM"; } else { @@ -165,11 +170,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject (void*)randomBuffPtr, randomSize); if (sessionResult == olm_error()) { - LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s", errorMessage); } else { - retCode = ERROR_CODE_OK; LOGD("## initOutboundSessionJni(): success - result=%lu", static_cast(sessionResult)); } } @@ -191,7 +196,10 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject } } - return retCode; + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } @@ -203,40 +211,28 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject * incoming PRE_KEY message.
* @param aOlmAccountId account instance * @param aOneTimeKeyMsg PRE_KEY message - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer, jobject aErrorMsg) +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer) { - jint retCode = ERROR_CODE_KO; + const char* errorMessage = NULL; OlmSession *sessionPtr = NULL; OlmAccount *accountPtr = NULL; size_t sessionResult; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## initInboundSessionJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; } else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) { LOGE("## initInboundSessionJni(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr=NULL"; } else if (!aOneTimeKeyMsgBuffer) { LOGE("## initInboundSessionJni(): failure - invalid message"); - } - else if (!aErrorMsg) - { - LOGE(" ## initInboundSessionJni(): failure - invalid error output"); - } - else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## initInboundSessionJni(): failure - unable to get error class"); - } - else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## initInboundSessionJni(): failure - unable to get error method ID"); + errorMessage = "invalid message"; } else { @@ -245,6 +241,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject if (!messagePtr) { LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM"); + errorMessage = "message JNI allocation OOM"; } else { @@ -255,19 +252,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject if (sessionResult == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s", errorMsgPtr); - - jstring errorJstring = env->NewStringUTF(errorMsgPtr); - - if (errorJstring) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_session_last_error(sessionPtr); + LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); } else { - retCode = ERROR_CODE_OK; LOGD("## initInboundSessionJni(): success - result=%lu", static_cast(sessionResult)); } @@ -275,7 +264,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); } } - return retCode; + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } /** @@ -284,11 +277,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject * @param aOlmAccountId account instance * @param aTheirIdentityKey the identity key of the recipient * @param aOneTimeKeyMsg encrypted message - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) { - jint retCode = ERROR_CODE_KO; + const char* errorMessage = NULL; + OlmSession *sessionPtr = NULL; OlmAccount *accountPtr = NULL; jbyte *messagePtr = NULL; @@ -298,26 +291,32 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; } else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr=NULL"; } else if (!aTheirIdentityKeyBuffer) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); + errorMessage = "invalid theirIdentityKey"; } else if (!aOneTimeKeyMsgBuffer) { LOGE("## initInboundSessionJni(): failure - invalid one time key message"); + errorMessage = "invalid invalid one time key message"; } else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - message JNI allocation OOM"); + errorMessage = "message JNI allocation OOM"; } else if(!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) { LOGE("## initInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); + errorMessage = "theirIdentityKey JNI allocation OOM"; } else { @@ -329,11 +328,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); if (sessionResult == olm_error()) { - LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s", errorMessage); } else { - retCode = ERROR_CODE_OK; LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(sessionResult)); } } @@ -349,7 +348,10 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); } - return retCode; + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } /** @@ -475,11 +477,11 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J * Encrypt a message using the session.
* @param aClearMsg clear text message * @param [out] aEncryptedMsg ciphered message - * @return ERROR_CODE_OK if encrypt operation succeed, ERROR_CODE_KO otherwise */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg) +JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg) { - jint retCode = ERROR_CODE_KO; + const char* errorMessage = NULL; + OlmSession *sessionPtr = NULL; jbyte *clearMsgPtr = NULL; jclass encryptedMsgJClass = 0; @@ -491,10 +493,12 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; } else if (!aClearMsgBuffer) { LOGE("## encryptMessageJni(): failure - invalid clear message"); + errorMessage = "invalid clear message"; } else if (!aEncryptedMsg) { @@ -503,18 +507,22 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, 0))) { LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM"); + errorMessage = "clear message JNI allocation OOM"; } else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) { LOGE("## encryptMessageJni(): failure - unable to get crypted message class"); + errorMessage = "unable to get crypted message class"; } else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) { LOGE("## encryptMessageJni(): failure - unable to get message field"); + errorMessage = "unable to get message field"; } else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) { LOGE("## encryptMessageJni(): failure - unable to get message type field"); + errorMessage = "unable to get message type field"; } else { @@ -532,6 +540,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { LOGE("## encryptMessageJni(): failure - random buffer init"); + errorMessage = "random buffer init"; } else { @@ -544,6 +553,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz if (!encryptedMsgPtr) { LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); + errorMessage = "encryptedMsgPtr buffer OOM"; } else { @@ -563,7 +573,8 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz encryptedMsgLength); if (result == olm_error()) { - LOGE("## encryptMessageJni(): failure - Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## encryptMessageJni(): failure - Msg=%s", errorMessage); } else { @@ -577,7 +588,6 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr); env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring); - retCode = ERROR_CODE_OK; LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", static_cast(result), static_cast(messageType), static_cast((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr); } @@ -594,16 +604,21 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); } - return retCode; + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } } /** * Decrypt a message using the session.
* @param aEncryptedMsg message to decrypt - * @return decrypted message if operation succeed, null otherwise + * @return decrypted message if operation succeed */ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) { + const char* errorMessage = NULL; + jbyteArray decryptedMsgRet = 0; jclass encryptedMsgJClass = 0; @@ -622,30 +637,37 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; } else if (!aEncryptedMsg) { LOGE("## decryptMessageJni(): failure - invalid encrypted message"); + errorMessage = "invalid encrypted message"; } else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) { LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); + errorMessage = "unable to get encrypted message class"; } else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) { LOGE("## decryptMessageJni(): failure - unable to get message field"); + errorMessage = "unable to get message field"; } else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) { LOGE("## decryptMessageJni(): failure - unable to get message type field"); + errorMessage = "unable to get message type field"; } else if (!(encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) { LOGE("## decryptMessageJni(): failure - JNI encrypted object "); + errorMessage = "JNI encrypted object"; } else if (!(encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) { LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + errorMessage = "encrypted message JNI allocation OOM"; } else { @@ -668,7 +690,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec if (maxPlainTextLength == olm_error()) { - LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s", errorMessage); } else { @@ -687,7 +710,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec maxPlainTextLength); if (plaintextLength == olm_error()) { - LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s", errorMessage); } else { @@ -715,6 +739,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec free(plainTextMsgPtr); } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return decryptedMsgRet; } @@ -725,6 +754,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec */ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; jbyteArray returnValue = 0; LOGD("## getSessionIdentifierJni(): IN "); @@ -734,6 +764,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, if (!sessionPtr) { LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; } else { @@ -746,6 +777,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, if (!sessionIdPtr) { LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); + errorMessage = "identifier allocation OOM"; } else { @@ -753,7 +785,8 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, if (result == olm_error()) { - LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s", errorMessage); } else { @@ -770,6 +803,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, } } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return returnValue; } @@ -777,15 +815,13 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, /** * Serialize and encrypt session instance into a base64 string.
* @param aKey key used to encrypt the serialized session data -* @param[out] aErrorMsg error message set if operation failed * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer, jobject aErrorMsg) +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { + const char* errorMessage = NULL; + jstring pickledDataRetValue = 0; - jclass errorMsgJClass = 0; - jmethodID errorMsgMethodId = 0; - jstring errorJstring = 0; jbyte* keyPtr = NULL; OlmSession* sessionPtr = NULL; @@ -794,26 +830,17 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) { LOGE(" ## serializeJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; } else if (!aKeyBuffer) { LOGE(" ## serializeJni(): failure - invalid key"); - } - else if (!aErrorMsg) - { - LOGE(" ## serializeJni(): failure - invalid error object"); - } - else if (!(errorMsgJClass = env->GetObjectClass(aErrorMsg))) - { - LOGE(" ## serializeJni(): failure - unable to get error class"); - } - else if (!(errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) - { - LOGE(" ## serializeJni(): failure - unable to get error method ID"); + errorMessage = "invalid key"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "ikeyPtr JNI allocation OOM"; } else { @@ -827,6 +854,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, if (!pickledPtr) { LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; } else { @@ -837,13 +865,8 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr); - - if ((errorJstring = env->NewStringUTF(errorMsgPtr))) - { - env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); - } + errorMessage = olm_session_last_error(sessionPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_session() Msg=%s", errorMessage); } else { @@ -863,6 +886,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return pickledDataRetValue; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 95b421b..004031e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -33,24 +33,24 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); // outbound session -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey); +JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey); // inbound sessions: establishment based on PRE KEY message -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg, jobject aErrorMsg); -JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg); +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // match inbound sessions: based on PRE KEY message JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // encrypt/decrypt -JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); +JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); // serialization -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus -- cgit v1.2.3 From 7f6a63068bd29309e4e75d8af8fce24b6636dffe Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 14:49:51 +0100 Subject: Fix a C compilation warning. --- java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 9205fc0..e8661c7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -123,7 +123,7 @@ jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingCl { LOGE("## getAccountInstanceId() failure - invalid instance of"); } - else if (loaderClass = aJniEnv->GetObjectClass(aJavaObject)) + else if ((loaderClass = aJniEnv->GetObjectClass(aJavaObject))) { jfieldID instanceIdField = aJniEnv->GetFieldID(loaderClass, "mNativeId", "J"); -- cgit v1.2.3 From 9df5dd9c4257982d22955d6b9ee55fc1e9dcb25f Mon Sep 17 00:00:00 2001 From: ylecollen Date: Wed, 4 Jan 2017 18:30:35 +0100 Subject: The olm objects are serialized as byte[] instead of strings. --- .../java/org/matrix/olm/CommonSerializeUtils.java | 16 +++++------ .../src/main/java/org/matrix/olm/OlmAccount.java | 24 ++++++++-------- .../org/matrix/olm/OlmInboundGroupSession.java | 33 +++++++++++----------- .../org/matrix/olm/OlmOutboundGroupSession.java | 25 ++++++++-------- .../src/main/java/org/matrix/olm/OlmSession.java | 22 +++++++-------- .../src/main/java/org/matrix/olm/OlmUtility.java | 6 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 6 ++-- .../src/main/jni/olm_inbound_group_session.cpp | 2 -- .../src/main/jni/olm_outbound_group_session.cpp | 12 ++++---- .../src/main/jni/olm_outbound_group_session.h | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 15 +++++----- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 2 +- 12 files changed, 81 insertions(+), 84 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java index 72437e4..b8c7215 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -39,11 +39,11 @@ abstract class CommonSerializeUtils { aOutStream.defaultWriteObject(); // generate serialization key - String key = OlmUtility.getRandomKey(); + byte[] key = OlmUtility.getRandomKey(); // compute pickle string StringBuffer errorMsg = new StringBuffer(); - String pickledData = serialize(key, errorMsg); + byte[] pickledData = serialize(key, errorMsg); if(null == pickledData) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg)); @@ -62,12 +62,12 @@ abstract class CommonSerializeUtils { protected void deserialize(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { aInStream.defaultReadObject(); - String key = (String) aInStream.readObject(); - String pickledData = (String) aInStream.readObject(); + byte[] key = (byte[]) aInStream.readObject(); + byte[] pickledData = (byte[]) aInStream.readObject(); - if (TextUtils.isEmpty(key)) { + if (null == key) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); - } else if (TextUtils.isEmpty(pickledData)) { + } else if (null == pickledData) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); } @@ -75,6 +75,6 @@ abstract class CommonSerializeUtils { Log.d(LOG_TAG,"## deserializeObject(): success"); } - protected abstract String serialize(String aKey, StringBuffer aErrorMsg); - protected abstract void deserialize(String aSerializedData, String aKey) throws IOException; + protected abstract byte[] serialize(byte[] aKey, StringBuffer aErrorMsg); + protected abstract void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 9d8e6d6..3a78365 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -418,27 +418,27 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } /** - * Return an account as a base64 string.
+ * Return an account as a bytes buffer.
* The account is serialized and encrypted with aKey. * In case of failure, an error human readable * description is provide in aErrorMsg. * @param aKey encryption key * @param aErrorMsg error message description - * @return pickled base64 string if operation succeed, null otherwise + * @return the account as bytes buffer */ @Override - protected String serialize(String aKey, StringBuffer aErrorMsg) { - String pickleRetValue = null; + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; // sanity check if(null == aErrorMsg) { Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); - } else if(TextUtils.isEmpty(aKey)) { + } else if (null == aKey) { aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); } else { aErrorMsg.setLength(0); try { - pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8")), "UTF-8"); + pickleRetValue = serializeJni(aKey); } catch (Exception e) { Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -451,13 +451,13 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private native byte[] serializeJni(byte[] aKey); /** - * Loads an account from a pickled base64 string.
- * See {@link #serialize(String, StringBuffer)} - * @param aSerializedData pickled account in a base64 string format + * Loads an account from a pickled bytes buffer.
+ * See {@link #serialize(byte[], StringBuffer)} + * @param aSerializedData bytes buffer * @param aKey key used to encrypted */ @Override - protected void deserialize(String aSerializedData, String aKey) throws IOException { + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { if (!createNewAccount()) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); } @@ -466,10 +466,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { try { String jniError; - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { errorMsg.append(jniError); } } catch (Exception e) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 41eeba1..dc1b80d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -44,7 +44,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Result in {@link #decryptMessage(String)} */ - static class DecryptMessageResult { + public static class DecryptMessageResult { /** decrypt message **/ public String mDecryptedMessage; @@ -135,6 +135,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Retrieve the base64-encoded identifier for this inbound group session. * @return the session ID + * @throws OlmException the failure reason */ public String sessionIdentifier() throws OlmException { try { @@ -197,28 +198,28 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } /** - * Return the current inbound group session as a base64 serialized string.
+ * Return the current inbound group session as a bytes buffer.
* The session is serialized and encrypted with aKey. * In case of failure, an error human readable * description is provide in aErrorMsg. * @param aKey encryption key * @param aErrorMsg error message description - * @return pickled base64 string if operation succeed, null otherwise + * @return pickled bytes buffer if operation succeed, null otherwise */ @Override - protected String serialize(String aKey, StringBuffer aErrorMsg) { - String pickleRetValue = null; + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; // sanity check if(null == aErrorMsg) { Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); aErrorMsg.append("aErrorMsg=null"); - } else if(TextUtils.isEmpty(aKey)) { + } else if (null == aKey) { aErrorMsg.append("Invalid input parameters in serialize()"); } else { aErrorMsg.setLength(0); try { - pickleRetValue = new String(serializeJni(aKey.getBytes("UTF-8")), "UTF-8"); + pickleRetValue = serializeJni(aKey); } catch (Exception e) { Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -228,7 +229,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return pickleRetValue; } /** - * JNI counter part of {@link #serialize(String, StringBuffer)}. + * JNI counter part of {@link #serialize(byte[], StringBuffer)}. * @param aKey encryption key * @return pickled base64 string if operation succeed, null otherwise */ @@ -236,12 +237,12 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Loads an account from a pickled base64 string.
- * See {@link #serialize(String, StringBuffer)} - * @param aSerializedData pickled account in a base64 string format + * See {@link #serialize(byte[], StringBuffer)} + * @param aSerializedData pickled account in a bytes buffer * @param aKey key used to encrypted */ @Override - protected void deserialize(String aSerializedData, String aKey) throws IOException { + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { if (!createNewSession()) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); } @@ -250,10 +251,10 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri try { String jniError; - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { errorMsg.append(jniError); } } catch (Exception e) { @@ -268,9 +269,9 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } /** - * JNI counter part of {@link #deserialize(String, String)}. - * @param aSerializedData pickled session in a base64 string format - * @param aKey key used to encrypted in {@link #serialize(String, StringBuffer)} + * JNI counter part of {@link #deserialize(byte[], byte[])}. + * @param aSerializedData pickled session in a base64 sbytes buffer + * @param aKey key used to encrypted in {@link #serialize(byte[], StringBuffer)} * @return null if operation succeed, an error message if operation failed */ private native String deserializeJni(byte[] aSerializedData, byte[] aKey); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index c27addb..534636c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -117,6 +117,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser /** * Get a base64-encoded identifier for this session. * @return session identifier + * @throws OlmException the failure reason */ public String sessionIdentifier() throws OlmException { try { @@ -210,26 +211,26 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } /** - * Return the current outbound group session as a base64 serialized string.
+ * Return the current outbound group session as a base64 byte buffers.
* The session is serialized and encrypted with aKey. * In case of failure, an error human readable * description is provide in aErrorMsg. * @param aKey encryption key * @param aErrorMsg error message description - * @return pickled base64 string if operation succeed, null otherwise + * @return pickled base64 bytes buffer if operation succeed, null otherwise */ @Override - protected String serialize(String aKey, StringBuffer aErrorMsg) { - String pickleRetValue = null; + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; // sanity check if(null == aErrorMsg) { Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); - } else if(TextUtils.isEmpty(aKey)) { + } else if (null == aKey) { aErrorMsg.append("Invalid input parameters in serialize()"); } else { try { - pickleRetValue = serializeJni(aKey.getBytes("UTF-8")); + pickleRetValue = serializeJni(aKey); } catch (Exception e) { Log.e(LOG_TAG,"## serialize(): failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -238,17 +239,17 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return pickleRetValue; } - private native String serializeJni(byte[] aKey); + private native byte[] serializeJni(byte[] aKey); /** * Loads an account from a pickled base64 string.
- * See {@link #serialize(String, StringBuffer)} - * @param aSerializedData pickled account in a base64 string format + * See {@link #serialize(byte[], StringBuffer)} + * @param aSerializedData pickled account in a base64 bytes buffer * @param aKey key used to encrypted */ @Override - protected void deserialize(String aSerializedData, String aKey) throws IOException { + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { if (!createNewSession()) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); } @@ -257,10 +258,10 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser try { String jniError; - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { errorMsg.append(jniError); } } catch (Exception e) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 9138309..bc190ed 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -336,27 +336,27 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } /** - * Return a session as a base64 string.
+ * Return a session as a bytes buffer.
* The account is serialized and encrypted with aKey. * In case of failure, an error human readable * description is provide in aErrorMsg. * @param aKey encryption key * @param aErrorMsg error message description - * @return pickled base64 string if operation succeed, null otherwise + * @return session as a bytes buffer */ @Override - protected String serialize(String aKey, StringBuffer aErrorMsg) { - String pickleRetValue = null; + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; // sanity check if(null == aErrorMsg) { Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); - } else if(TextUtils.isEmpty(aKey)) { + } else if (null == aKey) { aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); } else { aErrorMsg.setLength(0); try { - pickleRetValue = serializeJni(aKey.getBytes("UTF-8")); + pickleRetValue = serializeJni(aKey); } catch (Exception e) { Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); aErrorMsg.append(e.getMessage()); @@ -365,16 +365,16 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native String serializeJni(byte[] aKey); + private native byte[] serializeJni(byte[] aKey); /** * Loads an account from a pickled base64 string.
- * See {@link #serialize(String, StringBuffer)} + * See {@link #serialize(byte[], StringBuffer)} * @param aSerializedData pickled account in a base64 string format * @param aKey key used to encrypted */ @Override - protected void deserialize(String aSerializedData, String aKey) throws IOException { + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { if (!createNewSession()) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); } @@ -383,10 +383,10 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { try { String jniError; - if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData.getBytes("UTF-8"), aKey.getBytes("UTF-8")))) { + } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { errorMsg.append(jniError); } } catch (Exception e) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index d3c185f..28d8b58 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -135,13 +135,13 @@ public class OlmUtility { /** * Helper method to compute a string based on random integers. - * @return string containing randoms integer values + * @return bytes buffer containing randoms integer values */ - public static String getRandomKey() { + public static byte[] getRandomKey() { SecureRandom secureRandom = new SecureRandom(); byte[] buffer = new byte[RANDOM_KEY_SIZE]; secureRandom.nextBytes(buffer); - return new String(buffer); + return buffer; } /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index bac8b34..53eace7 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -558,7 +558,6 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi size_t pickledLength = olm_pickle_account_length(accountPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); @@ -586,8 +585,8 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); - pickledDataRetValue = env->NewByteArray(pickledLength+1); - env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength+1, (jbyte*)pickledPtr); + pickledDataRetValue = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength, (jbyte*)pickledPtr); } free(pickledPtr); @@ -643,7 +642,6 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_account(accountPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 223b3d8..315f607 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -361,7 +361,6 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en size_t pickledLength = olm_pickle_inbound_group_session_length(sessionPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); @@ -444,7 +443,6 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_inbound_group_session(sessionPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 982840c..e8fd38b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -381,11 +381,11 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE * @param aKey key used to encrypt the serialized session data * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; + jbyteArray returnValue = 0; - jstring pickledDataRetValue = 0; jbyte* keyPtr = NULL; OlmOutboundGroupSession* sessionPtr = NULL; @@ -411,7 +411,6 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, size_t pickledLength = olm_pickle_outbound_group_session_length(sessionPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); @@ -436,8 +435,10 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, { // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + + returnValue = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); } } @@ -455,7 +456,7 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } - return pickledDataRetValue; + return returnValue; } @@ -493,7 +494,6 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *en size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_outbound_group_session(sessionPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index 1156b77..fb3bf87 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -40,7 +40,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); // serialization -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index f09ace6..7cde2cd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -754,7 +754,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec */ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) { - const char* errorMessage = NULL; + const char* errorMessage = NULL; jbyteArray returnValue = 0; LOGD("## getSessionIdentifierJni(): IN "); @@ -817,11 +817,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, * @param aKey key used to encrypt the serialized session data * @return a base64 string if operation succeed, null otherwise **/ -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; + jbyteArray returnValue = 0; - jstring pickledDataRetValue = 0; jbyte* keyPtr = NULL; OlmSession* sessionPtr = NULL; @@ -847,7 +847,6 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, size_t pickledLength = olm_pickle_session_length(sessionPtr); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## serializeJni(): key=%s",(char const *)keyPtr); void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); @@ -872,8 +871,10 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, { // build success output (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + + returnValue = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); } free(pickledPtr); @@ -891,10 +892,9 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } - return pickledDataRetValue; + return returnValue; } - JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { OlmSession* sessionPtr = NULL; @@ -929,7 +929,6 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): key=%s",(char const *)keyPtr); LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); size_t result = olm_unpickle_session(sessionPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 004031e..ef92395 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -50,7 +50,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); // serialization -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus -- cgit v1.2.3 From 90c55806c081b2610a08a48a6cc897e0121ab3b7 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Thu, 5 Jan 2017 09:42:25 +0100 Subject: fix an invalid test --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index e8fd38b..bfe5a4e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -69,7 +69,7 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv { LOGE(" ## createNewSessionJni(): failure - outbound group session size = 0"); } - else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) + else if ((sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) { sessionPtr = olm_outbound_group_session(sessionPtr); LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); -- cgit v1.2.3 From eec8a50cafc75c025a98133520e8d8e9cf97e115 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Thu, 5 Jan 2017 10:16:14 +0100 Subject: Move the exception test --- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index e8661c7..7146f4e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -62,22 +62,26 @@ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) newObj = env->NewObject(cls, constructor); jbyteArray tempByteArray = env->NewByteArray(bufferLen); - if (newObj && tempByteArray && !env->ExceptionOccurred()) + if (newObj && tempByteArray) { env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); - jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); - if (buffer) + if (!env->ExceptionOccurred()) { - memcpy(*aBuffer2Ptr, buffer, bufferLen); - retCode = true; + jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); - // clear tempByteArray to hide sensitive data. - memset(buffer, 0, bufferLen); - env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer); + if (buffer) + { + memcpy(*aBuffer2Ptr, buffer, bufferLen); + retCode = true; - // ensure that the buffer is released - env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT); + // clear tempByteArray to hide sensitive data. + memset(buffer, 0, bufferLen); + env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer); + + // ensure that the buffer is released + env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT); + } } } -- cgit v1.2.3 From 03396102691409083143882ee1ed54e137f183d2 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 10:01:01 +0100 Subject: Simplify the function declarations in olm_jni to avoid having to cast the getXXX methods --- .../src/main/java/org/matrix/olm/OlmAccount.java | 2 -- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 20 +++++------ .../src/main/jni/olm_inbound_group_session.cpp | 24 ++++++------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 11 +++--- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 41 ++++++++++------------ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 40 ++++++++++----------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 10 +++--- 7 files changed, 71 insertions(+), 77 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 3a78365..6737963 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -17,10 +17,8 @@ package org.matrix.olm; -import android.text.TextUtils; import android.util.Log; -import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 53eace7..7441da4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -60,7 +60,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz { LOGD("## releaseAccountJni(): IN"); - OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); if (!accountPtr) { @@ -152,7 +152,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject { const char* errorMessage = NULL; jbyteArray byteArrayRetValue = NULL; - OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); if (!accountPtr) { @@ -220,7 +220,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject **/ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz) { - OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); size_t maxKeys = -1; if (!accountPtr) @@ -244,7 +244,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thi JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) { const char* errorMessage = NULL; - OlmAccount *accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); + OlmAccount *accountPtr = getAccountInstanceId(env, thiz); if (!accountPtr) { @@ -304,7 +304,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t { const char* errorMessage = NULL; jbyteArray byteArrayRetValue = NULL; - OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); LOGD("## oneTimeKeysJni(): IN"); @@ -380,7 +380,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t LOGE("## removeOneTimeKeysJni(): failure - invalid session ptr"); errorMessage = "invalid session ptr"; } - else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + else if(!(accountPtr = getAccountInstanceId(env, thiz))) { LOGE("## removeOneTimeKeysJni(): failure - invalid account ptr"); errorMessage = "invalid account ptr"; @@ -415,7 +415,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; - OlmAccount* accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz); + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); if (!accountPtr) { @@ -460,7 +460,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t LOGE("## signMessageJni(): failure - invalid aMessage param"); errorMessage = "invalid aMessage param"; } - else if(!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + else if (!(accountPtr = getAccountInstanceId(env, thiz))) { LOGE("## signMessageJni(): failure - invalid account ptr"); errorMessage = "invalid account ptr"; @@ -543,7 +543,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi LOGE(" ## serializeJni(): failure - invalid key"); errorMessage = "invalid key"; } - else if (!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + else if (!(accountPtr = getAccountInstanceId(env, thiz))) { LOGE(" ## serializeJni(): failure - invalid account ptr"); errorMessage = "invalid account ptr"; @@ -625,7 +625,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz { LOGE(" ## deserializeJni(): failure - serialized data"); } - else if (!(accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz))) + else if (!(accountPtr = getAccountInstanceId(env, thiz))) { LOGE(" ## deserializeJni(): failure - account failure OOM"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 315f607..dd3e0a9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -26,11 +26,11 @@ using namespace AndroidOlmSdk; */ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { - OlmInboundGroupSession* sessionPtr = NULL; + OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env,thiz); LOGD("## releaseSessionJni(): InBound group session IN"); - if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); } @@ -88,13 +88,13 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) { const char* errorMessage = NULL; - OlmInboundGroupSession *sessionPtr = NULL; + OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); jbyte* sessionKeyPtr = NULL; size_t sessionResult; LOGD("## initInboundGroupSessionJni(): inbound group session IN"); - if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## initInboundGroupSessionJni(): failure - invalid inbound group session instance"); errorMessage = "invalid inbound group session instance"; @@ -143,12 +143,12 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JN JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; - OlmInboundGroupSession *sessionPtr = NULL; + OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); jbyteArray returnValue = 0; LOGD("## sessionIdentifierJni(): inbound group session IN"); - if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## sessionIdentifierJni(): failure - invalid inbound group session instance"); errorMessage = "invalid inbound group session instance"; @@ -202,14 +202,14 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn jbyteArray decryptedMsgBuffer = 0; const char* errorMessage = NULL; - OlmInboundGroupSession *sessionPtr = NULL; + OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); jbyte *encryptedMsgPtr = NULL; jclass indexObjJClass = 0; jfieldID indexMsgFieldId; LOGD("## decryptMessageJni(): inbound group session IN"); - if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); errorMessage = "invalid inbound group session ptr=NULL"; @@ -337,11 +337,11 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en jbyteArray pickledDataRet = 0; jbyte* keyPtr = NULL; - OlmInboundGroupSession* sessionPtr = NULL; + OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env, thiz); LOGD("## inbound group session serializeJni(): IN"); - if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## serializeJni(): failure - invalid session ptr"); errorMessage = "invalid session ptr"; @@ -411,14 +411,14 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { - OlmInboundGroupSession* sessionPtr = NULL; + OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env, thiz); jstring errorMessageRetValue = 0; jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); - if (!(sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## deserializeJni(): failure - session failure OOM"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 1c80388..73a529d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -68,11 +68,12 @@ extern "C" { // internal helper functions bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize); -jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); + +struct OlmSession* getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmAccount* getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmInboundGroupSession* getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmOutboundGroupSession* getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmUtility* getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index 7146f4e..a1f5c59 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -111,8 +111,8 @@ bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) * Read the instance ID of the calling object. * @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked -* @param aCallingClass java calling clas name -* @return the instance ID if operation succeed, -1 if instance ID was not found. +* @param aCallingClass java calling class name +* @return the related instance ID **/ jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass) { @@ -125,7 +125,7 @@ jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingCl if (requiredClass && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) { - LOGE("## getAccountInstanceId() failure - invalid instance of"); + LOGE("## getInstanceId() failure - invalid instance of"); } else if ((loaderClass = aJniEnv->GetObjectClass(aJavaObject))) { @@ -162,58 +162,53 @@ jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingCl * Read the account instance ID of the calling object. * @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if operation succeed, -1 if instance ID was not found. +* @return the related OlmAccount. **/ -jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +struct OlmAccount* getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT); - return instanceId; + return (struct OlmAccount*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT); } /** * Read the session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. +* @return the related OlmSession. **/ -jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +struct OlmSession* getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION); - return instanceId; + return (struct OlmSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION); } /** * Read the inbound group session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. +* @return the related OlmInboundGroupSession. **/ -jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +struct OlmInboundGroupSession* getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION); - return instanceId; + return (struct OlmInboundGroupSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION); } /** * Read the outbound group session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. +* @return the related OlmOutboundGroupSession **/ -jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +struct OlmOutboundGroupSession* getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION); - return instanceId; + return (struct OlmOutboundGroupSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION); } /** * Read the utility instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table * @param aJavaObject reference to the object on which the method is invoked -* @return the instance ID if read succeed, -1 otherwise. +* @return the related OlmUtility **/ -jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +struct OlmUtility* getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) { - jlong instanceId = getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); - return instanceId; + return (struct OlmUtility*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 7cde2cd..d1459ae 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -55,7 +55,7 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject t JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { LOGD("## releaseSessionJni(): IN"); - OlmSession* sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz); + OlmSession* sessionPtr = getSessionInstanceId(env, thiz); if (!sessionPtr) { @@ -108,11 +108,11 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thi **/ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) { + OlmSession* sessionPtr = getSessionInstanceId(env, thiz); const char* errorMessage = NULL; - OlmSession* sessionPtr = NULL; OlmAccount* accountPtr = NULL; - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## initOutboundSessionJni(): failure - invalid Session ptr=NULL"); errorMessage = "invalid Session ptr=NULL"; @@ -215,11 +215,11 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer) { const char* errorMessage = NULL; - OlmSession *sessionPtr = NULL; + OlmSession *sessionPtr = getSessionInstanceId(env,thiz); OlmAccount *accountPtr = NULL; size_t sessionResult; - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## initInboundSessionJni(): failure - invalid Session ptr=NULL"); errorMessage = "invalid Session ptr=NULL"; @@ -282,13 +282,13 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, { const char* errorMessage = NULL; - OlmSession *sessionPtr = NULL; + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); OlmAccount *accountPtr = NULL; jbyte *messagePtr = NULL; jbyte *theirIdentityKeyPtr = NULL; size_t sessionResult; - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); errorMessage = "invalid Session ptr=NULL"; @@ -363,10 +363,10 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) { jint retCode = ERROR_CODE_KO; - OlmSession *sessionPtr = NULL; + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *messagePtr = NULL; - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## matchesInboundSessionJni(): failure - invalid Session ptr=NULL"); } @@ -415,11 +415,11 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) { jint retCode = ERROR_CODE_KO; - OlmSession *sessionPtr = NULL; + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *messagePtr = NULL; jbyte *theirIdentityKeyPtr = NULL; - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); } @@ -482,7 +482,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz { const char* errorMessage = NULL; - OlmSession *sessionPtr = NULL; + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *clearMsgPtr = NULL; jclass encryptedMsgJClass = 0; jfieldID encryptedMsgFieldId; @@ -490,7 +490,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz LOGD("## encryptMessageJni(): IN "); - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); errorMessage = "invalid Session ptr=NULL"; @@ -627,14 +627,14 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec jfieldID encryptedMsgFieldId; jfieldID typeMsgFieldId; // ptrs - OlmSession *sessionPtr = NULL; + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); const char *encryptedMsgPtr = NULL; // <= obtained from encryptedMsgJstring uint8_t *plainTextMsgPtr = NULL; char *tempEncryptedPtr = NULL; LOGD("## decryptMessageJni(): IN - OlmSession"); - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); errorMessage = "invalid Session ptr=NULL"; @@ -759,7 +759,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, LOGD("## getSessionIdentifierJni(): IN "); - OlmSession *sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz); + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); if (!sessionPtr) { @@ -823,11 +823,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi jbyteArray returnValue = 0; jbyte* keyPtr = NULL; - OlmSession* sessionPtr = NULL; + OlmSession* sessionPtr = getSessionInstanceId(env, thiz); LOGD("## serializeJni(): IN"); - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## serializeJni(): failure - invalid session ptr"); errorMessage = "invalid session ptr"; @@ -897,14 +897,14 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { - OlmSession* sessionPtr = NULL; + OlmSession* sessionPtr = getSessionInstanceId(env, thiz); jstring errorMessageRetValue = 0; jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); - if (!(sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + if (!sessionPtr) { LOGE(" ## deserializeJni(): failure - session failure OOM"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index f4a0c80..c4e6811 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -59,7 +59,7 @@ JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz) JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz) { - OlmUtility* utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz); + OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); LOGD("## releaseUtilityJni(): IN"); @@ -88,14 +88,14 @@ JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignatureBuffer, jbyteArray aKeyBuffer, jbyteArray aMessageBuffer) { jstring errorMessageRetValue = 0; - OlmUtility* utilityPtr = NULL; + OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); jbyte* signaturePtr = NULL; jbyte* keyPtr = NULL; jbyte* messagePtr = NULL; LOGD("## verifyEd25519SignatureJni(): IN"); - if (!(utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) + if (!utilityPtr) { LOGE(" ## verifyEd25519SignatureJni(): failure - invalid utility ptr=NULL"); } @@ -170,12 +170,12 @@ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, { jbyteArray sha256Ret = 0; - OlmUtility* utilityPtr = NULL; + OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); jbyte* messagePtr = NULL; LOGD("## sha256Jni(): IN"); - if (!(utilityPtr = (OlmUtility*)getUtilityInstanceId(env,thiz))) + if (!utilityPtr) { LOGE(" ## sha256Jni(): failure - invalid utility ptr=NULL"); } -- cgit v1.2.3 From f257580cb1adb798943b2b9bc54192320c2821e2 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 10:25:18 +0100 Subject: verifyEd25519Signature triggers an exception instead of filling an error buffer --- .../java/org/matrix/olm/OlmUtilityTest.java | 37 ++++++++++++---- .../src/main/java/org/matrix/olm/OlmException.java | 50 +++++++++++----------- .../src/main/java/org/matrix/olm/OlmUtility.java | 39 ++++++++--------- 3 files changed, 72 insertions(+), 54 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index 4096001..bd53e6e 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -58,7 +58,7 @@ public class OlmUtilityTest { @Test public void test01VerifyEd25519Signing() { String fingerPrintKey = null; - StringBuffer errorMsg = new StringBuffer(); + String errorMsg = null; String message = "{\"algorithms\":[\"m.megolm.v1.aes-sha2\",\"m.olm.v1.curve25519-aes-sha2\"],\"device_id\":\"YMBYCWTWCG\",\"keys\":{\"curve25519:YMBYCWTWCG\":\"KZFa5YUXV2EOdhK8dcGMMHWB67stdgAP4+xwiS69mCU\",\"ed25519:YMBYCWTWCG\":\"0cEgQJJqjgtXUGp4ZXQQmh36RAxwxr8HJw2E9v1gvA0\"},\"user_id\":\"@mxBob14774891254276b253f42-f267-43ec-bad9-767142bfea30:localhost:8480\"}"; OlmAccount account = null; @@ -98,22 +98,43 @@ public class OlmUtilityTest { OlmUtility utility = new OlmUtility(); // verify signature - errorMsg.append("init with anything"); - boolean isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message, errorMsg); + boolean isVerified; + + isVerified = false; + errorMsg = null; + try { + isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message); + } catch (Exception e) { + errorMsg = e.getMessage(); + } assertTrue(isVerified); - assertTrue(String.valueOf(errorMsg).isEmpty()); + assertTrue(TextUtils.isEmpty(errorMsg)); // check a bad signature is detected => errorMsg = BAD_MESSAGE_MAC String badSignature = "Bad signature Bad signature Bad signature.."; - isVerified = utility.verifyEd25519Signature(badSignature, fingerPrintKey, message, errorMsg); + + isVerified = false; + errorMsg = null; + try { + isVerified = utility.verifyEd25519Signature(badSignature, fingerPrintKey, message); + } catch (Exception e) { + errorMsg = e.getMessage(); + } assertFalse(isVerified); - assertFalse(String.valueOf(errorMsg).isEmpty()); + assertTrue(!TextUtils.isEmpty(errorMsg)); // check bad fingerprint size => errorMsg = INVALID_BASE64 String badSizeFingerPrintKey = fingerPrintKey.substring(fingerPrintKey.length()/2); - isVerified = utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message, errorMsg); + + isVerified = false; + errorMsg = null; + try { + isVerified = utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message); + } catch (Exception e) { + errorMsg = e.getMessage(); + } assertFalse(isVerified); - assertFalse(String.valueOf(errorMsg).isEmpty()); + assertTrue(!TextUtils.isEmpty(errorMsg)); utility.releaseUtility(); assertTrue(utility.isReleased()); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index a6f1805..d02b7fc 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -27,33 +27,35 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 10; - public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 20; - public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 21; - public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 22; - public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 23; - public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 24; - public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 25; - public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 26; - public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 27; + public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 100; + public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 101; + public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 102; + public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 103; + public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 104; + public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 105; + public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 106; + public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 107; - public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 30; - public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 31; - public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER = 32; - public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION = 33; + public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 200; + public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 201; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER = 202; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION = 203; - public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 40; - public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 41; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 42; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 43; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 44; + public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 300; + public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 301; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 302; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 303; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 304; - public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 50; - public static final int EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION = 51; - public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION = 52; - public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM = 53; - public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 54; - public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 55; - public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 56; + public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 400; + public static final int EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION = 401; + public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION = 402; + public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM = 403; + public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 404; + public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405; + public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406; + + public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 500; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed"; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 28d8b58..3b1d9e1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -70,33 +70,28 @@ public class OlmUtility { * @param aSignature the base64-encoded message signature to be checked. * @param aFingerprintKey the ed25519 key (fingerprint key) * @param aMessage the signed message - * @param aError error message description * @return true if the signature is verified, false otherwise + * @exception OlmException the failure reason */ - public boolean verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage, StringBuffer aError) { - boolean retCode = false; - String jniError; - - if (null == aError) { - Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input error parameter"); - } else { - aError.setLength(0); - - try { - if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { - Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); - aError.append("JAVA sanity check failure - invalid input parameters"); - } else if (null == (jniError = verifyEd25519SignatureJni(aSignature.getBytes("UTF-8"), aFingerprintKey.getBytes("UTF-8"), aMessage.getBytes("UTF-8")))) { - retCode = true; - } else { - aError.append(jniError); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## verifyEd25519Signature(): failed " + e.getMessage()); + public boolean verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage) throws OlmException { + String errorMessage = null; + + try { + if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); + errorMessage = "JAVA sanity check failure - invalid input parameters"; + } else { + errorMessage = verifyEd25519SignatureJni(aSignature.getBytes("UTF-8"), aFingerprintKey.getBytes("UTF-8"), aMessage.getBytes("UTF-8")); } + } catch (Exception e) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): failed " + e.getMessage()); } - return retCode; + if (!TextUtils.isEmpty(errorMessage)) { + throw new OlmException(OlmException.EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE, errorMessage); + } + + return true; } /** -- cgit v1.2.3 From 13d3f4a1c78282c2ba3fcb3c0e29fe9e045c9e4e Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 13:55:04 +0100 Subject: The serialization / deserialization unit test did not fail when there was an error --- .../androidTest/java/org/matrix/olm/OlmAccountTest.java | 8 +++++++- .../java/org/matrix/olm/OlmGroupSessionTest.java | 11 +++++++++++ .../androidTest/java/org/matrix/olm/OlmSessionTest.java | 5 +++++ .../androidTest/java/org/matrix/olm/OlmUtilityTest.java | 16 ++++++++++++++-- 4 files changed, 37 insertions(+), 3 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 569b520..699d966 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -96,6 +96,7 @@ public class OlmAccountTest { mOlmAccount = new OlmAccount(); } catch (OlmException e) { e.printStackTrace(); + assertTrue("OlmAccount failed " + e.getMessage(), false); } assertNotNull(mOlmAccount); @@ -109,6 +110,7 @@ public class OlmAccountTest { mOlmAccount = new OlmAccount(); } catch (OlmException e) { e.printStackTrace(); + assertTrue("OlmAccount failed " + e.getMessage(), false); } assertNotNull(mOlmAccount); mIsAccountCreated = true; @@ -261,7 +263,7 @@ public class OlmAccountTest { FileOutputStream fileOutput; ObjectOutputStream objectOutput; OlmAccount accountRef = null; - OlmAccount accountDeserial; + OlmAccount accountDeserial = null; try { accountRef = new OlmAccount(); @@ -330,18 +332,22 @@ public class OlmAccountTest { } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test13Serialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); } catch (ClassNotFoundException e) { Log.e(LOG_TAG, "## test13Serialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); } catch (IOException e) { Log.e(LOG_TAG, "## test13Serialization(): Exception IOException Msg==" + e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); } /*catch (OlmException e) { Log.e(LOG_TAG, "## test13Serialization(): Exception OlmException Msg==" + e.getMessage()); }*/ catch (Exception e) { Log.e(LOG_TAG, "## test13Serialization(): Exception Msg==" + e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index c532179..9be6375 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -175,6 +175,7 @@ public class OlmGroupSessionTest { try { result = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage); } catch (Exception e) { + assertTrue(e.getMessage(), false); } // test decrypted message @@ -262,14 +263,19 @@ public class OlmGroupSessionTest { assertTrue(outboundGroupSessionSerial.isReleased()); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue(e.getMessage(), false); } catch (ClassNotFoundException e) { Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } catch (OlmException e) { Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception OlmException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } catch (IOException e) { Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception IOException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } catch (Exception e) { Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } } @@ -342,14 +348,19 @@ public class OlmGroupSessionTest { assertTrue(bobInboundGroupSessionSerial.isReleased()); } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue(e.getMessage(), false); } catch (ClassNotFoundException e) { Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } catch (OlmException e) { Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception OlmException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } catch (IOException e) { Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception IOException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } catch (Exception e) { Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index ec2582f..bb24f7a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -454,6 +454,7 @@ public class OlmSessionTest { bobSession = new OlmSession(); } catch (OlmException e) { e.printStackTrace(); + assertTrue(e.getMessage(), false); } assertTrue(0!=bobSession.getOlmSessionId()); @@ -803,18 +804,22 @@ public class OlmSessionTest { } catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue(e.getMessage(), false); } catch (ClassNotFoundException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } catch (IOException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } /*catch (OlmException e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); }*/ catch (Exception e) { Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index bd53e6e..cc14e7c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -95,7 +95,13 @@ public class OlmUtilityTest { assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); // instantiate utility object - OlmUtility utility = new OlmUtility(); + OlmUtility utility = null; + + try { + utility = new OlmUtility(); + } catch (Exception e) { + assertTrue("failed to create OlmUtility", false); + } // verify signature boolean isVerified; @@ -145,7 +151,13 @@ public class OlmUtilityTest { @Test public void test02sha256() { - OlmUtility utility = new OlmUtility(); + OlmUtility utility = null; + + try { + utility = new OlmUtility(); + } catch (Exception e) { + assertTrue("OlmUtility creation failed", false); + } String msgToHash = "The quick brown fox jumps over the lazy dog"; String hashResult = utility.sha256(msgToHash); -- cgit v1.2.3 From 7bf7a7e4158df882028df510e8d76009f2640d96 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 13:55:58 +0100 Subject: use the same way to name the creation method i.e. createNewXX. Avoid the initWithXX. --- .../src/main/java/org/matrix/olm/OlmAccount.java | 57 ++++++------------- .../src/main/java/org/matrix/olm/OlmException.java | 1 + .../org/matrix/olm/OlmInboundGroupSession.java | 44 +++++++-------- .../src/main/java/org/matrix/olm/OlmManager.java | 2 - .../org/matrix/olm/OlmOutboundGroupSession.java | 45 +++++++-------- .../src/main/java/org/matrix/olm/OlmSession.java | 43 ++++---------- .../src/main/java/org/matrix/olm/OlmUtility.java | 11 +++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 66 +++++++++------------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 1 - .../src/main/jni/olm_inbound_group_session.cpp | 8 +++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 36 ++++-------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 1 - .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 9 +-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 2 +- 14 files changed, 131 insertions(+), 195 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 6737963..3e7d01d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -17,6 +17,7 @@ package org.matrix.olm; +import android.text.TextUtils; import android.util.Log; import org.json.JSONObject; @@ -61,7 +62,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private transient long mNativeId; public OlmAccount() throws OlmException { - initNewAccount(); + createNewAccount(); } /** @@ -85,43 +86,23 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * Destroy the corresponding OLM account native object.
* This method must ALWAYS be called when this JAVA instance * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #initNewAccountJni()}. + * See {@link #createNewAccountJni()}. */ private native void releaseAccountJni(); /** * Create and initialize a native account instance.
- * Wrapper for {@link #initNewAccountJni()}. * To be called before any other API call. * @exception OlmException the failure reason */ - private void initNewAccount() throws OlmException { + private void createNewAccount() throws OlmException { try { - mNativeId = initNewAccountJni(); + mNativeId = createNewAccountJni(); } catch (Exception e) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); } } - /** - * Create and initialize an OLM account in native side.
- * Do not forget to call {@link #releaseAccount()} when JAVA side is done. - * @return native account instance identifier (see {@link #mNativeId}) - */ - private native long initNewAccountJni(); - - /** - * Create a native account instance without any initialization.
- * Since the account is left uninitialized, this - * method is intended to be used in the serialization mechanism (see {@link #readObject(ObjectInputStream)}).
- * Public wrapper for {@link #createNewAccountJni()}. - * @return true if init succeed, false otherwise. - */ - private boolean createNewAccount() { - mNativeId = initNewAccountJni(); - return (0 != mNativeId); - } - /** * Create an OLM account in native side.
* Do not forget to call {@link #releaseAccount()} when JAVA side is done. @@ -408,10 +389,9 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { /** * Kick off the deserialization mechanism. * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception + * @throws Exception exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream aInStream) throws Exception { deserialize(aInStream); } @@ -453,31 +433,28 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * See {@link #serialize(byte[], StringBuffer)} * @param aSerializedData bytes buffer * @param aKey key used to encrypted + * @exception Exception the exception */ @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { - if (!createNewAccount()) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); - } - - StringBuffer errorMsg = new StringBuffer(); + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + createNewAccount(); + String errorMsg; try { - String jniError; if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { - errorMsg.append(jniError); + errorMsg = "invalid input parameters"; + } else { + errorMsg = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg.append(e.getMessage()); + errorMsg = e.getMessage(); } - if (errorMsg.length() > 0) { + if (!TextUtils.isEmpty(errorMsg)) { releaseAccount(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index d02b7fc..155724b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -55,6 +55,7 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405; public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406; + public static final int EXCEPTION_CODE_UTILITY_CREATION = 501; public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 500; // exception human readable messages diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index dc1b80d..d9075c8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -61,11 +61,8 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @throws OlmException constructor failure */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { - if(createNewSession()) { - initInboundGroupSession(aSessionKey); - } else { - throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION); - } + createNewSession(); + initInboundGroupSession(aSessionKey); } /** @@ -88,11 +85,14 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Create and save the session native instance ID.
* To be called before any other API call. - * @return true if init succeed, false otherwise. + * @exception OlmException the failure reason */ - private boolean createNewSession() { - mNativeId = createNewSessionJni(); - return (0 != mNativeId); + private void createNewSession() throws OlmException { + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION, e.getMessage()); + } } /** @@ -190,10 +190,9 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Kick off the deserialization mechanism. * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception + * @throws Exception exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream aInStream) throws Exception { deserialize(aInStream); } @@ -242,29 +241,26 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * @param aKey key used to encrypted */ @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { - if (!createNewSession()) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); - } + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + createNewSession(); - StringBuffer errorMsg = new StringBuffer(); + String errorMsg; try { - String jniError; if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { - errorMsg.append(jniError); + errorMsg = "invalid input parameters"; + } else { + errorMsg = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg.append(e.getMessage()); + errorMsg = e.getMessage(); } - if (errorMsg.length() > 0) { + if (!TextUtils.isEmpty(errorMsg)) { releaseSession(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 1605392..2efb0c2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -42,8 +42,6 @@ public class OlmManager { } public String getSdkOlmVersion() { - //Date currentDate = Calendar.getInstance().getTime(); - //String retVal = new SimpleDateFormat("yyyyMMdd_HH:mm:ss").format(currentDate); return SDK_OLM_VERSION; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index 534636c..a7972d3 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -50,11 +50,8 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * @throws OlmException constructor failure */ public OlmOutboundGroupSession() throws OlmException { - if(createNewSession()) { - initOutboundGroupSession(); - } else { - throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, OlmException.EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION); - } + createNewSession(); + initOutboundGroupSession(); } /** @@ -78,11 +75,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * Create and save the session native instance ID. * Wrapper for {@link #createNewSessionJni()}.
* To be called before any other API call. - * @return true if init succeed, false otherwise. + * @exception OlmException the exception. */ - private boolean createNewSession() { - mNativeId = createNewSessionJni(); - return (0 != mNativeId); + private void createNewSession() throws OlmException { + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, e.getMessage()); + } } /** @@ -203,10 +203,9 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser /** * Kick off the deserialization mechanism. * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception + * @throws Exception exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream aInStream) throws Exception { deserialize(aInStream); } @@ -247,31 +246,29 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * See {@link #serialize(byte[], StringBuffer)} * @param aSerializedData pickled account in a base64 bytes buffer * @param aKey key used to encrypted + * @exception Exception the exception */ @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { - if (!createNewSession()) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); - } + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + createNewSession(); - StringBuffer errorMsg = new StringBuffer(); + String errorMsg = null; try { - String jniError; if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { - errorMsg.append(jniError); + errorMsg = "invalid input parameters"; + } else { + errorMsg = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg.append(e.getMessage()); + errorMsg = e.getMessage(); } - if (errorMsg.length() > 0) { + if (!TextUtils.isEmpty(errorMsg)) { releaseSession(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index bc190ed..2436f0d 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -43,9 +43,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { private transient long mNativeId; public OlmSession() throws OlmException { - if(!initNewSession()) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, OlmException.EXCEPTION_MSG_INIT_SESSION_CREATION); - } + createNewSession(); } /** @@ -60,7 +58,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * Destroy the corresponding OLM session native object.
* This method must ALWAYS be called when this JAVA instance * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #initNewSessionJni()}. + * See {@link #createNewSessionJni()}. */ private native void releaseSessionJni(); @@ -73,34 +71,19 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { mNativeId = 0; } - /** - * Create and save the session native instance ID. - * Wrapper for {@link #initNewSessionJni()}.
- * To be called before any other API call. - * @return true if init succeed, false otherwise. - */ - private boolean initNewSession() { - mNativeId = initNewSessionJni(); - return (0 != mNativeId); - } - - /** - * Create the corresponding OLM session in native side.
- * Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native session instance identifier (see {@link #mNativeId}) - */ - private native long initNewSessionJni(); - /** * Create a native account instance without any initialization.
* Since the account is left uninitialized, this * method is intended to be used in the serialization mechanism (see {@link #readObject(ObjectInputStream)}).
* Public wrapper for {@link #createNewSessionJni()}. - * @return true if init succeed, false otherwise. + * @exception OlmException the exception */ - private boolean createNewSession() { - mNativeId = initNewSessionJni(); - return (0 != mNativeId); + private void createNewSession() throws OlmException { + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, e.getMessage()); + } } /** @@ -331,7 +314,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @throws IOException exception * @throws ClassNotFoundException exception */ - private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + private void readObject(ObjectInputStream aInStream) throws Exception { deserialize(aInStream); } @@ -374,10 +357,8 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @param aKey key used to encrypted */ @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException { - if (!createNewSession()) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION,OlmException.EXCEPTION_MSG_INIT_ACCOUNT_CREATION); - } + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + createNewSession(); StringBuffer errorMsg = new StringBuffer(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 3b1d9e1..d520da6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -29,7 +29,6 @@ public class OlmUtility { private static final String LOG_TAG = "OlmUtility"; public static final int RANDOM_KEY_SIZE = 32; - public static final int RANDOM_RANGE = 256; /** Instance Id returned by JNI. * This value uniquely identifies this utility instance. @@ -46,11 +45,11 @@ public class OlmUtility { * @return true if init succeed, false otherwise. */ private boolean initUtility() { - mNativeId = initUtilityJni(); + mNativeId = createUtilityJni(); return (0 != mNativeId); } - private native long initUtilityJni(); + private native long createUtilityJni(); /** * Release native instance.
@@ -136,6 +135,12 @@ public class OlmUtility { SecureRandom secureRandom = new SecureRandom(); byte[] buffer = new byte[RANDOM_KEY_SIZE]; secureRandom.nextBytes(buffer); + + // the key is saved as string + // so avoid the UTF8 marker bytes + for(int i = 0; i < RANDOM_KEY_SIZE; i++) { + buffer[i] = (byte)(buffer[i] & 0x7F); + } return buffer; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 7441da4..4da0d67 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -42,49 +42,13 @@ OlmAccount* initializeAccountMemory() return accountPtr; } -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## createNewAccountJni(): IN"); - OlmAccount* accountPtr = initializeAccountMemory(); - - LOGD(" ## createNewAccountJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); - return (jlong)(intptr_t)accountPtr; -} - -/** - * Release the account allocation made by initializeAccountMemory().
- * This method MUST be called when java counter part account instance is done. - * - */ -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## releaseAccountJni(): IN"); - - OlmAccount* accountPtr = getAccountInstanceId(env, thiz); - - if (!accountPtr) - { - LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); - } - else - { - LOGD(" ## releaseAccountJni(): accountPtr=%p",accountPtr); - olm_clear_account(accountPtr); - - LOGD(" ## releaseAccountJni(): IN"); - // even if free(NULL) does not crash, logs are performed for debug purpose - free(accountPtr); - LOGD(" ## releaseAccountJni(): OUT"); - } -} - /** -* Initialize a new account and return it to JAVA side.
+* Create a new account and return it to JAVA side.
* Since a C prt is returned as a jlong, special care will be taken * to make the cast (OlmAccount* => jlong) platform independent. * @return the initialized OlmAccount* instance **/ -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; OlmAccount *accountPtr = initializeAccountMemory(); @@ -139,6 +103,32 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi return (jlong)(intptr_t)accountPtr; } +/** + * Release the account allocation made by initializeAccountMemory().
+ * This method MUST be called when java counter part account instance is done. + * + */ +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## releaseAccountJni(): IN"); + + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); + + if (!accountPtr) + { + LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); + } + else + { + LOGD(" ## releaseAccountJni(): accountPtr=%p",accountPtr); + olm_clear_account(accountPtr); + + LOGD(" ## releaseAccountJni(): IN"); + // even if free(NULL) does not crash, logs are performed for debug purpose + free(accountPtr); + LOGD(" ## releaseAccountJni(): OUT"); + } +} // ********************************************************************* // ************************* IDENTITY KEYS API ************************* diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 5b73acd..2bfb39c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -30,7 +30,6 @@ extern "C" { // account creation/destruction JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz); // identity keys diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index dd3e0a9..7dd250b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -58,6 +58,7 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env **/ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; OlmInboundGroupSession* sessionPtr = NULL; size_t sessionSize = 0; @@ -67,6 +68,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * if (!sessionSize) { LOGE(" ## createNewSessionJni(): failure - inbound group session size = 0"); + errorMessage = "inbound group session size = 0"; } else if ((sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) { @@ -76,6 +78,12 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * else { LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); + errorMessage = "inbound group session OOM"; + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } return (jlong)(intptr_t)sessionPtr; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index d1459ae..6e26071 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -48,7 +48,16 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject t LOGD("## createNewSessionJni(): IN"); OlmSession* accountPtr = initializeSessionMemory(); - LOGD(" ## createNewSessionJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); + if (!accountPtr) + { + LOGE("## initNewAccount(): failure - init session OOM"); + env->ThrowNew(env->FindClass("java/lang/Exception"), "init session OOM"); + } + else + { + LOGD(" ## createNewSessionJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); + } + return (jlong)(intptr_t)accountPtr; } @@ -70,31 +79,6 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz } } -/** -* Initialize a new session and return it to JAVA side.
-* Since a C prt is returned as a jlong, special care will be taken -* to make the cast (OlmSession* => jlong) platform independent. -* @return the initialized OlmSession* instance if init succeed, NULL otherwise -**/ -JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## initNewSessionJni(): OlmSession IN"); - - OlmSession* sessionPtr = initializeSessionMemory(); - - // init account memory allocation - if (!sessionPtr) - { - LOGE(" ## initNewSessionJni(): failure - init session OOM"); - } - else - { - LOGD(" ## initNewSessionJni(): success - OLM session created"); - } - - return (jlong)(intptr_t)sessionPtr; -} - // ********************************************************************* // ********************** OUTBOUND SESSION ***************************** // ********************************************************************* diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index ef92395..76f59c5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -29,7 +29,6 @@ extern "C" { // session creation/destruction JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); // outbound session diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index c4e6811..b26cfae 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -37,20 +37,21 @@ OlmUtility* initializeUtilityMemory() return utilityPtr; } -JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz) +JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(createUtilityJni)(JNIEnv *env, jobject thiz) { OlmUtility* utilityPtr = initializeUtilityMemory(); - LOGD("## initUtilityJni(): IN"); + LOGD("## createUtilityJni(): IN"); // init account memory allocation if (!utilityPtr) { - LOGE(" ## initUtilityJni(): failure - init OOM"); + LOGE(" ## createUtilityJni(): failure - init OOM"); + env->ThrowNew(env->FindClass("java/lang/Exception"), "init OOM"); } else { - LOGD(" ## initUtilityJni(): success"); + LOGD(" ## createUtilityJni(): success"); } return (jlong)(intptr_t)utilityPtr; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h index 16d9e7a..de4b290 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h @@ -27,7 +27,7 @@ #ifdef __cplusplus extern "C" { #endif -JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(initUtilityJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(createUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignature, jbyteArray aKey, jbyteArray aMessage); JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHash); -- cgit v1.2.3 From 30c8d069bc37d8d72f91aacb3ae5bd64f603ad3d Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 13:56:41 +0100 Subject: The crypto objects are now saved as String to keep the backward compliancy. --- .../java/org/matrix/olm/CommonSerializeUtils.java | 26 +++++++++++++++------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java index b8c7215..30f8352 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -48,22 +48,32 @@ abstract class CommonSerializeUtils { if(null == pickledData) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg)); } else { - aOutStream.writeObject(key); - aOutStream.writeObject(pickledData); + aOutStream.writeObject(new String(key, "UTF-8")); + aOutStream.writeObject(new String(pickledData, "UTF-8")); } } /** * Kick off the deserialization mechanism. * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception + * @throws Exception the exception */ - protected void deserialize(ObjectInputStream aInStream) throws IOException, ClassNotFoundException { + protected void deserialize(ObjectInputStream aInStream) throws Exception { aInStream.defaultReadObject(); - byte[] key = (byte[]) aInStream.readObject(); - byte[] pickledData = (byte[]) aInStream.readObject(); + String keyAsString = (String)aInStream.readObject(); + String pickledDataAsString = (String)aInStream.readObject(); + + byte[] key; + byte[] pickledData; + + try { + key = keyAsString.getBytes("UTF-8"); + pickledData = pickledDataAsString.getBytes("UTF-8"); + + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, e.getMessage()); + } if (null == key) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); @@ -76,5 +86,5 @@ abstract class CommonSerializeUtils { } protected abstract byte[] serialize(byte[] aKey, StringBuffer aErrorMsg); - protected abstract void deserialize(byte[] aSerializedData, byte[] aKey) throws IOException; + protected abstract void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception; } -- cgit v1.2.3 From 99ff3d15c81b20bc1f4cfd62c33137db8c6e8044 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 15:03:15 +0100 Subject: remove the useless malloc(len+1) + zero terminated --- .../src/main/java/org/matrix/olm/OlmSession.java | 6 ++-- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 15 ++------- .../src/main/jni/olm_inbound_group_session.cpp | 12 +++---- .../src/main/jni/olm_outbound_group_session.cpp | 26 +++++---------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 39 ++++++++-------------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 2 +- 6 files changed, 34 insertions(+), 66 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 2436f0d..170b1a5 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -262,7 +262,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { OlmMessage encryptedMsgRetValue = new OlmMessage(); try { - encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue); + encryptedMsgRetValue.mCipherText = new String(encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## encryptMessage(): failed " + e.getMessage()); throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE, e.getMessage()); @@ -271,7 +271,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return encryptedMsgRetValue; } - private native void encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); + private native byte[] encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); /** * Decrypt a message using the session.
@@ -314,7 +314,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * @throws IOException exception * @throws ClassNotFoundException exception */ - private void readObject(ObjectInputStream aInStream) throws Exception { + private void readObject(ObjectInputStream aInStream) throws Exception { deserialize(aInStream); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 4da0d67..30828d9 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -462,8 +462,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t // signature memory allocation size_t signatureLength = olm_account_signature_length(accountPtr); - size_t bufferLen = signatureLength + 1; - void* signedMsgPtr = malloc(bufferLen * sizeof(uint8_t)); + void* signedMsgPtr = malloc(signatureLength * sizeof(uint8_t)); if (!signedMsgPtr) { @@ -486,14 +485,10 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t } else { - // info: signatureLength is always equal to resultSign - (static_cast(signedMsgPtr))[signatureLength] = static_cast('\0'); - LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); signedMsgRetValueBuffer = env->NewByteArray(signatureLength); env->SetByteArrayRegion(signedMsgRetValueBuffer, 0 , signatureLength, (jbyte*)signedMsgPtr); - } free(signedMsgPtr); @@ -549,7 +544,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); if (!pickledPtr) { @@ -570,11 +565,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi } else { - // build success output - (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - - LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); - + LOGD(" ## serializeJni(): success - result=%lu pickled starts with = %10s", static_cast(result), static_cast(pickledPtr)); pickledDataRetValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength, (jbyte*)pickledPtr); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 7dd250b..2e6e4af 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -167,7 +167,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); - uint8_t *sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)); + uint8_t *sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)); if (!sessionIdPtr) { @@ -185,8 +185,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN } else { - sessionIdPtr[result] = static_cast('\0'); - LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId starts with =%10s",static_cast(result), (char*)sessionIdPtr); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); @@ -280,7 +279,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn uint32_t messageIndex = 0; // allocate output decrypted message - uint8_t *plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); + uint8_t *plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); // decrypt, but before reload encrypted buffer (previous one was destroyed) memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); @@ -370,7 +369,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); - void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); if (!pickledPtr) { @@ -391,8 +390,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en } else { - (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled starts with %10s", static_cast(result), static_cast(pickledPtr)); pickledDataRet = env->NewByteArray(pickledLength); env->SetByteArrayRegion(pickledDataRet, 0 , pickledLength, (jbyte*)pickledPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index bfe5a4e..827e8fd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -161,7 +161,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); - uint8_t *sessionIdPtr = (uint8_t*)malloc((lengthSessionId+1)*sizeof(uint8_t)); + uint8_t *sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)); if (!sessionIdPtr) { @@ -179,13 +179,10 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J } else { - // update length - sessionIdPtr[result] = static_cast('\0'); - returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); - LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId=%s",static_cast(result), reinterpret_cast(sessionIdPtr)); + LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId starts with %10s",static_cast(result), reinterpret_cast(sessionIdPtr)); } // free alloc @@ -251,7 +248,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * size_t sessionKeyLength = olm_outbound_group_session_key_length(sessionPtr); LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); - uint8_t *sessionKeyPtr = (uint8_t*)malloc((sessionKeyLength+1)*sizeof(uint8_t)); + uint8_t *sessionKeyPtr = (uint8_t*)malloc(sessionKeyLength*sizeof(uint8_t)); if (!sessionKeyPtr) { @@ -269,9 +266,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * } else { - // update length - sessionKeyPtr[result] = static_cast('\0'); - LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%s",static_cast(result), reinterpret_cast(sessionKeyPtr)); + LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey starts with %10s",static_cast(result), reinterpret_cast(sessionKeyPtr)); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionKeyPtr); @@ -323,7 +318,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE // compute max encrypted length size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); - uint8_t *encryptedMsgPtr = (uint8_t*)malloc((encryptedMsgLength+1)*sizeof(uint8_t)); + uint8_t *encryptedMsgPtr = (uint8_t*)malloc(encryptedMsgLength*sizeof(uint8_t)); if (!encryptedMsgPtr) { @@ -348,10 +343,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE } else { - // update decrypted buffer size - encryptedMsgPtr[encryptedLength] = static_cast('\0'); - - LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); + LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%10s",static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); encryptedMsgRet = env->NewByteArray(encryptedLength); env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedLength, (jbyte*)encryptedMsgPtr); @@ -412,7 +404,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); if(!pickledPtr) { @@ -433,9 +425,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e } else { - // build success output - (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled starts with %10s", static_cast(result), static_cast(pickledPtr)); returnValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 6e26071..d6ede41 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -461,15 +461,16 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J * Encrypt a message using the session.
* @param aClearMsg clear text message * @param [out] aEncryptedMsg ciphered message + * @return the encrypted message */ -JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg) +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg) { + jbyteArray encryptedMsgRet = 0; const char* errorMessage = NULL; OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *clearMsgPtr = NULL; jclass encryptedMsgJClass = 0; - jfieldID encryptedMsgFieldId; jfieldID typeMsgFieldId; LOGD("## encryptMessageJni(): IN "); @@ -498,11 +499,6 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz LOGE("## encryptMessageJni(): failure - unable to get crypted message class"); errorMessage = "unable to get crypted message class"; } - else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) - { - LOGE("## encryptMessageJni(): failure - unable to get message field"); - errorMessage = "unable to get message field"; - } else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) { LOGE("## encryptMessageJni(): failure - unable to get message type field"); @@ -532,7 +528,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz size_t clearMsgLength = (size_t)env->GetArrayLength(aClearMsgBuffer); size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); - void *encryptedMsgPtr = malloc((encryptedMsgLength+1)*sizeof(uint8_t)); + void *encryptedMsgPtr = malloc(encryptedMsgLength*sizeof(uint8_t)); if (!encryptedMsgPtr) { @@ -562,17 +558,13 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz } else { - // update encrypted buffer size - (static_cast(encryptedMsgPtr))[result] = static_cast('\0'); - // update message type: PRE KEY or normal env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); - // update message: encryptedMsgPtr => encryptedJstring - jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr); - env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring); + encryptedMsgRet = env->NewByteArray(encryptedMsgLength); + env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedMsgLength, (jbyte*)encryptedMsgPtr); - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", static_cast(result), static_cast(messageType), static_cast((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr); + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg starts with %10s", static_cast(result), static_cast(messageType), static_cast((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr); } free(encryptedMsgPtr); @@ -592,6 +584,8 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz { env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } + + return encryptedMsgRet; } /** @@ -682,7 +676,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); // allocate output decrypted message - plainTextMsgPtr = static_cast(malloc((maxPlainTextLength+1)*sizeof(uint8_t))); + plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); // decrypt, but before reload encrypted buffer (previous one was destroyed) memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); @@ -756,7 +750,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, size_t lengthSessionId = olm_session_id_length(sessionPtr); LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",static_cast(lengthSessionId)); - void *sessionIdPtr = malloc((lengthSessionId+1)*sizeof(uint8_t)); + void *sessionIdPtr = malloc(lengthSessionId*sizeof(uint8_t)); if (!sessionIdPtr) { @@ -774,10 +768,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, } else { - // update length - (static_cast(sessionIdPtr))[result] = static_cast('\0'); - - LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",static_cast(result), (char*)sessionIdPtr); + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId= starts with %10s",static_cast(result), (char*)sessionIdPtr); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); @@ -832,7 +823,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - void *pickledPtr = malloc((pickledLength+1)*sizeof(uint8_t)); + void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); if (!pickledPtr) { @@ -853,9 +844,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi } else { - // build success output - (static_cast(pickledPtr))[pickledLength] = static_cast('\0'); - LOGD(" ## serializeJni(): success - result=%lu pickled=%s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled starts with %s", static_cast(result), static_cast(pickledPtr)); returnValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 76f59c5..01cf96c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -43,7 +43,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // encrypt/decrypt -JNIEXPORT void OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); -- cgit v1.2.3 From 26a7ef8ddc2b9dd05d40a3d586acd778375f7cb1 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 15:12:15 +0100 Subject: Clear some data before releasing them --- .../OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp | 1 + .../OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 2e6e4af..a2b1624 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -307,6 +307,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn if (plainTextMsgPtr) { + memset(plainTextMsgPtr, 0, maxPlainTextLength*sizeof(uint8_t)); free(plainTextMsgPtr); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 827e8fd..7330a20 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -129,6 +129,8 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); } + // clear the random buffer + memset(randomBuffPtr, 0, randomLength); free(randomBuffPtr); } } -- cgit v1.2.3 From a14bf30c43d87e6316fd984a6be76de0c9a9ba7a Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 15:29:23 +0100 Subject: add sanity checks when releasing the objects --- .../java/org/matrix/olm/CommonSerializeUtils.java | 1 - .../src/main/java/org/matrix/olm/OlmAccount.java | 6 +++-- .../src/main/java/org/matrix/olm/OlmException.java | 8 ++----- .../org/matrix/olm/OlmInboundGroupSession.java | 4 +++- .../org/matrix/olm/OlmOutboundGroupSession.java | 6 +++-- .../src/main/java/org/matrix/olm/OlmSession.java | 27 +++++++++++++--------- .../src/main/java/org/matrix/olm/OlmUtility.java | 21 ++++++++++------- 7 files changed, 42 insertions(+), 31 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java index 30f8352..93a85fd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -17,7 +17,6 @@ package org.matrix.olm; -import android.text.TextUtils; import android.util.Log; import java.io.IOException; diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 3e7d01d..6c1caf0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -77,8 +77,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * Release native account and invalid its JAVA reference counter part.
* Public API for {@link #releaseAccountJni()}. */ - public void releaseAccount(){ - releaseAccountJni(); + public void releaseAccount() { + if (0 != mNativeId) { + releaseAccountJni(); + } mNativeId = 0; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 155724b..93a2425 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -55,15 +55,11 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405; public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406; - public static final int EXCEPTION_CODE_UTILITY_CREATION = 501; - public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 500; + public static final int EXCEPTION_CODE_UTILITY_CREATION = 500; + public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 501; // exception human readable messages - public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "createNewSession() failed"; - public static final String EXCEPTION_MSG_NEW_INBOUND_GROUP_SESSION = "createNewSession() failed"; public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters"; - public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "initNewAccount() failed"; - public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "initNewSession() failed"; /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION}, * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}..**/ diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index d9075c8..09e5276 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -70,7 +70,9 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * Public API for {@link #releaseSessionJni()}. */ public void releaseSession(){ - releaseSessionJni(); + if (0 != mNativeId) { + releaseSessionJni(); + } mNativeId = 0; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index a7972d3..d26b9b6 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -59,7 +59,9 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * Public API for {@link #releaseSessionJni()}. */ public void releaseSession() { - releaseSessionJni(); + if (0 != mNativeId) { + releaseSessionJni(); + } mNativeId = 0; } @@ -252,7 +254,7 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { createNewSession(); - String errorMsg = null; + String errorMsg; try { if ((null == aSerializedData) || (null == aKey)) { diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 170b1a5..92cc110 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -66,8 +66,10 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. */ - public void releaseSession(){ - releaseSessionJni(); + public void releaseSession() { + if (0 != mNativeId) { + releaseSessionJni(); + } mNativeId = 0; } @@ -262,7 +264,11 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { OlmMessage encryptedMsgRetValue = new OlmMessage(); try { - encryptedMsgRetValue.mCipherText = new String(encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue), "UTF-8"); + byte[] encryptedMessageBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue); + + if (null != encryptedMessageBuffer) { + encryptedMsgRetValue.mCipherText = new String(encryptedMessageBuffer, "UTF-8"); + } } catch (Exception e) { Log.e(LOG_TAG, "## encryptMessage(): failed " + e.getMessage()); throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE, e.getMessage()); @@ -360,24 +366,23 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { createNewSession(); - StringBuffer errorMsg = new StringBuffer(); + String errorMsg; try { - String jniError; if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg.append("invalid input parameters"); - } else if (null != (jniError = deserializeJni(aSerializedData, aKey))) { - errorMsg.append(jniError); + errorMsg = "invalid input parameters"; + } else { + errorMsg = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg.append(e.getMessage()); + errorMsg = e.getMessage(); } - if (errorMsg.length() > 0) { + if (!TextUtils.isEmpty(errorMsg)) { releaseSession(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, String.valueOf(errorMsg)); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index d520da6..32a5830 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -35,18 +35,21 @@ public class OlmUtility { **/ private long mNativeId; - public OlmUtility() { + public OlmUtility() throws OlmException { initUtility(); } /** * Create a native utility instance. * To be called before any other API call. - * @return true if init succeed, false otherwise. + * @exception OlmException the exception */ - private boolean initUtility() { - mNativeId = createUtilityJni(); - return (0 != mNativeId); + private void initUtility() throws OlmException { + try { + mNativeId = createUtilityJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_UTILITY_CREATION, e.getMessage()); + } } private native long createUtilityJni(); @@ -55,8 +58,10 @@ public class OlmUtility { * Release native instance.
* Public API for {@link #releaseUtilityJni()}. */ - public void releaseUtility(){ - releaseUtilityJni(); + public void releaseUtility() { + if (0 != mNativeId) { + releaseUtilityJni(); + } mNativeId = 0; } private native void releaseUtilityJni(); @@ -111,7 +116,7 @@ public class OlmUtility { * @return hash value if operation succeed, null otherwise */ public String sha256(String aMessageToHash) { - String hashRetValue = null; + String hashRetValue = null; if (null != aMessageToHash) { try { -- cgit v1.2.3 From 29339bc00a52391d78d7f9b723880ce5577d8981 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Mon, 9 Jan 2017 16:39:54 +0100 Subject: Update getSdkOlmVersion to provide the git commit --- java/android/OlmLibSdk/olm-sdk/build.gradle | 25 ++++++++++++++++++++++ .../java/org/matrix/olm/OlmAccountTest.java | 2 +- .../src/main/java/org/matrix/olm/OlmManager.java | 13 ++++++++--- 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle index 188acb6..9ce4d37 100644 --- a/java/android/OlmLibSdk/olm-sdk/build.gradle +++ b/java/android/OlmLibSdk/olm-sdk/build.gradle @@ -15,7 +15,17 @@ android { testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { + debug { + resValue "string", "git_olm_revision", "\"${gitRevision()}\"" + resValue "string", "git_olm_revision_unix_date", "\"${gitRevisionUnixDate()}\"" + resValue "string", "git_olm_revision_date", "\"${gitRevisionDate()}\"" + } + release { + resValue "string", "git_olm_revision", "\"${gitRevision()}\"" + resValue "string", "git_olm_revision_unix_date", "\"${gitRevisionUnixDate()}\"" + resValue "string", "git_olm_revision_date", "\"${gitRevisionDate()}\"" + minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } @@ -93,6 +103,21 @@ def getNdkBuildCmd() { return ndkBuildCmd } +def gitRevision() { + def cmd = "git rev-parse --short HEAD" + return cmd.execute().text.trim() +} + +def gitRevisionUnixDate() { + def cmd = "git show -s --format=%ct HEAD^{commit}" + return cmd.execute().text.trim() +} + +def gitRevisionDate() { + def cmd = "git show -s --format=%ci HEAD^{commit}" + return cmd.execute().text.trim() +} + dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') compile 'com.android.support:appcompat-v7:21.+' diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index 699d966..d474f12 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -65,7 +65,7 @@ public class OlmAccountTest { String olmLibVersion = mOlmManager.getOlmLibVersion(); assertNotNull(olmLibVersion); - String olmSdkVersion = mOlmManager.getSdkOlmVersion(); + String olmSdkVersion = mOlmManager.getSdkOlmVersion(getInstrumentation().getContext()); assertNotNull(olmLibVersion); Log.d(LOG_TAG, "## setUpClass(): Versions - Android Olm SDK = "+olmSdkVersion+" Olm lib ="+olmLibVersion); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java index 2efb0c2..c1e6031 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -17,6 +17,7 @@ package org.matrix.olm; +import android.content.Context; import android.util.Log; /** @@ -25,7 +26,6 @@ import android.util.Log; */ public class OlmManager { private static final String LOG_TAG = "OlmManager"; - private static final String SDK_OLM_VERSION = "V0.1.0_1"; /** * Constructor. @@ -41,8 +41,15 @@ public class OlmManager { } } - public String getSdkOlmVersion() { - return SDK_OLM_VERSION; + /** + * Provide the android library version + * @param context the context + * @return the library version + */ + public String getSdkOlmVersion(Context context) { + String gitVersion = context.getResources().getString(R.string.git_olm_revision); + String date = context.getResources().getString(R.string.git_olm_revision_date); + return gitVersion + "-" + date; } /** -- cgit v1.2.3 From eeb210f733924d9c48e82c66e53f0630f05d894e Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 10 Jan 2017 11:40:57 +0100 Subject: -> Check the function descriptions -> Update the deserialization methods (the jni methods create an object instance before deserializing them. --- .../src/main/java/org/matrix/olm/OlmAccount.java | 156 +++++++------------ .../src/main/java/org/matrix/olm/OlmException.java | 4 +- .../org/matrix/olm/OlmInboundGroupSession.java | 106 ++++++------- .../org/matrix/olm/OlmOutboundGroupSession.java | 104 +++++++------ .../src/main/java/org/matrix/olm/OlmSession.java | 130 +++++++++++----- .../src/main/java/org/matrix/olm/OlmUtility.java | 79 +++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 118 ++++++++------ .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 8 +- .../src/main/jni/olm_inbound_group_session.cpp | 169 ++++++++++++--------- .../src/main/jni/olm_inbound_group_session.h | 6 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 5 - .../src/main/jni/olm_outbound_group_session.cpp | 153 +++++++++++-------- .../src/main/jni/olm_outbound_group_session.h | 3 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 93 +++++++----- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 6 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 11 +- 16 files changed, 662 insertions(+), 489 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 6c1caf0..9ebaaf1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,8 +26,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; /** @@ -62,9 +60,21 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private transient long mNativeId; public OlmAccount() throws OlmException { - createNewAccount(); + try { + mNativeId = createNewAccountJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); + } } + /** + * Create a new account and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmAccount* to jlong) platform independent. + * @return the initialized OlmAccount* instance or throw an exception if fails + **/ + private native long createNewAccountJni(); + /** * Getter on the account ID. * @return native account ID @@ -92,26 +102,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ private native void releaseAccountJni(); - /** - * Create and initialize a native account instance.
- * To be called before any other API call. - * @exception OlmException the failure reason - */ - private void createNewAccount() throws OlmException { - try { - mNativeId = createNewAccountJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); - } - } - - /** - * Create an OLM account in native side.
- * Do not forget to call {@link #releaseAccount()} when JAVA side is done. - * @return native account instance identifier (see {@link #mNativeId}) - */ - private native long createNewAccountJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -146,7 +136,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if (null != identityKeysBuffer) { try { identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer, "UTF-8")); - //Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); } catch (Exception e) { Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); } @@ -154,14 +143,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); } - return toStringMap(identityKeysJsonObj); + return OlmUtility.toStringMap(identityKeysJsonObj); } /** * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
* Keys are Base64 encoded. * These keys must be published on the server. - * @return byte array containing the identity keys if operation succeed, null otherwise + * @return the identity keys or throw an exception if it fails */ private native byte[] identityKeysJni(); @@ -173,6 +162,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return maxOneTimeKeysJni(); } + /** + * Return the largest number of "one time keys" this account can store. + * @return the max number of "one time keys", -1 otherwise + */ private native long maxOneTimeKeysJni(); /** @@ -190,6 +183,12 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } + /** + * Generate a number of new one time keys.
If total number of keys stored + * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. + * An exception is thrown if the operation fails.
+ * @param aNumberOfKeys number of keys to generate + */ private native void generateOneTimeKeysJni(int aNumberOfKeys); /** @@ -221,7 +220,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if( null != oneTimeKeysBuffer) { try { oneTimeKeysJsonObj = new JSONObject(new String(oneTimeKeysBuffer, "UTF-8")); - //Log.d(LOG_TAG, "## oneTimeKeys(): OneTime Json keys=" + oneTimeKeysJsonObj.toString()); } catch (Exception e) { Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); } @@ -229,7 +227,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); } - return toStringMapMap(oneTimeKeysJsonObj); + return OlmUtility.toStringMapMap(oneTimeKeysJsonObj); } /** @@ -237,7 +235,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * The returned data is a JSON-formatted object with the single property * curve25519, which is itself an object mapping key id to * base64-encoded Curve25519 key.
- * @return byte array containing the one time keys if operation succeed, null otherwise + * @return byte array containing the one time keys or throw an exception if it fails */ private native byte[] oneTimeKeysJni(); @@ -252,7 +250,8 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if (null != aSession) { try { - res = (removeOneTimeKeysJni(aSession.getOlmSessionId()) >= 0); + removeOneTimeKeysJni(aSession.getOlmSessionId()); + res = true; Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result=" + res); } catch (Exception e) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS, e.getMessage()); @@ -264,10 +263,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { /** * Remove the "one time keys" that the session used from the account. + * An exception is thrown if the operation fails. * @param aNativeOlmSessionId native session instance identifier - * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed */ - private native int removeOneTimeKeysJni(long aNativeOlmSessionId); + private native void removeOneTimeKeysJni(long aNativeOlmSessionId); /** * Marks the current set of "one time keys" as being published. @@ -281,6 +280,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } + /** + * Marks the current set of "one time keys" as being published. + * An exception is thrown if the operation fails. + */ private native void markOneTimeKeysAsPublishedJni(); /** @@ -312,68 +315,13 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return result; } - private native byte[] signMessageJni(byte[] aMessage); - - /** - * Build a string-string dictionary from a jsonObject.
- * @param jsonObject the object to parse - * @return the map - */ - private static Map toStringMap(JSONObject jsonObject) { - if (null != jsonObject) { - HashMap map = new HashMap<>(); - Iterator keysItr = jsonObject.keys(); - while(keysItr.hasNext()) { - String key = keysItr.next(); - try { - Object value = jsonObject.get(key); - - if (value instanceof String) { - map.put(key, (String) value); - } else { - Log.e(LOG_TAG, "## toStringMap(): unexpected type " + value.getClass()); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## toStringMap(): failed " + e.getMessage()); - } - } - - return map; - } - - return null; - } - /** - * Build a string-string dictionary of string dictionary from a jsonObject.
- * @param jsonObject the object to parse - * @return the map + * Sign a message with the ed25519 fingerprint key for this account.
+ * The signed message is returned by the method. + * @param aMessage message to sign + * @return the signed message */ - private static Map> toStringMapMap(JSONObject jsonObject) { - if (null != jsonObject) { - HashMap> map = new HashMap<>(); - - Iterator keysItr = jsonObject.keys(); - while(keysItr.hasNext()) { - String key = keysItr.next(); - try { - Object value = jsonObject.get(key); - - if (value instanceof JSONObject) { - map.put(key, toStringMap((JSONObject) value)); - } else { - Log.e(LOG_TAG, "## toStringMapMap(): unexpected type " + value.getClass()); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## toStringMapMap(): failed " + e.getMessage()); - } - } - - return map; - } - - return null; - } + private native byte[] signMessageJni(byte[] aMessage); //============================================================================================================== // Serialization management @@ -428,7 +376,12 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native byte[] serializeJni(byte[] aKey); + /** + * Serialize and encrypt account instance.
+ * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ + private native byte[] serializeJni(byte[] aKeyBuffer); /** * Loads an account from a pickled bytes buffer.
@@ -439,15 +392,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewAccount(); - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -460,5 +412,11 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } - private native String deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); + /** + * Allocate a new account and initialize it with the serialisation data.
+ * @param aSerializedDataBuffer the account serialisation buffer + * @param aKeyBuffer the key used to encrypt the serialized account data + * @return the deserialized account + **/ + private native long deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 93a2425..b0b1a6a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index 09e5276..571bddb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.matrix.olm; - import android.text.TextUtils; import android.util.Log; @@ -55,16 +54,32 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. - * The session key parameter is retrieved from an outbound group session - * See {@link #createNewSession()} and {@link #initInboundGroupSession(String)} + * The session key parameter is retrieved from an outbound group session. * @param aSessionKey session key * @throws OlmException constructor failure */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { - createNewSession(); - initInboundGroupSession(aSessionKey); + if (TextUtils.isEmpty(aSessionKey)) { + Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); + } else { + try { + mNativeId = createNewSessionJni(aSessionKey.getBytes("UTF-8")); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); + } + } } + /** + * Initialize a new inbound group session and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmInboundGroupSession* to jlong) platform independent. + * @param aSessionKeyBuffer session key from an outbound session + * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. + **/ + private native long createNewSessionJni(byte[] aSessionKeyBuffer); + /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. @@ -80,30 +95,10 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * Destroy the corresponding OLM inbound group session native object.
* This method must ALWAYS be called when this JAVA instance * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #createNewSessionJni()}. + * See {@link #createNewSessionJni(byte[])}. */ private native void releaseSessionJni(); - /** - * Create and save the session native instance ID.
- * To be called before any other API call. - * @exception OlmException the failure reason - */ - private void createNewSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION, e.getMessage()); - } - } - - /** - * Create the corresponding OLM inbound group session in native side.
- * Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native session instance identifier (see {@link #mNativeId}) - */ - private native long createNewSessionJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -112,28 +107,6 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return (0 == mNativeId); } - /** - * Start a new inbound group session.
- * The session key parameter is retrieved from an outbound group session - * see {@link OlmOutboundGroupSession#sessionKey()} - * @param aSessionKey session key - * @exception OlmException the failure reason - */ - private void initInboundGroupSession(String aSessionKey) throws OlmException { - if (TextUtils.isEmpty(aSessionKey)) { - Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); - } else { - try { - initInboundGroupSessionJni(aSessionKey.getBytes("UTF-8")); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); - } - } - } - - private native void initInboundGroupSessionJni(byte[] aSessionKeyBuffer); - /** * Retrieve the base64-encoded identifier for this inbound group session. * @return the session ID @@ -148,6 +121,11 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } } + /** + * Get a base64-encoded identifier for this inbound group session. + * An exception is thrown if the operation fails. + * @return the base64-encoded identifier + */ private native byte[] sessionIdentifierJni(); /** @@ -174,6 +152,13 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return result; } + /** + * Decrypt a message. + * An exception is thrown if the operation fails. + * @param aEncryptedMsg the encrypted message + * @param aDecryptMessageResult the decryptMessage informaton + * @return the decrypted message + */ private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult); //============================================================================================================== @@ -232,7 +217,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * JNI counter part of {@link #serialize(byte[], StringBuffer)}. * @param aKey encryption key - * @return pickled base64 string if operation succeed, null otherwise + * @return the serialized session */ private native byte[] serializeJni(byte[] aKey); @@ -244,16 +229,14 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewSession(); - - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -267,10 +250,11 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } /** - * JNI counter part of {@link #deserialize(byte[], byte[])}. - * @param aSerializedData pickled session in a base64 sbytes buffer - * @param aKey key used to encrypted in {@link #serialize(byte[], StringBuffer)} - * @return null if operation succeed, an error message if operation failed - */ - private native String deserializeJni(byte[] aSerializedData, byte[] aKey); + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index d26b9b6..0481824 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,14 +46,24 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * Constructor.
* Create and save a new session native instance ID and * initialise a new outbound group session.
- * See {@link #createNewSession()} and {@link #initOutboundGroupSession()} * @throws OlmException constructor failure */ public OlmOutboundGroupSession() throws OlmException { - createNewSession(); - initOutboundGroupSession(); + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, e.getMessage()); + } } + /** + * Create the corresponding OLM outbound group session in native side.
+ * An exception is thrown if the operation fails. + * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native session instance identifier (see {@link #mNativeId}) + */ + private native long createNewSessionJni(); + /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. @@ -73,27 +83,6 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ private native void releaseSessionJni(); - /** - * Create and save the session native instance ID. - * Wrapper for {@link #createNewSessionJni()}.
- * To be called before any other API call. - * @exception OlmException the exception. - */ - private void createNewSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, e.getMessage()); - } - } - - /** - * Create the corresponding OLM outbound group session in native side.
- * Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native session instance identifier (see {@link #mNativeId}) - */ - private native long createNewSessionJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -102,20 +91,6 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return (0 == mNativeId); } - /** - * Start a new outbound group session.
- * @exception OlmException the failre reason - */ - private void initOutboundGroupSession() throws OlmException { - try { - initOutboundGroupSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION, e.getMessage()); - } - } - - private native void initOutboundGroupSessionJni(); - /** * Get a base64-encoded identifier for this session. * @return session identifier @@ -130,6 +105,11 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } } + /** + * Return the session identifier. + * An exception is thrown if the operation fails. + * @return the session identifier + */ private native byte[] sessionIdentifierJni(); /** @@ -141,6 +121,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser public int messageIndex() { return messageIndexJni(); } + + /** + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * An exception is thrown if the operation fails. + * @return current session index + */ private native int messageIndexJni(); /** @@ -159,6 +147,11 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } } + /** + * Return the session key. + * An exception is thrown if the operation fails. + * @return the session key + */ private native byte[] sessionKeyJni(); /** @@ -186,8 +179,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return retValue; } - private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); + /** + * Encrypt a bytes buffer messages. + * An exception is thrown if the operation fails. + * @param aClearMsgBuffer the message to encode + * @return the encoded message + */ + private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); //============================================================================================================== // Serialization management @@ -240,8 +239,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return pickleRetValue; } - private native byte[] serializeJni(byte[] aKey); + /** + * JNI counter part of {@link #serialize(byte[], StringBuffer)}. + * An exception is thrown if the operation fails. + * @param aKey encryption key + * @return the serialized session + */ + private native byte[] serializeJni(byte[] aKey); /** * Loads an account from a pickled base64 string.
@@ -252,16 +257,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewSession(); - - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -274,6 +277,13 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } } - private native String deserializeJni(byte[] aSerializedData, byte[] aKey); + /** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java index 92cc110..da2e963 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -43,9 +43,20 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { private transient long mNativeId; public OlmSession() throws OlmException { - createNewSession(); + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, e.getMessage()); + } } + /** + * Create an OLM session in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native account instance identifier or throw an exception. + */ + private native long createNewSessionJni(); + /** * Getter on the session ID. * @return native session ID @@ -73,28 +84,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { mNativeId = 0; } - /** - * Create a native account instance without any initialization.
- * Since the account is left uninitialized, this - * method is intended to be used in the serialization mechanism (see {@link #readObject(ObjectInputStream)}).
- * Public wrapper for {@link #createNewSessionJni()}. - * @exception OlmException the exception - */ - private void createNewSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, e.getMessage()); - } - } - - /** - * Create an OLM account in native side.
- * Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native account instance identifier (see {@link #mNativeId}) - */ - private native long createNewSessionJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -125,6 +114,15 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } } + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
The recipient is defined as the entity + * with whom the session is established. + * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient + **/ private native void initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey); /** @@ -149,6 +147,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } } + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aOneTimeKeyMsg PRE_KEY message + */ private native void initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg); /** @@ -176,6 +181,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } } + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message based on the recipient identity key.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aOneTimeKeyMsg encrypted message + */ private native void initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); /** @@ -201,6 +214,11 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return null; } + /** + * Get the session identifier for this session. + * An exception is thrown if the operation fails. + * @return the session identifier + */ private native byte[] getSessionIdentifierJni(); /** @@ -208,13 +226,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * Public API for {@link #matchesInboundSessionJni(byte[])}. * @param aOneTimeKeyMsg PRE KEY message - * @return this if operation succeed, null otherwise + * @return true if the one time key matches. */ public boolean matchesInboundSession(String aOneTimeKeyMsg) { boolean retCode = false; try { - retCode = (0 == matchesInboundSessionJni(aOneTimeKeyMsg.getBytes("UTF-8"))); + retCode = matchesInboundSessionJni(aOneTimeKeyMsg.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG, "## matchesInboundSession(): failed " + e.getMessage()); } @@ -222,8 +240,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return retCode; } - private native int matchesInboundSessionJni(byte[] aOneTimeKeyMsg); - + /** + * Checks if the PRE_KEY message is for this in-bound session.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * An exception is thrown if the operation fails. + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches + */ + private native boolean matchesInboundSessionJni(byte[] aOneTimeKeyMsg); /** * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session based on the sender identity key.
@@ -237,7 +261,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { boolean retCode = false; try { - retCode = (0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey.getBytes("UTF-8"), aOneTimeKeyMsg.getBytes("UTF-8"))); + retCode = matchesInboundSessionFromIdKeyJni(aTheirIdentityKey.getBytes("UTF-8"), aOneTimeKeyMsg.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG, "## matchesInboundSessionFrom(): failed " + e.getMessage()); } @@ -245,8 +269,15 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return retCode; } - private native int matchesInboundSessionFromIdKeyJni(byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); - + /** + * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * An exception is thrown if the operation fails. + * @param aTheirIdentityKey the identity key of the sender + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches. + */ + private native boolean matchesInboundSessionFromIdKeyJni(byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); /** * Encrypt a message using the session.
@@ -277,6 +308,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return encryptedMsgRetValue; } + /** + * Encrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aClearMsg clear text message + * @param aEncryptedMsg ciphered message + * @return the encrypted message + */ private native byte[] encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); /** @@ -298,7 +336,12 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage()); } } - + /** + * Decrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aEncryptedMsg message to decrypt + * @return the decrypted message + */ private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg); //============================================================================================================== @@ -354,7 +397,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native byte[] serializeJni(byte[] aKey); + + /** + * Serialize and encrypt session instance.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ + private native byte[] serializeJni(byte[] aKeyBuffer); /** * Loads an account from a pickled base64 string.
@@ -364,16 +414,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewSession(); - - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -385,7 +433,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); } } - - private native String deserializeJni(byte[] aSerializedData, byte[] aKey); + /** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 32a5830..12f3663 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,12 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; +import org.json.JSONObject; + import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; /** * Olm SDK helper class. @@ -108,7 +113,6 @@ public class OlmUtility { */ private native String verifyEd25519SignatureJni(byte[] aSignature, byte[] aFingerprintKey, byte[] aMessage); - /** * Compute the hash(SHA-256) value of the string given in parameter(aMessageToHash).
* The hash value is the returned by the method. @@ -129,9 +133,15 @@ public class OlmUtility { return hashRetValue; } + /** + * Compute the digest (SHA 256) for the message passed in parameter.
+ * The digest value is the function return value. + * An exception is thrown if the operation fails. + * @param aMessage the message + * @return digest of the message. + **/ private native byte[] sha256Jni(byte[] aMessage); - /** * Helper method to compute a string based on random integers. * @return bytes buffer containing randoms integer values @@ -156,5 +166,66 @@ public class OlmUtility { public boolean isReleased() { return (0 == mNativeId); } + + /** + * Build a string-string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + public static Map toStringMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap map = new HashMap<>(); + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof String) { + map.put(key, (String) value); + } else { + Log.e(LOG_TAG, "## toStringMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } + + /** + * Build a string-string dictionary of string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + public static Map> toStringMapMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap> map = new HashMap<>(); + + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof JSONObject) { + map.put(key, toStringMap((JSONObject) value)); + } else { + Log.e(LOG_TAG, "## toStringMapMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMapMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 30828d9..6e62f50 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -20,9 +20,9 @@ using namespace AndroidOlmSdk; /** -* Init memory allocation for account creation. -* @return valid memory allocation, NULL otherwise -**/ + * Init memory allocation for account creation. + * @return valid memory allocation, NULL otherwise + **/ OlmAccount* initializeAccountMemory() { size_t accountSize = olm_account_size(); @@ -43,11 +43,11 @@ OlmAccount* initializeAccountMemory() } /** -* Create a new account and return it to JAVA side.
-* Since a C prt is returned as a jlong, special care will be taken -* to make the cast (OlmAccount* => jlong) platform independent. -* @return the initialized OlmAccount* instance -**/ + * Create a new account and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmAccount* => jlong) platform independent. + * @return the initialized OlmAccount* instance or throw an exception if fails + **/ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -98,6 +98,12 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject t if (errorMessage) { + // release the allocated data + if (accountPtr) + { + olm_clear_account(accountPtr); + free(accountPtr); + } env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } @@ -106,7 +112,6 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject t /** * Release the account allocation made by initializeAccountMemory().
* This method MUST be called when java counter part account instance is done. - * */ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) { @@ -133,11 +138,12 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz // ********************************************************************* // ************************* IDENTITY KEYS API ************************* // ********************************************************************* + /** -* Get identity keys: Ed25519 fingerprint key and Curve25519 identity key.
-* The keys are returned in the byte array. -* @return a valid byte array if operation succeed, null otherwise -**/ + * Get identity keys: Ed25519 fingerprint key and Curve25519 identity key.
+ * The keys are returned in the byte array. + * @return the identity keys or throw an exception if it fails + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -204,10 +210,14 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject // ********************************************************************* // ************************* ONE TIME KEYS API ************************* // ********************************************************************* + /** - * Get the maximum number of "one time keys" the account can store. - * -**/ + * Get the public parts of the unpublished "one time keys" for the account.
+ * The returned data is a JSON-formatted object with the single property + * curve25519, which is itself an object mapping key id to + * base64-encoded Curve25519 key.
+ * @return byte array containing the one time keys or throw an exception if it fails + */ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz) { OlmAccount* accountPtr = getAccountInstanceId(env, thiz); @@ -229,8 +239,9 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thi /** * Generate "one time keys". + * An exception is thrown if the operation fails. * @param aNumberOfKeys number of keys to generate -**/ + **/ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) { const char* errorMessage = NULL; @@ -289,7 +300,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject * Get "one time keys".
* Return the public parts of the unpublished "one time keys" for the account * @return a valid byte array if operation succeed, null otherwise -**/ + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -354,14 +365,12 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t /** * Remove the "one time keys" that the session used from the account. - * Return the public parts of the unpublished "one time keys" for the account + * An exception is thrown if the operation fails. * @param aNativeOlmSessionId session instance - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise -**/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) + **/ +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) { const char* errorMessage = NULL; - jint retCode = ERROR_CODE_KO; OlmAccount* accountPtr = NULL; OlmSession* sessionPtr = (OlmSession*)aNativeOlmSessionId; @@ -370,7 +379,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t LOGE("## removeOneTimeKeysJni(): failure - invalid session ptr"); errorMessage = "invalid session ptr"; } - else if(!(accountPtr = getAccountInstanceId(env, thiz))) + else if (!(accountPtr = getAccountInstanceId(env, thiz))) { LOGE("## removeOneTimeKeysJni(): failure - invalid account ptr"); errorMessage = "invalid account ptr"; @@ -381,12 +390,11 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t if (result == olm_error()) { // the account doesn't have any matching "one time keys".. - LOGW("## removeOneTimeKeysJni(): failure - removing one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + LOGW("## removeOneTimeKeysJni(): failure - removing one time keys Msg=%s", olm_account_last_error(accountPtr)); errorMessage = (const char *)olm_account_last_error(accountPtr); } else { - retCode = ERROR_CODE_OK; LOGD("## removeOneTimeKeysJni(): success"); } } @@ -395,13 +403,12 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t { env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } - - return retCode; } /** * Mark the current set of "one time keys" as being published. -**/ + * An exception is thrown if the operation fails. + **/ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -438,7 +445,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, * The signed message is returned by the function. * @param aMessage message to sign * @return the signed message, null otherwise -**/ + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) { const char* errorMessage = NULL; @@ -510,10 +517,10 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t } /** -* Serialize and encrypt account instance into a base64 string.
-* @param aKeyBuffer key used to encrypt the serialized account data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt account instance.
+ * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -544,7 +551,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); + void* pickledPtr = malloc(pickledLength * sizeof(uint8_t)); if (!pickledPtr) { @@ -565,7 +572,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi } else { - LOGD(" ## serializeJni(): success - result=%lu pickled starts with = %10s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); pickledDataRetValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength, (jbyte*)pickledPtr); } @@ -588,11 +595,18 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi return pickledDataRetValue; } - -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new account and initialise it with the serialisation data.
+ * @param aSerializedDataBuffer the account serialisation buffer + * @param aKeyBuffer the key used to encrypt the serialized account data + * @return the deserialised account + **/ +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { + const char* errorMessage = NULL; + OlmAccount* accountPtr = NULL; - jstring errorMessageRetValue = 0; + jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; @@ -601,22 +615,27 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { - LOGE(" ## deserializeJni(): failure - serialized data"); + LOGE(" ## deserializeJni(): failure - invalid serialized data"); + errorMessage = "invalid serialized data"; } - else if (!(accountPtr = getAccountInstanceId(env, thiz))) + else if (!(accountPtr = initializeAccountMemory())) { LOGE(" ## deserializeJni(): failure - account failure OOM"); + errorMessage = "account failure OOM"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { @@ -632,9 +651,8 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_account_last_error(accountPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); } else { @@ -653,5 +671,15 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (accountPtr) + { + olm_clear_account(accountPtr); + free(accountPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)accountPtr; } \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h index 2bfb39c..42b2c2a 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz); JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); // signing @@ -47,7 +47,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t // serialization JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer); -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index a2b1624..14e338b 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -22,7 +22,6 @@ using namespace AndroidOlmSdk; /** * Release the session allocation made by initializeInboundGroupSessionMemory().
* This method MUST be called when java counter part account instance is done. - * */ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { @@ -51,103 +50,91 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env } /** -* Initialize a new inbound group session and return it to JAVA side.
-* Since a C prt is returned as a jlong, special care will be taken -* to make the cast (OlmInboundGroupSession* => jlong) platform independent. -* @return the initialized OlmInboundGroupSession* instance if init succeed, NULL otherwise -**/ -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) + * Initialize a new inbound group session and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmInboundGroupSession* => jlong) platform independent. + * @param aSessionKeyBuffer session key from an outbound session + * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. + **/ +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) { const char* errorMessage = NULL; OlmInboundGroupSession* sessionPtr = NULL; - size_t sessionSize = 0; + jbyte* sessionKeyPtr = NULL; + size_t sessionSize = olm_inbound_group_session_size(); LOGD("## createNewSessionJni(): inbound group session IN"); - sessionSize = olm_inbound_group_session_size(); if (!sessionSize) { LOGE(" ## createNewSessionJni(): failure - inbound group session size = 0"); errorMessage = "inbound group session size = 0"; } - else if ((sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) - { - sessionPtr = olm_inbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - inbound group session size=%lu",static_cast(sessionSize)); - } - else + else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) { LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); errorMessage = "inbound group session OOM"; } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)sessionPtr; -} - -/** - * Create a new in-bound session.
- * @param aSessionKey session key from an outbound session - */ -JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) -{ - const char* errorMessage = NULL; - OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); - jbyte* sessionKeyPtr = NULL; - size_t sessionResult; - - LOGD("## initInboundGroupSessionJni(): inbound group session IN"); - - if (!sessionPtr) - { - LOGE(" ## initInboundGroupSessionJni(): failure - invalid inbound group session instance"); - errorMessage = "invalid inbound group session instance"; - } else if (!aSessionKeyBuffer) { - LOGE(" ## initInboundGroupSessionJni(): failure - invalid aSessionKey"); + LOGE(" ## createNewSessionJni(): failure - invalid aSessionKey"); errorMessage = "invalid aSessionKey"; } else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) { - LOGE(" ## initInboundGroupSessionJni(): failure - session key JNI allocation OOM"); + LOGE(" ## createNewSessionJni(): failure - session key JNI allocation OOM"); errorMessage = "Session key JNI allocation OOM"; } else { + sessionPtr = olm_inbound_group_session(sessionPtr); + size_t sessionKeyLength = (size_t)env->GetArrayLength(aSessionKeyBuffer); - LOGD(" ## initInboundGroupSessionJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); + LOGD(" ## createNewSessionJni(): sessionKeyLength=%lu", static_cast(sessionKeyLength)); + + size_t sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); - sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); - if (sessionResult == olm_error()) { + if (sessionResult == olm_error()) + { errorMessage = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## initInboundGroupSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); + LOGE(" ## createNewSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); } else { - LOGD(" ## initInboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); + LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); } - } + } - // free local alloc - if (sessionKeyPtr) - { - env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); - } + if (sessionKeyPtr) + { + env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } if (errorMessage) { + // release the allocated session + if (sessionPtr) + { + olm_clear_inbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } + + return (jlong)(intptr_t)sessionPtr; } /** -* Get a base64-encoded identifier for this inbound group session. -*/ + * Get a base64-encoded identifier for this inbound group session. + * An exception is thrown if the operation fails. + * @return the base64-encoded identifier + */ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -185,7 +172,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN } else { - LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId starts with =%10s",static_cast(result), (char*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); @@ -203,7 +190,13 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN return returnValue; } - +/** + * Decrypt a message. + * An exception is thrown if the operation fails. + * @param aEncryptedMsg the encrypted message + * @param aDecryptMessageResult the decryptMessage information + * @return the decrypted message + */ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult) { jbyteArray decryptedMsgBuffer = 0; @@ -335,10 +328,11 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn /** -* Serialize and encrypt session instance into a base64 string.
-* @param aKeyBuffer key used to encrypt the serialized session data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt session instance into a base64 string.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized session data + * @return a base64 string if operation succeed, null otherwise + **/ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -391,7 +385,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en } else { - LOGD(" ## serializeJni(): success - result=%lu pickled starts with %10s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); pickledDataRet = env->NewByteArray(pickledLength); env->SetByteArrayRegion(pickledDataRet, 0 , pickledLength, (jbyte*)pickledPtr); @@ -415,38 +409,58 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en return pickledDataRet; } - -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { - OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env, thiz); - jstring errorMessageRetValue = 0; + const char* errorMessage = NULL; + + OlmInboundGroupSession* sessionPtr = NULL; + size_t sessionSize = olm_inbound_group_session_size(); jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); - if (!sessionPtr) + if (!sessionSize) + { + LOGE(" ## deserializeJni(): failure - inbound group session size = 0"); + errorMessage = "inbound group session size = 0"; + } + else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) { LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; } else if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "serialized data"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { + sessionPtr = olm_inbound_group_session(sessionPtr); + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); @@ -459,9 +473,8 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_inbound_group_session() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_inbound_group_session() Msg=%s", errorMessage); } else { @@ -480,5 +493,15 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_inbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h index a631acf..00990dd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -30,16 +30,14 @@ extern "C" { // session creation/destruction JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); -JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex); // serialization JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); - +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h index 73a529d..e6a49e2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h @@ -53,12 +53,7 @@ namespace AndroidOlmSdk { - // Error codes definition - static const int ERROR_CODE_OK = 0; - static const int ERROR_CODE_KO = -1; - // constants - static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 7330a20..689f1b4 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -52,13 +52,15 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en } /** -* Initialize a new outbound group session and return it to JAVA side.
-* Since a C prt is returned as a jlong, special care will be taken -* to make the cast (OlmOutboundGroupSession* => jlong) platform independent. -* @return the initialized OlmOutboundGroupSession* instance if init succeed, NULL otherwise -**/ + * Initialize a new outbound group session and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmOutboundGroupSession* => jlong) platform independent. + * @return the initialized OlmOutboundGroupSession* instance or throw an exception + **/ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; + OlmOutboundGroupSession* sessionPtr = NULL; size_t sessionSize = 0; @@ -68,65 +70,45 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv if (0 == sessionSize) { LOGE(" ## createNewSessionJni(): failure - outbound group session size = 0"); + errorMessage = "outbound group session size = 0"; } - else if ((sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) - { - sessionPtr = olm_outbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); - } - else + else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) { LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); - } - - return (jlong)(intptr_t)sessionPtr; -} - -/** - * Start a new outbound session.
- */ -JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - - LOGD("## initOutboundGroupSessionJni(): IN"); - - OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - - if (!sessionPtr) - { - LOGE(" ## initOutboundGroupSessionJni(): failure - invalid outbound group session instance"); - errorMessage = "invalid outbound group session instance"; + errorMessage = "outbound group session OOM"; } else { + sessionPtr = olm_outbound_group_session(sessionPtr); + LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); + // compute random buffer size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); uint8_t *randomBuffPtr = NULL; - LOGW(" ## initOutboundGroupSessionJni(): randomLength=%lu",static_cast(randomLength)); + LOGW(" ## createNewSessionJni(): randomLength=%lu",static_cast(randomLength)); if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { - LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init"); + LOGE(" ## createNewSessionJni(): failure - random buffer init"); errorMessage = "random buffer init"; } else { if (0 == randomLength) { - LOGW(" ## initOutboundGroupSessionJni(): random buffer is not required"); + LOGW(" ## createNewSessionJni(): random buffer is not required"); } size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); if (sessionResult == olm_error()) { errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s", errorMessage); + LOGE(" ## createNewSessionJni(): failure - init outbound session creation Msg=%s", errorMessage); } else { - LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); + LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); } // clear the random buffer @@ -137,13 +119,23 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( if (errorMessage) { + if (sessionPtr) + { + olm_clear_outbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } + + return (jlong)(intptr_t)sessionPtr; } /** -* Get a base64-encoded identifier for this outbound group session. -*/ + * Return the session identifier. + * An exception is thrown if the operation fails. + * @return the session identifier + */ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { LOGD("## sessionIdentifierJni(): outbound group session IN"); @@ -184,7 +176,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); - LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId starts with %10s",static_cast(result), reinterpret_cast(sessionIdPtr)); + LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId= %.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionIdPtr)); } // free alloc @@ -202,11 +194,12 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J /** -* Get the current message index for this session.
-* Each message is sent with an increasing index, this -* method returns the index for the next message. -* @return current session index -*/ + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * An exception is thrown if the operation fails. + * @return current session index + */ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz) { OlmOutboundGroupSession *sessionPtr = NULL; @@ -229,8 +222,10 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, } /** -* Get the base64-encoded current ratchet key for this session.
-*/ + * Return the session key. + * An exception is thrown if the operation fails. + * @return the session key + */ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) { LOGD("## sessionKeyJni(): outbound group session IN"); @@ -268,7 +263,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * } else { - LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey starts with %10s",static_cast(result), reinterpret_cast(sessionKeyPtr)); + LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionKeyPtr)); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionKeyPtr); @@ -287,6 +282,12 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * return returnValue; } +/** + * Encrypt a bytes buffer messages. + * An exception is thrown if the operation fails. + * @param aClearMsgBuffer the message to encode + * @return the encoded message + */ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) { LOGD("## encryptMessageJni(): IN"); @@ -345,7 +346,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE } else { - LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%10s",static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); + LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%.*s",static_cast(encryptedLength), static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); encryptedMsgRet = env->NewByteArray(encryptedLength); env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedLength, (jbyte*)encryptedMsgPtr); @@ -369,12 +370,12 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE return encryptedMsgRet; } - /** -* Serialize and encrypt session instance into a base64 string.
-* @param aKey key used to encrypt the serialized session data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt session instance into a base64 string.
+ * An exception is thrown if the operation fails. + * @param aKey key used to encrypt the serialized session data + * @return a base64 string if operation succeed, null otherwise + **/ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -427,7 +428,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e } else { - LOGD(" ## serializeJni(): success - result=%lu pickled starts with %10s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(result), static_cast(pickledPtr)); returnValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); @@ -451,38 +452,57 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e return returnValue; } - -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { + const char* errorMessage = NULL; + size_t sessionSize = olm_outbound_group_session_size(); OlmOutboundGroupSession* sessionPtr = NULL; - jstring errorMessageRetValue = 0; + jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); - if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!sessionSize) + { + LOGE(" ## deserializeJni(): failure - outbound group session size = 0"); + errorMessage = "outbound group session size = 0"; + } + else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) { LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; } else if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "invalid serialized data"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { + sessionPtr = olm_outbound_group_session(sessionPtr); size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); @@ -495,9 +515,8 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *en pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_outbound_group_session() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_outbound_group_session() Msg=%s", errorMessage); } else { @@ -516,6 +535,16 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *en env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_outbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h index fb3bf87..f6abba2 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -32,7 +32,6 @@ extern "C" { JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); @@ -41,7 +40,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE // serialization JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index d6ede41..034e0e8 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -83,13 +83,13 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz // ********************** OUTBOUND SESSION ***************************** // ********************************************************************* /** -* Create a new in-bound session for sending/receiving messages from an -* incoming PRE_KEY message.
The recipient is defined as the entity -* with whom the session is established. -* @param aOlmAccountId account instance -* @param aTheirIdentityKey the identity key of the recipient -* @param aTheirOneTimeKey the one time key of the recipient -**/ + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
The recipient is defined as the entity + * with whom the session is established. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient or an exception is thrown + **/ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) { OlmSession* sessionPtr = getSessionInstanceId(env, thiz); @@ -193,6 +193,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject /** * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY message.
+ * An exception is thrown if the operation fails. * @param aOlmAccountId account instance * @param aOneTimeKeyMsg PRE_KEY message */ @@ -258,6 +259,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject /** * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY message based on the recipient identity key.
+ * An exception is thrown if the operation fails. * @param aOlmAccountId account instance * @param aTheirIdentityKey the identity key of the recipient * @param aOneTimeKeyMsg encrypted message @@ -342,11 +344,11 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, * Checks if the PRE_KEY message is for this in-bound session.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aOneTimeKeyMsg PRE KEY message - * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + * @return true if the PRE_KEY message matches */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) { - jint retCode = ERROR_CODE_KO; + jboolean retCode = JNI_FALSE; OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *messagePtr = NULL; @@ -374,7 +376,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje } else { - retCode = ERROR_CODE_OK; + retCode = JNI_TRUE; LOGD("## matchesInboundSessionJni(): success - result=%lu", static_cast(matchResult)); } } @@ -388,17 +390,16 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje return retCode; } - /** * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aTheirIdentityKey the identity key of the sender * @param aOneTimeKeyMsg PRE KEY message - * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + * @return true if the PRE_KEY message matches. */ -JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) +JNIEXPORT jboolean JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) { - jint retCode = ERROR_CODE_KO; + jboolean retCode = JNI_FALSE; OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *messagePtr = NULL; jbyte *theirIdentityKeyPtr = NULL; @@ -437,7 +438,7 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J } else { - retCode = ERROR_CODE_OK; + retCode = JNI_TRUE; LOGD("## matchesInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(matchResult)); } } @@ -456,9 +457,9 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J return retCode; } - /** * Encrypt a message using the session.
+ * An exception is thrown if the operation fails. * @param aClearMsg clear text message * @param [out] aEncryptedMsg ciphered message * @return the encrypted message @@ -564,7 +565,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec encryptedMsgRet = env->NewByteArray(encryptedMsgLength); env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedMsgLength, (jbyte*)encryptedMsgPtr); - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg starts with %10s", static_cast(result), static_cast(messageType), static_cast((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr); + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%.*s", static_cast(result), static_cast(messageType), static_cast(result), (const char*)encryptedMsgPtr); } free(encryptedMsgPtr); @@ -590,6 +591,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec /** * Decrypt a message using the session.
+ * An exception is thrown if the operation fails. * @param aEncryptedMsg message to decrypt * @return decrypted message if operation succeed */ @@ -725,11 +727,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec return decryptedMsgRet; } - /** -* Get the session identifier for this session. -* @return the session identifier if operation succeed, null otherwise -*/ + * Get the session identifier for this session. + * An exception is thrown if the operation fails. + * @return the session identifier + */ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -768,7 +770,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, } else { - LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId= starts with %10s",static_cast(result), (char*)sessionIdPtr); + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); @@ -786,12 +788,12 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, return returnValue; } - /** -* Serialize and encrypt session instance into a base64 string.
-* @param aKey key used to encrypt the serialized session data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt session instance.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -868,10 +870,17 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi return returnValue; } -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { - OlmSession* sessionPtr = getSessionInstanceId(env, thiz); - jstring errorMessageRetValue = 0; + const char* errorMessage = NULL; + OlmSession* sessionPtr = initializeSessionMemory(); jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; @@ -880,22 +889,27 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz if (!sessionPtr) { LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; } else if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "serialized data"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { @@ -911,9 +925,8 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); } else { @@ -932,5 +945,15 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; } \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h index 01cf96c..b8cdd2f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h @@ -39,8 +39,8 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // match inbound sessions: based on PRE KEY message -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // encrypt/decrypt JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); @@ -50,7 +50,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, // serialization JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index b26cfae..c4ac9fd 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -162,11 +162,12 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j } /** -* Compute the digest (SHA 256) for the message passed in parameter.
-* The digest value is the function return value. -* @param aMessage -* @return digest of the message if operation succeed, null otherwise -**/ + * Compute the digest (SHA 256) for the message passed in parameter.
+ * The digest value is the function return value. + * An exception is thrown if the operation fails. + * @param aMessage the message + * @return digest of the message. + **/ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHashBuffer) { jbyteArray sha256Ret = 0; -- cgit v1.2.3 From 4323bec5d6e71fdb38d88ea4f68cf6923092bcc2 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 10 Jan 2017 11:32:52 +0000 Subject: README.rst: fix formatting --- java/android/OlmLibSdk/README.rst | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/java/android/OlmLibSdk/README.rst b/java/android/OlmLibSdk/README.rst index 7729506..6a9eae8 100644 --- a/java/android/OlmLibSdk/README.rst +++ b/java/android/OlmLibSdk/README.rst @@ -1,26 +1,29 @@ OlmLibSdk ========= -OlmLibSdk exposes An android wrapper to libolm. - +OlmLibSdk exposes an android wrapper to libolm. Installation ------------ - Create a libs directory in your project directory - Copy the olm-sdk.aar into it. - In your build.gradle file, add in the android section - repositories { - flatDir { - dir 'libs' - } - } - Add in the dependencies category - compile(name: 'olm-sdk', ext: 'aar') +Create a libs directory in your project directory +Copy the olm-sdk.aar into it. + +In your build.gradle file, add in the android section:: + + repositories { + flatDir { + dir 'libs' + } + } + +Add in the dependencies category:: + + compile(name: 'olm-sdk', ext: 'aar') Development ----------- -import the project from the /java/android/OlmLibSdk path. +import the project from the ``/java/android/OlmLibSdk`` path. The project contains some JNI files and some Java wraper files. -The project contains some tests under AndroidTests package. \ No newline at end of file +The project contains some tests under AndroidTests package. -- cgit v1.2.3 From 03ae28e0873486649421b9428c4407851a89241c Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 10 Jan 2017 14:45:20 +0100 Subject: Update after a new review --- .../java/org/matrix/olm/OlmAccountTest.java | 7 +------ .../java/org/matrix/olm/OlmSessionTest.java | 20 +++++--------------- .../java/org/matrix/olm/OlmUtilityTest.java | 14 +++----------- .../java/org/matrix/olm/CommonSerializeUtils.java | 8 +------- .../src/main/java/org/matrix/olm/OlmAccount.java | 9 +-------- .../src/main/java/org/matrix/olm/OlmUtility.java | 12 ++++-------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 4 +++- .../src/main/jni/olm_inbound_group_session.cpp | 4 ++-- .../src/main/jni/olm_outbound_group_session.cpp | 2 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 14 ++++++++------ .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 16 +++++----------- 11 files changed, 34 insertions(+), 76 deletions(-) diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java index d474f12..ffbbca1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -389,17 +389,12 @@ public class OlmAccountTest { assertTrue(e.getMessage(),false); } - boolean sessionRetCode = true; - try { - sessionRetCode = olmAccount.removeOneTimeKeys(null); + olmAccount.removeOneTimeKeys(null); } catch (Exception e) { assertTrue(e.getMessage(), false); } - // test against no matching keys - assertFalse(sessionRetCode); - olmAccount.releaseAccount(); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java index bb24f7a..e08b151 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -174,13 +174,11 @@ public class OlmSessionTest { assertTrue(clearMsg.equals(decryptedMsg)); // clean objects.. - boolean res = false; try { - res = bobAccount.removeOneTimeKeys(bobSession); + bobAccount.removeOneTimeKeys(bobSession); } catch (Exception e) { assertTrue(e.getMessage(), false); } - assertTrue(res); // release accounts bobAccount.releaseAccount(); @@ -402,13 +400,11 @@ public class OlmSessionTest { assertTrue(clearMsg1.equals(decryptedMsg1)); // clean objects.. - boolean res = false; try { - res = bobAccount.removeOneTimeKeys(bobSession); + bobAccount.removeOneTimeKeys(bobSession); } catch (Exception e) { assertTrue(e.getMessage(), false); } - assertTrue(res); bobAccount.releaseAccount(); aliceAccount.releaseAccount(); @@ -585,13 +581,11 @@ public class OlmSessionTest { //assertTrue(false==bobSession.matchesInboundSessionFrom(bobIdentityKey, encryptedAliceToBobMsg1.mCipherText)); // release objects - boolean res = false; try { - res = bobAccount.removeOneTimeKeys(bobSession); + bobAccount.removeOneTimeKeys(bobSession); } catch (Exception e) { assertTrue(e.getMessage(), false); } - assertTrue(res); aliceAccount.releaseAccount(); bobAccount.releaseAccount(); @@ -782,13 +776,11 @@ public class OlmSessionTest { assertTrue(clearMsg3.equals(decryptedMsg3)); // clean objects.. - boolean res = false; try { - res = bobAccount.removeOneTimeKeys(bobSession); + bobAccount.removeOneTimeKeys(bobSession); } catch (Exception e) { assertTrue(e.getMessage(), false); } - assertTrue(res); bobAccount.releaseAccount(); aliceAccount.releaseAccount(); @@ -1002,13 +994,11 @@ public class OlmSessionTest { assertTrue(!aliceSession.matchesInboundSessionFrom(null,null)); // release objects - boolean res = false; try { - res = bobAccount.removeOneTimeKeys(bobSession); + bobAccount.removeOneTimeKeys(bobSession); } catch (Exception e) { assertTrue(e.getMessage(), false); } - assertTrue(res); aliceAccount.releaseAccount(); bobAccount.releaseAccount(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java index cc14e7c..b560bff 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -104,42 +104,34 @@ public class OlmUtilityTest { } // verify signature - boolean isVerified; - - isVerified = false; errorMsg = null; try { - isVerified = utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message); + utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message); } catch (Exception e) { errorMsg = e.getMessage(); } - assertTrue(isVerified); assertTrue(TextUtils.isEmpty(errorMsg)); // check a bad signature is detected => errorMsg = BAD_MESSAGE_MAC String badSignature = "Bad signature Bad signature Bad signature.."; - isVerified = false; errorMsg = null; try { - isVerified = utility.verifyEd25519Signature(badSignature, fingerPrintKey, message); + utility.verifyEd25519Signature(badSignature, fingerPrintKey, message); } catch (Exception e) { errorMsg = e.getMessage(); } - assertFalse(isVerified); assertTrue(!TextUtils.isEmpty(errorMsg)); // check bad fingerprint size => errorMsg = INVALID_BASE64 String badSizeFingerPrintKey = fingerPrintKey.substring(fingerPrintKey.length()/2); - isVerified = false; errorMsg = null; try { - isVerified = utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message); + utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message); } catch (Exception e) { errorMsg = e.getMessage(); } - assertFalse(isVerified); assertTrue(!TextUtils.isEmpty(errorMsg)); utility.releaseUtility(); diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java index 93a85fd..229963f 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -70,17 +70,11 @@ abstract class CommonSerializeUtils { key = keyAsString.getBytes("UTF-8"); pickledData = pickledDataAsString.getBytes("UTF-8"); + deserialize(pickledData, key); } catch (Exception e) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, e.getMessage()); } - if (null == key) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); - } else if (null == pickledData) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); - } - - deserialize(pickledData, key); Log.d(LOG_TAG,"## deserializeObject(): success"); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 9ebaaf1..26c3e60 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -242,23 +242,16 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { /** * Remove the "one time keys" that the session used from the account. * @param aSession session instance - * @return true if the operation succeeded. * @throws OlmException the failure reason */ - public boolean removeOneTimeKeys(OlmSession aSession) throws OlmException { - boolean res = false; - + public void removeOneTimeKeys(OlmSession aSession) throws OlmException { if (null != aSession) { try { removeOneTimeKeysJni(aSession.getOlmSessionId()); - res = true; - Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result=" + res); } catch (Exception e) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS, e.getMessage()); } } - - return res; } /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 12f3663..bf9ef90 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -73,17 +73,14 @@ public class OlmUtility { /** * Verify an ed25519 signature.
- * If the signature is verified, the method returns true. If false is returned, an error description is provided in aError. - * If the key was too small, aError is set to "OLM.INVALID_BASE64". - * If the signature was invalid, aError is set to "OLM.BAD_MESSAGE_MAC".
+ * An exception is thrown if the operation fails. * @param aSignature the base64-encoded message signature to be checked. * @param aFingerprintKey the ed25519 key (fingerprint key) * @param aMessage the signed message - * @return true if the signature is verified, false otherwise * @exception OlmException the failure reason */ - public boolean verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage) throws OlmException { - String errorMessage = null; + public void verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage) throws OlmException { + String errorMessage; try { if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { @@ -94,13 +91,12 @@ public class OlmUtility { } } catch (Exception e) { Log.e(LOG_TAG, "## verifyEd25519Signature(): failed " + e.getMessage()); + errorMessage = e.getMessage(); } if (!TextUtils.isEmpty(errorMessage)) { throw new OlmException(OlmException.EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE, errorMessage); } - - return true; } /** diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 6e62f50..40081ac 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp @@ -92,6 +92,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject t if (randomBuffPtr) { + memset(randomBuffPtr, 0, randomSize); free(randomBuffPtr); } } @@ -286,6 +287,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject if (randomBufferPtr) { + memset(randomBufferPtr, 0, randomLength); free(randomBufferPtr); } } @@ -642,7 +644,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickled=%.*s", static_cast (pickledLength), (char const *)pickledPtr); size_t result = olm_unpickle_account(accountPtr, (void const *)keyPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 14e338b..23910bb 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -254,7 +254,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn else { memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",static_cast(encryptedMsgLength),encryptedMsgPtr); + LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%.*s",static_cast(encryptedMsgLength), static_cast(encryptedMsgLength), encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, @@ -464,7 +464,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickled=%.*s", static_cast(pickledLength), (char const *)pickledPtr); size_t result = olm_unpickle_inbound_group_session(sessionPtr, (void const *)keyPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index 689f1b4..a821709 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -506,7 +506,7 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickled=%.*s", static_cast(pickledLength), (char const *)pickledPtr); size_t result = olm_unpickle_outbound_group_session(sessionPtr, (void const *)keyPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp index 034e0e8..5ca49db 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp @@ -143,7 +143,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject { size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); size_t theirOneTimeKeyLength = (size_t)env->GetArrayLength(aTheirOneTimeKeyBuffer); - LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr); + LOGD("## initOutboundSessionJni(): identityKey=%.*s oneTimeKey=%.*s", static_cast(theirIdentityKeyLength), theirIdentityKeyPtr, static_cast(theirOneTimeKeyLength), theirOneTimeKeyPtr); size_t sessionResult = olm_create_outbound_session(sessionPtr, accountPtr, @@ -175,6 +175,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject if (randomBuffPtr) { + memset(randomBuffPtr, 0, randomSize); free(randomBuffPtr); } } @@ -231,7 +232,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject else { size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); - LOGD("## initInboundSessionJni(): messageLength=%lu message=%s", static_cast(messageLength), messagePtr); + LOGD("## initInboundSessionJni(): messageLength=%lu message=%.*s", static_cast(messageLength), static_cast(messageLength), messagePtr); sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); @@ -309,7 +310,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); - LOGD("## initInboundSessionFromIdKeyJni(): message=%s messageLength=%lu",messagePtr,static_cast(messageLength)); + LOGD("## initInboundSessionFromIdKeyJni(): message=%.*s messageLength=%lu", static_cast(messageLength), messagePtr, static_cast(messageLength)); sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); if (sessionResult == olm_error()) @@ -571,6 +572,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec free(encryptedMsgPtr); } + memset(randomBuffPtr, 0, randomLength); free(randomBuffPtr); } } @@ -659,7 +661,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec // create a dedicated temp buffer to be used in next Olm API calls tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): MsgType=%lu encryptedMsgLength=%lu encryptedMsg=%s",static_cast(encryptedMsgType),static_cast(encryptedMsgLength),encryptedMsgPtr); + LOGD("## decryptMessageJni(): MsgType=%lu encryptedMsgLength=%lu encryptedMsg=%.*s",static_cast(encryptedMsgType),static_cast(encryptedMsgLength), static_cast(encryptedMsgLength), encryptedMsgPtr); // get max plaintext length size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, @@ -846,7 +848,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi } else { - LOGD(" ## serializeJni(): success - result=%lu pickled starts with %s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); returnValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); @@ -916,7 +918,7 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%s",(char const *)pickledPtr); + LOGD(" ## deserializeJni(): pickled=%.*s",static_cast(pickledLength), (char const *)pickledPtr); size_t result = olm_unpickle_session(sessionPtr, (void const *)keyPtr, diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp index c4ac9fd..f6fe719 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp @@ -78,9 +78,6 @@ JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz /** * Verify an ed25519 signature. - * If the key was too small then the message will be "OLM.INVALID_BASE64". - * If the signature was invalid then the message will be "OLM.BAD_MESSAGE_MAC". - * * @param aSignature the base64-encoded message signature to be checked. * @param aKey the ed25519 key (fingerprint key) * @param aMessage the message which was signed @@ -122,7 +119,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); size_t messageLength = (size_t)env->GetArrayLength(aMessageBuffer); LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",static_cast(signatureLength),static_cast(keyLength),static_cast(messageLength)); - LOGD(" ## verifyEd25519SignatureJni(): key=%s",keyPtr); + LOGD(" ## verifyEd25519SignatureJni(): key=%.*s", static_cast(keyLength), keyPtr); size_t result = olm_ed25519_verify(utilityPtr, (void const *)keyPtr, @@ -194,7 +191,7 @@ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, // get lengths size_t messageLength = (size_t)env->GetArrayLength(aMessageToHashBuffer); size_t hashLength = olm_sha256_length(utilityPtr); - void* hashValuePtr = malloc((hashLength+1)*sizeof(uint8_t)); + void* hashValuePtr = malloc((hashLength)*sizeof(uint8_t)); if (!hashValuePtr) { @@ -213,12 +210,9 @@ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, } else { - // update length - (static_cast(hashValuePtr))[result] = static_cast('\0'); - LOGD("## sha256Jni(): success - result=%lu hashValue=%s",static_cast(result), (char*)hashValuePtr); - - sha256Ret = env->NewByteArray(result); - env->SetByteArrayRegion(sha256Ret, 0 , result, (jbyte*)hashValuePtr); + LOGD("## sha256Jni(): success - result=%lu hashValue=%.*s",static_cast(result), static_cast(result), (char*)hashValuePtr); + sha256Ret = env->NewByteArray(result); + env->SetByteArrayRegion(sha256Ret, 0 , result, (jbyte*)hashValuePtr); } free(hashValuePtr); -- cgit v1.2.3 From ccbb9606b725b8f1d7eeccf14c358b146aeee491 Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 10 Jan 2017 16:06:21 +0100 Subject: Move the android project from /Java/Android/OlmLibSdk --- .DS_Store | Bin 0 -> 6148 bytes README.rst | 2 +- android/.DS_Store | Bin 0 -> 6148 bytes android/README.rst | 29 + android/build.gradle | 23 + android/gradle.properties | 19 + android/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes android/gradle/wrapper/gradle-wrapper.properties | 6 + android/gradlew | 160 +++ android/gradlew.bat | 90 ++ android/olm-sdk/build.gradle | 130 +++ .../java/org/matrix/olm/OlmAccountTest.java | 493 ++++++++++ .../java/org/matrix/olm/OlmGroupSessionTest.java | 525 ++++++++++ .../java/org/matrix/olm/OlmSessionTest.java | 1014 ++++++++++++++++++++ .../java/org/matrix/olm/OlmUtilityTest.java | 161 ++++ .../java/org/matrix/olm/TestHelper.java | 82 ++ android/olm-sdk/src/main/AndroidManifest.xml | 8 + .../java/org/matrix/olm/CommonSerializeUtils.java | 83 ++ .../src/main/java/org/matrix/olm/OlmAccount.java | 415 ++++++++ .../src/main/java/org/matrix/olm/OlmException.java | 85 ++ .../org/matrix/olm/OlmInboundGroupSession.java | 260 +++++ .../src/main/java/org/matrix/olm/OlmManager.java | 64 ++ .../src/main/java/org/matrix/olm/OlmMessage.java | 36 + .../org/matrix/olm/OlmOutboundGroupSession.java | 289 ++++++ .../src/main/java/org/matrix/olm/OlmSession.java | 445 +++++++++ .../src/main/java/org/matrix/olm/OlmUtility.java | 227 +++++ android/olm-sdk/src/main/jni/Android.mk | 59 ++ android/olm-sdk/src/main/jni/Application.mk | 3 + android/olm-sdk/src/main/jni/olm_account.cpp | 687 +++++++++++++ android/olm-sdk/src/main/jni/olm_account.h | 56 ++ .../src/main/jni/olm_inbound_group_session.cpp | 507 ++++++++++ .../src/main/jni/olm_inbound_group_session.h | 46 + android/olm-sdk/src/main/jni/olm_jni.h | 78 ++ android/olm-sdk/src/main/jni/olm_jni_helper.cpp | 214 +++++ android/olm-sdk/src/main/jni/olm_jni_helper.h | 28 + android/olm-sdk/src/main/jni/olm_manager.cpp | 35 + android/olm-sdk/src/main/jni/olm_manager.h | 36 + .../src/main/jni/olm_outbound_group_session.cpp | 550 +++++++++++ .../src/main/jni/olm_outbound_group_session.h | 49 + android/olm-sdk/src/main/jni/olm_session.cpp | 961 +++++++++++++++++++ android/olm-sdk/src/main/jni/olm_session.h | 59 ++ android/olm-sdk/src/main/jni/olm_utility.cpp | 228 +++++ android/olm-sdk/src/main/jni/olm_utility.h | 40 + android/olm-sdk/src/main/res/values/strings.xml | 3 + android/settings.gradle | 1 + java/android/OlmLibSdk/README.rst | 29 - java/android/OlmLibSdk/build.gradle | 23 - java/android/OlmLibSdk/gradle.properties | 19 - .../OlmLibSdk/gradle/wrapper/gradle-wrapper.jar | Bin 53636 -> 0 bytes .../gradle/wrapper/gradle-wrapper.properties | 6 - java/android/OlmLibSdk/gradlew | 160 --- java/android/OlmLibSdk/gradlew.bat | 90 -- java/android/OlmLibSdk/olm-sdk/build.gradle | 130 --- .../java/org/matrix/olm/OlmAccountTest.java | 493 ---------- .../java/org/matrix/olm/OlmGroupSessionTest.java | 525 ---------- .../java/org/matrix/olm/OlmSessionTest.java | 1014 -------------------- .../java/org/matrix/olm/OlmUtilityTest.java | 161 ---- .../java/org/matrix/olm/TestHelper.java | 82 -- .../OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml | 8 - .../java/org/matrix/olm/CommonSerializeUtils.java | 83 -- .../src/main/java/org/matrix/olm/OlmAccount.java | 415 -------- .../src/main/java/org/matrix/olm/OlmException.java | 85 -- .../org/matrix/olm/OlmInboundGroupSession.java | 260 ----- .../src/main/java/org/matrix/olm/OlmManager.java | 64 -- .../src/main/java/org/matrix/olm/OlmMessage.java | 36 - .../org/matrix/olm/OlmOutboundGroupSession.java | 289 ------ .../src/main/java/org/matrix/olm/OlmSession.java | 445 --------- .../src/main/java/org/matrix/olm/OlmUtility.java | 227 ----- .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk | 59 -- .../OlmLibSdk/olm-sdk/src/main/jni/Application.mk | 3 - .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 687 ------------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.h | 56 -- .../src/main/jni/olm_inbound_group_session.cpp | 507 ---------- .../src/main/jni/olm_inbound_group_session.h | 46 - .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 78 -- .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 214 ----- .../olm-sdk/src/main/jni/olm_jni_helper.h | 28 - .../OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp | 35 - .../OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h | 36 - .../src/main/jni/olm_outbound_group_session.cpp | 550 ----------- .../src/main/jni/olm_outbound_group_session.h | 49 - .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 961 ------------------- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 59 -- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp | 228 ----- .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h | 40 - .../olm-sdk/src/main/res/values/strings.xml | 3 - java/android/OlmLibSdk/settings.gradle | 1 - 87 files changed, 8285 insertions(+), 8285 deletions(-) create mode 100644 .DS_Store create mode 100644 android/.DS_Store create mode 100644 android/README.rst create mode 100644 android/build.gradle create mode 100644 android/gradle.properties create mode 100644 android/gradle/wrapper/gradle-wrapper.jar create mode 100644 android/gradle/wrapper/gradle-wrapper.properties create mode 100755 android/gradlew create mode 100644 android/gradlew.bat create mode 100644 android/olm-sdk/build.gradle create mode 100644 android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java create mode 100644 android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java create mode 100644 android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java create mode 100644 android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java create mode 100644 android/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java create mode 100644 android/olm-sdk/src/main/AndroidManifest.xml create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java create mode 100644 android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java create mode 100644 android/olm-sdk/src/main/jni/Android.mk create mode 100644 android/olm-sdk/src/main/jni/Application.mk create mode 100644 android/olm-sdk/src/main/jni/olm_account.cpp create mode 100644 android/olm-sdk/src/main/jni/olm_account.h create mode 100644 android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp create mode 100644 android/olm-sdk/src/main/jni/olm_inbound_group_session.h create mode 100644 android/olm-sdk/src/main/jni/olm_jni.h create mode 100644 android/olm-sdk/src/main/jni/olm_jni_helper.cpp create mode 100644 android/olm-sdk/src/main/jni/olm_jni_helper.h create mode 100644 android/olm-sdk/src/main/jni/olm_manager.cpp create mode 100644 android/olm-sdk/src/main/jni/olm_manager.h create mode 100644 android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp create mode 100644 android/olm-sdk/src/main/jni/olm_outbound_group_session.h create mode 100644 android/olm-sdk/src/main/jni/olm_session.cpp create mode 100644 android/olm-sdk/src/main/jni/olm_session.h create mode 100644 android/olm-sdk/src/main/jni/olm_utility.cpp create mode 100644 android/olm-sdk/src/main/jni/olm_utility.h create mode 100644 android/olm-sdk/src/main/res/values/strings.xml create mode 100644 android/settings.gradle delete mode 100644 java/android/OlmLibSdk/README.rst delete mode 100644 java/android/OlmLibSdk/build.gradle delete mode 100644 java/android/OlmLibSdk/gradle.properties delete mode 100644 java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar delete mode 100644 java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties delete mode 100755 java/android/OlmLibSdk/gradlew delete mode 100644 java/android/OlmLibSdk/gradlew.bat delete mode 100644 java/android/OlmLibSdk/olm-sdk/build.gradle delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h delete mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml delete mode 100644 java/android/OlmLibSdk/settings.gradle diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/README.rst b/README.rst index 6a509d4..4568fff 100644 --- a/README.rst +++ b/README.rst @@ -36,7 +36,7 @@ To build the javascript bindings, install emscripten from http://kripken.github. To build the android project for Android bindings, run: .. code:: bash - cd java/android/OlmLibSdk + cd android ./gradlew clean assembleRelease Release process diff --git a/android/.DS_Store b/android/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/android/.DS_Store differ diff --git a/android/README.rst b/android/README.rst new file mode 100644 index 0000000..46beaab --- /dev/null +++ b/android/README.rst @@ -0,0 +1,29 @@ +OlmLibSdk +========= + +OlmLibSdk exposes an android wrapper to libolm. + +Installation +------------ +Create a libs directory in your project directory +Copy the olm-sdk.aar into it. + +In your build.gradle file, add in the android section:: + + repositories { + flatDir { + dir 'libs' + } + } + +Add in the dependencies category:: + + compile(name: 'olm-sdk', ext: 'aar') + +Development +----------- +import the project from the ``android/`` path. + +The project contains some JNI files and some Java wraper files. + +The project contains some tests under AndroidTests package. diff --git a/android/build.gradle b/android/build.gradle new file mode 100644 index 0000000..77ce66e --- /dev/null +++ b/android/build.gradle @@ -0,0 +1,23 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:2.1.3' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..13d64a5 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,19 @@ +## Project-wide Gradle settings. +# +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# Default value: -Xmx10248m -XX:MaxPermSize=256m +# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# +# When configured, Gradle will run in incubating parallel mode. +# This option should only be used with decoupled projects. More details, visit +# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects +# org.gradle.parallel=true +#Wed Oct 05 11:49:34 CEST 2016 +systemProp.https.proxyPort=8080 +systemProp.http.proxyHost=batproxy +systemProp.https.proxyHost=batproxy +systemProp.http.proxyPort=8080 diff --git a/android/gradle/wrapper/gradle-wrapper.jar b/android/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..13372ae Binary files /dev/null and b/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..4ba4622 --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Thu Oct 13 09:38:01 CEST 2016 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/android/gradlew b/android/gradlew new file mode 100755 index 0000000..9d82f78 --- /dev/null +++ b/android/gradlew @@ -0,0 +1,160 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/android/gradlew.bat b/android/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/android/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/android/olm-sdk/build.gradle b/android/olm-sdk/build.gradle new file mode 100644 index 0000000..9ce4d37 --- /dev/null +++ b/android/olm-sdk/build.gradle @@ -0,0 +1,130 @@ +import org.apache.tools.ant.taskdefs.condition.Os + +apply plugin: 'com.android.library' + +android { + compileSdkVersion 21 + buildToolsVersion '21.1.2' + + defaultConfig { + minSdkVersion 11 + targetSdkVersion 21 + versionCode 1 + versionName "1.0" + version "0.2.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } + buildTypes { + debug { + resValue "string", "git_olm_revision", "\"${gitRevision()}\"" + resValue "string", "git_olm_revision_unix_date", "\"${gitRevisionUnixDate()}\"" + resValue "string", "git_olm_revision_date", "\"${gitRevisionDate()}\"" + } + + release { + resValue "string", "git_olm_revision", "\"${gitRevision()}\"" + resValue "string", "git_olm_revision_unix_date", "\"${gitRevisionUnixDate()}\"" + resValue "string", "git_olm_revision_date", "\"${gitRevisionDate()}\"" + + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + sourceSets.main { + jniLibs.srcDir 'src/main/libs' + jni.srcDirs = [] + } + + task buildJavaDoc(type: Javadoc) { + source = android.sourceSets.main.java.srcDirs + classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) + destinationDir = file("./doc/") + options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PRIVATE + failOnError false + } + + task ndkBuildNativeRelease(type: Exec, description: 'NDK building..') { + println 'ndkBuildNativeRelease starts..' + workingDir file('src/main') + commandLine getNdkBuildCmd(), 'NDK_DEBUG=0' + } + + task ndkBuildNativeDebug(type: Exec, description: 'NDK building..') { + println 'ndkBuildNativeDebug starts..' + workingDir file('src/main') + commandLine getNdkBuildCmd(), 'NDK_DEBUG=1' + } + + task cleanNative(type: Exec, description: 'Clean NDK build') { + workingDir file('src/main') + commandLine getNdkBuildCmd(), 'clean' + } + + tasks.withType(JavaCompile) { + compileTask -> if (compileTask.name.startsWith('compileDebugJava')) { + println 'test compile: Debug' + compileTask.dependsOn ndkBuildNativeDebug + } else if (compileTask.name.startsWith('compileReleaseJava')) { + println 'test compile: Release' + compileTask.dependsOn ndkBuildNativeRelease + } + compileTask.dependsOn buildJavaDoc + } + + clean.dependsOn cleanNative + + + libraryVariants.all { variant -> + variant.outputs.each { output -> + def outputFile = output.outputFile + if (outputFile != null && outputFile.name.endsWith('.aar')) { + def fileName = outputFile.name.replace(".aar", "-${version}.aar") + output.outputFile = new File(outputFile.parent, fileName) + } + } + } +} + +def getNdkFolder() { + Properties properties = new Properties() + properties.load(project.rootProject.file('local.properties').newDataInputStream()) + def ndkFolder = properties.getProperty('ndk.dir', null) + if (ndkFolder == null) + throw new GradleException("NDK location missing. Define it with ndk.dir in the local.properties file") + + return ndkFolder +} + +def getNdkBuildCmd() { + def ndkBuildCmd = getNdkFolder() + "/ndk-build" + if (Os.isFamily(Os.FAMILY_WINDOWS)) + ndkBuildCmd += ".cmd" + + return ndkBuildCmd +} + +def gitRevision() { + def cmd = "git rev-parse --short HEAD" + return cmd.execute().text.trim() +} + +def gitRevisionUnixDate() { + def cmd = "git show -s --format=%ct HEAD^{commit}" + return cmd.execute().text.trim() +} + +def gitRevisionDate() { + def cmd = "git show -s --format=%ci HEAD^{commit}" + return cmd.execute().text.trim() +} + +dependencies { + compile fileTree(include: ['*.jar'], dir: 'libs') + compile 'com.android.support:appcompat-v7:21.+' + + testCompile 'junit:junit:4.12' + androidTestCompile 'junit:junit:4.12' + androidTestCompile 'com.android.support:support-annotations:21.0.0' + androidTestCompile 'com.android.support.test:runner:0.5' + androidTestCompile 'com.android.support.test:rules:0.5' +} diff --git a/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java new file mode 100644 index 0000000..ffbbca1 --- /dev/null +++ b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java @@ -0,0 +1,493 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.content.Context; +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONException; +import org.json.JSONObject; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Map; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmAccountTest { + private static final String LOG_TAG = "OlmAccountTest"; + private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50; + + private static OlmAccount mOlmAccount; + private static OlmManager mOlmManager; + private boolean mIsAccountCreated; + private final String FILE_NAME = "SerialTestFile"; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String olmLibVersion = mOlmManager.getOlmLibVersion(); + assertNotNull(olmLibVersion); + String olmSdkVersion = mOlmManager.getSdkOlmVersion(getInstrumentation().getContext()); + assertNotNull(olmLibVersion); + Log.d(LOG_TAG, "## setUpClass(): Versions - Android Olm SDK = "+olmSdkVersion+" Olm lib ="+olmLibVersion); + } + + @AfterClass + public static void tearDownClass() { + // TBD + } + + @Before + public void setUp() { + if(mIsAccountCreated) { + assertNotNull(mOlmAccount); + } + } + + @After + public void tearDown() { + // TBD + } + + /** + * Basic test: creation and release. + */ + @Test + public void test01CreateReleaseAccount() { + try { + mOlmAccount = new OlmAccount(); + } catch (OlmException e) { + e.printStackTrace(); + assertTrue("OlmAccount failed " + e.getMessage(), false); + } + assertNotNull(mOlmAccount); + + mOlmAccount.releaseAccount(); + assertTrue(0 == mOlmAccount.getOlmAccountId()); + } + + @Test + public void test02CreateAccount() { + try { + mOlmAccount = new OlmAccount(); + } catch (OlmException e) { + e.printStackTrace(); + assertTrue("OlmAccount failed " + e.getMessage(), false); + } + assertNotNull(mOlmAccount); + mIsAccountCreated = true; + } + + @Test + public void test04GetOlmAccountId() { + long olmNativeInstance = mOlmAccount.getOlmAccountId(); + Log.d(LOG_TAG,"## testGetOlmAccountId olmNativeInstance="+olmNativeInstance); + assertTrue(0!=olmNativeInstance); + } + + /** + * Test if {@link OlmAccount#identityKeys()} returns a JSON object + * that contains the following keys: {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} + * and {@link OlmAccount#JSON_KEY_IDENTITY_KEY} + */ + @Test + public void test05IdentityKeys() { + Map identityKeys = null; + try { + identityKeys = mOlmAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + assertNotNull(identityKeys); + Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeys); + + // is JSON_KEY_FINGER_PRINT_KEY present? + String fingerPrintKey = TestHelper.getFingerprintKey(identityKeys); + assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); + + // is JSON_KEY_IDENTITY_KEY present? + String identityKey = TestHelper.getIdentityKey(identityKeys); + assertTrue("identity key missing",!TextUtils.isEmpty(identityKey)); + } + + //**************************************************** + //***************** ONE TIME KEYS TESTS ************** + //**************************************************** + @Test + public void test06MaxOneTimeKeys() { + long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys(); + Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys); + + assertTrue(maxOneTimeKeys>0); + } + + /** + * Test one time keys generation. + */ + @Test + public void test07GenerateOneTimeKeys() { + String error = null; + + try { + mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + error = e.getMessage(); + } + + assertTrue(null == error); + } + + /** + * Test the generated amount of one time keys = GENERATION_ONE_TIME_KEYS_NUMBER. + */ + @Test + public void test08OneTimeKeysJsonFormat() { + int oneTimeKeysCount = 0; + Map> oneTimeKeysJson = null; + + try { + oneTimeKeysJson = mOlmAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(oneTimeKeysJson); + + try { + Map map = oneTimeKeysJson.get(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=map); + + // test the count of the generated one time keys: + oneTimeKeysCount = map.size(); + + assertTrue("Expected count="+GENERATION_ONE_TIME_KEYS_NUMBER+" found="+oneTimeKeysCount,GENERATION_ONE_TIME_KEYS_NUMBER==oneTimeKeysCount); + + } catch (Exception e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + } + + @Test + public void test10RemoveOneTimeKeysForSession() { + OlmSession olmSession = null; + try { + olmSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + long sessionId = olmSession.getOlmSessionId(); + assertTrue(0 != sessionId); + + String errorMessage = null; + + try { + mOlmAccount.removeOneTimeKeys(olmSession); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + olmSession.releaseSession(); + sessionId = olmSession.getOlmSessionId(); + assertTrue(0 == sessionId); + } + + @Test + public void test11MarkOneTimeKeysAsPublished() { + try { + mOlmAccount.markOneTimeKeysAsPublished(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + } + + @Test + public void test12SignMessage() { + String clearMsg = "String to be signed by olm"; + String signedMsg = null; + + try { + signedMsg = mOlmAccount.signMessage(clearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(signedMsg); + // additional tests are performed in test01VerifyEd25519Signing() + } + + + // ******************************************************** + // ************* SERIALIZATION TEST *********************** + // ******************************************************** + + @Test + public void test13Serialization() { + FileOutputStream fileOutput; + ObjectOutputStream objectOutput; + OlmAccount accountRef = null; + OlmAccount accountDeserial = null; + + try { + accountRef = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + try { + accountRef.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(),false); + } + + // get keys references + Map identityKeysRef = null; + + try { + identityKeysRef = accountRef.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + Map> oneTimeKeysRef = null; + + try { + oneTimeKeysRef = accountRef.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(identityKeysRef); + assertNotNull(oneTimeKeysRef); + + try { + Context context = getInstrumentation().getContext(); + //context.getFilesDir(); + fileOutput = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); + + // serialize account + objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(accountRef); + objectOutput.flush(); + objectOutput.close(); + + // deserialize account + FileInputStream fileInput = context.openFileInput(FILE_NAME); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + accountDeserial = (OlmAccount) objectInput.readObject(); + objectInput.close(); + assertNotNull(accountDeserial); + + // get de-serialized keys + Map identityKeysDeserial = accountDeserial.identityKeys(); + Map> oneTimeKeysDeserial = accountDeserial.oneTimeKeys(); + assertNotNull(identityKeysDeserial); + assertNotNull(oneTimeKeysDeserial); + + // compare identity keys + assertTrue(identityKeysDeserial.toString().equals(identityKeysRef.toString())); + + // compare onetime keys + assertTrue(oneTimeKeysDeserial.toString().equals(oneTimeKeysRef.toString())); + + accountRef.releaseAccount(); + accountDeserial.releaseAccount(); + } + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception IOException Msg==" + e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test13Serialization(): Exception Msg==" + e.getMessage()); + assertTrue("test13Serialization failed " + e.getMessage(), false); + } + } + + + // **************************************************** + // *************** SANITY CHECK TESTS ***************** + // **************************************************** + + @Test + public void test14GenerateOneTimeKeysError() { + // keys number = 0 => no error + + String errorMessage = null; + try { + mOlmAccount.generateOneTimeKeys(0); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(null == errorMessage); + + // keys number = negative value + errorMessage = null; + try { + mOlmAccount.generateOneTimeKeys(-50); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(null != errorMessage); + } + + @Test + public void test15RemoveOneTimeKeysForSessionError() { + OlmAccount olmAccount = null; + try { + olmAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + try { + olmAccount.removeOneTimeKeys(null); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + olmAccount.releaseAccount(); + } + + @Test + public void test16SignMessageError() { + OlmAccount olmAccount = null; + try { + olmAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + String signedMsg = null; + + try { + signedMsg = olmAccount.signMessage(null); + } catch (Exception e) { + } + + assertNull(signedMsg); + + olmAccount.releaseAccount(); + } + + /** + * Create multiple accounts and check that identity keys are still different. + * This test validates random series are provide enough random values. + */ + @Test + public void test17MultipleAccountCreation() { + try { + OlmAccount account1 = new OlmAccount(); + OlmAccount account2 = new OlmAccount(); + OlmAccount account3 = new OlmAccount(); + OlmAccount account4 = new OlmAccount(); + OlmAccount account5 = new OlmAccount(); + OlmAccount account6 = new OlmAccount(); + OlmAccount account7 = new OlmAccount(); + OlmAccount account8 = new OlmAccount(); + OlmAccount account9 = new OlmAccount(); + OlmAccount account10 = new OlmAccount(); + + Map identityKeys1 = account1.identityKeys(); + Map identityKeys2 = account2.identityKeys(); + Map identityKeys3 = account3.identityKeys(); + Map identityKeys4 = account4.identityKeys(); + Map identityKeys5 = account5.identityKeys(); + Map identityKeys6 = account6.identityKeys(); + Map identityKeys7 = account7.identityKeys(); + Map identityKeys8 = account8.identityKeys(); + Map identityKeys9 = account9.identityKeys(); + Map identityKeys10 = account10.identityKeys(); + + String identityKey1 = TestHelper.getIdentityKey(identityKeys1); + String identityKey2 = TestHelper.getIdentityKey(identityKeys2); + assertFalse(identityKey1.equals(identityKey2)); + + String identityKey3 = TestHelper.getIdentityKey(identityKeys3); + assertFalse(identityKey2.equals(identityKey3)); + + String identityKey4 = TestHelper.getIdentityKey(identityKeys4); + assertFalse(identityKey3.equals(identityKey4)); + + String identityKey5 = TestHelper.getIdentityKey(identityKeys5); + assertFalse(identityKey4.equals(identityKey5)); + + String identityKey6 = TestHelper.getIdentityKey(identityKeys6); + assertFalse(identityKey5.equals(identityKey6)); + + String identityKey7 = TestHelper.getIdentityKey(identityKeys7); + assertFalse(identityKey6.equals(identityKey7)); + + String identityKey8 = TestHelper.getIdentityKey(identityKeys8); + assertFalse(identityKey7.equals(identityKey8)); + + String identityKey9 = TestHelper.getIdentityKey(identityKeys9); + assertFalse(identityKey8.equals(identityKey9)); + + String identityKey10 = TestHelper.getIdentityKey(identityKeys10); + assertFalse(identityKey9.equals(identityKey10)); + + account1.releaseAccount(); + account2.releaseAccount(); + account3.releaseAccount(); + account4.releaseAccount(); + account5.releaseAccount(); + account6.releaseAccount(); + account7.releaseAccount(); + account8.releaseAccount(); + account9.releaseAccount(); + account10.releaseAccount(); + + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + } +} diff --git a/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java new file mode 100644 index 0000000..9be6375 --- /dev/null +++ b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -0,0 +1,525 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.content.Context; +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmGroupSessionTest { + private static final String LOG_TAG = "OlmSessionTest"; + private final String FILE_NAME_SERIAL_OUT_SESSION = "SerialOutGroupSession"; + private final String FILE_NAME_SERIAL_IN_SESSION = "SerialInGroupSession"; + + private static OlmManager mOlmManager; + private static OlmOutboundGroupSession mAliceOutboundGroupSession; + private static String mAliceSessionIdentifier; + private static long mAliceMessageIndex; + private static final String CLEAR_MESSAGE1 = "Hello!"; + private static String mAliceToBobMessage; + private static OlmInboundGroupSession mBobInboundGroupSession; + private static String mAliceOutboundSessionKey; + private static String mBobSessionIdentifier; + private static String mBobDecryptedMessage; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + /** + * Basic test: + * - alice creates an outbound group session + * - bob creates an inbound group session with alice's outbound session key + * - alice encrypts a message with its session + * - bob decrypts the encrypted message with its session + * - decrypted message is identical to original alice message + */ + @Test + public void test01CreateOutboundSession() { + // alice creates OUTBOUND GROUP SESSION + try { + mAliceOutboundGroupSession = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + } + + @Test + public void test02GetOutboundGroupSessionIdentifier() { + // test session ID + mAliceSessionIdentifier = null; + + try { + mAliceSessionIdentifier = mAliceOutboundGroupSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(mAliceSessionIdentifier); + assertTrue(mAliceSessionIdentifier.length() > 0); + } + + @Test + public void test03GetOutboundGroupSessionKey() { + // test session Key + mAliceOutboundSessionKey = null; + + try { + mAliceOutboundSessionKey = mAliceOutboundGroupSession.sessionKey(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(mAliceOutboundSessionKey); + assertTrue(mAliceOutboundSessionKey.length() > 0); + } + + @Test + public void test04GetOutboundGroupMessageIndex() { + // test message index before any encryption + mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex(); + assertTrue(0 == mAliceMessageIndex); + } + + @Test + public void test05OutboundGroupEncryptMessage() { + // alice encrypts a message to bob + try { + mAliceToBobMessage = mAliceOutboundGroupSession.encryptMessage(CLEAR_MESSAGE1); + } catch (Exception e) { + assertTrue("Exception in bob encryptMessage, Exception code=" + e.getMessage(), false); + } + assertFalse(TextUtils.isEmpty(mAliceToBobMessage)); + + // test message index after encryption is incremented + mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex(); + assertTrue(1 == mAliceMessageIndex); + } + + @Test + public void test06CreateInboundGroupSession() { + // bob creates INBOUND GROUP SESSION with alice outbound key + try { + mBobInboundGroupSession = new OlmInboundGroupSession(mAliceOutboundSessionKey); + } catch (OlmException e) { + assertTrue("Exception in bob OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + } + + @Test + public void test08GetInboundGroupSessionIdentifier() { + // check both session identifiers are equals + mBobSessionIdentifier = null; + + try { + mBobSessionIdentifier = mBobInboundGroupSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertFalse(TextUtils.isEmpty(mBobSessionIdentifier)); + } + + @Test + public void test09SessionIdentifiersAreIdentical() { + // check both session identifiers are equals: alice vs bob + assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier)); + } + + @Test + public void test10InboundDecryptMessage() { + mBobDecryptedMessage = null; + OlmInboundGroupSession.DecryptMessageResult result = null; + + try { + result = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + // test decrypted message + mBobDecryptedMessage = result.mDecryptedMessage; + assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); + assertTrue(0 == result.mIndex); + } + + @Test + public void test11InboundDecryptedMessageIdentical() { + // test decrypted message + assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); + } + + @Test + public void test12ReleaseOutboundSession() { + // release group sessions + mAliceOutboundGroupSession.releaseSession(); + } + + @Test + public void test13ReleaseInboundSession() { + // release group sessions + mBobInboundGroupSession.releaseSession(); + } + + @Test + public void test14CheckUnreleaseedCount() { + assertTrue(mAliceOutboundGroupSession.isReleased()); + assertTrue(mBobInboundGroupSession.isReleased()); + } + + @Test + public void test15SerializeOutboundSession() { + OlmOutboundGroupSession outboundGroupSessionRef=null; + OlmOutboundGroupSession outboundGroupSessionSerial; + + // create one OUTBOUND GROUP SESSION + try { + outboundGroupSessionRef = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + assertNotNull(outboundGroupSessionRef); + + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_OUT_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(outboundGroupSessionRef); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_OUT_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject(); + assertNotNull(outboundGroupSessionSerial); + objectInput.close(); + + // get sessions keys + String sessionKeyRef = outboundGroupSessionRef.sessionKey(); + String sessionKeySerial = outboundGroupSessionSerial.sessionKey(); + assertFalse(TextUtils.isEmpty(sessionKeyRef)); + assertFalse(TextUtils.isEmpty(sessionKeySerial)); + + // session keys comparison + assertTrue(sessionKeyRef.equals(sessionKeySerial)); + + // get sessions IDs + String sessionIdRef = outboundGroupSessionRef.sessionIdentifier(); + String sessionIdSerial = outboundGroupSessionSerial.sessionIdentifier(); + assertFalse(TextUtils.isEmpty(sessionIdRef)); + assertFalse(TextUtils.isEmpty(sessionIdSerial)); + + // session IDs comparison + assertTrue(sessionIdRef.equals(sessionIdSerial)); + + outboundGroupSessionRef.releaseSession(); + outboundGroupSessionSerial.releaseSession(); + + assertTrue(outboundGroupSessionRef.isReleased()); + assertTrue(outboundGroupSessionSerial.isReleased()); + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (OlmException e) { + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception OlmException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (IOException e) { + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception IOException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (Exception e) { + Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } + } + + @Test + public void test16SerializeInboundSession() { + OlmOutboundGroupSession aliceOutboundGroupSession=null; + OlmInboundGroupSession bobInboundGroupSessionRef=null; + OlmInboundGroupSession bobInboundGroupSessionSerial; + + // alice creates OUTBOUND GROUP SESSION + try { + aliceOutboundGroupSession = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + assertNotNull(aliceOutboundGroupSession); + + // get the session key from the outbound group session + String sessionKeyRef = null; + + try { + sessionKeyRef = aliceOutboundGroupSession.sessionKey(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(sessionKeyRef); + + // bob creates INBOUND GROUP SESSION + try { + bobInboundGroupSessionRef = new OlmInboundGroupSession(sessionKeyRef); + } catch (OlmException e) { + assertTrue("Exception in OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + assertNotNull(bobInboundGroupSessionRef); + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_IN_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(bobInboundGroupSessionRef); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_IN_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + bobInboundGroupSessionSerial = (OlmInboundGroupSession)objectInput.readObject(); + assertNotNull(bobInboundGroupSessionSerial); + objectInput.close(); + + // get sessions IDs + String aliceSessionId = aliceOutboundGroupSession.sessionIdentifier(); + String sessionIdRef = bobInboundGroupSessionRef.sessionIdentifier(); + String sessionIdSerial = bobInboundGroupSessionSerial.sessionIdentifier(); + assertFalse(TextUtils.isEmpty(aliceSessionId)); + assertFalse(TextUtils.isEmpty(sessionIdRef)); + assertFalse(TextUtils.isEmpty(sessionIdSerial)); + + // session IDs comparison + assertTrue(aliceSessionId.equals(sessionIdSerial)); + assertTrue(sessionIdRef.equals(sessionIdSerial)); + + aliceOutboundGroupSession.releaseSession(); + bobInboundGroupSessionRef.releaseSession(); + bobInboundGroupSessionSerial.releaseSession(); + + assertTrue(aliceOutboundGroupSession.isReleased()); + assertTrue(bobInboundGroupSessionRef.isReleased()); + assertTrue(bobInboundGroupSessionSerial.isReleased()); + } catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (OlmException e) { + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception OlmException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (IOException e) { + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception IOException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } catch (Exception e) { + Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } + } + + /** + * Create multiple outbound group sessions and check that session Keys are different. + * This test validates random series are provide enough random values. + */ + @Test + public void test17MultipleOutboundSession() { + OlmOutboundGroupSession outboundGroupSession1; + OlmOutboundGroupSession outboundGroupSession2; + OlmOutboundGroupSession outboundGroupSession3; + OlmOutboundGroupSession outboundGroupSession4; + OlmOutboundGroupSession outboundGroupSession5; + OlmOutboundGroupSession outboundGroupSession6; + OlmOutboundGroupSession outboundGroupSession7; + OlmOutboundGroupSession outboundGroupSession8; + + try { + outboundGroupSession1 = new OlmOutboundGroupSession(); + outboundGroupSession2 = new OlmOutboundGroupSession(); + outboundGroupSession3 = new OlmOutboundGroupSession(); + outboundGroupSession4 = new OlmOutboundGroupSession(); + outboundGroupSession5 = new OlmOutboundGroupSession(); + outboundGroupSession6 = new OlmOutboundGroupSession(); + outboundGroupSession7 = new OlmOutboundGroupSession(); + outboundGroupSession8 = new OlmOutboundGroupSession(); + + // get the session key from the outbound group sessions + String sessionKey1 = outboundGroupSession1.sessionKey(); + String sessionKey2 = outboundGroupSession2.sessionKey(); + assertFalse(sessionKey1.equals(sessionKey2)); + + String sessionKey3 = outboundGroupSession3.sessionKey(); + assertFalse(sessionKey2.equals(sessionKey3)); + + String sessionKey4 = outboundGroupSession4.sessionKey(); + assertFalse(sessionKey3.equals(sessionKey4)); + + String sessionKey5 = outboundGroupSession5.sessionKey(); + assertFalse(sessionKey4.equals(sessionKey5)); + + String sessionKey6 = outboundGroupSession6.sessionKey(); + assertFalse(sessionKey5.equals(sessionKey6)); + + String sessionKey7 = outboundGroupSession7.sessionKey(); + assertFalse(sessionKey6.equals(sessionKey7)); + + String sessionKey8 = outboundGroupSession8.sessionKey(); + assertFalse(sessionKey7.equals(sessionKey8)); + + // get the session IDs from the outbound group sessions + String sessionId1 = outboundGroupSession1.sessionIdentifier(); + String sessionId2 = outboundGroupSession2.sessionIdentifier(); + assertFalse(sessionId1.equals(sessionId2)); + + String sessionId3 = outboundGroupSession3.sessionKey(); + assertFalse(sessionId2.equals(sessionId3)); + + String sessionId4 = outboundGroupSession4.sessionKey(); + assertFalse(sessionId3.equals(sessionId4)); + + String sessionId5 = outboundGroupSession5.sessionKey(); + assertFalse(sessionId4.equals(sessionId5)); + + String sessionId6 = outboundGroupSession6.sessionKey(); + assertFalse(sessionId5.equals(sessionId6)); + + String sessionId7 = outboundGroupSession7.sessionKey(); + assertFalse(sessionId6.equals(sessionId7)); + + String sessionId8 = outboundGroupSession8.sessionKey(); + assertFalse(sessionId7.equals(sessionId8)); + + outboundGroupSession1.releaseSession(); + outboundGroupSession2.releaseSession(); + outboundGroupSession3.releaseSession(); + outboundGroupSession4.releaseSession(); + outboundGroupSession5.releaseSession(); + outboundGroupSession6.releaseSession(); + outboundGroupSession7.releaseSession(); + outboundGroupSession8.releaseSession(); + + assertTrue(outboundGroupSession1.isReleased()); + assertTrue(outboundGroupSession2.isReleased()); + assertTrue(outboundGroupSession3.isReleased()); + assertTrue(outboundGroupSession4.isReleased()); + assertTrue(outboundGroupSession5.isReleased()); + assertTrue(outboundGroupSession6.isReleased()); + assertTrue(outboundGroupSession7.isReleased()); + assertTrue(outboundGroupSession8.isReleased()); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + } + + /** + * Specific test for the following run time error: + * "JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0 in call to NewStringUTF".
+ * When the msg to decrypt contain emojis, depending on the android platform, the NewStringUTF() behaves differently and + * can even crash. + * This issue is described in details here: https://github.com/eclipsesource/J2V8/issues/142 + */ + @Test + public void test18TestBadCharacterCrashInDecrypt() { + OlmInboundGroupSession bobInboundGroupSession=null; + + // values taken from a "real life" crash case + String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; + String msgToDecryptWithEmoji = "AwgNEpABpjs+tYF+0y8bWtzAgYAC3N55p5cPJEEiGPU1kxIHSY7f2aG5Fj4wmcsXUkhDv0UePj922kgf+Q4dFsPHKq2aVA93n8DJAQ/FRfcM98B9E6sKCZ/PsCF78uBvF12Aaq9D3pUHBopdd7llUfVq29d5y6ZwX5VDoqV2utsATkKjXYV9CbfZuvvBMQ30ZLjEtyUUBJDY9K4FxEFcULytA/IkVnATTG9ERuLF/yB6ukSFR+iUWRYAmtuOuU0k9BvaqezbGqNoK5Grlkes+dYX6/0yUObumcw9/iAI"; + + // bob creates INBOUND GROUP SESSION + try { + bobInboundGroupSession = new OlmInboundGroupSession(sessionKeyRef); + } catch (OlmException e) { + assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false); + } + + OlmInboundGroupSession.DecryptMessageResult result = null; + + try { + result = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji); + } catch (Exception e) { + assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getMessage(), false); + } + + assertNotNull(result.mDecryptedMessage); + assertTrue(13 == result.mIndex); + } + + /** + * Specific test to check an error message is returned by decryptMessage() API.
+ * A corrupted encrypted message is passed, and a INVALID_BASE64 is + * espexted. + **/ + @Test + public void test19TestErrorMessageReturnedInDecrypt() { + OlmInboundGroupSession bobInboundGroupSession=null; + final String EXPECTED_ERROR_MESSAGE= "INVALID_BASE64"; + + String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; + String corruptedEncryptedMsg = "AwgANYTHINGf87ge45ge7gr*/rg5ganything4gr41rrgr4re55tanythingmcsXUkhDv0UePj922kgf+"; + + // valid INBOUND GROUP SESSION + try { + bobInboundGroupSession = new OlmInboundGroupSession(sessionKeyRef); + } catch (OlmException e) { + assertTrue("Exception in test19TestErrorMessageReturnedInDecrypt, Exception code=" + e.getExceptionCode(), false); + } + + String exceptionMessage = null; + try { + bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg); + } catch (OlmException e) { + exceptionMessage = e.getMessage(); + } + + assertTrue(0!=EXPECTED_ERROR_MESSAGE.length()); + assertTrue(EXPECTED_ERROR_MESSAGE.equals(exceptionMessage)); + } +} + diff --git a/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java new file mode 100644 index 0000000..e08b151 --- /dev/null +++ b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java @@ -0,0 +1,1014 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.content.Context; +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONObject; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.Map; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmSessionTest { + private static final String LOG_TAG = "OlmSessionTest"; + private final String INVALID_PRE_KEY = "invalid PRE KEY hu hu!"; + private final String FILE_NAME_SERIAL_SESSION = "SerialSession"; + private final int ONE_TIME_KEYS_NUMBER = 4; + + private static OlmManager mOlmManager; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + /** + * Basic test: + * - alice creates an account + * - bob creates an account + * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey) + * - alice encrypts a message with its session + * - bob creates an inbound session based on alice's encrypted message + * - bob decrypts the encrypted message with its session + */ + @Test + public void test01AliceToBob() { + final int ONE_TIME_KEYS_NUMBER = 5; + String bobIdentityKey = null; + String bobOneTimeKey=null; + OlmAccount bobAccount = null; + OlmAccount aliceAccount = null; + + // ALICE & BOB ACCOUNTS CREATION + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // get bob identity key + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); + assertTrue(null!=bobIdentityKey); + + // get bob one time keys + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); + assertNotNull(bobOneTimeKey); + + // CREATE ALICE SESSION + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE ALICE OUTBOUND SESSION and encrypt message to bob + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + String clearMsg = "Heloo bob , this is alice!"; + OlmMessage encryptedMsgToBob = null; + try { + encryptedMsgToBob = aliceSession.encryptMessage(clearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsgToBob); + assertNotNull(encryptedMsgToBob.mCipherText); + Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText); + + // CREATE BOB INBOUND SESSION and decrypt message from alice + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=bobSession.getOlmSessionId()); + + try { + bobSession.initInboundSession(bobAccount, encryptedMsgToBob.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } + + String decryptedMsg = null; + try { + decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(decryptedMsg); + + // MESSAGE COMPARISON: decrypted vs encrypted + assertTrue(clearMsg.equals(decryptedMsg)); + + // clean objects.. + try { + bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + // release accounts + bobAccount.releaseAccount(); + aliceAccount.releaseAccount(); + assertTrue(bobAccount.isReleased()); + assertTrue(aliceAccount.isReleased()); + + // release sessions + bobSession.releaseSession(); + aliceSession.releaseSession(); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); + } + + + /** + * Same as test01AliceToBob but with bob who's encrypting messages + * to alice and alice decrypt them.
+ * - alice creates an account + * - bob creates an account + * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey) + * - alice encrypts a message with its own session + * - bob creates an inbound session based on alice's encrypted message + * - bob decrypts the encrypted message with its own session + * - bob encrypts messages with its own session + * - alice decrypts bob's messages with its own message + * - alice encrypts a message + * - bob decrypts the encrypted message + */ + @Test + public void test02AliceToBobBackAndForth() { + String bobIdentityKey; + String bobOneTimeKey; + OlmAccount aliceAccount = null; + OlmAccount bobAccount = null; + + // creates alice & bob accounts + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // get bob identity key + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); + assertTrue(null!=bobIdentityKey); + + // get bob one time keys + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); + assertNotNull(bobOneTimeKey); + + // CREATE ALICE SESSION + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE ALICE OUTBOUND SESSION and encrypt message to bob + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + String helloClearMsg = "Hello I'm Alice!"; + + OlmMessage encryptedAliceToBobMsg1 = null; + + try { + encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(encryptedAliceToBobMsg1); + assertNotNull(encryptedAliceToBobMsg1.mCipherText); + + // CREATE BOB INBOUND SESSION and decrypt message from alice + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + + assertTrue(0!=bobSession.getOlmSessionId()); + + try { + bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } + + // DECRYPT MESSAGE FROM ALICE + String decryptedMsg01 = null; + try { + decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(decryptedMsg01); + + // MESSAGE COMPARISON: decrypted vs encrypted + assertTrue(helloClearMsg.equals(decryptedMsg01)); + + // BACK/FORTH MESSAGE COMPARISON + String clearMsg1 = "Hello I'm Bob!"; + String clearMsg2 = "Isn't life grand?"; + String clearMsg3 = "Let's go to the opera."; + + // bob encrypts messages + OlmMessage encryptedMsg1 = null; + try { + encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsg1); + + OlmMessage encryptedMsg2 = null; + try { + encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsg2); + + + OlmMessage encryptedMsg3 = null; + try { + encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsg3); + + // alice decrypts bob's messages + String decryptedMsg1 = null; + try { + decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(decryptedMsg1); + String decryptedMsg2 = null; + try { + decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(decryptedMsg2); + String decryptedMsg3 = null; + try { + decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(decryptedMsg3); + + // comparison tests + assertTrue(clearMsg1.equals(decryptedMsg1)); + assertTrue(clearMsg2.equals(decryptedMsg2)); + assertTrue(clearMsg3.equals(decryptedMsg3)); + + // and one more from alice to bob + clearMsg1 = "another message from Alice to Bob!!"; + encryptedMsg1 = null; + + try { + encryptedMsg1 = aliceSession.encryptMessage(clearMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsg1); + + decryptedMsg1 = null; + try { + decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(decryptedMsg1); + assertTrue(clearMsg1.equals(decryptedMsg1)); + + // comparison test + assertTrue(clearMsg1.equals(decryptedMsg1)); + + // clean objects.. + try { + bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + bobAccount.releaseAccount(); + aliceAccount.releaseAccount(); + assertTrue(bobAccount.isReleased()); + assertTrue(aliceAccount.isReleased()); + + bobSession.releaseSession(); + aliceSession.releaseSession(); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); + } + + + @Test + public void test03AliceBobSessionId() { + // creates alice & bob accounts + OlmAccount aliceAccount = null; + OlmAccount bobAccount = null; + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // CREATE ALICE SESSION + + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE ALICE SESSION + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + e.printStackTrace(); + assertTrue(e.getMessage(), false); + } + assertTrue(0!=bobSession.getOlmSessionId()); + + String aliceSessionId = null; + try { + aliceSessionId = aliceSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(aliceSessionId); + + String bobSessionId = null; + try { + bobSessionId = bobSession.sessionIdentifier(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(bobSessionId); + + // must be the same for both ends of the conversation + assertTrue(aliceSessionId.equals(bobSessionId)); + + aliceAccount.releaseAccount(); + bobAccount.releaseAccount(); + assertTrue(aliceAccount.isReleased()); + assertTrue(bobAccount.isReleased()); + + bobSession.releaseSession(); + aliceSession.releaseSession(); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); + } + + @Test + public void test04MatchInboundSession() { + OlmAccount aliceAccount=null, bobAccount=null; + OlmSession aliceSession = null, bobSession = null; + + // ACCOUNTS CREATION + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(), false); + } + + // CREATE ALICE SESSION + try { + aliceSession = new OlmSession(); + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg=" + e.getMessage(), false); + } + + // get bob/luke identity key + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + Map aliceIdentityKeys = null; + + try { + aliceIdentityKeys = aliceAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); + String aliceIdentityKey = TestHelper.getIdentityKey(aliceIdentityKeys); + + // get bob/luke one time keys + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + try { + aliceAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeys, 1); + + // create alice inbound session for bob + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + String aliceClearMsg = "hello helooo to bob!"; + OlmMessage encryptedAliceToBobMsg1 = null; + + try { + encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertFalse(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); + + // init bob session with alice PRE KEY + try { + bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } + + // test matchesInboundSession() and matchesInboundSessionFrom() + assertTrue(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); + assertTrue(bobSession.matchesInboundSessionFrom(aliceIdentityKey, encryptedAliceToBobMsg1.mCipherText)); + // following requires olm native lib new version with https://github.com/matrix-org/olm-backup/commit/7e9f3bebb8390f975a76c0188ce4cb460fe6692e + //assertTrue(false==bobSession.matchesInboundSessionFrom(bobIdentityKey, encryptedAliceToBobMsg1.mCipherText)); + + // release objects + try { + bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + aliceAccount.releaseAccount(); + bobAccount.releaseAccount(); + assertTrue(aliceAccount.isReleased()); + assertTrue(bobAccount.isReleased()); + + aliceSession.releaseSession(); + bobSession.releaseSession(); + assertTrue(aliceSession.isReleased()); + assertTrue(bobSession.isReleased()); + } + + // ******************************************************** + // ************* SERIALIZATION TEST *********************** + // ******************************************************** + /** + * Same as {@link #test02AliceToBobBackAndForth()}, but alice's session + * is serialized and de-serialized before performing the final + * comparison (encrypt vs ) + */ + @Test + public void test05SessionSerialization() { + final int ONE_TIME_KEYS_NUMBER = 1; + String bobIdentityKey; + String bobOneTimeKey; + OlmAccount aliceAccount = null; + OlmAccount bobAccount = null; + OlmSession aliceSessionDeserial = null; + + // creates alice & bob accounts + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + // test accounts creation + assertTrue(0!=bobAccount.getOlmAccountId()); + assertTrue(0!=aliceAccount.getOlmAccountId()); + + // get bob identity key + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); + assertTrue(null!=bobIdentityKey); + + // get bob one time keys + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); + assertNotNull(bobOneTimeKey); + + // CREATE ALICE SESSION + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=aliceSession.getOlmSessionId()); + + // CREATE ALICE OUTBOUND SESSION and encrypt message to bob + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + String helloClearMsg = "Hello I'm Alice!"; + + OlmMessage encryptedAliceToBobMsg1 = null; + try { + encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedAliceToBobMsg1); + assertNotNull(encryptedAliceToBobMsg1.mCipherText); + + // CREATE BOB INBOUND SESSION and decrypt message from alice + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + assertTrue(0!=bobSession.getOlmSessionId()); + + // init bob session with alice PRE KEY + try { + bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); + } catch (Exception e) { + assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); + } + + // DECRYPT MESSAGE FROM ALICE + String decryptedMsg01 = null; + + try { + decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(decryptedMsg01); + + // MESSAGE COMPARISON: decrypted vs encrypted + assertTrue(helloClearMsg.equals(decryptedMsg01)); + + // BACK/FORTH MESSAGE COMPARISON + String clearMsg1 = "Hello I'm Bob!"; + String clearMsg2 = "Isn't life grand?"; + String clearMsg3 = "Let's go to the opera."; + + // bob encrypts messages + OlmMessage encryptedMsg1 = null; + try { + encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsg1); + + OlmMessage encryptedMsg2 = null; + try { + encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsg2); + + OlmMessage encryptedMsg3 = null; + try { + encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsg3); + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(aliceSession); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + aliceSessionDeserial = (OlmSession) objectInput.readObject(); + objectInput.close(); + + // test deserialize return value + assertNotNull(aliceSessionDeserial); + + // de-serialized alice session decrypts bob's messages + String decryptedMsg1 = aliceSessionDeserial.decryptMessage(encryptedMsg1); + assertNotNull(decryptedMsg1); + String decryptedMsg2 = aliceSessionDeserial.decryptMessage(encryptedMsg2); + assertNotNull(decryptedMsg2); + String decryptedMsg3 = aliceSessionDeserial.decryptMessage(encryptedMsg3); + assertNotNull(decryptedMsg3); + + // comparison tests + assertTrue(clearMsg1.equals(decryptedMsg1)); + assertTrue(clearMsg2.equals(decryptedMsg2)); + assertTrue(clearMsg3.equals(decryptedMsg3)); + + // clean objects.. + try { + bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + bobAccount.releaseAccount(); + aliceAccount.releaseAccount(); + assertTrue(bobAccount.isReleased()); + assertTrue(aliceAccount.isReleased()); + + bobSession.releaseSession(); + aliceSession.releaseSession(); + aliceSessionDeserial.releaseSession(); + assertTrue(bobSession.isReleased()); + assertTrue(aliceSession.isReleased()); + assertTrue(aliceSessionDeserial.isReleased()); + } + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + assertTrue(e.getMessage(), false); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + assertTrue(e.getMessage(), false); + } + } + + + // **************************************************** + // *************** SANITY CHECK TESTS ***************** + // **************************************************** + + @Test + public void test06SanityCheckErrors() { + final int ONE_TIME_KEYS_NUMBER = 5; + OlmAccount bobAccount = null; + OlmAccount aliceAccount = null; + + // ALICE & BOB ACCOUNTS CREATION + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(), false); + } + + // get bob identity key + Map bobIdentityKeys = null; + + try { + bobIdentityKeys = bobAccount.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); + assertTrue(null != bobIdentityKey); + + // get bob one time keys + try { + bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + Map> bobOneTimeKeys = null; + + try { + bobOneTimeKeys = bobAccount.oneTimeKeys(); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(bobOneTimeKeys); + String bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); + assertNotNull(bobOneTimeKey); + + // CREATE ALICE SESSION + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg=" + e.getMessage(), false); + } + + // SANITY CHECK TESTS FOR: initOutboundSessionWithAccount() + String errorMessage = null; + try { + aliceSession.initOutboundSession(null, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + errorMessage = null; + try { + aliceSession.initOutboundSession(aliceAccount, null, bobOneTimeKey); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + errorMessage = null; + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, null); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + errorMessage = null; + try { + aliceSession.initOutboundSession(null, null, null); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null != errorMessage); + + // init properly + errorMessage = null; + try { + aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + assertTrue(null == errorMessage); + + // SANITY CHECK TESTS FOR: encryptMessage() + OlmMessage message = null; + try { + message = aliceSession.encryptMessage(null); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertTrue(null==message); + + // encrypt properly + OlmMessage encryptedMsgToBob = null; + try { + encryptedMsgToBob = aliceSession.encryptMessage("A message for bob"); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + assertNotNull(encryptedMsgToBob); + + // SANITY CHECK TESTS FOR: initInboundSessionWithAccount() + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + errorMessage = null; + try { + bobSession.initInboundSession(null, encryptedMsgToBob.mCipherText); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(!TextUtils.isEmpty(errorMessage)); + + errorMessage = null; + try { + bobSession.initInboundSession(bobAccount, null); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(!TextUtils.isEmpty(errorMessage)); + + errorMessage = null; + try { + bobSession.initInboundSession(bobAccount, INVALID_PRE_KEY); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(!TextUtils.isEmpty(errorMessage)); + + // init properly + errorMessage = null; + try { + bobSession.initInboundSession(bobAccount, encryptedMsgToBob.mCipherText); + } catch (Exception e) { + errorMessage = e.getMessage(); + } + + assertTrue(TextUtils.isEmpty(errorMessage)); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + + // SANITY CHECK TESTS FOR: decryptMessage() + String decryptedMsg = null; + try { + decryptedMsg = aliceSession.decryptMessage(null); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertTrue(null==decryptedMsg); + + // SANITY CHECK TESTS FOR: matchesInboundSession() + assertTrue(!aliceSession.matchesInboundSession(null)); + + // SANITY CHECK TESTS FOR: matchesInboundSessionFrom() + assertTrue(!aliceSession.matchesInboundSessionFrom(null,null)); + + // release objects + try { + bobAccount.removeOneTimeKeys(bobSession); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + aliceAccount.releaseAccount(); + bobAccount.releaseAccount(); + assertTrue(aliceAccount.isReleased()); + assertTrue(bobAccount.isReleased()); + + aliceSession.releaseSession(); + bobSession.releaseSession(); + assertTrue(aliceSession.isReleased()); + assertTrue(bobSession.isReleased()); + } + +} diff --git a/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java new file mode 100644 index 0000000..b560bff --- /dev/null +++ b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java @@ -0,0 +1,161 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.support.test.runner.AndroidJUnit4; +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONObject; +import org.junit.BeforeClass; +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.MethodSorters; + +import java.util.Map; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +@RunWith(AndroidJUnit4.class) +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OlmUtilityTest { + private static final String LOG_TAG = "OlmAccountTest"; + private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50; + + private static OlmManager mOlmManager; + + @BeforeClass + public static void setUpClass(){ + // load native lib + mOlmManager = new OlmManager(); + + String version = mOlmManager.getOlmLibVersion(); + assertNotNull(version); + Log.d(LOG_TAG, "## setUpClass(): lib version="+version); + } + + /** + * Test the signing API + */ + @Test + public void test01VerifyEd25519Signing() { + String fingerPrintKey = null; + String errorMsg = null; + String message = "{\"algorithms\":[\"m.megolm.v1.aes-sha2\",\"m.olm.v1.curve25519-aes-sha2\"],\"device_id\":\"YMBYCWTWCG\",\"keys\":{\"curve25519:YMBYCWTWCG\":\"KZFa5YUXV2EOdhK8dcGMMHWB67stdgAP4+xwiS69mCU\",\"ed25519:YMBYCWTWCG\":\"0cEgQJJqjgtXUGp4ZXQQmh36RAxwxr8HJw2E9v1gvA0\"},\"user_id\":\"@mxBob14774891254276b253f42-f267-43ec-bad9-767142bfea30:localhost:8480\"}"; + OlmAccount account = null; + + // create account + try { + account = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + assertNotNull(account); + + // sign message + String messageSignature = null; + + try { + messageSignature = account.signMessage(message); + } catch (Exception e) { + assertTrue(e.getMessage(), false); + } + + assertNotNull(messageSignature); + + // get identities key (finger print key) + Map identityKeys = null; + + try { + identityKeys = account.identityKeys(); + } catch (Exception e) { + assertTrue("identityKeys failed " + e.getMessage(), false); + } + + assertNotNull(identityKeys); + fingerPrintKey = TestHelper.getFingerprintKey(identityKeys); + assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); + + // instantiate utility object + OlmUtility utility = null; + + try { + utility = new OlmUtility(); + } catch (Exception e) { + assertTrue("failed to create OlmUtility", false); + } + + // verify signature + errorMsg = null; + try { + utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message); + } catch (Exception e) { + errorMsg = e.getMessage(); + } + assertTrue(TextUtils.isEmpty(errorMsg)); + + // check a bad signature is detected => errorMsg = BAD_MESSAGE_MAC + String badSignature = "Bad signature Bad signature Bad signature.."; + + errorMsg = null; + try { + utility.verifyEd25519Signature(badSignature, fingerPrintKey, message); + } catch (Exception e) { + errorMsg = e.getMessage(); + } + assertTrue(!TextUtils.isEmpty(errorMsg)); + + // check bad fingerprint size => errorMsg = INVALID_BASE64 + String badSizeFingerPrintKey = fingerPrintKey.substring(fingerPrintKey.length()/2); + + errorMsg = null; + try { + utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message); + } catch (Exception e) { + errorMsg = e.getMessage(); + } + assertTrue(!TextUtils.isEmpty(errorMsg)); + + utility.releaseUtility(); + assertTrue(utility.isReleased()); + + account.releaseAccount(); + assertTrue(account.isReleased()); + } + + @Test + public void test02sha256() { + OlmUtility utility = null; + + try { + utility = new OlmUtility(); + } catch (Exception e) { + assertTrue("OlmUtility creation failed", false); + } + String msgToHash = "The quick brown fox jumps over the lazy dog"; + + String hashResult = utility.sha256(msgToHash); + assertFalse(TextUtils.isEmpty(hashResult)); + + utility.releaseUtility(); + assertTrue(utility.isReleased()); + } +} diff --git a/android/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/android/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java new file mode 100644 index 0000000..4451f7a --- /dev/null +++ b/android/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java @@ -0,0 +1,82 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import java.util.ArrayList; +import java.util.Map; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +/** + * Helper class providing helper methods used in the Olm Android SDK unit tests. + */ +public class TestHelper { + + /** + * Return the identity key {@link OlmAccount#JSON_KEY_IDENTITY_KEY} from the JSON object. + * @param aIdentityKeysMap result of {@link OlmAccount#identityKeys()} + * @return identity key string if operation succeed, null otherwise + */ + static public String getIdentityKey(Map aIdentityKeysMap){ + String idKey = null; + + try { + idKey = aIdentityKeysMap.get(OlmAccount.JSON_KEY_IDENTITY_KEY); + } catch (Exception e) { + assertTrue("Exception MSg=" + e.getMessage(), false); + } + return idKey; + } + + /** + * Return the fingerprint key {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} from the JSON object. + * @param aIdentityKeysMap result of {@link OlmAccount#identityKeys()} + * @return fingerprint key string if operation succeed, null otherwise + */ + static public String getFingerprintKey(Map aIdentityKeysMap) { + String fingerprintKey = null; + + try { + fingerprintKey = aIdentityKeysMap.get(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); + } catch (Exception e) { + assertTrue("Exception MSg=" + e.getMessage(), false); + } + return fingerprintKey; + } + + /** + * Return the first one time key from the JSON object. + * @param aIdentityKeysMap result of {@link OlmAccount#oneTimeKeys()} + * @param aKeyPosition the position of the key to be retrieved + * @return one time key string if operation succeed, null otherwise + */ + static public String getOneTimeKey(Map> aIdentityKeysMap, int aKeyPosition) { + String firstOneTimeKey = null; + + try { + Map generatedKeys = aIdentityKeysMap.get(OlmAccount.JSON_KEY_ONE_TIME_KEY); + assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY + " object is missing", generatedKeys); + + firstOneTimeKey = (new ArrayList<>(generatedKeys.values())).get(aKeyPosition - 1); + } catch (Exception e) { + assertTrue("Exception Msg=" + e.getMessage(), false); + } + return firstOneTimeKey; + } +} diff --git a/android/olm-sdk/src/main/AndroidManifest.xml b/android/olm-sdk/src/main/AndroidManifest.xml new file mode 100644 index 0000000..902f2e3 --- /dev/null +++ b/android/olm-sdk/src/main/AndroidManifest.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/android/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java new file mode 100644 index 0000000..229963f --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java @@ -0,0 +1,83 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.util.Log; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +/** + * Helper class dedicated to serialization mechanism (template method pattern). + */ +abstract class CommonSerializeUtils { + private static final String LOG_TAG = "CommonSerializeUtils"; + + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception + */ + protected void serialize(ObjectOutputStream aOutStream) throws IOException { + aOutStream.defaultWriteObject(); + + // generate serialization key + byte[] key = OlmUtility.getRandomKey(); + + // compute pickle string + StringBuffer errorMsg = new StringBuffer(); + byte[] pickledData = serialize(key, errorMsg); + + if(null == pickledData) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg)); + } else { + aOutStream.writeObject(new String(key, "UTF-8")); + aOutStream.writeObject(new String(pickledData, "UTF-8")); + } + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws Exception the exception + */ + protected void deserialize(ObjectInputStream aInStream) throws Exception { + aInStream.defaultReadObject(); + + String keyAsString = (String)aInStream.readObject(); + String pickledDataAsString = (String)aInStream.readObject(); + + byte[] key; + byte[] pickledData; + + try { + key = keyAsString.getBytes("UTF-8"); + pickledData = pickledDataAsString.getBytes("UTF-8"); + + deserialize(pickledData, key); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, e.getMessage()); + } + + Log.d(LOG_TAG,"## deserializeObject(): success"); + } + + protected abstract byte[] serialize(byte[] aKey, StringBuffer aErrorMsg); + protected abstract void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception; +} diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java new file mode 100644 index 0000000..26c3e60 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -0,0 +1,415 @@ +/* + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONObject; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; +import java.util.Map; + +/** + * Account class used to create Olm sessions in conjunction with {@link OlmSession} class.
+ * OlmAccount provides APIs to retrieve the Olm keys. + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ +public class OlmAccount extends CommonSerializeUtils implements Serializable { + private static final long serialVersionUID = 3497486121598434824L; + private static final String LOG_TAG = "OlmAccount"; + + // JSON keys used in the JSON objects returned by JNI + /** As well as the identity key, each device creates a number of Curve25519 key pairs which are + also used to establish Olm sessions, but can only be used once. Once again, the private part + remains on the device. but the public part is published to the Matrix network **/ + public static final String JSON_KEY_ONE_TIME_KEY = "curve25519"; + + /** Curve25519 identity key is a public-key cryptographic system which can be used to establish a shared + secret.
In Matrix, each device has a long-lived Curve25519 identity key which is used to establish + Olm sessions with that device. The private key should never leave the device, but the + public part is signed with the Ed25519 fingerprint key ({@link #JSON_KEY_FINGER_PRINT_KEY}) and published to the network. **/ + public static final String JSON_KEY_IDENTITY_KEY = "curve25519"; + + /** Ed25519 finger print is a public-key cryptographic system for signing messages.
In Matrix, each device has + an Ed25519 key pair which serves to identify that device. The private the key should + never leave the device, but the public part is published to the Matrix network. **/ + public static final String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; + + /** Account Id returned by JNI. + * This value identifies uniquely the native account instance. + */ + private transient long mNativeId; + + public OlmAccount() throws OlmException { + try { + mNativeId = createNewAccountJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); + } + } + + /** + * Create a new account and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmAccount* to jlong) platform independent. + * @return the initialized OlmAccount* instance or throw an exception if fails + **/ + private native long createNewAccountJni(); + + /** + * Getter on the account ID. + * @return native account ID + */ + long getOlmAccountId(){ + return mNativeId; + } + + /** + * Release native account and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseAccountJni()}. + */ + public void releaseAccount() { + if (0 != mNativeId) { + releaseAccountJni(); + } + mNativeId = 0; + } + + /** + * Destroy the corresponding OLM account native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #createNewAccountJni()}. + */ + private native void releaseAccountJni(); + + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + + /** + * Return the identity keys (identity and fingerprint keys) in a dictionary.
+ * Public API for {@link #identityKeysJni()}.
+ * Ex: + * { + * "curve25519":"Vam++zZPMqDQM6ANKpO/uAl5ViJSHxV9hd+b0/fwRAg", + * "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I" + * } + * @return identity keys dictionary if operation succeeds, null otherwise + * @exception OlmException the failure reason + */ + public Map identityKeys() throws OlmException { + JSONObject identityKeysJsonObj = null; + + byte[] identityKeysBuffer; + + try { + identityKeysBuffer = identityKeysJni(); + } catch (Exception e) { + Log.e(LOG_TAG, "## identityKeys(): Failure - " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS, e.getMessage()); + } + + if (null != identityKeysBuffer) { + try { + identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer, "UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); + } + } else { + Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); + } + + return OlmUtility.toStringMap(identityKeysJsonObj); + } + + /** + * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
+ * Keys are Base64 encoded. + * These keys must be published on the server. + * @return the identity keys or throw an exception if it fails + */ + private native byte[] identityKeysJni(); + + /** + * Return the largest number of "one time keys" this account can store. + * @return the max number of "one time keys", -1 otherwise + */ + public long maxOneTimeKeys() { + return maxOneTimeKeysJni(); + } + + /** + * Return the largest number of "one time keys" this account can store. + * @return the max number of "one time keys", -1 otherwise + */ + private native long maxOneTimeKeysJni(); + + /** + * Generate a number of new one time keys.
If total number of keys stored + * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded.
+ * The corresponding keys are retrieved by {@link #oneTimeKeys()}. + * @param aNumberOfKeys number of keys to generate + * @exception OlmException the failure reason + */ + public void generateOneTimeKeys(int aNumberOfKeys) throws OlmException { + try { + generateOneTimeKeysJni(aNumberOfKeys); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS, e.getMessage()); + } + } + + /** + * Generate a number of new one time keys.
If total number of keys stored + * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. + * An exception is thrown if the operation fails.
+ * @param aNumberOfKeys number of keys to generate + */ + private native void generateOneTimeKeysJni(int aNumberOfKeys); + + /** + * Return the "one time keys" in a dictionary.
+ * The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}
+ * Ex: + * { "curve25519": + * { + * "AAAABQ":"qefVZd8qvjOpsFzoKSAdfUnJVkIreyxWFlipCHjSQQg", + * "AAAABA":"/X8szMU+p+lsTnr56wKjaLgjTMQQkCk8EIWEAilZtQ8", + * "AAAAAw":"qxNxxFHzevFntaaPdT0fhhO7tc7pco4+xB/5VRG81hA", + * } + * }
+ * Public API for {@link #oneTimeKeysJni()}.
+ * Note: these keys are to be published on the server. + * @return one time keys in string dictionary. + * @exception OlmException the failure reason + */ + public Map> oneTimeKeys() throws OlmException { + JSONObject oneTimeKeysJsonObj = null; + byte[] oneTimeKeysBuffer; + + try { + oneTimeKeysBuffer = oneTimeKeysJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS, e.getMessage()); + } + + if( null != oneTimeKeysBuffer) { + try { + oneTimeKeysJsonObj = new JSONObject(new String(oneTimeKeysBuffer, "UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); + } + } else { + Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); + } + + return OlmUtility.toStringMapMap(oneTimeKeysJsonObj); + } + + /** + * Get the public parts of the unpublished "one time keys" for the account.
+ * The returned data is a JSON-formatted object with the single property + * curve25519, which is itself an object mapping key id to + * base64-encoded Curve25519 key.
+ * @return byte array containing the one time keys or throw an exception if it fails + */ + private native byte[] oneTimeKeysJni(); + + /** + * Remove the "one time keys" that the session used from the account. + * @param aSession session instance + * @throws OlmException the failure reason + */ + public void removeOneTimeKeys(OlmSession aSession) throws OlmException { + if (null != aSession) { + try { + removeOneTimeKeysJni(aSession.getOlmSessionId()); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS, e.getMessage()); + } + } + } + + /** + * Remove the "one time keys" that the session used from the account. + * An exception is thrown if the operation fails. + * @param aNativeOlmSessionId native session instance identifier + */ + private native void removeOneTimeKeysJni(long aNativeOlmSessionId); + + /** + * Marks the current set of "one time keys" as being published. + * @exception OlmException the failure reason + */ + public void markOneTimeKeysAsPublished() throws OlmException { + try { + markOneTimeKeysAsPublishedJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED, e.getMessage()); + } + } + + /** + * Marks the current set of "one time keys" as being published. + * An exception is thrown if the operation fails. + */ + private native void markOneTimeKeysAsPublishedJni(); + + /** + * Sign a message with the ed25519 fingerprint key for this account.
+ * The signed message is returned by the method. + * @param aMessage message to sign + * @return the signed message + * @exception OlmException the failure reason + */ + public String signMessage(String aMessage) throws OlmException { + String result = null; + + if (null != aMessage) { + try { + byte[] utf8String = aMessage.getBytes("UTF-8"); + + if (null != utf8String) { + byte[] signedMessage = signMessageJni(utf8String); + + if (null != signedMessage) { + result = new String(signedMessage, "UTF-8"); + } + } + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE, e.getMessage()); + } + } + + return result; + } + + /** + * Sign a message with the ed25519 fingerprint key for this account.
+ * The signed message is returned by the method. + * @param aMessage message to sign + * @return the signed message + */ + private native byte[] signMessageJni(byte[] aMessage); + + //============================================================================================================== + // Serialization management + //============================================================================================================== + + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception + */ + private void writeObject(ObjectOutputStream aOutStream) throws IOException { + serialize(aOutStream); + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws Exception exception + */ + private void readObject(ObjectInputStream aInStream) throws Exception { + deserialize(aInStream); + } + + /** + * Return an account as a bytes buffer.
+ * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return the account as bytes buffer + */ + @Override + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); + } else if (null == aKey) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + try { + pickleRetValue = serializeJni(aKey); + } catch (Exception e) { + Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } + } + + return pickleRetValue; + } + + /** + * Serialize and encrypt account instance.
+ * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ + private native byte[] serializeJni(byte[] aKeyBuffer); + + /** + * Loads an account from a pickled bytes buffer.
+ * See {@link #serialize(byte[], StringBuffer)} + * @param aSerializedData bytes buffer + * @param aKey key used to encrypted + * @exception Exception the exception + */ + @Override + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + String errorMsg = null; + + try { + if ((null == aSerializedData) || (null == aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg = "invalid input parameters"; + } else { + mNativeId = deserializeJni(aSerializedData, aKey); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg = e.getMessage(); + } + + if (!TextUtils.isEmpty(errorMsg)) { + releaseAccount(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); + } + } + + /** + * Allocate a new account and initialize it with the serialisation data.
+ * @param aSerializedDataBuffer the account serialisation buffer + * @param aKeyBuffer the key used to encrypt the serialized account data + * @return the deserialized account + **/ + private native long deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); +} diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java new file mode 100644 index 0000000..b0b1a6a --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -0,0 +1,85 @@ +/* + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import java.io.IOException; + +/** + * Exception class to identify specific Olm SDK exceptions. + */ +public class OlmException extends IOException { + // exception codes + + public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 10; + + public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 100; + public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 101; + public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 102; + public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 103; + public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 104; + public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 105; + public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 106; + public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 107; + + public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 200; + public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 201; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER = 202; + public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION = 203; + + public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 300; + public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 301; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 302; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 303; + public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 304; + + public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 400; + public static final int EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION = 401; + public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION = 402; + public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM = 403; + public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 404; + public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405; + public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406; + + public static final int EXCEPTION_CODE_UTILITY_CREATION = 500; + public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 501; + + // exception human readable messages + public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters"; + + /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION}, + * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}..**/ + private final int mCode; + + /** Human readable message description **/ + private final String mMessage; + + public OlmException(int aExceptionCode, String aExceptionMessage) { + super(); + mCode = aExceptionCode; + mMessage = aExceptionMessage; + } + + public int getExceptionCode() { + return mCode; + } + + @Override + public String getMessage() { + return mMessage; + } +} diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java new file mode 100644 index 0000000..571bddb --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -0,0 +1,260 @@ +/* + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.text.TextUtils; +import android.util.Log; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * Class used to create an inbound Megolm session.
+ * Counter part of the outbound group session {@link OlmOutboundGroupSession}, this class decrypts the messages sent by the outbound side. + * + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ +public class OlmInboundGroupSession extends CommonSerializeUtils implements Serializable { + private static final long serialVersionUID = -772028491251653253L; + private static final String LOG_TAG = "OlmInboundGroupSession"; + + /** Session Id returned by JNI.
+ * This value uniquely identifies the native inbound group session instance. + */ + private transient long mNativeId; + + /** + * Result in {@link #decryptMessage(String)} + */ + public static class DecryptMessageResult { + /** decrypt message **/ + public String mDecryptedMessage; + + /** decrypt index **/ + public long mIndex; + } + + /** + * Constructor.
+ * Create and save a new native session instance ID and start a new inbound group session. + * The session key parameter is retrieved from an outbound group session. + * @param aSessionKey session key + * @throws OlmException constructor failure + */ + public OlmInboundGroupSession(String aSessionKey) throws OlmException { + if (TextUtils.isEmpty(aSessionKey)) { + Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); + } else { + try { + mNativeId = createNewSessionJni(aSessionKey.getBytes("UTF-8")); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); + } + } + } + + /** + * Initialize a new inbound group session and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmInboundGroupSession* to jlong) platform independent. + * @param aSessionKeyBuffer session key from an outbound session + * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. + **/ + private native long createNewSessionJni(byte[] aSessionKeyBuffer); + + /** + * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}. + */ + public void releaseSession(){ + if (0 != mNativeId) { + releaseSessionJni(); + } + mNativeId = 0; + } + + /** + * Destroy the corresponding OLM inbound group session native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #createNewSessionJni(byte[])}. + */ + private native void releaseSessionJni(); + + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + + /** + * Retrieve the base64-encoded identifier for this inbound group session. + * @return the session ID + * @throws OlmException the failure reason + */ + public String sessionIdentifier() throws OlmException { + try { + return new String(sessionIdentifierJni(), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER, e.getMessage()); + } + } + + /** + * Get a base64-encoded identifier for this inbound group session. + * An exception is thrown if the operation fails. + * @return the base64-encoded identifier + */ + private native byte[] sessionIdentifierJni(); + + /** + * Decrypt the message passed in parameter.
+ * 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 + */ + public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws OlmException { + DecryptMessageResult result = new DecryptMessageResult(); + + try { + byte[] decryptedMessageBuffer = decryptMessageJni(aEncryptedMsg.getBytes("UTF-8"), result); + + if (null != decryptedMessageBuffer) { + result.mDecryptedMessage = new String(decryptedMessageBuffer, "UTF-8"); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION, e.getMessage()); + } + + return result; + } + + /** + * Decrypt a message. + * An exception is thrown if the operation fails. + * @param aEncryptedMsg the encrypted message + * @param aDecryptMessageResult the decryptMessage informaton + * @return the decrypted message + */ + private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult); + + //============================================================================================================== + // Serialization management + //============================================================================================================== + + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception + */ + private void writeObject(ObjectOutputStream aOutStream) throws IOException { + serialize(aOutStream); + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws Exception exception + */ + private void readObject(ObjectInputStream aInStream) throws Exception { + deserialize(aInStream); + } + + /** + * Return the current inbound group session as a bytes buffer.
+ * The session is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled bytes buffer if operation succeed, null otherwise + */ + @Override + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); + aErrorMsg.append("aErrorMsg=null"); + } else if (null == aKey) { + aErrorMsg.append("Invalid input parameters in serialize()"); + } else { + aErrorMsg.setLength(0); + try { + pickleRetValue = serializeJni(aKey); + } catch (Exception e) { + Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } + } + + return pickleRetValue; + } + /** + * JNI counter part of {@link #serialize(byte[], StringBuffer)}. + * @param aKey encryption key + * @return the serialized session + */ + private native byte[] serializeJni(byte[] aKey); + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serialize(byte[], StringBuffer)} + * @param aSerializedData pickled account in a bytes buffer + * @param aKey key used to encrypted + */ + @Override + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + String errorMsg = null; + + try { + if ((null == aSerializedData) || (null == aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg = "invalid input parameters"; + } else { + mNativeId = deserializeJni(aSerializedData, aKey); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg = e.getMessage(); + } + + if (!TextUtils.isEmpty(errorMsg)) { + releaseSession(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); + } + } + + /** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); +} diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java new file mode 100644 index 0000000..c1e6031 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java @@ -0,0 +1,64 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.content.Context; +import android.util.Log; + +/** + * Olm SDK entry point class.
An OlmManager instance must be created at first to enable native library load. + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ +public class OlmManager { + private static final String LOG_TAG = "OlmManager"; + + /** + * Constructor. + */ + public OlmManager() { + } + + static { + try { + java.lang.System.loadLibrary("olm"); + } catch(UnsatisfiedLinkError e) { + Log.e(LOG_TAG,"Exception loadLibrary() - Msg="+e.getMessage()); + } + } + + /** + * Provide the android library version + * @param context the context + * @return the library version + */ + public String getSdkOlmVersion(Context context) { + String gitVersion = context.getResources().getString(R.string.git_olm_revision); + String date = context.getResources().getString(R.string.git_olm_revision_date); + return gitVersion + "-" + date; + } + + /** + * Get the OLM lib version. + * @return the lib version as a string + */ + public String getOlmLibVersion(){ + return getOlmLibVersionJni(); + } + public native String getOlmLibVersionJni(); +} + diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java new file mode 100644 index 0000000..08db993 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java @@ -0,0 +1,36 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +/** + * Message class used in Olm sessions to contain the encrypted data.
+ * See {@link OlmSession#decryptMessage(OlmMessage)} and {@link OlmSession#encryptMessage(String)}. + *
Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ +public class OlmMessage { + /** PRE KEY message type (used to establish new Olm session) **/ + public final static int MESSAGE_TYPE_PRE_KEY = 0; + /** normal message type **/ + public final static int MESSAGE_TYPE_MESSAGE = 1; + + /** the encrypted message **/ + public String mCipherText; + + /** defined by {@link #MESSAGE_TYPE_MESSAGE} or {@link #MESSAGE_TYPE_PRE_KEY}**/ + public long mType; +} diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java new file mode 100644 index 0000000..0481824 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -0,0 +1,289 @@ +/* + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + + +import android.text.TextUtils; +import android.util.Log; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * Class used to create an outbound a Megolm session.
+ * To send a first message in an encrypted room, the client should start a new outbound Megolm session. + * The session ID and the session key must be shared with each device in the room within. + * + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ +public class OlmOutboundGroupSession extends CommonSerializeUtils implements Serializable { + private static final long serialVersionUID = -3133097431283604416L; + private static final String LOG_TAG = "OlmOutboundGroupSession"; + + /** Session Id returned by JNI.
+ * This value uniquely identifies the native outbound group session instance. + */ + private transient long mNativeId; + + /** + * Constructor.
+ * Create and save a new session native instance ID and + * initialise a new outbound group session.
+ * @throws OlmException constructor failure + */ + public OlmOutboundGroupSession() throws OlmException { + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, e.getMessage()); + } + } + + /** + * Create the corresponding OLM outbound group session in native side.
+ * An exception is thrown if the operation fails. + * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native session instance identifier (see {@link #mNativeId}) + */ + private native long createNewSessionJni(); + + /** + * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}. + */ + public void releaseSession() { + if (0 != mNativeId) { + releaseSessionJni(); + } + mNativeId = 0; + } + + /** + * Destroy the corresponding OLM outbound group session native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #createNewSessionJni()}. + */ + private native void releaseSessionJni(); + + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + + /** + * Get a base64-encoded identifier for this session. + * @return session identifier + * @throws OlmException the failure reason + */ + public String sessionIdentifier() throws OlmException { + try { + return new String(sessionIdentifierJni(), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER, e.getMessage()); + } + } + + /** + * Return the session identifier. + * An exception is thrown if the operation fails. + * @return the session identifier + */ + private native byte[] sessionIdentifierJni(); + + /** + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * @return current session index + */ + public int messageIndex() { + return messageIndexJni(); + } + + /** + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * An exception is thrown if the operation fails. + * @return current session index + */ + private native int messageIndexJni(); + + /** + * Get the base64-encoded current ratchet key for this session.
+ * Each message is sent with a different ratchet key. This method returns the + * ratchet key that will be used for the next message. + * @return outbound session key + * @exception OlmException the failure reason + */ + public String sessionKey() throws OlmException { + try { + return new String(sessionKeyJni(), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionKey() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY, e.getMessage()); + } + } + + /** + * Return the session key. + * An exception is thrown if the operation fails. + * @return the session key + */ + private native byte[] sessionKeyJni(); + + /** + * Encrypt some plain-text message.
+ * The message given as parameter is encrypted and returned as the return value. + * @param aClearMsg message to be encrypted + * @return the encrypted message + * @exception OlmException the encryption failure reason + */ + public String encryptMessage(String aClearMsg) throws OlmException { + String retValue = null; + + if (!TextUtils.isEmpty(aClearMsg)) { + try { + byte[] encryptedBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8")); + + if (null != encryptedBuffer) { + retValue = new String(encryptedBuffer , "UTF-8"); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## encryptMessage() failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE, e.getMessage()); + } + } + + return retValue; + } + + /** + * Encrypt a bytes buffer messages. + * An exception is thrown if the operation fails. + * @param aClearMsgBuffer the message to encode + * @return the encoded message + */ + private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); + + //============================================================================================================== + // Serialization management + //============================================================================================================== + + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception + */ + private void writeObject(ObjectOutputStream aOutStream) throws IOException { + serialize(aOutStream); + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws Exception exception + */ + private void readObject(ObjectInputStream aInStream) throws Exception { + deserialize(aInStream); + } + + /** + * Return the current outbound group session as a base64 byte buffers.
+ * The session is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 bytes buffer if operation succeed, null otherwise + */ + @Override + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); + } else if (null == aKey) { + aErrorMsg.append("Invalid input parameters in serialize()"); + } else { + try { + pickleRetValue = serializeJni(aKey); + } catch (Exception e) { + Log.e(LOG_TAG,"## serialize(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } + } + + return pickleRetValue; + } + + /** + * JNI counter part of {@link #serialize(byte[], StringBuffer)}. + * An exception is thrown if the operation fails. + * @param aKey encryption key + * @return the serialized session + */ + private native byte[] serializeJni(byte[] aKey); + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serialize(byte[], StringBuffer)} + * @param aSerializedData pickled account in a base64 bytes buffer + * @param aKey key used to encrypted + * @exception Exception the exception + */ + @Override + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + String errorMsg = null; + + try { + if ((null == aSerializedData) || (null == aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg = "invalid input parameters"; + } else { + mNativeId = deserializeJni(aSerializedData, aKey); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg = e.getMessage(); + } + + if (!TextUtils.isEmpty(errorMsg)) { + releaseSession(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); + } + } + + /** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); + +} diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java new file mode 100644 index 0000000..da2e963 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java @@ -0,0 +1,445 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.text.TextUtils; +import android.util.Log; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.Serializable; + +/** + * Session class used to create Olm sessions in conjunction with {@link OlmAccount} class.
+ * Olm session is used to encrypt data between devices, especially to create Olm group sessions (see {@link OlmOutboundGroupSession} and {@link OlmInboundGroupSession}).
+ * To establish an Olm session with Bob, Alice calls {@link #initOutboundSession(OlmAccount, String, String)} with Bob's identity and onetime keys. Then Alice generates an encrypted PRE_KEY message ({@link #encryptMessage(String)}) + * used by Bob to open the Olm session in his side with {@link #initOutboundSession(OlmAccount, String, String)}. + * From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}. + *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. + */ +public class OlmSession extends CommonSerializeUtils implements Serializable { + private static final long serialVersionUID = -8975488639186976419L; + private static final String LOG_TAG = "OlmSession"; + + /** Session Id returned by JNI. + * This value uniquely identifies the native session instance. + **/ + private transient long mNativeId; + + public OlmSession() throws OlmException { + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, e.getMessage()); + } + } + + /** + * Create an OLM session in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native account instance identifier or throw an exception. + */ + private native long createNewSessionJni(); + + /** + * Getter on the session ID. + * @return native session ID + */ + long getOlmSessionId(){ + return mNativeId; + } + + /** + * Destroy the corresponding OLM session native object.
+ * This method must ALWAYS be called when this JAVA instance + * is destroyed (ie. garbage collected) to prevent memory leak in native side. + * See {@link #createNewSessionJni()}. + */ + private native void releaseSessionJni(); + + /** + * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}. + */ + public void releaseSession() { + if (0 != mNativeId) { + releaseSessionJni(); + } + mNativeId = 0; + } + + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + + /** + * Creates a new out-bound session for sending messages to a recipient + * identified by an identity key and a one time key.
+ * @param aAccount the account to associate with this session + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient + * @exception OlmException the failure reason + */ + public void initOutboundSession(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) throws OlmException { + if ((null == aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)) { + Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, "invalid input parameters"); + } else { + try { + initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## initOutboundSession(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, e.getMessage()); + } + } + } + + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
The recipient is defined as the entity + * with whom the session is established. + * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient + **/ + private native void initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey); + + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message ({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}).
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aAccount the account to associate with this session + * @param aPreKeyMsg PRE KEY message + * @exception OlmException the failure reason + */ + public void initInboundSession(OlmAccount aAccount, String aPreKeyMsg) throws OlmException { + if ((null == aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ + Log.e(LOG_TAG, "## initInboundSession(): invalid input parameters"); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, "invalid input parameters"); + } else { + try { + initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## initInboundSession(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, e.getMessage()); + } + } + } + + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aOneTimeKeyMsg PRE_KEY message + */ + private native void initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg); + + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message based on the sender identity key.
+ * Public API for {@link #initInboundSessionFromIdKeyJni(long, byte[], byte[])}. + * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * This method must only be called the first time a pre-key message is received from an inbound session. + * @param aAccount the account to associate with this session + * @param aTheirIdentityKey the sender identity key + * @param aPreKeyMsg PRE KEY message + * @exception OlmException the failure reason + */ + public void initInboundSessionFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) throws OlmException { + if ( (null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ + Log.e(LOG_TAG, "## initInboundSessionFrom(): invalid input parameters"); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, "invalid input parameters"); + } else { + try { + initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## initInboundSessionFrom(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, e.getMessage()); + } + } + } + + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message based on the recipient identity key.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aOneTimeKeyMsg encrypted message + */ + private native void initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); + + /** + * Get the session identifier.
Will be the same for both ends of the + * conversation. The session identifier is returned as a String object. + * Session Id sample: "session_id":"M4fOVwD6AABrkTKl" + * Public API for {@link #getSessionIdentifierJni()}. + * @return the session ID + * @exception OlmException the failure reason + */ + public String sessionIdentifier() throws OlmException { + try { + byte[] buffer = getSessionIdentifierJni(); + + if (null != buffer) { + return new String(buffer, "UTF-8"); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## sessionIdentifier(): " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER, e.getMessage()); + } + + return null; + } + + /** + * Get the session identifier for this session. + * An exception is thrown if the operation fails. + * @return the session identifier + */ + private native byte[] getSessionIdentifierJni(); + + /** + * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * Public API for {@link #matchesInboundSessionJni(byte[])}. + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the one time key matches. + */ + public boolean matchesInboundSession(String aOneTimeKeyMsg) { + boolean retCode = false; + + try { + retCode = matchesInboundSessionJni(aOneTimeKeyMsg.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## matchesInboundSession(): failed " + e.getMessage()); + } + + return retCode; + } + + /** + * Checks if the PRE_KEY message is for this in-bound session.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * An exception is thrown if the operation fails. + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches + */ + private native boolean matchesInboundSessionJni(byte[] aOneTimeKeyMsg); + + /** + * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session based on the sender identity key.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * Public API for {@link #matchesInboundSessionJni(byte[])}. + * @param aTheirIdentityKey the sender identity key + * @param aOneTimeKeyMsg PRE KEY message + * @return this if operation succeed, null otherwise + */ + public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) { + boolean retCode = false; + + try { + retCode = matchesInboundSessionFromIdKeyJni(aTheirIdentityKey.getBytes("UTF-8"), aOneTimeKeyMsg.getBytes("UTF-8")); + } catch (Exception e) { + Log.e(LOG_TAG, "## matchesInboundSessionFrom(): failed " + e.getMessage()); + } + + return retCode; + } + + /** + * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * An exception is thrown if the operation fails. + * @param aTheirIdentityKey the identity key of the sender + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches. + */ + private native boolean matchesInboundSessionFromIdKeyJni(byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); + + /** + * Encrypt a message using the session.
+ * The encrypted message is returned in a OlmMessage object. + * Public API for {@link #encryptMessageJni(byte[], OlmMessage)}. + * @param aClearMsg message to encrypted + * @return the encrypted message + * @exception OlmException the failure reason + */ + public OlmMessage encryptMessage(String aClearMsg) throws OlmException { + if (null == aClearMsg) { + return null; + } + + OlmMessage encryptedMsgRetValue = new OlmMessage(); + + try { + byte[] encryptedMessageBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue); + + if (null != encryptedMessageBuffer) { + encryptedMsgRetValue.mCipherText = new String(encryptedMessageBuffer, "UTF-8"); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## encryptMessage(): failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE, e.getMessage()); + } + + return encryptedMsgRetValue; + } + + /** + * Encrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aClearMsg clear text message + * @param aEncryptedMsg ciphered message + * @return the encrypted message + */ + private native byte[] encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); + + /** + * Decrypt a message using the session.
+ * The encrypted message is given as a OlmMessage object. + * @param aEncryptedMsg message to decrypt + * @return the decrypted message + * @exception OlmException the failure reason + */ + public String decryptMessage(OlmMessage aEncryptedMsg) throws OlmException { + if (null == aEncryptedMsg) { + return null; + } + + try { + return new String(decryptMessageJni(aEncryptedMsg), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## decryptMessage(): failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage()); + } + } + /** + * Decrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aEncryptedMsg message to decrypt + * @return the decrypted message + */ + private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg); + + //============================================================================================================== + // Serialization management + //============================================================================================================== + + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException exception + */ + private void writeObject(ObjectOutputStream aOutStream) throws IOException { + serialize(aOutStream); + } + + /** + * Kick off the deserialization mechanism. + * @param aInStream input stream + * @throws IOException exception + * @throws ClassNotFoundException exception + */ + private void readObject(ObjectInputStream aInStream) throws Exception { + deserialize(aInStream); + } + + /** + * Return a session as a bytes buffer.
+ * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return session as a bytes buffer + */ + @Override + protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { + byte[] pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + } else if (null == aKey) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + try { + pickleRetValue = serializeJni(aKey); + } catch (Exception e) { + Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); + aErrorMsg.append(e.getMessage()); + } + } + + return pickleRetValue; + } + + /** + * Serialize and encrypt session instance.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ + private native byte[] serializeJni(byte[] aKeyBuffer); + + /** + * Loads an account from a pickled base64 string.
+ * See {@link #serialize(byte[], StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + */ + @Override + protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { + String errorMsg = null; + + try { + if ((null == aSerializedData) || (null == aKey)) { + Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); + errorMsg = "invalid input parameters"; + } else { + mNativeId = deserializeJni(aSerializedData, aKey); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); + errorMsg = e.getMessage(); + } + + if (!TextUtils.isEmpty(errorMsg)) { + releaseSession(); + throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); + } + } + /** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); +} + diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java new file mode 100644 index 0000000..bf9ef90 --- /dev/null +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -0,0 +1,227 @@ +/* + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.matrix.olm; + +import android.text.TextUtils; +import android.util.Log; + +import org.json.JSONObject; + +import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Olm SDK helper class. + */ +public class OlmUtility { + private static final String LOG_TAG = "OlmUtility"; + + public static final int RANDOM_KEY_SIZE = 32; + + /** Instance Id returned by JNI. + * This value uniquely identifies this utility instance. + **/ + private long mNativeId; + + public OlmUtility() throws OlmException { + initUtility(); + } + + /** + * Create a native utility instance. + * To be called before any other API call. + * @exception OlmException the exception + */ + private void initUtility() throws OlmException { + try { + mNativeId = createUtilityJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_UTILITY_CREATION, e.getMessage()); + } + } + + private native long createUtilityJni(); + + /** + * Release native instance.
+ * Public API for {@link #releaseUtilityJni()}. + */ + public void releaseUtility() { + if (0 != mNativeId) { + releaseUtilityJni(); + } + mNativeId = 0; + } + private native void releaseUtilityJni(); + + /** + * Verify an ed25519 signature.
+ * An exception is thrown if the operation fails. + * @param aSignature the base64-encoded message signature to be checked. + * @param aFingerprintKey the ed25519 key (fingerprint key) + * @param aMessage the signed message + * @exception OlmException the failure reason + */ + public void verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage) throws OlmException { + String errorMessage; + + try { + if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); + errorMessage = "JAVA sanity check failure - invalid input parameters"; + } else { + errorMessage = verifyEd25519SignatureJni(aSignature.getBytes("UTF-8"), aFingerprintKey.getBytes("UTF-8"), aMessage.getBytes("UTF-8")); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## verifyEd25519Signature(): failed " + e.getMessage()); + errorMessage = e.getMessage(); + } + + if (!TextUtils.isEmpty(errorMessage)) { + throw new OlmException(OlmException.EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE, errorMessage); + } + } + + /** + * Verify an ed25519 signature. + * Return a human readable error message in case of verification failure. + * @param aSignature the base64-encoded message signature to be checked. + * @param aFingerprintKey the ed25519 key + * @param aMessage the signed message + * @return null if validation succeed, the error message string if operation failed + */ + private native String verifyEd25519SignatureJni(byte[] aSignature, byte[] aFingerprintKey, byte[] aMessage); + + /** + * Compute the hash(SHA-256) value of the string given in parameter(aMessageToHash).
+ * The hash value is the returned by the method. + * @param aMessageToHash message to be hashed + * @return hash value if operation succeed, null otherwise + */ + public String sha256(String aMessageToHash) { + String hashRetValue = null; + + if (null != aMessageToHash) { + try { + hashRetValue = new String(sha256Jni(aMessageToHash.getBytes("UTF-8")), "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## sha256(): failed " + e.getMessage()); + } + } + + return hashRetValue; + } + + /** + * Compute the digest (SHA 256) for the message passed in parameter.
+ * The digest value is the function return value. + * An exception is thrown if the operation fails. + * @param aMessage the message + * @return digest of the message. + **/ + private native byte[] sha256Jni(byte[] aMessage); + + /** + * Helper method to compute a string based on random integers. + * @return bytes buffer containing randoms integer values + */ + public static byte[] getRandomKey() { + SecureRandom secureRandom = new SecureRandom(); + byte[] buffer = new byte[RANDOM_KEY_SIZE]; + secureRandom.nextBytes(buffer); + + // the key is saved as string + // so avoid the UTF8 marker bytes + for(int i = 0; i < RANDOM_KEY_SIZE; i++) { + buffer[i] = (byte)(buffer[i] & 0x7F); + } + return buffer; + } + + /** + * Return true the object resources have been released.
+ * @return true the object resources have been released + */ + public boolean isReleased() { + return (0 == mNativeId); + } + + /** + * Build a string-string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + public static Map toStringMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap map = new HashMap<>(); + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof String) { + map.put(key, (String) value); + } else { + Log.e(LOG_TAG, "## toStringMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } + + /** + * Build a string-string dictionary of string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + public static Map> toStringMapMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap> map = new HashMap<>(); + + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof JSONObject) { + map.put(key, toStringMap((JSONObject) value)); + } else { + Log.e(LOG_TAG, "## toStringMapMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMapMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } +} + diff --git a/android/olm-sdk/src/main/jni/Android.mk b/android/olm-sdk/src/main/jni/Android.mk new file mode 100644 index 0000000..97d747c --- /dev/null +++ b/android/olm-sdk/src/main/jni/Android.mk @@ -0,0 +1,59 @@ +LOCAL_PATH := $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_MODULE := olm +MAJOR := 2 +MINOR := 0 +PATCH := 0 +OLM_VERSION := $(MAJOR).$(MINOR).$(PATCH) +SRC_ROOT_DIR := ../../../../.. + +$(info LOCAL_PATH=$(LOCAL_PATH)) +$(info SRC_ROOT_DIR=$(SRC_ROOT_DIR)) +$(info OLM_VERSION=$(OLM_VERSION)) + +LOCAL_CPPFLAGS+= -std=c++11 -Wall +LOCAL_CONLYFLAGS+= -std=c99 +LOCAL_CFLAGS+= -DOLMLIB_VERSION_MAJOR=$(MAJOR) \ +-DOLMLIB_VERSION_MINOR=$(MINOR) \ +-DOLMLIB_VERSION_PATCH=$(PATCH) + +#LOCAL_CFLAGS+= -DNDK_DEBUG + +LOCAL_C_INCLUDES+= $(LOCAL_PATH)/$(SRC_ROOT_DIR)/include/ \ +$(LOCAL_PATH)/$(SRC_ROOT_DIR)/lib + +$(info LOCAL_C_INCLUDES=$(LOCAL_C_INCLUDES)) + +LOCAL_SRC_FILES := $(SRC_ROOT_DIR)/src/account.cpp \ +$(SRC_ROOT_DIR)/src/base64.cpp \ +$(SRC_ROOT_DIR)/src/cipher.cpp \ +$(SRC_ROOT_DIR)/src/crypto.cpp \ +$(SRC_ROOT_DIR)/src/memory.cpp \ +$(SRC_ROOT_DIR)/src/message.cpp \ +$(SRC_ROOT_DIR)/src/olm.cpp \ +$(SRC_ROOT_DIR)/src/pickle.cpp \ +$(SRC_ROOT_DIR)/src/ratchet.cpp \ +$(SRC_ROOT_DIR)/src/session.cpp \ +$(SRC_ROOT_DIR)/src/utility.cpp \ +$(SRC_ROOT_DIR)/src/ed25519.c \ +$(SRC_ROOT_DIR)/src/error.c \ +$(SRC_ROOT_DIR)/src/inbound_group_session.c \ +$(SRC_ROOT_DIR)/src/megolm.c \ +$(SRC_ROOT_DIR)/src/outbound_group_session.c \ +$(SRC_ROOT_DIR)/src/pickle_encoding.c \ +$(SRC_ROOT_DIR)/lib/crypto-algorithms/sha256.c \ +$(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \ +$(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \ +olm_account.cpp \ +olm_session.cpp \ +olm_jni_helper.cpp \ +olm_inbound_group_session.cpp \ +olm_outbound_group_session.cpp \ +olm_utility.cpp \ +olm_manager.cpp + +LOCAL_LDLIBS := -llog + +include $(BUILD_SHARED_LIBRARY) + diff --git a/android/olm-sdk/src/main/jni/Application.mk b/android/olm-sdk/src/main/jni/Application.mk new file mode 100644 index 0000000..6516f5e --- /dev/null +++ b/android/olm-sdk/src/main/jni/Application.mk @@ -0,0 +1,3 @@ +APP_PLATFORM := android-16 +APP_ABI := arm64-v8a armeabi-v7a armeabi x86_64 x86 +APP_STL := gnustl_static \ No newline at end of file diff --git a/android/olm-sdk/src/main/jni/olm_account.cpp b/android/olm-sdk/src/main/jni/olm_account.cpp new file mode 100644 index 0000000..40081ac --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_account.cpp @@ -0,0 +1,687 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_account.h" + +using namespace AndroidOlmSdk; + +/** + * Init memory allocation for account creation. + * @return valid memory allocation, NULL otherwise + **/ +OlmAccount* initializeAccountMemory() +{ + size_t accountSize = olm_account_size(); + OlmAccount* accountPtr = (OlmAccount*)malloc(accountSize); + + if (accountPtr) + { + // init account object + accountPtr = olm_account(accountPtr); + LOGD("## initializeAccountMemory(): success - OLM account size=%lu",static_cast(accountSize)); + } + else + { + LOGE("## initializeAccountMemory(): failure - OOM"); + } + + return accountPtr; +} + +/** + * Create a new account and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmAccount* => jlong) platform independent. + * @return the initialized OlmAccount* instance or throw an exception if fails + **/ +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) +{ + const char* errorMessage = NULL; + OlmAccount *accountPtr = initializeAccountMemory(); + + // init account memory allocation + if (!accountPtr) + { + LOGE("## initNewAccount(): failure - init account OOM"); + errorMessage = "init account OOM"; + } + else + { + // get random buffer size + size_t randomSize = olm_create_account_random_length(accountPtr); + + LOGD("## initNewAccount(): randomSize=%lu", static_cast(randomSize)); + + uint8_t *randomBuffPtr = NULL; + size_t accountRetCode; + + // allocate random buffer + if ((0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) + { + LOGE("## initNewAccount(): failure - random buffer init"); + errorMessage = "random buffer init"; + } + else + { + // create account + accountRetCode = olm_create_account(accountPtr, (void*)randomBuffPtr, randomSize); + + if (accountRetCode == olm_error()) + { + LOGE("## initNewAccount(): failure - account creation failed Msg=%s", olm_account_last_error(accountPtr)); + errorMessage = olm_account_last_error(accountPtr); + } + + LOGD("## initNewAccount(): success - OLM account created"); + LOGD("## initNewAccount(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); + } + + if (randomBuffPtr) + { + memset(randomBuffPtr, 0, randomSize); + free(randomBuffPtr); + } + } + + if (errorMessage) + { + // release the allocated data + if (accountPtr) + { + olm_clear_account(accountPtr); + free(accountPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)accountPtr; +} +/** + * Release the account allocation made by initializeAccountMemory().
+ * This method MUST be called when java counter part account instance is done. + */ +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## releaseAccountJni(): IN"); + + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); + + if (!accountPtr) + { + LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); + } + else + { + LOGD(" ## releaseAccountJni(): accountPtr=%p",accountPtr); + olm_clear_account(accountPtr); + + LOGD(" ## releaseAccountJni(): IN"); + // even if free(NULL) does not crash, logs are performed for debug purpose + free(accountPtr); + LOGD(" ## releaseAccountJni(): OUT"); + } +} + +// ********************************************************************* +// ************************* IDENTITY KEYS API ************************* +// ********************************************************************* + +/** + * Get identity keys: Ed25519 fingerprint key and Curve25519 identity key.
+ * The keys are returned in the byte array. + * @return the identity keys or throw an exception if it fails + **/ +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz) +{ + const char* errorMessage = NULL; + jbyteArray byteArrayRetValue = NULL; + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); + + if (!accountPtr) + { + LOGE("## identityKeys(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr"; + } + else + { + LOGD("## identityKeys(): accountPtr =%p", accountPtr); + + // identity keys allocation + size_t identityKeysLength = olm_account_identity_keys_length(accountPtr); + uint8_t *identityKeysBytesPtr = (uint8_t*)malloc(identityKeysLength); + + if (!identityKeysBytesPtr) + { + LOGE("## identityKeys(): failure - identity keys array OOM"); + errorMessage = "identity keys array OOM"; + } + else + { + // retrieve key pairs in identityKeysBytesPtr + size_t keysResult = olm_account_identity_keys(accountPtr, identityKeysBytesPtr, identityKeysLength); + + if (keysResult == olm_error()) + { + errorMessage = (const char *)olm_account_last_error(accountPtr); + LOGE("## identityKeys(): failure - error getting identity keys Msg=%s", errorMessage); + } + else + { + // allocate the byte array to be returned to java + byteArrayRetValue = env->NewByteArray(identityKeysLength); + + if (!byteArrayRetValue) + { + LOGE("## identityKeys(): failure - return byte array OOM"); + errorMessage = "byte array OOM"; + } + else + { + env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, identityKeysLength, (const jbyte*)identityKeysBytesPtr); + LOGD("## identityKeys(): success - result=%lu", static_cast(keysResult)); + } + } + + free(identityKeysBytesPtr); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return byteArrayRetValue; +} + +// ********************************************************************* +// ************************* ONE TIME KEYS API ************************* +// ********************************************************************* + +/** + * Get the public parts of the unpublished "one time keys" for the account.
+ * The returned data is a JSON-formatted object with the single property + * curve25519, which is itself an object mapping key id to + * base64-encoded Curve25519 key.
+ * @return byte array containing the one time keys or throw an exception if it fails + */ +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz) +{ + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); + size_t maxKeys = -1; + + if (!accountPtr) + { + LOGE("## maxOneTimeKey(): failure - invalid Account ptr=NULL"); + } + else + { + maxKeys = olm_account_max_number_of_one_time_keys(accountPtr); + } + + LOGD("## maxOneTimeKey(): Max keys=%lu", static_cast(maxKeys)); + + return (jlong)maxKeys; +} + +/** + * Generate "one time keys". + * An exception is thrown if the operation fails. + * @param aNumberOfKeys number of keys to generate + **/ +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) +{ + const char* errorMessage = NULL; + OlmAccount *accountPtr = getAccountInstanceId(env, thiz); + + if (!accountPtr) + { + LOGE("## generateOneTimeKeysJni(): failure - invalid Account ptr"); + errorMessage = "invalid Account ptr"; + } + else + { + // keys memory allocation + size_t randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); + LOGD("## generateOneTimeKeysJni(): randomLength=%lu", static_cast(randomLength)); + + uint8_t *randomBufferPtr = NULL; + + if ((0 != randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) + { + LOGE("## generateOneTimeKeysJni(): failure - random buffer init"); + errorMessage = "random buffer init"; + } + else + { + LOGD("## generateOneTimeKeysJni(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); + + // retrieve key pairs in keysBytesPtr + size_t result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); + + if (result == olm_error()) + { + errorMessage = olm_account_last_error(accountPtr); + LOGE("## generateOneTimeKeysJni(): failure - error generating one time keys Msg=%s", errorMessage); + } + else + { + LOGD("## generateOneTimeKeysJni(): success - result=%lu", static_cast(result)); + } + } + + + if (randomBufferPtr) + { + memset(randomBufferPtr, 0, randomLength); + free(randomBufferPtr); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } +} + +/** + * Get "one time keys".
+ * Return the public parts of the unpublished "one time keys" for the account + * @return a valid byte array if operation succeed, null otherwise + **/ +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz) +{ + const char* errorMessage = NULL; + jbyteArray byteArrayRetValue = NULL; + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); + + LOGD("## oneTimeKeysJni(): IN"); + + if (!accountPtr) + { + LOGE("## oneTimeKeysJni(): failure - invalid Account ptr"); + errorMessage = "invalid Account ptr"; + } + else + { + // keys memory allocation + size_t keysLength = olm_account_one_time_keys_length(accountPtr); + uint8_t *keysBytesPtr = (uint8_t *)malloc(keysLength*sizeof(uint8_t)); + + if (!keysBytesPtr) + { + LOGE("## oneTimeKeysJni(): failure - one time keys array OOM"); + errorMessage = "one time keys array OOM"; + } + else + { + // retrieve key pairs in keysBytesPtr + size_t keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); + + if (keysResult == olm_error()) { + LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); + } + else + { + // allocate the byte array to be returned to java + byteArrayRetValue = env->NewByteArray(keysLength); + + if (!byteArrayRetValue) + { + LOGE("## oneTimeKeysJni(): failure - return byte array OOM"); + errorMessage = "return byte array OOM"; + } + else + { + env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, keysLength, (const jbyte*)keysBytesPtr); + LOGD("## oneTimeKeysJni(): success"); + } + } + + free(keysBytesPtr); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return byteArrayRetValue; +} + +/** + * Remove the "one time keys" that the session used from the account. + * An exception is thrown if the operation fails. + * @param aNativeOlmSessionId session instance + **/ +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) +{ + const char* errorMessage = NULL; + OlmAccount* accountPtr = NULL; + OlmSession* sessionPtr = (OlmSession*)aNativeOlmSessionId; + + if (!sessionPtr) + { + LOGE("## removeOneTimeKeysJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; + } + else if (!(accountPtr = getAccountInstanceId(env, thiz))) + { + LOGE("## removeOneTimeKeysJni(): failure - invalid account ptr"); + errorMessage = "invalid account ptr"; + } + else + { + size_t result = olm_remove_one_time_keys(accountPtr, sessionPtr); + + if (result == olm_error()) + { // the account doesn't have any matching "one time keys".. + LOGW("## removeOneTimeKeysJni(): failure - removing one time keys Msg=%s", olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); + } + else + { + LOGD("## removeOneTimeKeysJni(): success"); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } +} + +/** + * Mark the current set of "one time keys" as being published. + * An exception is thrown if the operation fails. + **/ +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) +{ + const char* errorMessage = NULL; + OlmAccount* accountPtr = getAccountInstanceId(env, thiz); + + if (!accountPtr) + { + LOGE("## markOneTimeKeysAsPublishedJni(): failure - invalid account ptr"); + errorMessage = "invalid account ptr"; + } + else + { + size_t result = olm_account_mark_keys_as_published(accountPtr); + + if (result == olm_error()) + { + LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",(const char *)olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); + } + else + { + LOGD("## markOneTimeKeysAsPublishedJni(): success - retCode=%lu",static_cast(result)); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } +} + +/** + * Sign a message with the ed25519 key (fingerprint) for this account.
+ * The signed message is returned by the function. + * @param aMessage message to sign + * @return the signed message, null otherwise + **/ +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) +{ + const char* errorMessage = NULL; + OlmAccount* accountPtr = NULL; + jbyteArray signedMsgRetValueBuffer = NULL; + + if (!aMessage) + { + LOGE("## signMessageJni(): failure - invalid aMessage param"); + errorMessage = "invalid aMessage param"; + } + else if (!(accountPtr = getAccountInstanceId(env, thiz))) + { + LOGE("## signMessageJni(): failure - invalid account ptr"); + errorMessage = "invalid account ptr"; + } + else + { + int messageLength = env->GetArrayLength(aMessage); + jbyte* messageToSign = env->GetByteArrayElements(aMessage, NULL); + + // signature memory allocation + size_t signatureLength = olm_account_signature_length(accountPtr); + void* signedMsgPtr = malloc(signatureLength * sizeof(uint8_t)); + + if (!signedMsgPtr) + { + LOGE("## signMessageJni(): failure - signature allocation OOM"); + errorMessage = "signature allocation OOM"; + } + else + { + // sign message + size_t resultSign = olm_account_sign(accountPtr, + (void*)messageToSign, + (size_t)messageLength, + signedMsgPtr, + signatureLength); + + if (resultSign == olm_error()) + { + LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); + errorMessage = (const char *)olm_account_last_error(accountPtr); + } + else + { + LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); + + signedMsgRetValueBuffer = env->NewByteArray(signatureLength); + env->SetByteArrayRegion(signedMsgRetValueBuffer, 0 , signatureLength, (jbyte*)signedMsgPtr); + } + + free(signedMsgPtr); + } + + // release messageToSign + if (messageToSign) + { + env->ReleaseByteArrayElements(aMessage, messageToSign, JNI_ABORT); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return signedMsgRetValueBuffer; +} + +/** + * Serialize and encrypt account instance.
+ * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + jbyteArray pickledDataRetValue = 0; + jbyte* keyPtr = NULL; + OlmAccount* accountPtr = NULL; + + LOGD("## serializeJni(): IN"); + + if (!aKeyBuffer) + { + LOGE(" ## serializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!(accountPtr = getAccountInstanceId(env, thiz))) + { + LOGE(" ## serializeJni(): failure - invalid account ptr"); + errorMessage = "invalid account ptr"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, NULL))) + { + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; + } + else + { + size_t pickledLength = olm_pickle_account_length(accountPtr); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + + void* pickledPtr = malloc(pickledLength * sizeof(uint8_t)); + + if (!pickledPtr) + { + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; + } + else + { + size_t result = olm_pickle_account(accountPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_account_last_error(accountPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_account() Msg=%s", errorMessage); + } + else + { + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); + pickledDataRetValue = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength, (jbyte*)pickledPtr); + } + + free(pickledPtr); + } + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return pickledDataRetValue; +} + +/** + * Allocate a new account and initialise it with the serialisation data.
+ * @param aSerializedDataBuffer the account serialisation buffer + * @param aKeyBuffer the key used to encrypt the serialized account data + * @return the deserialised account + **/ +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + + OlmAccount* accountPtr = NULL; + + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; + + LOGD("## deserializeJni(): IN"); + + if (!aKeyBuffer) + { + LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!aSerializedDataBuffer) + { + LOGE(" ## deserializeJni(): failure - invalid serialized data"); + errorMessage = "invalid serialized data"; + } + else if (!(accountPtr = initializeAccountMemory())) + { + LOGE(" ## deserializeJni(): failure - account failure OOM"); + errorMessage = "account failure OOM"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; + } + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; + } + else + { + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): pickled=%.*s", static_cast (pickledLength), (char const *)pickledPtr); + + size_t result = olm_unpickle_account(accountPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_account_last_error(accountPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); + } + else + { + LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); + } + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (pickledPtr) + { + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); + } + + if (errorMessage) + { + if (accountPtr) + { + olm_clear_account(accountPtr); + free(accountPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)accountPtr; +} \ No newline at end of file diff --git a/android/olm-sdk/src/main/jni/olm_account.h b/android/olm-sdk/src/main/jni/olm_account.h new file mode 100644 index 0000000..42b2c2a --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_account.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLACCOUNT_H +#define _OMLACCOUNT_H + +#include "olm_jni.h" +#include "olm/olm.h" + +#define OLM_ACCOUNT_FUNC_DEF(func_name) FUNC_DEF(OlmAccount,func_name) +#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +// account creation/destruction +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz); + +// identity keys +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz); + +// one time keys +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); + +// signing +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); + +// serialization +JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp new file mode 100644 index 0000000..23910bb --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -0,0 +1,507 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_inbound_group_session.h" + +using namespace AndroidOlmSdk; + +/** + * Release the session allocation made by initializeInboundGroupSessionMemory().
+ * This method MUST be called when java counter part account instance is done. + */ +JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) +{ + OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env,thiz); + + LOGD("## releaseSessionJni(): InBound group session IN"); + + if (!sessionPtr) + { + LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); + } + else + { + LOGD(" ## releaseSessionJni(): sessionPtr=%p", sessionPtr); +#ifdef ENABLE_JNI_LOG + size_t retCode = olm_clear_inbound_group_session(sessionPtr); + LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); +#else + olm_clear_inbound_group_session(sessionPtr); +#endif + + LOGD(" ## releaseSessionJni(): free IN"); + free(sessionPtr); + LOGD(" ## releaseSessionJni(): free OUT"); + } +} + +/** + * Initialize a new inbound group session and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmInboundGroupSession* => jlong) platform independent. + * @param aSessionKeyBuffer session key from an outbound session + * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. + **/ +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) +{ + const char* errorMessage = NULL; + OlmInboundGroupSession* sessionPtr = NULL; + jbyte* sessionKeyPtr = NULL; + size_t sessionSize = olm_inbound_group_session_size(); + + LOGD("## createNewSessionJni(): inbound group session IN"); + + if (!sessionSize) + { + LOGE(" ## createNewSessionJni(): failure - inbound group session size = 0"); + errorMessage = "inbound group session size = 0"; + } + else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) + { + LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); + errorMessage = "inbound group session OOM"; + } + else if (!aSessionKeyBuffer) + { + LOGE(" ## createNewSessionJni(): failure - invalid aSessionKey"); + errorMessage = "invalid aSessionKey"; + } + else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) + { + LOGE(" ## createNewSessionJni(): failure - session key JNI allocation OOM"); + errorMessage = "Session key JNI allocation OOM"; + } + else + { + sessionPtr = olm_inbound_group_session(sessionPtr); + + size_t sessionKeyLength = (size_t)env->GetArrayLength(aSessionKeyBuffer); + LOGD(" ## createNewSessionJni(): sessionKeyLength=%lu", static_cast(sessionKeyLength)); + + size_t sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); + + if (sessionResult == olm_error()) + { + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## createNewSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); + } + else + { + LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); + } + } + + if (sessionKeyPtr) + { + env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + if (errorMessage) + { + // release the allocated session + if (sessionPtr) + { + olm_clear_inbound_group_session(sessionPtr); + free(sessionPtr); + } + + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; +} + +/** + * Get a base64-encoded identifier for this inbound group session. + * An exception is thrown if the operation fails. + * @return the base64-encoded identifier + */ +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +{ + const char* errorMessage = NULL; + OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); + jbyteArray returnValue = 0; + + LOGD("## sessionIdentifierJni(): inbound group session IN"); + + if (!sessionPtr) + { + LOGE(" ## sessionIdentifierJni(): failure - invalid inbound group session instance"); + errorMessage = "invalid inbound group session instance"; + } + else + { + // get the size to alloc + size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); + LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); + + uint8_t *sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)); + + if (!sessionIdPtr) + { + LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); + errorMessage = "inbound group session identifier allocation OOM"; + } + else + { + size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + + if (result == olm_error()) + { + errorMessage = (const char *)olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); + } + else + { + LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); + + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); + } + + free(sessionIdPtr); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + +/** + * Decrypt a message. + * An exception is thrown if the operation fails. + * @param aEncryptedMsg the encrypted message + * @param aDecryptMessageResult the decryptMessage information + * @return the decrypted message + */ +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult) +{ + jbyteArray decryptedMsgBuffer = 0; + const char* errorMessage = NULL; + + OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); + jbyte *encryptedMsgPtr = NULL; + jclass indexObjJClass = 0; + jfieldID indexMsgFieldId; + + LOGD("## decryptMessageJni(): inbound group session IN"); + + if (!sessionPtr) + { + LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); + errorMessage = "invalid inbound group session ptr=NULL"; + } + else if (!aEncryptedMsgBuffer) + { + LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); + errorMessage = "invalid encrypted message"; + } + else if (!aDecryptionResult) + { + LOGE(" ## decryptMessageJni(): failure - invalid index object"); + errorMessage = "invalid index object"; + } + else if (!(encryptedMsgPtr = env->GetByteArrayElements(aEncryptedMsgBuffer, 0))) + { + LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + errorMessage = "encrypted message JNI allocation OOM"; + } + else if (!(indexObjJClass = env->GetObjectClass(aDecryptionResult))) + { + LOGE("## decryptMessageJni(): failure - unable to get index class"); + errorMessage = "unable to get index class"; + } + else if (!(indexMsgFieldId = env->GetFieldID(indexObjJClass,"mIndex","J"))) + { + LOGE("## decryptMessageJni(): failure - unable to get index type field"); + errorMessage = "unable to get index type field"; + } + else + { + // get encrypted message length + size_t encryptedMsgLength = (size_t)env->GetArrayLength(aEncryptedMsgBuffer); + uint8_t *tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); + + // create a dedicated temp buffer to be used in next Olm API calls + if (!tempEncryptedPtr) + { + LOGE(" ## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); + errorMessage = "tempEncryptedPtr allocation OOM"; + } + else + { + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%.*s",static_cast(encryptedMsgLength), static_cast(encryptedMsgLength), encryptedMsgPtr); + + // get max plaintext length + size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, + tempEncryptedPtr, + encryptedMsgLength); + if (maxPlainTextLength == olm_error()) + { + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s", errorMessage); + } + else + { + LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); + + uint32_t messageIndex = 0; + + // allocate output decrypted message + uint8_t *plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); + + // decrypt, but before reload encrypted buffer (previous one was destroyed) + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + size_t plaintextLength = olm_group_decrypt(sessionPtr, + tempEncryptedPtr, + encryptedMsgLength, + plainTextMsgPtr, + maxPlainTextLength, + &messageIndex); + if (plaintextLength == olm_error()) + { + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s", errorMessage); + } + else + { + // update index + env->SetLongField(aDecryptionResult, indexMsgFieldId, (jlong)messageIndex); + + decryptedMsgBuffer = env->NewByteArray(plaintextLength); + env->SetByteArrayRegion(decryptedMsgBuffer, 0 , plaintextLength, (jbyte*)plainTextMsgPtr); + + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); + } + + if (plainTextMsgPtr) + { + memset(plainTextMsgPtr, 0, maxPlainTextLength*sizeof(uint8_t)); + free(plainTextMsgPtr); + } + } + + if (tempEncryptedPtr) + { + free(tempEncryptedPtr); + } + } + } + + // free alloc + if (encryptedMsgPtr) + { + env->ReleaseByteArrayElements(aEncryptedMsgBuffer, encryptedMsgPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return decryptedMsgBuffer; +} + + +/** + * Serialize and encrypt session instance into a base64 string.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized session data + * @return a base64 string if operation succeed, null otherwise + **/ +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + + jbyteArray pickledDataRet = 0; + jbyte* keyPtr = NULL; + OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env, thiz); + + LOGD("## inbound group session serializeJni(): IN"); + + if (!sessionPtr) + { + LOGE(" ## serializeJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; + } + else if (!aKeyBuffer) + { + LOGE(" ## serializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; + } + else + { + size_t pickledLength = olm_pickle_inbound_group_session_length(sessionPtr); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); + + void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); + + if (!pickledPtr) + { + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; + } + else + { + size_t result = olm_pickle_inbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s", errorMessage); + } + else + { + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); + + pickledDataRet = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(pickledDataRet, 0 , pickledLength, (jbyte*)pickledPtr); + } + + free(pickledPtr); + } + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return pickledDataRet; +} + +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + + OlmInboundGroupSession* sessionPtr = NULL; + size_t sessionSize = olm_inbound_group_session_size(); + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; + + LOGD("## deserializeJni(): IN"); + + if (!sessionSize) + { + LOGE(" ## deserializeJni(): failure - inbound group session size = 0"); + errorMessage = "inbound group session size = 0"; + } + else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) + { + LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; + } + else if (!aKeyBuffer) + { + LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!aSerializedDataBuffer) + { + LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "serialized data"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; + } + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; + } + else + { + sessionPtr = olm_inbound_group_session(sessionPtr); + + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): pickled=%.*s", static_cast(pickledLength), (char const *)pickledPtr); + + size_t result = olm_unpickle_inbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_inbound_group_session() Msg=%s", errorMessage); + } + else + { + LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); + } + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (pickledPtr) + { + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); + } + + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_inbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; +} diff --git a/android/olm-sdk/src/main/jni/olm_inbound_group_session.h b/android/olm-sdk/src/main/jni/olm_inbound_group_session.h new file mode 100644 index 0000000..00990dd --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_inbound_group_session.h @@ -0,0 +1,46 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLINBOUND_GROUP_SESSION_H +#define _OMLINBOUND_GROUP_SESSION_H + +#include "olm_jni.h" +#include "olm/olm.h" +#include "olm/inbound_group_session.h" + +#define OLM_INBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmInboundGroupSession,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +// session creation/destruction +JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); + +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex); + +// serialization +JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/android/olm-sdk/src/main/jni/olm_jni.h b/android/olm-sdk/src/main/jni/olm_jni.h new file mode 100644 index 0000000..e6a49e2 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_jni.h @@ -0,0 +1,78 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLJNI_H +#define _OMLJNI_H + +#include +#include +#include +#include +#include +#include + + +#define TAG "OlmJniNative" + +/* logging macros */ +//#define ENABLE_JNI_LOG + +#ifdef NDK_DEBUG + #warning NDK_DEBUG is defined! +#endif + +#ifdef ENABLE_JNI_LOG + #warning ENABLE_JNI_LOG is defined! +#endif + +#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) + +#ifdef ENABLE_JNI_LOG + #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) + #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) +#else + #define LOGD(...) + #define LOGW(...) +#endif + +#define FUNC_DEF(class_name,func_name) JNICALL Java_org_matrix_olm_##class_name##_##func_name + +namespace AndroidOlmSdk +{ + +} + + +#ifdef __cplusplus +extern "C" { +#endif + +// internal helper functions +bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize); + +struct OlmSession* getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmAccount* getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmInboundGroupSession* getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmOutboundGroupSession* getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); +struct OlmUtility* getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/android/olm-sdk/src/main/jni/olm_jni_helper.cpp b/android/olm-sdk/src/main/jni/olm_jni_helper.cpp new file mode 100644 index 0000000..a1f5c59 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -0,0 +1,214 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_jni_helper.h" +#include "olm/olm.h" +#include + +using namespace AndroidOlmSdk; + +/** +* Init a buffer with a given number of random values. +* @param aBuffer2Ptr the buffer to be initialized +* @param aRandomSize the number of random values to apply +* @return true if operation succeed, false otherwise +**/ +bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) +{ + bool retCode = false; + int bufferLen = aRandomSize*sizeof(uint8_t); + + if (!aBuffer2Ptr) + { + LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); + } + else if (!aRandomSize) + { + LOGE("## setRandomInBuffer(): failure - random size=0"); + } + else if (!(*aBuffer2Ptr = (uint8_t*)malloc(bufferLen))) + { + LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); + } + else + { + LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); + + // use the secureRandom class + jclass cls = env->FindClass("java/security/SecureRandom"); + + if (cls) + { + jobject newObj = 0; + jmethodID constructor = env->GetMethodID(cls, "", "()V"); + jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V"); + + if (constructor) + { + newObj = env->NewObject(cls, constructor); + jbyteArray tempByteArray = env->NewByteArray(bufferLen); + + if (newObj && tempByteArray) + { + env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); + + if (!env->ExceptionOccurred()) + { + jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); + + if (buffer) + { + memcpy(*aBuffer2Ptr, buffer, bufferLen); + retCode = true; + + // clear tempByteArray to hide sensitive data. + memset(buffer, 0, bufferLen); + env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer); + + // ensure that the buffer is released + env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT); + } + } + } + + if (tempByteArray) + { + env->DeleteLocalRef(tempByteArray); + } + + if (newObj) + { + env->DeleteLocalRef(newObj); + } + } + } + + // debug purpose + /*for(int i = 0; i < aRandomSize; i++) + { + LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]); + }*/ + } + + return retCode; +} + +/** +* Read the instance ID of the calling object. +* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @param aCallingClass java calling class name +* @return the related instance ID +**/ +jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass) +{ + jlong instanceId = 0; + + if (aJniEnv) + { + jclass requiredClass = aJniEnv->FindClass(aCallingClass); + jclass loaderClass = 0; + + if (requiredClass && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) + { + LOGE("## getInstanceId() failure - invalid instance of"); + } + else if ((loaderClass = aJniEnv->GetObjectClass(aJavaObject))) + { + jfieldID instanceIdField = aJniEnv->GetFieldID(loaderClass, "mNativeId", "J"); + + if (instanceIdField) + { + instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); + LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId); + } + else + { + LOGE("## getInstanceId() ERROR! GetFieldID=null"); + } + + aJniEnv->DeleteLocalRef(loaderClass); + } + else + { + LOGE("## getInstanceId() ERROR! GetObjectClass=null"); + } + } + else + { + LOGE("## getInstanceId() ERROR! aJniEnv=NULL"); + } + + LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); + + return instanceId; +} + +/** +* Read the account instance ID of the calling object. +* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the related OlmAccount. +**/ +struct OlmAccount* getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + return (struct OlmAccount*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT); +} + +/** +* Read the session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the related OlmSession. +**/ +struct OlmSession* getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + return (struct OlmSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION); +} + +/** +* Read the inbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the related OlmInboundGroupSession. +**/ +struct OlmInboundGroupSession* getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + return (struct OlmInboundGroupSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION); +} + +/** +* Read the outbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the related OlmOutboundGroupSession +**/ +struct OlmOutboundGroupSession* getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + return (struct OlmOutboundGroupSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION); +} + +/** +* Read the utility instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table +* @param aJavaObject reference to the object on which the method is invoked +* @return the related OlmUtility +**/ +struct OlmUtility* getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) +{ + return (struct OlmUtility*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); +} diff --git a/android/olm-sdk/src/main/jni/olm_jni_helper.h b/android/olm-sdk/src/main/jni/olm_jni_helper.h new file mode 100644 index 0000000..a181b32 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_jni_helper.h @@ -0,0 +1,28 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_jni.h" + +// constant strings +namespace AndroidOlmSdk +{ + static const char *CLASS_OLM_INBOUND_GROUP_SESSION = "org/matrix/olm/OlmInboundGroupSession"; + static const char *CLASS_OLM_OUTBOUND_GROUP_SESSION = "org/matrix/olm/OlmOutboundGroupSession"; + static const char *CLASS_OLM_SESSION = "org/matrix/olm/OlmSession"; + static const char *CLASS_OLM_ACCOUNT = "org/matrix/olm/OlmAccount"; + static const char *CLASS_OLM_UTILITY = "org/matrix/olm/OlmUtility"; +} diff --git a/android/olm-sdk/src/main/jni/olm_manager.cpp b/android/olm-sdk/src/main/jni/olm_manager.cpp new file mode 100644 index 0000000..8ee0df7 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_manager.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_manager.h" + +using namespace AndroidOlmSdk; + +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) +{ + uint8_t majorVer=0, minorVer=0, patchVer=0; + jstring returnValueStr=0; + char buff[150]; + + olm_get_library_version(&majorVer, &minorVer, &patchVer); + LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); + + snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); + returnValueStr = env->NewStringUTF((const char*)buff); + + return returnValueStr; +} \ No newline at end of file diff --git a/android/olm-sdk/src/main/jni/olm_manager.h b/android/olm-sdk/src/main/jni/olm_manager.h new file mode 100644 index 0000000..5fb6da2 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_manager.h @@ -0,0 +1,36 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLMANAGER_H +#define _OMLMANAGER_H + +#include "olm_jni.h" +#include "olm/olm.h" + +#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp new file mode 100644 index 0000000..a821709 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -0,0 +1,550 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_outbound_group_session.h" + +using namespace AndroidOlmSdk; + +/** + * Release the session allocation made by initializeOutboundGroupSessionMemory().
+ * This method MUST be called when java counter part account instance is done. + * + */ +JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## releaseSessionJni(): OutBound group session IN"); + + OlmOutboundGroupSession* sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); + + if (!sessionPtr) + { + LOGE(" ## releaseSessionJni(): failure - invalid outbound group session instance"); + } + else + { + LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); + +#ifdef ENABLE_JNI_LOG + size_t retCode = olm_clear_outbound_group_session(sessionPtr); + LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",static_cast(retCode)); +#else + olm_clear_outbound_group_session(sessionPtr); +#endif + + LOGD(" ## releaseSessionJni(): free IN"); + free(sessionPtr); + LOGD(" ## releaseSessionJni(): free OUT"); + } +} + +/** + * Initialize a new outbound group session and return it to JAVA side.
+ * Since a C prt is returned as a jlong, special care will be taken + * to make the cast (OlmOutboundGroupSession* => jlong) platform independent. + * @return the initialized OlmOutboundGroupSession* instance or throw an exception + **/ +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) +{ + const char* errorMessage = NULL; + + OlmOutboundGroupSession* sessionPtr = NULL; + size_t sessionSize = 0; + + LOGD("## createNewSessionJni(): outbound group session IN"); + sessionSize = olm_outbound_group_session_size(); + + if (0 == sessionSize) + { + LOGE(" ## createNewSessionJni(): failure - outbound group session size = 0"); + errorMessage = "outbound group session size = 0"; + } + else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) + { + LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); + errorMessage = "outbound group session OOM"; + } + else + { + sessionPtr = olm_outbound_group_session(sessionPtr); + LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); + + // compute random buffer + size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); + uint8_t *randomBuffPtr = NULL; + + LOGW(" ## createNewSessionJni(): randomLength=%lu",static_cast(randomLength)); + + if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) + { + LOGE(" ## createNewSessionJni(): failure - random buffer init"); + errorMessage = "random buffer init"; + } + else + { + if (0 == randomLength) + { + LOGW(" ## createNewSessionJni(): random buffer is not required"); + } + + size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); + + if (sessionResult == olm_error()) { + errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## createNewSessionJni(): failure - init outbound session creation Msg=%s", errorMessage); + } + else + { + LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); + } + + // clear the random buffer + memset(randomBuffPtr, 0, randomLength); + free(randomBuffPtr); + } + } + + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_outbound_group_session(sessionPtr); + free(sessionPtr); + } + + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; +} + +/** + * Return the session identifier. + * An exception is thrown if the operation fails. + * @return the session identifier + */ +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## sessionIdentifierJni(): outbound group session IN"); + + const char* errorMessage = NULL; + OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); + jbyteArray returnValue = 0; + + if (!sessionPtr) + { + LOGE(" ## sessionIdentifierJni(): failure - invalid outbound group session instance"); + errorMessage = "invalid outbound group session instance"; + } + else + { + // get the size to alloc + size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); + LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); + + uint8_t *sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)); + + if (!sessionIdPtr) + { + LOGE(" ## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); + errorMessage = "outbound identifier allocation OOM"; + } + else + { + size_t result = olm_outbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + + if (result == olm_error()) + { + errorMessage = reinterpret_cast(olm_outbound_group_session_last_error(sessionPtr)); + LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s", errorMessage); + } + else + { + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); + + LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId= %.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionIdPtr)); + } + + // free alloc + free(sessionIdPtr); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + + +/** + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * An exception is thrown if the operation fails. + * @return current session index + */ +JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz) +{ + OlmOutboundGroupSession *sessionPtr = NULL; + jint indexRetValue = 0; + + LOGD("## messageIndexJni(): IN"); + + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE(" ## messageIndexJni(): failure - invalid outbound group session instance"); + } + else + { + indexRetValue = static_cast(olm_outbound_group_session_message_index(sessionPtr)); + } + + LOGD(" ## messageIndexJni(): success - index=%d",indexRetValue); + + return indexRetValue; +} + +/** + * Return the session key. + * An exception is thrown if the operation fails. + * @return the session key + */ +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## sessionKeyJni(): outbound group session IN"); + + const char* errorMessage = NULL; + OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); + jbyteArray returnValue = 0; + + if (!sessionPtr) + { + LOGE(" ## sessionKeyJni(): failure - invalid outbound group session instance"); + errorMessage = "invalid outbound group session instance"; + } + else + { + // get the size to alloc + size_t sessionKeyLength = olm_outbound_group_session_key_length(sessionPtr); + LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); + + uint8_t *sessionKeyPtr = (uint8_t*)malloc(sessionKeyLength*sizeof(uint8_t)); + + if (!sessionKeyPtr) + { + LOGE(" ## sessionKeyJni(): failure - session key allocation OOM"); + errorMessage = "session key allocation OOM"; + } + else + { + size_t result = olm_outbound_group_session_key(sessionPtr, sessionKeyPtr, sessionKeyLength); + + if (result == olm_error()) + { + errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s", errorMessage); + } + else + { + LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionKeyPtr)); + + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionKeyPtr); + } + + // free alloc + free(sessionKeyPtr); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + +/** + * Encrypt a bytes buffer messages. + * An exception is thrown if the operation fails. + * @param aClearMsgBuffer the message to encode + * @return the encoded message + */ +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) +{ + LOGD("## encryptMessageJni(): IN"); + + const char* errorMessage = NULL; + jbyteArray encryptedMsgRet = 0; + + OlmOutboundGroupSession *sessionPtr = NULL; + jbyte* clearMsgPtr = NULL; + + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE(" ## encryptMessageJni(): failure - invalid outbound group session ptr=NULL"); + errorMessage = "invalid outbound group session ptr=NULL"; + } + else if (!aClearMsgBuffer) + { + LOGE(" ## encryptMessageJni(): failure - invalid clear message"); + errorMessage = "invalid clear message"; + } + else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, NULL))) + { + LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM"); + errorMessage = "clear message JNI allocation OOM"; + } + else + { + // get clear message length + size_t clearMsgLength = (size_t)env->GetArrayLength(aClearMsgBuffer); + LOGD(" ## encryptMessageJni(): clearMsgLength=%lu",static_cast(clearMsgLength)); + + // compute max encrypted length + size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); + uint8_t *encryptedMsgPtr = (uint8_t*)malloc(encryptedMsgLength*sizeof(uint8_t)); + + if (!encryptedMsgPtr) + { + LOGE(" ## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); + errorMessage = "encryptedMsgPtr buffer OOM"; + } + else + { + LOGD(" ## encryptMessageJni(): estimated encryptedMsgLength=%lu",static_cast(encryptedMsgLength)); + + size_t encryptedLength = olm_group_encrypt(sessionPtr, + (uint8_t*)clearMsgPtr, + clearMsgLength, + encryptedMsgPtr, + encryptedMsgLength); + + + if (encryptedLength == olm_error()) + { + errorMessage = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s", errorMessage); + } + else + { + LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%.*s",static_cast(encryptedLength), static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); + + encryptedMsgRet = env->NewByteArray(encryptedLength); + env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedLength, (jbyte*)encryptedMsgPtr); + } + + free(encryptedMsgPtr); + } + } + + // free alloc + if (clearMsgPtr) + { + env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return encryptedMsgRet; +} + +/** + * Serialize and encrypt session instance into a base64 string.
+ * An exception is thrown if the operation fails. + * @param aKey key used to encrypt the serialized session data + * @return a base64 string if operation succeed, null otherwise + **/ +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + jbyteArray returnValue = 0; + + jbyte* keyPtr = NULL; + OlmOutboundGroupSession* sessionPtr = NULL; + + LOGD("## outbound group session serializeJni(): IN"); + + if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + { + LOGE(" ## serializeJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; + } + else if (!aKeyBuffer) + { + LOGE(" ## serializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; + } + else + { + size_t pickledLength = olm_pickle_outbound_group_session_length(sessionPtr); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + + void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); + + if(!pickledPtr) + { + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; + } + else + { + size_t result = olm_pickle_outbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s", errorMessage); + } + else + { + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(result), static_cast(pickledPtr)); + + returnValue = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); + } + } + + free(pickledPtr); + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + size_t sessionSize = olm_outbound_group_session_size(); + OlmOutboundGroupSession* sessionPtr = NULL; + + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; + + LOGD("## deserializeJni(): IN"); + + if (!sessionSize) + { + LOGE(" ## deserializeJni(): failure - outbound group session size = 0"); + errorMessage = "outbound group session size = 0"; + } + else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) + { + LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; + } + else if (!aKeyBuffer) + { + LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!aSerializedDataBuffer) + { + LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "invalid serialized data"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; + } + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; + } + else + { + sessionPtr = olm_outbound_group_session(sessionPtr); + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): pickled=%.*s", static_cast(pickledLength), (char const *)pickledPtr); + + size_t result = olm_unpickle_outbound_group_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_outbound_group_session() Msg=%s", errorMessage); + } + else + { + LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); + } + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (pickledPtr) + { + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); + } + + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_outbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; +} + diff --git a/android/olm-sdk/src/main/jni/olm_outbound_group_session.h b/android/olm-sdk/src/main/jni/olm_outbound_group_session.h new file mode 100644 index 0000000..f6abba2 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_outbound_group_session.h @@ -0,0 +1,49 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLOUTBOUND_GROUP_SESSION_H +#define _OMLOUTBOUND_GROUP_SESSION_H + +#include "olm_jni.h" +#include "olm/olm.h" +#include "olm/outbound_group_session.h" + +#define OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmOutboundGroupSession,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +// session creation/destruction +JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); + +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); + +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); + +// serialization +JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/android/olm-sdk/src/main/jni/olm_session.cpp b/android/olm-sdk/src/main/jni/olm_session.cpp new file mode 100644 index 0000000..5ca49db --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_session.cpp @@ -0,0 +1,961 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_session.h" + +using namespace AndroidOlmSdk; + +/** +* Init memory allocation for a session creation.
+* Make sure releaseSessionJni() is called when one is done with the session instance. +* @return valid memory allocation, NULL otherwise +**/ +OlmSession* initializeSessionMemory() +{ + size_t sessionSize = olm_session_size(); + OlmSession* sessionPtr = (OlmSession*)malloc(sessionSize); + + if (sessionPtr) + { + // init session object + sessionPtr = olm_session(sessionPtr); + LOGD("## initializeSessionMemory(): success - OLM session size=%lu",static_cast(sessionSize)); + } + else + { + LOGE("## initializeSessionMemory(): failure - OOM"); + } + + return sessionPtr; +} + +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## createNewSessionJni(): IN"); + OlmSession* accountPtr = initializeSessionMemory(); + + if (!accountPtr) + { + LOGE("## initNewAccount(): failure - init session OOM"); + env->ThrowNew(env->FindClass("java/lang/Exception"), "init session OOM"); + } + else + { + LOGD(" ## createNewSessionJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); + } + + return (jlong)(intptr_t)accountPtr; +} + +JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## releaseSessionJni(): IN"); + OlmSession* sessionPtr = getSessionInstanceId(env, thiz); + + if (!sessionPtr) + { + LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); + } + else + { + olm_clear_session(sessionPtr); + + // even if free(NULL) does not crash, logs are performed for debug purpose + free(sessionPtr); + } +} + +// ********************************************************************* +// ********************** OUTBOUND SESSION ***************************** +// ********************************************************************* +/** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
The recipient is defined as the entity + * with whom the session is established. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient or an exception is thrown + **/ +JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) +{ + OlmSession* sessionPtr = getSessionInstanceId(env, thiz); + const char* errorMessage = NULL; + OlmAccount* accountPtr = NULL; + + if (!sessionPtr) + { + LOGE("## initOutboundSessionJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; + } + else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) + { + LOGE("## initOutboundSessionJni(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr=NULL"; + } + else if (!aTheirIdentityKeyBuffer || !aTheirOneTimeKeyBuffer) + { + LOGE("## initOutboundSessionJni(): failure - invalid keys"); + errorMessage = "invalid keys"; + } + else + { + size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); + uint8_t *randomBuffPtr = NULL; + + LOGD("## initOutboundSessionJni(): randomSize=%lu",static_cast(randomSize)); + + if ( (0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) + { + LOGE("## initOutboundSessionJni(): failure - random buffer init"); + errorMessage = "random buffer init"; + } + else + { + jbyte* theirIdentityKeyPtr = NULL; + jbyte* theirOneTimeKeyPtr = NULL; + + // convert identity & one time keys to C strings + if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) + { + LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM"); + errorMessage = "identityKey JNI allocation OOM"; + } + else if (!(theirOneTimeKeyPtr = env->GetByteArrayElements(aTheirOneTimeKeyBuffer, 0))) + { + LOGE("## initOutboundSessionJni(): failure - one time Key JNI allocation OOM"); + errorMessage = "one time Key JNI allocation OOM"; + } + else + { + size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); + size_t theirOneTimeKeyLength = (size_t)env->GetArrayLength(aTheirOneTimeKeyBuffer); + LOGD("## initOutboundSessionJni(): identityKey=%.*s oneTimeKey=%.*s", static_cast(theirIdentityKeyLength), theirIdentityKeyPtr, static_cast(theirOneTimeKeyLength), theirOneTimeKeyPtr); + + size_t sessionResult = olm_create_outbound_session(sessionPtr, + accountPtr, + theirIdentityKeyPtr, + theirIdentityKeyLength, + theirOneTimeKeyPtr, + theirOneTimeKeyLength, + (void*)randomBuffPtr, + randomSize); + if (sessionResult == olm_error()) { + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s", errorMessage); + } + else + { + LOGD("## initOutboundSessionJni(): success - result=%lu", static_cast(sessionResult)); + } + } + + if (theirIdentityKeyPtr) + { + env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); + } + + if (theirOneTimeKeyPtr) + { + env->ReleaseByteArrayElements(aTheirOneTimeKeyBuffer, theirOneTimeKeyPtr, JNI_ABORT); + } + + if (randomBuffPtr) + { + memset(randomBuffPtr, 0, randomSize); + free(randomBuffPtr); + } + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } +} + + +// ********************************************************************* +// *********************** INBOUND SESSION ***************************** +// ********************************************************************* +/** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aOneTimeKeyMsg PRE_KEY message + */ +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer) +{ + const char* errorMessage = NULL; + OlmSession *sessionPtr = getSessionInstanceId(env,thiz); + OlmAccount *accountPtr = NULL; + size_t sessionResult; + + if (!sessionPtr) + { + LOGE("## initInboundSessionJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; + } + else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) + { + LOGE("## initInboundSessionJni(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr=NULL"; + } + else if (!aOneTimeKeyMsgBuffer) + { + LOGE("## initInboundSessionJni(): failure - invalid message"); + errorMessage = "invalid message"; + } + else + { + jbyte* messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0); + + if (!messagePtr) + { + LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM"); + errorMessage = "message JNI allocation OOM"; + } + else + { + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); + LOGD("## initInboundSessionJni(): messageLength=%lu message=%.*s", static_cast(messageLength), static_cast(messageLength), messagePtr); + + sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); + + if (sessionResult == olm_error()) + { + errorMessage = olm_session_last_error(sessionPtr); + LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); + } + else + { + LOGD("## initInboundSessionJni(): success - result=%lu", static_cast(sessionResult)); + } + + // free local alloc + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } +} + +/** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message based on the recipient identity key.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aOneTimeKeyMsg encrypted message + */ +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) +{ + const char* errorMessage = NULL; + + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); + OlmAccount *accountPtr = NULL; + jbyte *messagePtr = NULL; + jbyte *theirIdentityKeyPtr = NULL; + size_t sessionResult; + + if (!sessionPtr) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; + } + else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Account ptr=NULL"); + errorMessage = "invalid Account ptr=NULL"; + } + else if (!aTheirIdentityKeyBuffer) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); + errorMessage = "invalid theirIdentityKey"; + } + else if (!aOneTimeKeyMsgBuffer) + { + LOGE("## initInboundSessionJni(): failure - invalid one time key message"); + errorMessage = "invalid invalid one time key message"; + } + else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - message JNI allocation OOM"); + errorMessage = "message JNI allocation OOM"; + } + else if(!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) + { + LOGE("## initInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); + errorMessage = "theirIdentityKey JNI allocation OOM"; + } + else + { + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); + size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); + + LOGD("## initInboundSessionFromIdKeyJni(): message=%.*s messageLength=%lu", static_cast(messageLength), messagePtr, static_cast(messageLength)); + + sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); + if (sessionResult == olm_error()) + { + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s", errorMessage); + } + else + { + LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(sessionResult)); + } + } + + // free local alloc + if (messagePtr) + { + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); + } + + if (theirIdentityKeyPtr) + { + env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } +} + +/** + * Checks if the PRE_KEY message is for this in-bound session.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches + */ +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) +{ + jboolean retCode = JNI_FALSE; + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); + jbyte *messagePtr = NULL; + + if (!sessionPtr) + { + LOGE("## matchesInboundSessionJni(): failure - invalid Session ptr=NULL"); + } + else if (!aOneTimeKeyMsgBuffer) + { + LOGE("## matchesInboundSessionJni(): failure - invalid one time key message"); + } + else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) + { + LOGE("## matchesInboundSessionJni(): failure - one time key JNI allocation OOM"); + } + else + { + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); + + size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); + //if(matchResult == olm_error()) { + // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 + if (matchResult != 1) { + LOGE("## matchesInboundSessionJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + } + else + { + retCode = JNI_TRUE; + LOGD("## matchesInboundSessionJni(): success - result=%lu", static_cast(matchResult)); + } + } + + // free local alloc + if (messagePtr) + { + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); + } + + return retCode; +} + +/** + * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * @param aTheirIdentityKey the identity key of the sender + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches. + */ +JNIEXPORT jboolean JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) +{ + jboolean retCode = JNI_FALSE; + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); + jbyte *messagePtr = NULL; + jbyte *theirIdentityKeyPtr = NULL; + + if (!sessionPtr) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); + } + else if (!aTheirIdentityKeyBuffer) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); + } + else if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); + } + else if (!aOneTimeKeyMsgBuffer) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid one time key message"); + } + else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - one time key JNI allocation OOM"); + } + else + { + size_t identityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); + size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); + size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); + + //if(matchResult == olm_error()) { + // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 + if (matchResult != 1) + { + LOGE("## matchesInboundSessionFromIdKeyJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); + } + else + { + retCode = JNI_TRUE; + LOGD("## matchesInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(matchResult)); + } + } + + // free local alloc + if (theirIdentityKeyPtr) + { + env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); + } + + if (messagePtr) + { + env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); + } + + return retCode; +} + +/** + * Encrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aClearMsg clear text message + * @param [out] aEncryptedMsg ciphered message + * @return the encrypted message + */ +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg) +{ + jbyteArray encryptedMsgRet = 0; + const char* errorMessage = NULL; + + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); + jbyte *clearMsgPtr = NULL; + jclass encryptedMsgJClass = 0; + jfieldID typeMsgFieldId; + + LOGD("## encryptMessageJni(): IN "); + + if (!sessionPtr) + { + LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; + } + else if (!aClearMsgBuffer) + { + LOGE("## encryptMessageJni(): failure - invalid clear message"); + errorMessage = "invalid clear message"; + } + else if (!aEncryptedMsg) + { + LOGE("## encryptMessageJni(): failure - invalid encrypted message"); + } + else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, 0))) + { + LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM"); + errorMessage = "clear message JNI allocation OOM"; + } + else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) + { + LOGE("## encryptMessageJni(): failure - unable to get crypted message class"); + errorMessage = "unable to get crypted message class"; + } + else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) + { + LOGE("## encryptMessageJni(): failure - unable to get message type field"); + errorMessage = "unable to get message type field"; + } + else + { + // get message type + size_t messageType = olm_encrypt_message_type(sessionPtr); + uint8_t *randomBuffPtr = NULL; + + // compute random buffer + // Note: olm_encrypt_random_length() can return 0, which means + // it just does not need new random data to encrypt a new message + size_t randomLength = olm_encrypt_random_length(sessionPtr); + + LOGD("## encryptMessageJni(): randomLength=%lu", static_cast(randomLength)); + + if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) + { + LOGE("## encryptMessageJni(): failure - random buffer init"); + errorMessage = "random buffer init"; + } + else + { + // alloc buffer for encrypted message + size_t clearMsgLength = (size_t)env->GetArrayLength(aClearMsgBuffer); + size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); + + void *encryptedMsgPtr = malloc(encryptedMsgLength*sizeof(uint8_t)); + + if (!encryptedMsgPtr) + { + LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); + errorMessage = "encryptedMsgPtr buffer OOM"; + } + else + { + if (0 == randomLength) + { + LOGW("## encryptMessageJni(): random buffer is not required"); + } + + LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu clearMsgLength=%lu encryptedMsgLength=%lu",static_cast(messageType),static_cast(randomLength), static_cast(clearMsgLength), static_cast(encryptedMsgLength)); + // encrypt message + size_t result = olm_encrypt(sessionPtr, + (void const *)clearMsgPtr, + clearMsgLength, + randomBuffPtr, + randomLength, + encryptedMsgPtr, + encryptedMsgLength); + if (result == olm_error()) + { + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## encryptMessageJni(): failure - Msg=%s", errorMessage); + } + else + { + // update message type: PRE KEY or normal + env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); + + encryptedMsgRet = env->NewByteArray(encryptedMsgLength); + env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedMsgLength, (jbyte*)encryptedMsgPtr); + + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%.*s", static_cast(result), static_cast(messageType), static_cast(result), (const char*)encryptedMsgPtr); + } + + free(encryptedMsgPtr); + } + + memset(randomBuffPtr, 0, randomLength); + free(randomBuffPtr); + } + } + + // free alloc + if (clearMsgPtr) + { + env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return encryptedMsgRet; +} + +/** + * Decrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aEncryptedMsg message to decrypt + * @return decrypted message if operation succeed + */ +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) +{ + const char* errorMessage = NULL; + + jbyteArray decryptedMsgRet = 0; + + jclass encryptedMsgJClass = 0; + jstring encryptedMsgJstring = 0; // <= obtained from encryptedMsgFieldId + // field IDs + jfieldID encryptedMsgFieldId; + jfieldID typeMsgFieldId; + // ptrs + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); + const char *encryptedMsgPtr = NULL; // <= obtained from encryptedMsgJstring + uint8_t *plainTextMsgPtr = NULL; + char *tempEncryptedPtr = NULL; + + LOGD("## decryptMessageJni(): IN - OlmSession"); + + if (!sessionPtr) + { + LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; + } + else if (!aEncryptedMsg) + { + LOGE("## decryptMessageJni(): failure - invalid encrypted message"); + errorMessage = "invalid encrypted message"; + } + else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) + { + LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); + errorMessage = "unable to get encrypted message class"; + } + else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) + { + LOGE("## decryptMessageJni(): failure - unable to get message field"); + errorMessage = "unable to get message field"; + } + else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) + { + LOGE("## decryptMessageJni(): failure - unable to get message type field"); + errorMessage = "unable to get message type field"; + } + else if (!(encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) + { + LOGE("## decryptMessageJni(): failure - JNI encrypted object "); + errorMessage = "JNI encrypted object"; + } + else if (!(encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) + { + LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); + errorMessage = "encrypted message JNI allocation OOM"; + } + else + { + // get message type + size_t encryptedMsgType = (size_t)env->GetLongField(aEncryptedMsg, typeMsgFieldId); + // get encrypted message length + size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(encryptedMsgJstring); + + // create a dedicated temp buffer to be used in next Olm API calls + tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + LOGD("## decryptMessageJni(): MsgType=%lu encryptedMsgLength=%lu encryptedMsg=%.*s",static_cast(encryptedMsgType),static_cast(encryptedMsgLength), static_cast(encryptedMsgLength), encryptedMsgPtr); + + // get max plaintext length + size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, + static_cast(encryptedMsgType), + static_cast(tempEncryptedPtr), + encryptedMsgLength); + // Note: tempEncryptedPtr is destroyed by olm_decrypt_max_plaintext_length() + + if (maxPlainTextLength == olm_error()) + { + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s", errorMessage); + } + else + { + LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); + + // allocate output decrypted message + plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); + + // decrypt, but before reload encrypted buffer (previous one was destroyed) + memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); + size_t plaintextLength = olm_decrypt(sessionPtr, + encryptedMsgType, + (void*)tempEncryptedPtr, + encryptedMsgLength, + plainTextMsgPtr, + maxPlainTextLength); + if (plaintextLength == olm_error()) + { + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s", errorMessage); + } + else + { + decryptedMsgRet = env->NewByteArray(plaintextLength); + env->SetByteArrayRegion(decryptedMsgRet, 0 , plaintextLength, (jbyte*)plainTextMsgPtr); + + LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); + } + } + } + + // free alloc + if (encryptedMsgPtr) + { + env->ReleaseStringUTFChars(encryptedMsgJstring, encryptedMsgPtr); + } + + if (tempEncryptedPtr) + { + free(tempEncryptedPtr); + } + + if (plainTextMsgPtr) + { + free(plainTextMsgPtr); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return decryptedMsgRet; +} + +/** + * Get the session identifier for this session. + * An exception is thrown if the operation fails. + * @return the session identifier + */ +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) +{ + const char* errorMessage = NULL; + jbyteArray returnValue = 0; + + LOGD("## getSessionIdentifierJni(): IN "); + + OlmSession *sessionPtr = getSessionInstanceId(env, thiz); + + if (!sessionPtr) + { + LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); + errorMessage = "invalid Session ptr=NULL"; + } + else + { + // get the size to alloc to contain the id + size_t lengthSessionId = olm_session_id_length(sessionPtr); + LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",static_cast(lengthSessionId)); + + void *sessionIdPtr = malloc(lengthSessionId*sizeof(uint8_t)); + + if (!sessionIdPtr) + { + LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); + errorMessage = "identifier allocation OOM"; + } + else + { + size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId); + + if (result == olm_error()) + { + errorMessage = (const char *)olm_session_last_error(sessionPtr); + LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s", errorMessage); + } + else + { + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); + + returnValue = env->NewByteArray(result); + env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); + } + + free(sessionIdPtr); + } + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + +/** + * Serialize and encrypt session instance.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + jbyteArray returnValue = 0; + + jbyte* keyPtr = NULL; + OlmSession* sessionPtr = getSessionInstanceId(env, thiz); + + LOGD("## serializeJni(): IN"); + + if (!sessionPtr) + { + LOGE(" ## serializeJni(): failure - invalid session ptr"); + errorMessage = "invalid session ptr"; + } + else if (!aKeyBuffer) + { + LOGE(" ## serializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "ikeyPtr JNI allocation OOM"; + } + else + { + size_t pickledLength = olm_pickle_session_length(sessionPtr); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + + void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); + + if (!pickledPtr) + { + LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); + errorMessage = "pickledPtr buffer OOM"; + } + else + { + size_t result = olm_pickle_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_session_last_error(sessionPtr); + LOGE(" ## serializeJni(): failure - olm_pickle_session() Msg=%s", errorMessage); + } + else + { + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); + + returnValue = env->NewByteArray(pickledLength); + env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); + } + + free(pickledPtr); + } + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return returnValue; +} + +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +{ + const char* errorMessage = NULL; + OlmSession* sessionPtr = initializeSessionMemory(); + jbyte* keyPtr = NULL; + jbyte* pickledPtr = NULL; + + LOGD("## deserializeJni(): IN"); + + if (!sessionPtr) + { + LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; + } + else if (!aKeyBuffer) + { + LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!aSerializedDataBuffer) + { + LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "serialized data"; + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; + } + else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) + { + LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; + } + else + { + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); + LOGD(" ## deserializeJni(): pickled=%.*s",static_cast(pickledLength), (char const *)pickledPtr); + + size_t result = olm_unpickle_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if (result == olm_error()) + { + errorMessage = olm_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); + } + else + { + LOGD(" ## initJni(): success - result=%lu ", static_cast(result)); + } + } + + // free alloc + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (pickledPtr) + { + env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); + } + + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; +} \ No newline at end of file diff --git a/android/olm-sdk/src/main/jni/olm_session.h b/android/olm-sdk/src/main/jni/olm_session.h new file mode 100644 index 0000000..b8cdd2f --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_session.h @@ -0,0 +1,59 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLSESSION_H +#define _OMLSESSION_H + +#include "olm_jni.h" +#include "olm/olm.h" + +#define OLM_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmSession,func_name) + +#ifdef __cplusplus +extern "C" { +#endif + +// session creation/destruction +JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); + +// outbound session +JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey); + +// inbound sessions: establishment based on PRE KEY message +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg); +JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); + +// match inbound sessions: based on PRE KEY message +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); + +// encrypt/decrypt +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); + +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); + +// serialization +JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/android/olm-sdk/src/main/jni/olm_utility.cpp b/android/olm-sdk/src/main/jni/olm_utility.cpp new file mode 100644 index 0000000..f6fe719 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_utility.cpp @@ -0,0 +1,228 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "olm_utility.h" + +using namespace AndroidOlmSdk; + +OlmUtility* initializeUtilityMemory() +{ + size_t utilitySize = olm_utility_size(); + OlmUtility* utilityPtr = (OlmUtility*)malloc(utilitySize); + + if (utilityPtr) + { + utilityPtr = olm_utility(utilityPtr); + LOGD("## initializeUtilityMemory(): success - OLM utility size=%lu",static_cast(utilitySize)); + } + else + { + LOGE("## initializeUtilityMemory(): failure - OOM"); + } + + return utilityPtr; +} + +JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(createUtilityJni)(JNIEnv *env, jobject thiz) +{ + OlmUtility* utilityPtr = initializeUtilityMemory(); + + LOGD("## createUtilityJni(): IN"); + + // init account memory allocation + if (!utilityPtr) + { + LOGE(" ## createUtilityJni(): failure - init OOM"); + env->ThrowNew(env->FindClass("java/lang/Exception"), "init OOM"); + } + else + { + LOGD(" ## createUtilityJni(): success"); + } + + return (jlong)(intptr_t)utilityPtr; +} + + +JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz) +{ + OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); + + LOGD("## releaseUtilityJni(): IN"); + + if (!utilityPtr) + { + LOGE("## releaseUtilityJni(): failure - utility ptr=NULL"); + } + else + { + olm_clear_utility(utilityPtr); + free(utilityPtr); + } +} + + +/** + * Verify an ed25519 signature. + * @param aSignature the base64-encoded message signature to be checked. + * @param aKey the ed25519 key (fingerprint key) + * @param aMessage the message which was signed + * @return 0 if validation succeed, an error message string if operation failed + */ +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignatureBuffer, jbyteArray aKeyBuffer, jbyteArray aMessageBuffer) +{ + jstring errorMessageRetValue = 0; + OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); + jbyte* signaturePtr = NULL; + jbyte* keyPtr = NULL; + jbyte* messagePtr = NULL; + + LOGD("## verifyEd25519SignatureJni(): IN"); + + if (!utilityPtr) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - invalid utility ptr=NULL"); + } + else if (!aSignatureBuffer || !aKeyBuffer || !aMessageBuffer) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - invalid input parameters "); + } + else if (!(signaturePtr = env->GetByteArrayElements(aSignatureBuffer, 0))) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - signature JNI allocation OOM"); + } + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - key JNI allocation OOM"); + } + else if (!(messagePtr = env->GetByteArrayElements(aMessageBuffer, 0))) + { + LOGE(" ## verifyEd25519SignatureJni(): failure - message JNI allocation OOM"); + } + else + { + size_t signatureLength = (size_t)env->GetArrayLength(aSignatureBuffer); + size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); + size_t messageLength = (size_t)env->GetArrayLength(aMessageBuffer); + LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",static_cast(signatureLength),static_cast(keyLength),static_cast(messageLength)); + LOGD(" ## verifyEd25519SignatureJni(): key=%.*s", static_cast(keyLength), keyPtr); + + size_t result = olm_ed25519_verify(utilityPtr, + (void const *)keyPtr, + keyLength, + (void const *)messagePtr, + messageLength, + (void*)signaturePtr, + signatureLength); + if (result == olm_error()) { + const char *errorMsgPtr = olm_utility_last_error(utilityPtr); + errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + LOGE("## verifyEd25519SignatureJni(): failure - olm_ed25519_verify Msg=%s",errorMsgPtr); + } + else + { + LOGD("## verifyEd25519SignatureJni(): success - result=%lu", static_cast(result)); + } + } + + // free alloc + if (signaturePtr) + { + env->ReleaseByteArrayElements(aSignatureBuffer, signaturePtr, JNI_ABORT); + } + + if (keyPtr) + { + env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); + } + + if (messagePtr) + { + env->ReleaseByteArrayElements(aMessageBuffer, messagePtr, JNI_ABORT); + } + + return errorMessageRetValue; +} + +/** + * Compute the digest (SHA 256) for the message passed in parameter.
+ * The digest value is the function return value. + * An exception is thrown if the operation fails. + * @param aMessage the message + * @return digest of the message. + **/ +JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHashBuffer) +{ + jbyteArray sha256Ret = 0; + + OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); + jbyte* messagePtr = NULL; + + LOGD("## sha256Jni(): IN"); + + if (!utilityPtr) + { + LOGE(" ## sha256Jni(): failure - invalid utility ptr=NULL"); + } + else if(!aMessageToHashBuffer) + { + LOGE(" ## sha256Jni(): failure - invalid message parameters "); + } + else if(!(messagePtr = env->GetByteArrayElements(aMessageToHashBuffer, 0))) + { + LOGE(" ## sha256Jni(): failure - message JNI allocation OOM"); + } + else + { + // get lengths + size_t messageLength = (size_t)env->GetArrayLength(aMessageToHashBuffer); + size_t hashLength = olm_sha256_length(utilityPtr); + void* hashValuePtr = malloc((hashLength)*sizeof(uint8_t)); + + if (!hashValuePtr) + { + LOGE("## sha256Jni(): failure - hash value allocation OOM"); + } + else + { + size_t result = olm_sha256(utilityPtr, + (void const *)messagePtr, + messageLength, + (void *)hashValuePtr, + hashLength); + if (result == olm_error()) + { + LOGE("## sha256Jni(): failure - hash creation Msg=%s",(const char *)olm_utility_last_error(utilityPtr)); + } + else + { + LOGD("## sha256Jni(): success - result=%lu hashValue=%.*s",static_cast(result), static_cast(result), (char*)hashValuePtr); + sha256Ret = env->NewByteArray(result); + env->SetByteArrayRegion(sha256Ret, 0 , result, (jbyte*)hashValuePtr); + } + + free(hashValuePtr); + } + } + + if (messagePtr) + { + env->ReleaseByteArrayElements(aMessageToHashBuffer, messagePtr, JNI_ABORT); + } + + return sha256Ret; +} \ No newline at end of file diff --git a/android/olm-sdk/src/main/jni/olm_utility.h b/android/olm-sdk/src/main/jni/olm_utility.h new file mode 100644 index 0000000..de4b290 --- /dev/null +++ b/android/olm-sdk/src/main/jni/olm_utility.h @@ -0,0 +1,40 @@ +/* + * Copyright 2016 OpenMarket Ltd + * Copyright 2016 Vector Creations Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef _OMLUTILITY_H +#define _OMLUTILITY_H + +#include "olm_jni.h" +#include "olm/olm.h" + +#define OLM_UTILITY_FUNC_DEF(func_name) FUNC_DEF(OlmUtility,func_name) + + +#ifdef __cplusplus +extern "C" { +#endif +JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(createUtilityJni)(JNIEnv *env, jobject thiz); +JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignature, jbyteArray aKey, jbyteArray aMessage); +JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHash); +#ifdef __cplusplus +} +#endif + + + +#endif diff --git a/android/olm-sdk/src/main/res/values/strings.xml b/android/olm-sdk/src/main/res/values/strings.xml new file mode 100644 index 0000000..93bea1d --- /dev/null +++ b/android/olm-sdk/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + OlmSdk + diff --git a/android/settings.gradle b/android/settings.gradle new file mode 100644 index 0000000..d11302c --- /dev/null +++ b/android/settings.gradle @@ -0,0 +1 @@ +include ':olm-sdk' diff --git a/java/android/OlmLibSdk/README.rst b/java/android/OlmLibSdk/README.rst deleted file mode 100644 index 6a9eae8..0000000 --- a/java/android/OlmLibSdk/README.rst +++ /dev/null @@ -1,29 +0,0 @@ -OlmLibSdk -========= - -OlmLibSdk exposes an android wrapper to libolm. - -Installation ------------- -Create a libs directory in your project directory -Copy the olm-sdk.aar into it. - -In your build.gradle file, add in the android section:: - - repositories { - flatDir { - dir 'libs' - } - } - -Add in the dependencies category:: - - compile(name: 'olm-sdk', ext: 'aar') - -Development ------------ -import the project from the ``/java/android/OlmLibSdk`` path. - -The project contains some JNI files and some Java wraper files. - -The project contains some tests under AndroidTests package. diff --git a/java/android/OlmLibSdk/build.gradle b/java/android/OlmLibSdk/build.gradle deleted file mode 100644 index 77ce66e..0000000 --- a/java/android/OlmLibSdk/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:2.1.3' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/java/android/OlmLibSdk/gradle.properties b/java/android/OlmLibSdk/gradle.properties deleted file mode 100644 index 13d64a5..0000000 --- a/java/android/OlmLibSdk/gradle.properties +++ /dev/null @@ -1,19 +0,0 @@ -## Project-wide Gradle settings. -# -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html -# -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -# -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true -#Wed Oct 05 11:49:34 CEST 2016 -systemProp.https.proxyPort=8080 -systemProp.http.proxyHost=batproxy -systemProp.https.proxyHost=batproxy -systemProp.http.proxyPort=8080 diff --git a/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar b/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 13372ae..0000000 Binary files a/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties b/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 4ba4622..0000000 --- a/java/android/OlmLibSdk/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Thu Oct 13 09:38:01 CEST 2016 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip diff --git a/java/android/OlmLibSdk/gradlew b/java/android/OlmLibSdk/gradlew deleted file mode 100755 index 9d82f78..0000000 --- a/java/android/OlmLibSdk/gradlew +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash - -############################################################################## -## -## Gradle start up script for UN*X -## -############################################################################## - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" - -warn ( ) { - echo "$*" -} - -die ( ) { - echo - echo "$*" - echo - exit 1 -} - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; -esac - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" - else - JAVACMD="$JAVA_HOME/bin/java" - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=$((i+1)) - done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac -fi - -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" - -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/java/android/OlmLibSdk/gradlew.bat b/java/android/OlmLibSdk/gradlew.bat deleted file mode 100644 index 8a0b282..0000000 --- a/java/android/OlmLibSdk/gradlew.bat +++ /dev/null @@ -1,90 +0,0 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle deleted file mode 100644 index 9ce4d37..0000000 --- a/java/android/OlmLibSdk/olm-sdk/build.gradle +++ /dev/null @@ -1,130 +0,0 @@ -import org.apache.tools.ant.taskdefs.condition.Os - -apply plugin: 'com.android.library' - -android { - compileSdkVersion 21 - buildToolsVersion '21.1.2' - - defaultConfig { - minSdkVersion 11 - targetSdkVersion 21 - versionCode 1 - versionName "1.0" - version "0.2.0" - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" - } - buildTypes { - debug { - resValue "string", "git_olm_revision", "\"${gitRevision()}\"" - resValue "string", "git_olm_revision_unix_date", "\"${gitRevisionUnixDate()}\"" - resValue "string", "git_olm_revision_date", "\"${gitRevisionDate()}\"" - } - - release { - resValue "string", "git_olm_revision", "\"${gitRevision()}\"" - resValue "string", "git_olm_revision_unix_date", "\"${gitRevisionUnixDate()}\"" - resValue "string", "git_olm_revision_date", "\"${gitRevisionDate()}\"" - - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - sourceSets.main { - jniLibs.srcDir 'src/main/libs' - jni.srcDirs = [] - } - - task buildJavaDoc(type: Javadoc) { - source = android.sourceSets.main.java.srcDirs - classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) - destinationDir = file("./doc/") - options.memberLevel = org.gradle.external.javadoc.JavadocMemberLevel.PRIVATE - failOnError false - } - - task ndkBuildNativeRelease(type: Exec, description: 'NDK building..') { - println 'ndkBuildNativeRelease starts..' - workingDir file('src/main') - commandLine getNdkBuildCmd(), 'NDK_DEBUG=0' - } - - task ndkBuildNativeDebug(type: Exec, description: 'NDK building..') { - println 'ndkBuildNativeDebug starts..' - workingDir file('src/main') - commandLine getNdkBuildCmd(), 'NDK_DEBUG=1' - } - - task cleanNative(type: Exec, description: 'Clean NDK build') { - workingDir file('src/main') - commandLine getNdkBuildCmd(), 'clean' - } - - tasks.withType(JavaCompile) { - compileTask -> if (compileTask.name.startsWith('compileDebugJava')) { - println 'test compile: Debug' - compileTask.dependsOn ndkBuildNativeDebug - } else if (compileTask.name.startsWith('compileReleaseJava')) { - println 'test compile: Release' - compileTask.dependsOn ndkBuildNativeRelease - } - compileTask.dependsOn buildJavaDoc - } - - clean.dependsOn cleanNative - - - libraryVariants.all { variant -> - variant.outputs.each { output -> - def outputFile = output.outputFile - if (outputFile != null && outputFile.name.endsWith('.aar')) { - def fileName = outputFile.name.replace(".aar", "-${version}.aar") - output.outputFile = new File(outputFile.parent, fileName) - } - } - } -} - -def getNdkFolder() { - Properties properties = new Properties() - properties.load(project.rootProject.file('local.properties').newDataInputStream()) - def ndkFolder = properties.getProperty('ndk.dir', null) - if (ndkFolder == null) - throw new GradleException("NDK location missing. Define it with ndk.dir in the local.properties file") - - return ndkFolder -} - -def getNdkBuildCmd() { - def ndkBuildCmd = getNdkFolder() + "/ndk-build" - if (Os.isFamily(Os.FAMILY_WINDOWS)) - ndkBuildCmd += ".cmd" - - return ndkBuildCmd -} - -def gitRevision() { - def cmd = "git rev-parse --short HEAD" - return cmd.execute().text.trim() -} - -def gitRevisionUnixDate() { - def cmd = "git show -s --format=%ct HEAD^{commit}" - return cmd.execute().text.trim() -} - -def gitRevisionDate() { - def cmd = "git show -s --format=%ci HEAD^{commit}" - return cmd.execute().text.trim() -} - -dependencies { - compile fileTree(include: ['*.jar'], dir: 'libs') - compile 'com.android.support:appcompat-v7:21.+' - - testCompile 'junit:junit:4.12' - androidTestCompile 'junit:junit:4.12' - androidTestCompile 'com.android.support:support-annotations:21.0.0' - androidTestCompile 'com.android.support.test:runner:0.5' - androidTestCompile 'com.android.support.test:rules:0.5' -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java deleted file mode 100644 index ffbbca1..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java +++ /dev/null @@ -1,493 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.content.Context; -import android.support.test.runner.AndroidJUnit4; -import android.text.TextUtils; -import android.util.Log; - -import org.json.JSONException; -import org.json.JSONObject; -import org.junit.After; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Map; - -import static android.support.test.InstrumentationRegistry.getInstrumentation; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class OlmAccountTest { - private static final String LOG_TAG = "OlmAccountTest"; - private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50; - - private static OlmAccount mOlmAccount; - private static OlmManager mOlmManager; - private boolean mIsAccountCreated; - private final String FILE_NAME = "SerialTestFile"; - - @BeforeClass - public static void setUpClass(){ - // load native lib - mOlmManager = new OlmManager(); - - String olmLibVersion = mOlmManager.getOlmLibVersion(); - assertNotNull(olmLibVersion); - String olmSdkVersion = mOlmManager.getSdkOlmVersion(getInstrumentation().getContext()); - assertNotNull(olmLibVersion); - Log.d(LOG_TAG, "## setUpClass(): Versions - Android Olm SDK = "+olmSdkVersion+" Olm lib ="+olmLibVersion); - } - - @AfterClass - public static void tearDownClass() { - // TBD - } - - @Before - public void setUp() { - if(mIsAccountCreated) { - assertNotNull(mOlmAccount); - } - } - - @After - public void tearDown() { - // TBD - } - - /** - * Basic test: creation and release. - */ - @Test - public void test01CreateReleaseAccount() { - try { - mOlmAccount = new OlmAccount(); - } catch (OlmException e) { - e.printStackTrace(); - assertTrue("OlmAccount failed " + e.getMessage(), false); - } - assertNotNull(mOlmAccount); - - mOlmAccount.releaseAccount(); - assertTrue(0 == mOlmAccount.getOlmAccountId()); - } - - @Test - public void test02CreateAccount() { - try { - mOlmAccount = new OlmAccount(); - } catch (OlmException e) { - e.printStackTrace(); - assertTrue("OlmAccount failed " + e.getMessage(), false); - } - assertNotNull(mOlmAccount); - mIsAccountCreated = true; - } - - @Test - public void test04GetOlmAccountId() { - long olmNativeInstance = mOlmAccount.getOlmAccountId(); - Log.d(LOG_TAG,"## testGetOlmAccountId olmNativeInstance="+olmNativeInstance); - assertTrue(0!=olmNativeInstance); - } - - /** - * Test if {@link OlmAccount#identityKeys()} returns a JSON object - * that contains the following keys: {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} - * and {@link OlmAccount#JSON_KEY_IDENTITY_KEY} - */ - @Test - public void test05IdentityKeys() { - Map identityKeys = null; - try { - identityKeys = mOlmAccount.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - assertNotNull(identityKeys); - Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeys); - - // is JSON_KEY_FINGER_PRINT_KEY present? - String fingerPrintKey = TestHelper.getFingerprintKey(identityKeys); - assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); - - // is JSON_KEY_IDENTITY_KEY present? - String identityKey = TestHelper.getIdentityKey(identityKeys); - assertTrue("identity key missing",!TextUtils.isEmpty(identityKey)); - } - - //**************************************************** - //***************** ONE TIME KEYS TESTS ************** - //**************************************************** - @Test - public void test06MaxOneTimeKeys() { - long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys(); - Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys); - - assertTrue(maxOneTimeKeys>0); - } - - /** - * Test one time keys generation. - */ - @Test - public void test07GenerateOneTimeKeys() { - String error = null; - - try { - mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - error = e.getMessage(); - } - - assertTrue(null == error); - } - - /** - * Test the generated amount of one time keys = GENERATION_ONE_TIME_KEYS_NUMBER. - */ - @Test - public void test08OneTimeKeysJsonFormat() { - int oneTimeKeysCount = 0; - Map> oneTimeKeysJson = null; - - try { - oneTimeKeysJson = mOlmAccount.oneTimeKeys(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(oneTimeKeysJson); - - try { - Map map = oneTimeKeysJson.get(OlmAccount.JSON_KEY_ONE_TIME_KEY); - assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=map); - - // test the count of the generated one time keys: - oneTimeKeysCount = map.size(); - - assertTrue("Expected count="+GENERATION_ONE_TIME_KEYS_NUMBER+" found="+oneTimeKeysCount,GENERATION_ONE_TIME_KEYS_NUMBER==oneTimeKeysCount); - - } catch (Exception e) { - assertTrue("Exception MSg="+e.getMessage(), false); - } - } - - @Test - public void test10RemoveOneTimeKeysForSession() { - OlmSession olmSession = null; - try { - olmSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - long sessionId = olmSession.getOlmSessionId(); - assertTrue(0 != sessionId); - - String errorMessage = null; - - try { - mOlmAccount.removeOneTimeKeys(olmSession); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - assertTrue(null != errorMessage); - - olmSession.releaseSession(); - sessionId = olmSession.getOlmSessionId(); - assertTrue(0 == sessionId); - } - - @Test - public void test11MarkOneTimeKeysAsPublished() { - try { - mOlmAccount.markOneTimeKeysAsPublished(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - } - - @Test - public void test12SignMessage() { - String clearMsg = "String to be signed by olm"; - String signedMsg = null; - - try { - signedMsg = mOlmAccount.signMessage(clearMsg); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(signedMsg); - // additional tests are performed in test01VerifyEd25519Signing() - } - - - // ******************************************************** - // ************* SERIALIZATION TEST *********************** - // ******************************************************** - - @Test - public void test13Serialization() { - FileOutputStream fileOutput; - ObjectOutputStream objectOutput; - OlmAccount accountRef = null; - OlmAccount accountDeserial = null; - - try { - accountRef = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - - try { - accountRef.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - assertTrue(e.getMessage(),false); - } - - // get keys references - Map identityKeysRef = null; - - try { - identityKeysRef = accountRef.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - Map> oneTimeKeysRef = null; - - try { - oneTimeKeysRef = accountRef.oneTimeKeys(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(identityKeysRef); - assertNotNull(oneTimeKeysRef); - - try { - Context context = getInstrumentation().getContext(); - //context.getFilesDir(); - fileOutput = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); - - // serialize account - objectOutput = new ObjectOutputStream(fileOutput); - objectOutput.writeObject(accountRef); - objectOutput.flush(); - objectOutput.close(); - - // deserialize account - FileInputStream fileInput = context.openFileInput(FILE_NAME); - ObjectInputStream objectInput = new ObjectInputStream(fileInput); - accountDeserial = (OlmAccount) objectInput.readObject(); - objectInput.close(); - assertNotNull(accountDeserial); - - // get de-serialized keys - Map identityKeysDeserial = accountDeserial.identityKeys(); - Map> oneTimeKeysDeserial = accountDeserial.oneTimeKeys(); - assertNotNull(identityKeysDeserial); - assertNotNull(oneTimeKeysDeserial); - - // compare identity keys - assertTrue(identityKeysDeserial.toString().equals(identityKeysRef.toString())); - - // compare onetime keys - assertTrue(oneTimeKeysDeserial.toString().equals(oneTimeKeysRef.toString())); - - accountRef.releaseAccount(); - accountDeserial.releaseAccount(); - } - catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test13Serialization(): Exception FileNotFoundException Msg=="+e.getMessage()); - assertTrue("test13Serialization failed " + e.getMessage(), false); - } - catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test13Serialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); - assertTrue("test13Serialization failed " + e.getMessage(), false); - } - catch (IOException e) { - Log.e(LOG_TAG, "## test13Serialization(): Exception IOException Msg==" + e.getMessage()); - assertTrue("test13Serialization failed " + e.getMessage(), false); - } - /*catch (OlmException e) { - Log.e(LOG_TAG, "## test13Serialization(): Exception OlmException Msg==" + e.getMessage()); - }*/ - catch (Exception e) { - Log.e(LOG_TAG, "## test13Serialization(): Exception Msg==" + e.getMessage()); - assertTrue("test13Serialization failed " + e.getMessage(), false); - } - } - - - // **************************************************** - // *************** SANITY CHECK TESTS ***************** - // **************************************************** - - @Test - public void test14GenerateOneTimeKeysError() { - // keys number = 0 => no error - - String errorMessage = null; - try { - mOlmAccount.generateOneTimeKeys(0); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - - assertTrue(null == errorMessage); - - // keys number = negative value - errorMessage = null; - try { - mOlmAccount.generateOneTimeKeys(-50); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - - assertTrue(null != errorMessage); - } - - @Test - public void test15RemoveOneTimeKeysForSessionError() { - OlmAccount olmAccount = null; - try { - olmAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - - try { - olmAccount.removeOneTimeKeys(null); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - olmAccount.releaseAccount(); - } - - @Test - public void test16SignMessageError() { - OlmAccount olmAccount = null; - try { - olmAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - String signedMsg = null; - - try { - signedMsg = olmAccount.signMessage(null); - } catch (Exception e) { - } - - assertNull(signedMsg); - - olmAccount.releaseAccount(); - } - - /** - * Create multiple accounts and check that identity keys are still different. - * This test validates random series are provide enough random values. - */ - @Test - public void test17MultipleAccountCreation() { - try { - OlmAccount account1 = new OlmAccount(); - OlmAccount account2 = new OlmAccount(); - OlmAccount account3 = new OlmAccount(); - OlmAccount account4 = new OlmAccount(); - OlmAccount account5 = new OlmAccount(); - OlmAccount account6 = new OlmAccount(); - OlmAccount account7 = new OlmAccount(); - OlmAccount account8 = new OlmAccount(); - OlmAccount account9 = new OlmAccount(); - OlmAccount account10 = new OlmAccount(); - - Map identityKeys1 = account1.identityKeys(); - Map identityKeys2 = account2.identityKeys(); - Map identityKeys3 = account3.identityKeys(); - Map identityKeys4 = account4.identityKeys(); - Map identityKeys5 = account5.identityKeys(); - Map identityKeys6 = account6.identityKeys(); - Map identityKeys7 = account7.identityKeys(); - Map identityKeys8 = account8.identityKeys(); - Map identityKeys9 = account9.identityKeys(); - Map identityKeys10 = account10.identityKeys(); - - String identityKey1 = TestHelper.getIdentityKey(identityKeys1); - String identityKey2 = TestHelper.getIdentityKey(identityKeys2); - assertFalse(identityKey1.equals(identityKey2)); - - String identityKey3 = TestHelper.getIdentityKey(identityKeys3); - assertFalse(identityKey2.equals(identityKey3)); - - String identityKey4 = TestHelper.getIdentityKey(identityKeys4); - assertFalse(identityKey3.equals(identityKey4)); - - String identityKey5 = TestHelper.getIdentityKey(identityKeys5); - assertFalse(identityKey4.equals(identityKey5)); - - String identityKey6 = TestHelper.getIdentityKey(identityKeys6); - assertFalse(identityKey5.equals(identityKey6)); - - String identityKey7 = TestHelper.getIdentityKey(identityKeys7); - assertFalse(identityKey6.equals(identityKey7)); - - String identityKey8 = TestHelper.getIdentityKey(identityKeys8); - assertFalse(identityKey7.equals(identityKey8)); - - String identityKey9 = TestHelper.getIdentityKey(identityKeys9); - assertFalse(identityKey8.equals(identityKey9)); - - String identityKey10 = TestHelper.getIdentityKey(identityKeys10); - assertFalse(identityKey9.equals(identityKey10)); - - account1.releaseAccount(); - account2.releaseAccount(); - account3.releaseAccount(); - account4.releaseAccount(); - account5.releaseAccount(); - account6.releaseAccount(); - account7.releaseAccount(); - account8.releaseAccount(); - account9.releaseAccount(); - account10.releaseAccount(); - - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - } -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java deleted file mode 100644 index 9be6375..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.content.Context; -import android.support.test.runner.AndroidJUnit4; -import android.text.TextUtils; -import android.util.Log; - -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -import static android.support.test.InstrumentationRegistry.getInstrumentation; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class OlmGroupSessionTest { - private static final String LOG_TAG = "OlmSessionTest"; - private final String FILE_NAME_SERIAL_OUT_SESSION = "SerialOutGroupSession"; - private final String FILE_NAME_SERIAL_IN_SESSION = "SerialInGroupSession"; - - private static OlmManager mOlmManager; - private static OlmOutboundGroupSession mAliceOutboundGroupSession; - private static String mAliceSessionIdentifier; - private static long mAliceMessageIndex; - private static final String CLEAR_MESSAGE1 = "Hello!"; - private static String mAliceToBobMessage; - private static OlmInboundGroupSession mBobInboundGroupSession; - private static String mAliceOutboundSessionKey; - private static String mBobSessionIdentifier; - private static String mBobDecryptedMessage; - - @BeforeClass - public static void setUpClass(){ - // load native lib - mOlmManager = new OlmManager(); - - String version = mOlmManager.getOlmLibVersion(); - assertNotNull(version); - Log.d(LOG_TAG, "## setUpClass(): lib version="+version); - } - - /** - * Basic test: - * - alice creates an outbound group session - * - bob creates an inbound group session with alice's outbound session key - * - alice encrypts a message with its session - * - bob decrypts the encrypted message with its session - * - decrypted message is identical to original alice message - */ - @Test - public void test01CreateOutboundSession() { - // alice creates OUTBOUND GROUP SESSION - try { - mAliceOutboundGroupSession = new OlmOutboundGroupSession(); - } catch (OlmException e) { - assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - } - - @Test - public void test02GetOutboundGroupSessionIdentifier() { - // test session ID - mAliceSessionIdentifier = null; - - try { - mAliceSessionIdentifier = mAliceOutboundGroupSession.sessionIdentifier(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(mAliceSessionIdentifier); - assertTrue(mAliceSessionIdentifier.length() > 0); - } - - @Test - public void test03GetOutboundGroupSessionKey() { - // test session Key - mAliceOutboundSessionKey = null; - - try { - mAliceOutboundSessionKey = mAliceOutboundGroupSession.sessionKey(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(mAliceOutboundSessionKey); - assertTrue(mAliceOutboundSessionKey.length() > 0); - } - - @Test - public void test04GetOutboundGroupMessageIndex() { - // test message index before any encryption - mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex(); - assertTrue(0 == mAliceMessageIndex); - } - - @Test - public void test05OutboundGroupEncryptMessage() { - // alice encrypts a message to bob - try { - mAliceToBobMessage = mAliceOutboundGroupSession.encryptMessage(CLEAR_MESSAGE1); - } catch (Exception e) { - assertTrue("Exception in bob encryptMessage, Exception code=" + e.getMessage(), false); - } - assertFalse(TextUtils.isEmpty(mAliceToBobMessage)); - - // test message index after encryption is incremented - mAliceMessageIndex = mAliceOutboundGroupSession.messageIndex(); - assertTrue(1 == mAliceMessageIndex); - } - - @Test - public void test06CreateInboundGroupSession() { - // bob creates INBOUND GROUP SESSION with alice outbound key - try { - mBobInboundGroupSession = new OlmInboundGroupSession(mAliceOutboundSessionKey); - } catch (OlmException e) { - assertTrue("Exception in bob OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - } - - @Test - public void test08GetInboundGroupSessionIdentifier() { - // check both session identifiers are equals - mBobSessionIdentifier = null; - - try { - mBobSessionIdentifier = mBobInboundGroupSession.sessionIdentifier(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertFalse(TextUtils.isEmpty(mBobSessionIdentifier)); - } - - @Test - public void test09SessionIdentifiersAreIdentical() { - // check both session identifiers are equals: alice vs bob - assertTrue(mAliceSessionIdentifier.equals(mBobSessionIdentifier)); - } - - @Test - public void test10InboundDecryptMessage() { - mBobDecryptedMessage = null; - OlmInboundGroupSession.DecryptMessageResult result = null; - - try { - result = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - // test decrypted message - mBobDecryptedMessage = result.mDecryptedMessage; - assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); - assertTrue(0 == result.mIndex); - } - - @Test - public void test11InboundDecryptedMessageIdentical() { - // test decrypted message - assertTrue(mBobDecryptedMessage.equals(CLEAR_MESSAGE1)); - } - - @Test - public void test12ReleaseOutboundSession() { - // release group sessions - mAliceOutboundGroupSession.releaseSession(); - } - - @Test - public void test13ReleaseInboundSession() { - // release group sessions - mBobInboundGroupSession.releaseSession(); - } - - @Test - public void test14CheckUnreleaseedCount() { - assertTrue(mAliceOutboundGroupSession.isReleased()); - assertTrue(mBobInboundGroupSession.isReleased()); - } - - @Test - public void test15SerializeOutboundSession() { - OlmOutboundGroupSession outboundGroupSessionRef=null; - OlmOutboundGroupSession outboundGroupSessionSerial; - - // create one OUTBOUND GROUP SESSION - try { - outboundGroupSessionRef = new OlmOutboundGroupSession(); - } catch (OlmException e) { - assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - assertNotNull(outboundGroupSessionRef); - - - // serialize alice session - Context context = getInstrumentation().getContext(); - try { - FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_OUT_SESSION, Context.MODE_PRIVATE); - ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); - objectOutput.writeObject(outboundGroupSessionRef); - objectOutput.flush(); - objectOutput.close(); - - // deserialize session - FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_OUT_SESSION); - ObjectInputStream objectInput = new ObjectInputStream(fileInput); - outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject(); - assertNotNull(outboundGroupSessionSerial); - objectInput.close(); - - // get sessions keys - String sessionKeyRef = outboundGroupSessionRef.sessionKey(); - String sessionKeySerial = outboundGroupSessionSerial.sessionKey(); - assertFalse(TextUtils.isEmpty(sessionKeyRef)); - assertFalse(TextUtils.isEmpty(sessionKeySerial)); - - // session keys comparison - assertTrue(sessionKeyRef.equals(sessionKeySerial)); - - // get sessions IDs - String sessionIdRef = outboundGroupSessionRef.sessionIdentifier(); - String sessionIdSerial = outboundGroupSessionSerial.sessionIdentifier(); - assertFalse(TextUtils.isEmpty(sessionIdRef)); - assertFalse(TextUtils.isEmpty(sessionIdSerial)); - - // session IDs comparison - assertTrue(sessionIdRef.equals(sessionIdSerial)); - - outboundGroupSessionRef.releaseSession(); - outboundGroupSessionSerial.releaseSession(); - - assertTrue(outboundGroupSessionRef.isReleased()); - assertTrue(outboundGroupSessionSerial.isReleased()); - } catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (OlmException e) { - Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception OlmException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (IOException e) { - Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception IOException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (Exception e) { - Log.e(LOG_TAG, "## test15SerializeOutboundSession(): Exception Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } - } - - @Test - public void test16SerializeInboundSession() { - OlmOutboundGroupSession aliceOutboundGroupSession=null; - OlmInboundGroupSession bobInboundGroupSessionRef=null; - OlmInboundGroupSession bobInboundGroupSessionSerial; - - // alice creates OUTBOUND GROUP SESSION - try { - aliceOutboundGroupSession = new OlmOutboundGroupSession(); - } catch (OlmException e) { - assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - assertNotNull(aliceOutboundGroupSession); - - // get the session key from the outbound group session - String sessionKeyRef = null; - - try { - sessionKeyRef = aliceOutboundGroupSession.sessionKey(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(sessionKeyRef); - - // bob creates INBOUND GROUP SESSION - try { - bobInboundGroupSessionRef = new OlmInboundGroupSession(sessionKeyRef); - } catch (OlmException e) { - assertTrue("Exception in OlmInboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - assertNotNull(bobInboundGroupSessionRef); - - // serialize alice session - Context context = getInstrumentation().getContext(); - try { - FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_IN_SESSION, Context.MODE_PRIVATE); - ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); - objectOutput.writeObject(bobInboundGroupSessionRef); - objectOutput.flush(); - objectOutput.close(); - - // deserialize session - FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_IN_SESSION); - ObjectInputStream objectInput = new ObjectInputStream(fileInput); - bobInboundGroupSessionSerial = (OlmInboundGroupSession)objectInput.readObject(); - assertNotNull(bobInboundGroupSessionSerial); - objectInput.close(); - - // get sessions IDs - String aliceSessionId = aliceOutboundGroupSession.sessionIdentifier(); - String sessionIdRef = bobInboundGroupSessionRef.sessionIdentifier(); - String sessionIdSerial = bobInboundGroupSessionSerial.sessionIdentifier(); - assertFalse(TextUtils.isEmpty(aliceSessionId)); - assertFalse(TextUtils.isEmpty(sessionIdRef)); - assertFalse(TextUtils.isEmpty(sessionIdSerial)); - - // session IDs comparison - assertTrue(aliceSessionId.equals(sessionIdSerial)); - assertTrue(sessionIdRef.equals(sessionIdSerial)); - - aliceOutboundGroupSession.releaseSession(); - bobInboundGroupSessionRef.releaseSession(); - bobInboundGroupSessionSerial.releaseSession(); - - assertTrue(aliceOutboundGroupSession.isReleased()); - assertTrue(bobInboundGroupSessionRef.isReleased()); - assertTrue(bobInboundGroupSessionSerial.isReleased()); - } catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception FileNotFoundException Msg=="+e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception ClassNotFoundException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (OlmException e) { - Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception OlmException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (IOException e) { - Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception IOException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } catch (Exception e) { - Log.e(LOG_TAG, "## test16SerializeInboundSession(): Exception Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } - } - - /** - * Create multiple outbound group sessions and check that session Keys are different. - * This test validates random series are provide enough random values. - */ - @Test - public void test17MultipleOutboundSession() { - OlmOutboundGroupSession outboundGroupSession1; - OlmOutboundGroupSession outboundGroupSession2; - OlmOutboundGroupSession outboundGroupSession3; - OlmOutboundGroupSession outboundGroupSession4; - OlmOutboundGroupSession outboundGroupSession5; - OlmOutboundGroupSession outboundGroupSession6; - OlmOutboundGroupSession outboundGroupSession7; - OlmOutboundGroupSession outboundGroupSession8; - - try { - outboundGroupSession1 = new OlmOutboundGroupSession(); - outboundGroupSession2 = new OlmOutboundGroupSession(); - outboundGroupSession3 = new OlmOutboundGroupSession(); - outboundGroupSession4 = new OlmOutboundGroupSession(); - outboundGroupSession5 = new OlmOutboundGroupSession(); - outboundGroupSession6 = new OlmOutboundGroupSession(); - outboundGroupSession7 = new OlmOutboundGroupSession(); - outboundGroupSession8 = new OlmOutboundGroupSession(); - - // get the session key from the outbound group sessions - String sessionKey1 = outboundGroupSession1.sessionKey(); - String sessionKey2 = outboundGroupSession2.sessionKey(); - assertFalse(sessionKey1.equals(sessionKey2)); - - String sessionKey3 = outboundGroupSession3.sessionKey(); - assertFalse(sessionKey2.equals(sessionKey3)); - - String sessionKey4 = outboundGroupSession4.sessionKey(); - assertFalse(sessionKey3.equals(sessionKey4)); - - String sessionKey5 = outboundGroupSession5.sessionKey(); - assertFalse(sessionKey4.equals(sessionKey5)); - - String sessionKey6 = outboundGroupSession6.sessionKey(); - assertFalse(sessionKey5.equals(sessionKey6)); - - String sessionKey7 = outboundGroupSession7.sessionKey(); - assertFalse(sessionKey6.equals(sessionKey7)); - - String sessionKey8 = outboundGroupSession8.sessionKey(); - assertFalse(sessionKey7.equals(sessionKey8)); - - // get the session IDs from the outbound group sessions - String sessionId1 = outboundGroupSession1.sessionIdentifier(); - String sessionId2 = outboundGroupSession2.sessionIdentifier(); - assertFalse(sessionId1.equals(sessionId2)); - - String sessionId3 = outboundGroupSession3.sessionKey(); - assertFalse(sessionId2.equals(sessionId3)); - - String sessionId4 = outboundGroupSession4.sessionKey(); - assertFalse(sessionId3.equals(sessionId4)); - - String sessionId5 = outboundGroupSession5.sessionKey(); - assertFalse(sessionId4.equals(sessionId5)); - - String sessionId6 = outboundGroupSession6.sessionKey(); - assertFalse(sessionId5.equals(sessionId6)); - - String sessionId7 = outboundGroupSession7.sessionKey(); - assertFalse(sessionId6.equals(sessionId7)); - - String sessionId8 = outboundGroupSession8.sessionKey(); - assertFalse(sessionId7.equals(sessionId8)); - - outboundGroupSession1.releaseSession(); - outboundGroupSession2.releaseSession(); - outboundGroupSession3.releaseSession(); - outboundGroupSession4.releaseSession(); - outboundGroupSession5.releaseSession(); - outboundGroupSession6.releaseSession(); - outboundGroupSession7.releaseSession(); - outboundGroupSession8.releaseSession(); - - assertTrue(outboundGroupSession1.isReleased()); - assertTrue(outboundGroupSession2.isReleased()); - assertTrue(outboundGroupSession3.isReleased()); - assertTrue(outboundGroupSession4.isReleased()); - assertTrue(outboundGroupSession5.isReleased()); - assertTrue(outboundGroupSession6.isReleased()); - assertTrue(outboundGroupSession7.isReleased()); - assertTrue(outboundGroupSession8.isReleased()); - } catch (OlmException e) { - assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); - } - } - - /** - * Specific test for the following run time error: - * "JNI DETECTED ERROR IN APPLICATION: input is not valid Modified UTF-8: illegal start byte 0xf0 in call to NewStringUTF".
- * When the msg to decrypt contain emojis, depending on the android platform, the NewStringUTF() behaves differently and - * can even crash. - * This issue is described in details here: https://github.com/eclipsesource/J2V8/issues/142 - */ - @Test - public void test18TestBadCharacterCrashInDecrypt() { - OlmInboundGroupSession bobInboundGroupSession=null; - - // values taken from a "real life" crash case - String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; - String msgToDecryptWithEmoji = "AwgNEpABpjs+tYF+0y8bWtzAgYAC3N55p5cPJEEiGPU1kxIHSY7f2aG5Fj4wmcsXUkhDv0UePj922kgf+Q4dFsPHKq2aVA93n8DJAQ/FRfcM98B9E6sKCZ/PsCF78uBvF12Aaq9D3pUHBopdd7llUfVq29d5y6ZwX5VDoqV2utsATkKjXYV9CbfZuvvBMQ30ZLjEtyUUBJDY9K4FxEFcULytA/IkVnATTG9ERuLF/yB6ukSFR+iUWRYAmtuOuU0k9BvaqezbGqNoK5Grlkes+dYX6/0yUObumcw9/iAI"; - - // bob creates INBOUND GROUP SESSION - try { - bobInboundGroupSession = new OlmInboundGroupSession(sessionKeyRef); - } catch (OlmException e) { - assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false); - } - - OlmInboundGroupSession.DecryptMessageResult result = null; - - try { - result = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji); - } catch (Exception e) { - assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getMessage(), false); - } - - assertNotNull(result.mDecryptedMessage); - assertTrue(13 == result.mIndex); - } - - /** - * Specific test to check an error message is returned by decryptMessage() API.
- * A corrupted encrypted message is passed, and a INVALID_BASE64 is - * espexted. - **/ - @Test - public void test19TestErrorMessageReturnedInDecrypt() { - OlmInboundGroupSession bobInboundGroupSession=null; - final String EXPECTED_ERROR_MESSAGE= "INVALID_BASE64"; - - String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; - String corruptedEncryptedMsg = "AwgANYTHINGf87ge45ge7gr*/rg5ganything4gr41rrgr4re55tanythingmcsXUkhDv0UePj922kgf+"; - - // valid INBOUND GROUP SESSION - try { - bobInboundGroupSession = new OlmInboundGroupSession(sessionKeyRef); - } catch (OlmException e) { - assertTrue("Exception in test19TestErrorMessageReturnedInDecrypt, Exception code=" + e.getExceptionCode(), false); - } - - String exceptionMessage = null; - try { - bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg); - } catch (OlmException e) { - exceptionMessage = e.getMessage(); - } - - assertTrue(0!=EXPECTED_ERROR_MESSAGE.length()); - assertTrue(EXPECTED_ERROR_MESSAGE.equals(exceptionMessage)); - } -} - diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java deleted file mode 100644 index e08b151..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.content.Context; -import android.support.test.runner.AndroidJUnit4; -import android.text.TextUtils; -import android.util.Log; - -import org.json.JSONObject; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.util.Map; - -import static android.support.test.InstrumentationRegistry.getInstrumentation; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class OlmSessionTest { - private static final String LOG_TAG = "OlmSessionTest"; - private final String INVALID_PRE_KEY = "invalid PRE KEY hu hu!"; - private final String FILE_NAME_SERIAL_SESSION = "SerialSession"; - private final int ONE_TIME_KEYS_NUMBER = 4; - - private static OlmManager mOlmManager; - - @BeforeClass - public static void setUpClass(){ - // load native lib - mOlmManager = new OlmManager(); - - String version = mOlmManager.getOlmLibVersion(); - assertNotNull(version); - Log.d(LOG_TAG, "## setUpClass(): lib version="+version); - } - - /** - * Basic test: - * - alice creates an account - * - bob creates an account - * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey) - * - alice encrypts a message with its session - * - bob creates an inbound session based on alice's encrypted message - * - bob decrypts the encrypted message with its session - */ - @Test - public void test01AliceToBob() { - final int ONE_TIME_KEYS_NUMBER = 5; - String bobIdentityKey = null; - String bobOneTimeKey=null; - OlmAccount bobAccount = null; - OlmAccount aliceAccount = null; - - // ALICE & BOB ACCOUNTS CREATION - try { - aliceAccount = new OlmAccount(); - bobAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - - // test accounts creation - assertTrue(0!=bobAccount.getOlmAccountId()); - assertTrue(0!=aliceAccount.getOlmAccountId()); - - // get bob identity key - Map bobIdentityKeys = null; - - try { - bobIdentityKeys = bobAccount.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); - assertTrue(null!=bobIdentityKey); - - // get bob one time keys - try { - bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - Map> bobOneTimeKeys = null; - - try { - bobOneTimeKeys = bobAccount.oneTimeKeys(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); - assertNotNull(bobOneTimeKey); - - // CREATE ALICE SESSION - OlmSession aliceSession = null; - try { - aliceSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - assertTrue(0!=aliceSession.getOlmSessionId()); - - // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - try { - aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - String clearMsg = "Heloo bob , this is alice!"; - OlmMessage encryptedMsgToBob = null; - try { - encryptedMsgToBob = aliceSession.encryptMessage(clearMsg); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsgToBob); - assertNotNull(encryptedMsgToBob.mCipherText); - Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText); - - // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = null; - try { - bobSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - assertTrue(0!=bobSession.getOlmSessionId()); - - try { - bobSession.initInboundSession(bobAccount, encryptedMsgToBob.mCipherText); - } catch (Exception e) { - assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); - } - - String decryptedMsg = null; - try { - decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(decryptedMsg); - - // MESSAGE COMPARISON: decrypted vs encrypted - assertTrue(clearMsg.equals(decryptedMsg)); - - // clean objects.. - try { - bobAccount.removeOneTimeKeys(bobSession); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - // release accounts - bobAccount.releaseAccount(); - aliceAccount.releaseAccount(); - assertTrue(bobAccount.isReleased()); - assertTrue(aliceAccount.isReleased()); - - // release sessions - bobSession.releaseSession(); - aliceSession.releaseSession(); - assertTrue(bobSession.isReleased()); - assertTrue(aliceSession.isReleased()); - } - - - /** - * Same as test01AliceToBob but with bob who's encrypting messages - * to alice and alice decrypt them.
- * - alice creates an account - * - bob creates an account - * - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey) - * - alice encrypts a message with its own session - * - bob creates an inbound session based on alice's encrypted message - * - bob decrypts the encrypted message with its own session - * - bob encrypts messages with its own session - * - alice decrypts bob's messages with its own message - * - alice encrypts a message - * - bob decrypts the encrypted message - */ - @Test - public void test02AliceToBobBackAndForth() { - String bobIdentityKey; - String bobOneTimeKey; - OlmAccount aliceAccount = null; - OlmAccount bobAccount = null; - - // creates alice & bob accounts - try { - aliceAccount = new OlmAccount(); - bobAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - - // test accounts creation - assertTrue(0!=bobAccount.getOlmAccountId()); - assertTrue(0!=aliceAccount.getOlmAccountId()); - - // get bob identity key - Map bobIdentityKeys = null; - - try { - bobIdentityKeys = bobAccount.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); - assertTrue(null!=bobIdentityKey); - - // get bob one time keys - try { - bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - Map> bobOneTimeKeys = null; - - try { - bobOneTimeKeys = bobAccount.oneTimeKeys(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); - assertNotNull(bobOneTimeKey); - - // CREATE ALICE SESSION - OlmSession aliceSession = null; - try { - aliceSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - assertTrue(0!=aliceSession.getOlmSessionId()); - - // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - try { - aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - String helloClearMsg = "Hello I'm Alice!"; - - OlmMessage encryptedAliceToBobMsg1 = null; - - try { - encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(encryptedAliceToBobMsg1); - assertNotNull(encryptedAliceToBobMsg1.mCipherText); - - // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = null; - try { - bobSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - - assertTrue(0!=bobSession.getOlmSessionId()); - - try { - bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); - } catch (Exception e) { - assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); - } - - // DECRYPT MESSAGE FROM ALICE - String decryptedMsg01 = null; - try { - decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(decryptedMsg01); - - // MESSAGE COMPARISON: decrypted vs encrypted - assertTrue(helloClearMsg.equals(decryptedMsg01)); - - // BACK/FORTH MESSAGE COMPARISON - String clearMsg1 = "Hello I'm Bob!"; - String clearMsg2 = "Isn't life grand?"; - String clearMsg3 = "Let's go to the opera."; - - // bob encrypts messages - OlmMessage encryptedMsg1 = null; - try { - encryptedMsg1 = bobSession.encryptMessage(clearMsg1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsg1); - - OlmMessage encryptedMsg2 = null; - try { - encryptedMsg2 = bobSession.encryptMessage(clearMsg2); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsg2); - - - OlmMessage encryptedMsg3 = null; - try { - encryptedMsg3 = bobSession.encryptMessage(clearMsg3); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsg3); - - // alice decrypts bob's messages - String decryptedMsg1 = null; - try { - decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(decryptedMsg1); - String decryptedMsg2 = null; - try { - decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(decryptedMsg2); - String decryptedMsg3 = null; - try { - decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(decryptedMsg3); - - // comparison tests - assertTrue(clearMsg1.equals(decryptedMsg1)); - assertTrue(clearMsg2.equals(decryptedMsg2)); - assertTrue(clearMsg3.equals(decryptedMsg3)); - - // and one more from alice to bob - clearMsg1 = "another message from Alice to Bob!!"; - encryptedMsg1 = null; - - try { - encryptedMsg1 = aliceSession.encryptMessage(clearMsg1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsg1); - - decryptedMsg1 = null; - try { - decryptedMsg1 = bobSession.decryptMessage(encryptedMsg1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(decryptedMsg1); - assertTrue(clearMsg1.equals(decryptedMsg1)); - - // comparison test - assertTrue(clearMsg1.equals(decryptedMsg1)); - - // clean objects.. - try { - bobAccount.removeOneTimeKeys(bobSession); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - bobAccount.releaseAccount(); - aliceAccount.releaseAccount(); - assertTrue(bobAccount.isReleased()); - assertTrue(aliceAccount.isReleased()); - - bobSession.releaseSession(); - aliceSession.releaseSession(); - assertTrue(bobSession.isReleased()); - assertTrue(aliceSession.isReleased()); - } - - - @Test - public void test03AliceBobSessionId() { - // creates alice & bob accounts - OlmAccount aliceAccount = null; - OlmAccount bobAccount = null; - try { - aliceAccount = new OlmAccount(); - bobAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - - // test accounts creation - assertTrue(0!=bobAccount.getOlmAccountId()); - assertTrue(0!=aliceAccount.getOlmAccountId()); - - // CREATE ALICE SESSION - - OlmSession aliceSession = null; - try { - aliceSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - assertTrue(0!=aliceSession.getOlmSessionId()); - - // CREATE ALICE SESSION - OlmSession bobSession = null; - try { - bobSession = new OlmSession(); - } catch (OlmException e) { - e.printStackTrace(); - assertTrue(e.getMessage(), false); - } - assertTrue(0!=bobSession.getOlmSessionId()); - - String aliceSessionId = null; - try { - aliceSessionId = aliceSession.sessionIdentifier(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(aliceSessionId); - - String bobSessionId = null; - try { - bobSessionId = bobSession.sessionIdentifier(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(bobSessionId); - - // must be the same for both ends of the conversation - assertTrue(aliceSessionId.equals(bobSessionId)); - - aliceAccount.releaseAccount(); - bobAccount.releaseAccount(); - assertTrue(aliceAccount.isReleased()); - assertTrue(bobAccount.isReleased()); - - bobSession.releaseSession(); - aliceSession.releaseSession(); - assertTrue(bobSession.isReleased()); - assertTrue(aliceSession.isReleased()); - } - - @Test - public void test04MatchInboundSession() { - OlmAccount aliceAccount=null, bobAccount=null; - OlmSession aliceSession = null, bobSession = null; - - // ACCOUNTS CREATION - try { - aliceAccount = new OlmAccount(); - bobAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(), false); - } - - // CREATE ALICE SESSION - try { - aliceSession = new OlmSession(); - bobSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg=" + e.getMessage(), false); - } - - // get bob/luke identity key - Map bobIdentityKeys = null; - - try { - bobIdentityKeys = bobAccount.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - Map aliceIdentityKeys = null; - - try { - aliceIdentityKeys = aliceAccount.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); - String aliceIdentityKey = TestHelper.getIdentityKey(aliceIdentityKeys); - - // get bob/luke one time keys - try { - bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - try { - aliceAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - Map> bobOneTimeKeys = null; - - try { - bobOneTimeKeys = bobAccount.oneTimeKeys(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - String bobOneTimeKey1 = TestHelper.getOneTimeKey(bobOneTimeKeys, 1); - - // create alice inbound session for bob - try { - aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - String aliceClearMsg = "hello helooo to bob!"; - OlmMessage encryptedAliceToBobMsg1 = null; - - try { - encryptedAliceToBobMsg1 = aliceSession.encryptMessage(aliceClearMsg); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertFalse(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); - - // init bob session with alice PRE KEY - try { - bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); - } catch (Exception e) { - assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); - } - - // test matchesInboundSession() and matchesInboundSessionFrom() - assertTrue(bobSession.matchesInboundSession(encryptedAliceToBobMsg1.mCipherText)); - assertTrue(bobSession.matchesInboundSessionFrom(aliceIdentityKey, encryptedAliceToBobMsg1.mCipherText)); - // following requires olm native lib new version with https://github.com/matrix-org/olm-backup/commit/7e9f3bebb8390f975a76c0188ce4cb460fe6692e - //assertTrue(false==bobSession.matchesInboundSessionFrom(bobIdentityKey, encryptedAliceToBobMsg1.mCipherText)); - - // release objects - try { - bobAccount.removeOneTimeKeys(bobSession); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - aliceAccount.releaseAccount(); - bobAccount.releaseAccount(); - assertTrue(aliceAccount.isReleased()); - assertTrue(bobAccount.isReleased()); - - aliceSession.releaseSession(); - bobSession.releaseSession(); - assertTrue(aliceSession.isReleased()); - assertTrue(bobSession.isReleased()); - } - - // ******************************************************** - // ************* SERIALIZATION TEST *********************** - // ******************************************************** - /** - * Same as {@link #test02AliceToBobBackAndForth()}, but alice's session - * is serialized and de-serialized before performing the final - * comparison (encrypt vs ) - */ - @Test - public void test05SessionSerialization() { - final int ONE_TIME_KEYS_NUMBER = 1; - String bobIdentityKey; - String bobOneTimeKey; - OlmAccount aliceAccount = null; - OlmAccount bobAccount = null; - OlmSession aliceSessionDeserial = null; - - // creates alice & bob accounts - try { - aliceAccount = new OlmAccount(); - bobAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - - // test accounts creation - assertTrue(0!=bobAccount.getOlmAccountId()); - assertTrue(0!=aliceAccount.getOlmAccountId()); - - // get bob identity key - Map bobIdentityKeys = null; - - try { - bobIdentityKeys = bobAccount.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); - assertTrue(null!=bobIdentityKey); - - // get bob one time keys - try { - bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - Map> bobOneTimeKeys = null; - - try { - bobOneTimeKeys = bobAccount.oneTimeKeys(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); - assertNotNull(bobOneTimeKey); - - // CREATE ALICE SESSION - OlmSession aliceSession = null; - try { - aliceSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - assertTrue(0!=aliceSession.getOlmSessionId()); - - // CREATE ALICE OUTBOUND SESSION and encrypt message to bob - try { - aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - String helloClearMsg = "Hello I'm Alice!"; - - OlmMessage encryptedAliceToBobMsg1 = null; - try { - encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedAliceToBobMsg1); - assertNotNull(encryptedAliceToBobMsg1.mCipherText); - - // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = null; - try { - bobSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - assertTrue(0!=bobSession.getOlmSessionId()); - - // init bob session with alice PRE KEY - try { - bobSession.initInboundSession(bobAccount, encryptedAliceToBobMsg1.mCipherText); - } catch (Exception e) { - assertTrue("initInboundSessionWithAccount failed " + e.getMessage(), false); - } - - // DECRYPT MESSAGE FROM ALICE - String decryptedMsg01 = null; - - try { - decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(decryptedMsg01); - - // MESSAGE COMPARISON: decrypted vs encrypted - assertTrue(helloClearMsg.equals(decryptedMsg01)); - - // BACK/FORTH MESSAGE COMPARISON - String clearMsg1 = "Hello I'm Bob!"; - String clearMsg2 = "Isn't life grand?"; - String clearMsg3 = "Let's go to the opera."; - - // bob encrypts messages - OlmMessage encryptedMsg1 = null; - try { - encryptedMsg1 = bobSession.encryptMessage(clearMsg1); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsg1); - - OlmMessage encryptedMsg2 = null; - try { - encryptedMsg2 = bobSession.encryptMessage(clearMsg2); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsg2); - - OlmMessage encryptedMsg3 = null; - try { - encryptedMsg3 = bobSession.encryptMessage(clearMsg3); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsg3); - - // serialize alice session - Context context = getInstrumentation().getContext(); - try { - FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE); - ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); - objectOutput.writeObject(aliceSession); - objectOutput.flush(); - objectOutput.close(); - - // deserialize session - FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION); - ObjectInputStream objectInput = new ObjectInputStream(fileInput); - aliceSessionDeserial = (OlmSession) objectInput.readObject(); - objectInput.close(); - - // test deserialize return value - assertNotNull(aliceSessionDeserial); - - // de-serialized alice session decrypts bob's messages - String decryptedMsg1 = aliceSessionDeserial.decryptMessage(encryptedMsg1); - assertNotNull(decryptedMsg1); - String decryptedMsg2 = aliceSessionDeserial.decryptMessage(encryptedMsg2); - assertNotNull(decryptedMsg2); - String decryptedMsg3 = aliceSessionDeserial.decryptMessage(encryptedMsg3); - assertNotNull(decryptedMsg3); - - // comparison tests - assertTrue(clearMsg1.equals(decryptedMsg1)); - assertTrue(clearMsg2.equals(decryptedMsg2)); - assertTrue(clearMsg3.equals(decryptedMsg3)); - - // clean objects.. - try { - bobAccount.removeOneTimeKeys(bobSession); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - bobAccount.releaseAccount(); - aliceAccount.releaseAccount(); - assertTrue(bobAccount.isReleased()); - assertTrue(aliceAccount.isReleased()); - - bobSession.releaseSession(); - aliceSession.releaseSession(); - aliceSessionDeserial.releaseSession(); - assertTrue(bobSession.isReleased()); - assertTrue(aliceSession.isReleased()); - assertTrue(aliceSessionDeserial.isReleased()); - } - catch (FileNotFoundException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); - assertTrue(e.getMessage(), false); - } - catch (ClassNotFoundException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } - catch (IOException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } - /*catch (OlmException e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); - }*/ - catch (Exception e) { - Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); - assertTrue(e.getMessage(), false); - } - } - - - // **************************************************** - // *************** SANITY CHECK TESTS ***************** - // **************************************************** - - @Test - public void test06SanityCheckErrors() { - final int ONE_TIME_KEYS_NUMBER = 5; - OlmAccount bobAccount = null; - OlmAccount aliceAccount = null; - - // ALICE & BOB ACCOUNTS CREATION - try { - aliceAccount = new OlmAccount(); - bobAccount = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(), false); - } - - // get bob identity key - Map bobIdentityKeys = null; - - try { - bobIdentityKeys = bobAccount.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - String bobIdentityKey = TestHelper.getIdentityKey(bobIdentityKeys); - assertTrue(null != bobIdentityKey); - - // get bob one time keys - try { - bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - Map> bobOneTimeKeys = null; - - try { - bobOneTimeKeys = bobAccount.oneTimeKeys(); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(bobOneTimeKeys); - String bobOneTimeKey = TestHelper.getOneTimeKey(bobOneTimeKeys,1); - assertNotNull(bobOneTimeKey); - - // CREATE ALICE SESSION - OlmSession aliceSession = null; - try { - aliceSession = new OlmSession(); - } catch (OlmException e) { - assertTrue("Exception Msg=" + e.getMessage(), false); - } - - // SANITY CHECK TESTS FOR: initOutboundSessionWithAccount() - String errorMessage = null; - try { - aliceSession.initOutboundSession(null, bobIdentityKey, bobOneTimeKey); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - assertTrue(null != errorMessage); - - errorMessage = null; - try { - aliceSession.initOutboundSession(aliceAccount, null, bobOneTimeKey); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - assertTrue(null != errorMessage); - - errorMessage = null; - try { - aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, null); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - assertTrue(null != errorMessage); - - errorMessage = null; - try { - aliceSession.initOutboundSession(null, null, null); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - assertTrue(null != errorMessage); - - // init properly - errorMessage = null; - try { - aliceSession.initOutboundSession(aliceAccount, bobIdentityKey, bobOneTimeKey); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - assertTrue(null == errorMessage); - - // SANITY CHECK TESTS FOR: encryptMessage() - OlmMessage message = null; - try { - message = aliceSession.encryptMessage(null); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertTrue(null==message); - - // encrypt properly - OlmMessage encryptedMsgToBob = null; - try { - encryptedMsgToBob = aliceSession.encryptMessage("A message for bob"); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - assertNotNull(encryptedMsgToBob); - - // SANITY CHECK TESTS FOR: initInboundSessionWithAccount() - OlmSession bobSession = null; - try { - bobSession = new OlmSession(); - errorMessage = null; - try { - bobSession.initInboundSession(null, encryptedMsgToBob.mCipherText); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - - assertTrue(!TextUtils.isEmpty(errorMessage)); - - errorMessage = null; - try { - bobSession.initInboundSession(bobAccount, null); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - - assertTrue(!TextUtils.isEmpty(errorMessage)); - - errorMessage = null; - try { - bobSession.initInboundSession(bobAccount, INVALID_PRE_KEY); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - - assertTrue(!TextUtils.isEmpty(errorMessage)); - - // init properly - errorMessage = null; - try { - bobSession.initInboundSession(bobAccount, encryptedMsgToBob.mCipherText); - } catch (Exception e) { - errorMessage = e.getMessage(); - } - - assertTrue(TextUtils.isEmpty(errorMessage)); - } catch (OlmException e) { - assertTrue("Exception Msg="+e.getMessage(), false); - } - - // SANITY CHECK TESTS FOR: decryptMessage() - String decryptedMsg = null; - try { - decryptedMsg = aliceSession.decryptMessage(null); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertTrue(null==decryptedMsg); - - // SANITY CHECK TESTS FOR: matchesInboundSession() - assertTrue(!aliceSession.matchesInboundSession(null)); - - // SANITY CHECK TESTS FOR: matchesInboundSessionFrom() - assertTrue(!aliceSession.matchesInboundSessionFrom(null,null)); - - // release objects - try { - bobAccount.removeOneTimeKeys(bobSession); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - aliceAccount.releaseAccount(); - bobAccount.releaseAccount(); - assertTrue(aliceAccount.isReleased()); - assertTrue(bobAccount.isReleased()); - - aliceSession.releaseSession(); - bobSession.releaseSession(); - assertTrue(aliceSession.isReleased()); - assertTrue(bobSession.isReleased()); - } - -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java deleted file mode 100644 index b560bff..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmUtilityTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.support.test.runner.AndroidJUnit4; -import android.text.TextUtils; -import android.util.Log; - -import org.json.JSONObject; -import org.junit.BeforeClass; -import org.junit.FixMethodOrder; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.junit.runners.MethodSorters; - -import java.util.Map; - -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -@RunWith(AndroidJUnit4.class) -@FixMethodOrder(MethodSorters.NAME_ASCENDING) -public class OlmUtilityTest { - private static final String LOG_TAG = "OlmAccountTest"; - private static final int GENERATION_ONE_TIME_KEYS_NUMBER = 50; - - private static OlmManager mOlmManager; - - @BeforeClass - public static void setUpClass(){ - // load native lib - mOlmManager = new OlmManager(); - - String version = mOlmManager.getOlmLibVersion(); - assertNotNull(version); - Log.d(LOG_TAG, "## setUpClass(): lib version="+version); - } - - /** - * Test the signing API - */ - @Test - public void test01VerifyEd25519Signing() { - String fingerPrintKey = null; - String errorMsg = null; - String message = "{\"algorithms\":[\"m.megolm.v1.aes-sha2\",\"m.olm.v1.curve25519-aes-sha2\"],\"device_id\":\"YMBYCWTWCG\",\"keys\":{\"curve25519:YMBYCWTWCG\":\"KZFa5YUXV2EOdhK8dcGMMHWB67stdgAP4+xwiS69mCU\",\"ed25519:YMBYCWTWCG\":\"0cEgQJJqjgtXUGp4ZXQQmh36RAxwxr8HJw2E9v1gvA0\"},\"user_id\":\"@mxBob14774891254276b253f42-f267-43ec-bad9-767142bfea30:localhost:8480\"}"; - OlmAccount account = null; - - // create account - try { - account = new OlmAccount(); - } catch (OlmException e) { - assertTrue(e.getMessage(),false); - } - assertNotNull(account); - - // sign message - String messageSignature = null; - - try { - messageSignature = account.signMessage(message); - } catch (Exception e) { - assertTrue(e.getMessage(), false); - } - - assertNotNull(messageSignature); - - // get identities key (finger print key) - Map identityKeys = null; - - try { - identityKeys = account.identityKeys(); - } catch (Exception e) { - assertTrue("identityKeys failed " + e.getMessage(), false); - } - - assertNotNull(identityKeys); - fingerPrintKey = TestHelper.getFingerprintKey(identityKeys); - assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey)); - - // instantiate utility object - OlmUtility utility = null; - - try { - utility = new OlmUtility(); - } catch (Exception e) { - assertTrue("failed to create OlmUtility", false); - } - - // verify signature - errorMsg = null; - try { - utility.verifyEd25519Signature(messageSignature, fingerPrintKey, message); - } catch (Exception e) { - errorMsg = e.getMessage(); - } - assertTrue(TextUtils.isEmpty(errorMsg)); - - // check a bad signature is detected => errorMsg = BAD_MESSAGE_MAC - String badSignature = "Bad signature Bad signature Bad signature.."; - - errorMsg = null; - try { - utility.verifyEd25519Signature(badSignature, fingerPrintKey, message); - } catch (Exception e) { - errorMsg = e.getMessage(); - } - assertTrue(!TextUtils.isEmpty(errorMsg)); - - // check bad fingerprint size => errorMsg = INVALID_BASE64 - String badSizeFingerPrintKey = fingerPrintKey.substring(fingerPrintKey.length()/2); - - errorMsg = null; - try { - utility.verifyEd25519Signature(messageSignature, badSizeFingerPrintKey, message); - } catch (Exception e) { - errorMsg = e.getMessage(); - } - assertTrue(!TextUtils.isEmpty(errorMsg)); - - utility.releaseUtility(); - assertTrue(utility.isReleased()); - - account.releaseAccount(); - assertTrue(account.isReleased()); - } - - @Test - public void test02sha256() { - OlmUtility utility = null; - - try { - utility = new OlmUtility(); - } catch (Exception e) { - assertTrue("OlmUtility creation failed", false); - } - String msgToHash = "The quick brown fox jumps over the lazy dog"; - - String hashResult = utility.sha256(msgToHash); - assertFalse(TextUtils.isEmpty(hashResult)); - - utility.releaseUtility(); - assertTrue(utility.isReleased()); - } -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java deleted file mode 100644 index 4451f7a..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/TestHelper.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import java.util.ArrayList; -import java.util.Map; - -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -/** - * Helper class providing helper methods used in the Olm Android SDK unit tests. - */ -public class TestHelper { - - /** - * Return the identity key {@link OlmAccount#JSON_KEY_IDENTITY_KEY} from the JSON object. - * @param aIdentityKeysMap result of {@link OlmAccount#identityKeys()} - * @return identity key string if operation succeed, null otherwise - */ - static public String getIdentityKey(Map aIdentityKeysMap){ - String idKey = null; - - try { - idKey = aIdentityKeysMap.get(OlmAccount.JSON_KEY_IDENTITY_KEY); - } catch (Exception e) { - assertTrue("Exception MSg=" + e.getMessage(), false); - } - return idKey; - } - - /** - * Return the fingerprint key {@link OlmAccount#JSON_KEY_FINGER_PRINT_KEY} from the JSON object. - * @param aIdentityKeysMap result of {@link OlmAccount#identityKeys()} - * @return fingerprint key string if operation succeed, null otherwise - */ - static public String getFingerprintKey(Map aIdentityKeysMap) { - String fingerprintKey = null; - - try { - fingerprintKey = aIdentityKeysMap.get(OlmAccount.JSON_KEY_FINGER_PRINT_KEY); - } catch (Exception e) { - assertTrue("Exception MSg=" + e.getMessage(), false); - } - return fingerprintKey; - } - - /** - * Return the first one time key from the JSON object. - * @param aIdentityKeysMap result of {@link OlmAccount#oneTimeKeys()} - * @param aKeyPosition the position of the key to be retrieved - * @return one time key string if operation succeed, null otherwise - */ - static public String getOneTimeKey(Map> aIdentityKeysMap, int aKeyPosition) { - String firstOneTimeKey = null; - - try { - Map generatedKeys = aIdentityKeysMap.get(OlmAccount.JSON_KEY_ONE_TIME_KEY); - assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY + " object is missing", generatedKeys); - - firstOneTimeKey = (new ArrayList<>(generatedKeys.values())).get(aKeyPosition - 1); - } catch (Exception e) { - assertTrue("Exception Msg=" + e.getMessage(), false); - } - return firstOneTimeKey; - } -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml b/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml deleted file mode 100644 index 902f2e3..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java deleted file mode 100644 index 229963f..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/CommonSerializeUtils.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.util.Log; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; - -/** - * Helper class dedicated to serialization mechanism (template method pattern). - */ -abstract class CommonSerializeUtils { - private static final String LOG_TAG = "CommonSerializeUtils"; - - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - protected void serialize(ObjectOutputStream aOutStream) throws IOException { - aOutStream.defaultWriteObject(); - - // generate serialization key - byte[] key = OlmUtility.getRandomKey(); - - // compute pickle string - StringBuffer errorMsg = new StringBuffer(); - byte[] pickledData = serialize(key, errorMsg); - - if(null == pickledData) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SERIALIZATION, String.valueOf(errorMsg)); - } else { - aOutStream.writeObject(new String(key, "UTF-8")); - aOutStream.writeObject(new String(pickledData, "UTF-8")); - } - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws Exception the exception - */ - protected void deserialize(ObjectInputStream aInStream) throws Exception { - aInStream.defaultReadObject(); - - String keyAsString = (String)aInStream.readObject(); - String pickledDataAsString = (String)aInStream.readObject(); - - byte[] key; - byte[] pickledData; - - try { - key = keyAsString.getBytes("UTF-8"); - pickledData = pickledDataAsString.getBytes("UTF-8"); - - deserialize(pickledData, key); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, e.getMessage()); - } - - Log.d(LOG_TAG,"## deserializeObject(): success"); - } - - protected abstract byte[] serialize(byte[] aKey, StringBuffer aErrorMsg); - protected abstract void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception; -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java deleted file mode 100644 index 26c3e60..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright 2017 OpenMarket Ltd - * Copyright 2017 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.text.TextUtils; -import android.util.Log; - -import org.json.JSONObject; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; -import java.util.Map; - -/** - * Account class used to create Olm sessions in conjunction with {@link OlmSession} class.
- * OlmAccount provides APIs to retrieve the Olm keys. - *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. - */ -public class OlmAccount extends CommonSerializeUtils implements Serializable { - private static final long serialVersionUID = 3497486121598434824L; - private static final String LOG_TAG = "OlmAccount"; - - // JSON keys used in the JSON objects returned by JNI - /** As well as the identity key, each device creates a number of Curve25519 key pairs which are - also used to establish Olm sessions, but can only be used once. Once again, the private part - remains on the device. but the public part is published to the Matrix network **/ - public static final String JSON_KEY_ONE_TIME_KEY = "curve25519"; - - /** Curve25519 identity key is a public-key cryptographic system which can be used to establish a shared - secret.
In Matrix, each device has a long-lived Curve25519 identity key which is used to establish - Olm sessions with that device. The private key should never leave the device, but the - public part is signed with the Ed25519 fingerprint key ({@link #JSON_KEY_FINGER_PRINT_KEY}) and published to the network. **/ - public static final String JSON_KEY_IDENTITY_KEY = "curve25519"; - - /** Ed25519 finger print is a public-key cryptographic system for signing messages.
In Matrix, each device has - an Ed25519 key pair which serves to identify that device. The private the key should - never leave the device, but the public part is published to the Matrix network. **/ - public static final String JSON_KEY_FINGER_PRINT_KEY = "ed25519"; - - /** Account Id returned by JNI. - * This value identifies uniquely the native account instance. - */ - private transient long mNativeId; - - public OlmAccount() throws OlmException { - try { - mNativeId = createNewAccountJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); - } - } - - /** - * Create a new account and return it to JAVA side.
- * Since a C prt is returned as a jlong, special care will be taken - * to make the cast (OlmAccount* to jlong) platform independent. - * @return the initialized OlmAccount* instance or throw an exception if fails - **/ - private native long createNewAccountJni(); - - /** - * Getter on the account ID. - * @return native account ID - */ - long getOlmAccountId(){ - return mNativeId; - } - - /** - * Release native account and invalid its JAVA reference counter part.
- * Public API for {@link #releaseAccountJni()}. - */ - public void releaseAccount() { - if (0 != mNativeId) { - releaseAccountJni(); - } - mNativeId = 0; - } - - /** - * Destroy the corresponding OLM account native object.
- * This method must ALWAYS be called when this JAVA instance - * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #createNewAccountJni()}. - */ - private native void releaseAccountJni(); - - /** - * Return true the object resources have been released.
- * @return true the object resources have been released - */ - public boolean isReleased() { - return (0 == mNativeId); - } - - /** - * Return the identity keys (identity and fingerprint keys) in a dictionary.
- * Public API for {@link #identityKeysJni()}.
- * Ex: - * { - * "curve25519":"Vam++zZPMqDQM6ANKpO/uAl5ViJSHxV9hd+b0/fwRAg", - * "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I" - * } - * @return identity keys dictionary if operation succeeds, null otherwise - * @exception OlmException the failure reason - */ - public Map identityKeys() throws OlmException { - JSONObject identityKeysJsonObj = null; - - byte[] identityKeysBuffer; - - try { - identityKeysBuffer = identityKeysJni(); - } catch (Exception e) { - Log.e(LOG_TAG, "## identityKeys(): Failure - " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS, e.getMessage()); - } - - if (null != identityKeysBuffer) { - try { - identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer, "UTF-8")); - } catch (Exception e) { - Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); - } - } else { - Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); - } - - return OlmUtility.toStringMap(identityKeysJsonObj); - } - - /** - * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
- * Keys are Base64 encoded. - * These keys must be published on the server. - * @return the identity keys or throw an exception if it fails - */ - private native byte[] identityKeysJni(); - - /** - * Return the largest number of "one time keys" this account can store. - * @return the max number of "one time keys", -1 otherwise - */ - public long maxOneTimeKeys() { - return maxOneTimeKeysJni(); - } - - /** - * Return the largest number of "one time keys" this account can store. - * @return the max number of "one time keys", -1 otherwise - */ - private native long maxOneTimeKeysJni(); - - /** - * Generate a number of new one time keys.
If total number of keys stored - * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded.
- * The corresponding keys are retrieved by {@link #oneTimeKeys()}. - * @param aNumberOfKeys number of keys to generate - * @exception OlmException the failure reason - */ - public void generateOneTimeKeys(int aNumberOfKeys) throws OlmException { - try { - generateOneTimeKeysJni(aNumberOfKeys); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS, e.getMessage()); - } - } - - /** - * Generate a number of new one time keys.
If total number of keys stored - * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. - * An exception is thrown if the operation fails.
- * @param aNumberOfKeys number of keys to generate - */ - private native void generateOneTimeKeysJni(int aNumberOfKeys); - - /** - * Return the "one time keys" in a dictionary.
- * The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}
- * Ex: - * { "curve25519": - * { - * "AAAABQ":"qefVZd8qvjOpsFzoKSAdfUnJVkIreyxWFlipCHjSQQg", - * "AAAABA":"/X8szMU+p+lsTnr56wKjaLgjTMQQkCk8EIWEAilZtQ8", - * "AAAAAw":"qxNxxFHzevFntaaPdT0fhhO7tc7pco4+xB/5VRG81hA", - * } - * }
- * Public API for {@link #oneTimeKeysJni()}.
- * Note: these keys are to be published on the server. - * @return one time keys in string dictionary. - * @exception OlmException the failure reason - */ - public Map> oneTimeKeys() throws OlmException { - JSONObject oneTimeKeysJsonObj = null; - byte[] oneTimeKeysBuffer; - - try { - oneTimeKeysBuffer = oneTimeKeysJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS, e.getMessage()); - } - - if( null != oneTimeKeysBuffer) { - try { - oneTimeKeysJsonObj = new JSONObject(new String(oneTimeKeysBuffer, "UTF-8")); - } catch (Exception e) { - Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); - } - } else { - Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); - } - - return OlmUtility.toStringMapMap(oneTimeKeysJsonObj); - } - - /** - * Get the public parts of the unpublished "one time keys" for the account.
- * The returned data is a JSON-formatted object with the single property - * curve25519, which is itself an object mapping key id to - * base64-encoded Curve25519 key.
- * @return byte array containing the one time keys or throw an exception if it fails - */ - private native byte[] oneTimeKeysJni(); - - /** - * Remove the "one time keys" that the session used from the account. - * @param aSession session instance - * @throws OlmException the failure reason - */ - public void removeOneTimeKeys(OlmSession aSession) throws OlmException { - if (null != aSession) { - try { - removeOneTimeKeysJni(aSession.getOlmSessionId()); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS, e.getMessage()); - } - } - } - - /** - * Remove the "one time keys" that the session used from the account. - * An exception is thrown if the operation fails. - * @param aNativeOlmSessionId native session instance identifier - */ - private native void removeOneTimeKeysJni(long aNativeOlmSessionId); - - /** - * Marks the current set of "one time keys" as being published. - * @exception OlmException the failure reason - */ - public void markOneTimeKeysAsPublished() throws OlmException { - try { - markOneTimeKeysAsPublishedJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED, e.getMessage()); - } - } - - /** - * Marks the current set of "one time keys" as being published. - * An exception is thrown if the operation fails. - */ - private native void markOneTimeKeysAsPublishedJni(); - - /** - * Sign a message with the ed25519 fingerprint key for this account.
- * The signed message is returned by the method. - * @param aMessage message to sign - * @return the signed message - * @exception OlmException the failure reason - */ - public String signMessage(String aMessage) throws OlmException { - String result = null; - - if (null != aMessage) { - try { - byte[] utf8String = aMessage.getBytes("UTF-8"); - - if (null != utf8String) { - byte[] signedMessage = signMessageJni(utf8String); - - if (null != signedMessage) { - result = new String(signedMessage, "UTF-8"); - } - } - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE, e.getMessage()); - } - } - - return result; - } - - /** - * Sign a message with the ed25519 fingerprint key for this account.
- * The signed message is returned by the method. - * @param aMessage message to sign - * @return the signed message - */ - private native byte[] signMessageJni(byte[] aMessage); - - //============================================================================================================== - // Serialization management - //============================================================================================================== - - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serialize(aOutStream); - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws Exception exception - */ - private void readObject(ObjectInputStream aInStream) throws Exception { - deserialize(aInStream); - } - - /** - * Return an account as a bytes buffer.
- * The account is serialized and encrypted with aKey. - * In case of failure, an error human readable - * description is provide in aErrorMsg. - * @param aKey encryption key - * @param aErrorMsg error message description - * @return the account as bytes buffer - */ - @Override - protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { - byte[] pickleRetValue = null; - - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); - } else if (null == aKey) { - aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); - } else { - aErrorMsg.setLength(0); - try { - pickleRetValue = serializeJni(aKey); - } catch (Exception e) { - Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return pickleRetValue; - } - - /** - * Serialize and encrypt account instance.
- * @param aKeyBuffer key used to encrypt the serialized account data - * @return the serialised account as bytes buffer. - **/ - private native byte[] serializeJni(byte[] aKeyBuffer); - - /** - * Loads an account from a pickled bytes buffer.
- * See {@link #serialize(byte[], StringBuffer)} - * @param aSerializedData bytes buffer - * @param aKey key used to encrypted - * @exception Exception the exception - */ - @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - String errorMsg = null; - - try { - if ((null == aSerializedData) || (null == aKey)) { - Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg = "invalid input parameters"; - } else { - mNativeId = deserializeJni(aSerializedData, aKey); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg = e.getMessage(); - } - - if (!TextUtils.isEmpty(errorMsg)) { - releaseAccount(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); - } - } - - /** - * Allocate a new account and initialize it with the serialisation data.
- * @param aSerializedDataBuffer the account serialisation buffer - * @param aKeyBuffer the key used to encrypt the serialized account data - * @return the deserialized account - **/ - private native long deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java deleted file mode 100644 index b0b1a6a..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2017 OpenMarket Ltd - * Copyright 2017 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import java.io.IOException; - -/** - * Exception class to identify specific Olm SDK exceptions. - */ -public class OlmException extends IOException { - // exception codes - - public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 10; - - public static final int EXCEPTION_CODE_ACCOUNT_SERIALIZATION = 100; - public static final int EXCEPTION_CODE_ACCOUNT_DESERIALIZATION = 101; - public static final int EXCEPTION_CODE_ACCOUNT_IDENTITY_KEYS = 102; - public static final int EXCEPTION_CODE_ACCOUNT_GENERATE_ONE_TIME_KEYS = 103; - public static final int EXCEPTION_CODE_ACCOUNT_ONE_TIME_KEYS = 104; - public static final int EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS = 105; - public static final int EXCEPTION_CODE_ACCOUNT_MARK_ONE_KEYS_AS_PUBLISHED = 106; - public static final int EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE = 107; - - public static final int EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION = 200; - public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 201; - public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER = 202; - public static final int EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION = 203; - - public static final int EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION = 300; - public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 301; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER = 302; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY = 303; - public static final int EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE = 304; - - public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 400; - public static final int EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION = 401; - public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION = 402; - public static final int EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM = 403; - public static final int EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE = 404; - public static final int EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE = 405; - public static final int EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER = 406; - - public static final int EXCEPTION_CODE_UTILITY_CREATION = 500; - public static final int EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE = 501; - - // exception human readable messages - public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters"; - - /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION}, - * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION}, {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}..**/ - private final int mCode; - - /** Human readable message description **/ - private final String mMessage; - - public OlmException(int aExceptionCode, String aExceptionMessage) { - super(); - mCode = aExceptionCode; - mMessage = aExceptionMessage; - } - - public int getExceptionCode() { - return mCode; - } - - @Override - public String getMessage() { - return mMessage; - } -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java deleted file mode 100644 index 571bddb..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2017 OpenMarket Ltd - * Copyright 2017 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.text.TextUtils; -import android.util.Log; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -/** - * Class used to create an inbound Megolm session.
- * Counter part of the outbound group session {@link OlmOutboundGroupSession}, this class decrypts the messages sent by the outbound side. - * - *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. - */ -public class OlmInboundGroupSession extends CommonSerializeUtils implements Serializable { - private static final long serialVersionUID = -772028491251653253L; - private static final String LOG_TAG = "OlmInboundGroupSession"; - - /** Session Id returned by JNI.
- * This value uniquely identifies the native inbound group session instance. - */ - private transient long mNativeId; - - /** - * Result in {@link #decryptMessage(String)} - */ - public static class DecryptMessageResult { - /** decrypt message **/ - public String mDecryptedMessage; - - /** decrypt index **/ - public long mIndex; - } - - /** - * Constructor.
- * Create and save a new native session instance ID and start a new inbound group session. - * The session key parameter is retrieved from an outbound group session. - * @param aSessionKey session key - * @throws OlmException constructor failure - */ - public OlmInboundGroupSession(String aSessionKey) throws OlmException { - if (TextUtils.isEmpty(aSessionKey)) { - Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); - } else { - try { - mNativeId = createNewSessionJni(aSessionKey.getBytes("UTF-8")); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); - } - } - } - - /** - * Initialize a new inbound group session and return it to JAVA side.
- * Since a C prt is returned as a jlong, special care will be taken - * to make the cast (OlmInboundGroupSession* to jlong) platform independent. - * @param aSessionKeyBuffer session key from an outbound session - * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. - **/ - private native long createNewSessionJni(byte[] aSessionKeyBuffer); - - /** - * Release native session and invalid its JAVA reference counter part.
- * Public API for {@link #releaseSessionJni()}. - */ - public void releaseSession(){ - if (0 != mNativeId) { - releaseSessionJni(); - } - mNativeId = 0; - } - - /** - * Destroy the corresponding OLM inbound group session native object.
- * This method must ALWAYS be called when this JAVA instance - * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #createNewSessionJni(byte[])}. - */ - private native void releaseSessionJni(); - - /** - * Return true the object resources have been released.
- * @return true the object resources have been released - */ - public boolean isReleased() { - return (0 == mNativeId); - } - - /** - * Retrieve the base64-encoded identifier for this inbound group session. - * @return the session ID - * @throws OlmException the failure reason - */ - public String sessionIdentifier() throws OlmException { - try { - return new String(sessionIdentifierJni(), "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_IDENTIFIER, e.getMessage()); - } - } - - /** - * Get a base64-encoded identifier for this inbound group session. - * An exception is thrown if the operation fails. - * @return the base64-encoded identifier - */ - private native byte[] sessionIdentifierJni(); - - /** - * Decrypt the message passed in parameter.
- * 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 - */ - public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws OlmException { - DecryptMessageResult result = new DecryptMessageResult(); - - try { - byte[] decryptedMessageBuffer = decryptMessageJni(aEncryptedMsg.getBytes("UTF-8"), result); - - if (null != decryptedMessageBuffer) { - result.mDecryptedMessage = new String(decryptedMessageBuffer, "UTF-8"); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## decryptMessage() failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_INBOUND_GROUP_SESSION_DECRYPT_SESSION, e.getMessage()); - } - - return result; - } - - /** - * Decrypt a message. - * An exception is thrown if the operation fails. - * @param aEncryptedMsg the encrypted message - * @param aDecryptMessageResult the decryptMessage informaton - * @return the decrypted message - */ - private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult); - - //============================================================================================================== - // Serialization management - //============================================================================================================== - - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serialize(aOutStream); - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws Exception exception - */ - private void readObject(ObjectInputStream aInStream) throws Exception { - deserialize(aInStream); - } - - /** - * Return the current inbound group session as a bytes buffer.
- * The session is serialized and encrypted with aKey. - * In case of failure, an error human readable - * description is provide in aErrorMsg. - * @param aKey encryption key - * @param aErrorMsg error message description - * @return pickled bytes buffer if operation succeed, null otherwise - */ - @Override - protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { - byte[] pickleRetValue = null; - - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); - aErrorMsg.append("aErrorMsg=null"); - } else if (null == aKey) { - aErrorMsg.append("Invalid input parameters in serialize()"); - } else { - aErrorMsg.setLength(0); - try { - pickleRetValue = serializeJni(aKey); - } catch (Exception e) { - Log.e(LOG_TAG, "## serialize() failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return pickleRetValue; - } - /** - * JNI counter part of {@link #serialize(byte[], StringBuffer)}. - * @param aKey encryption key - * @return the serialized session - */ - private native byte[] serializeJni(byte[] aKey); - - /** - * Loads an account from a pickled base64 string.
- * See {@link #serialize(byte[], StringBuffer)} - * @param aSerializedData pickled account in a bytes buffer - * @param aKey key used to encrypted - */ - @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - String errorMsg = null; - - try { - if ((null == aSerializedData) || (null == aKey)) { - Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg = "invalid input parameters"; - } else { - mNativeId = deserializeJni(aSerializedData, aKey); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg = e.getMessage(); - } - - if (!TextUtils.isEmpty(errorMsg)) { - releaseSession(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); - } - } - - /** - * Allocate a new session and initialize it with the serialisation data.
- * An exception is thrown if the operation fails. - * @param aSerializedData the session serialisation buffer - * @param aKey the key used to encrypt the serialized account data - * @return the deserialized session - **/ - private native long deserializeJni(byte[] aSerializedData, byte[] aKey); -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java deleted file mode 100644 index c1e6031..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.content.Context; -import android.util.Log; - -/** - * Olm SDK entry point class.
An OlmManager instance must be created at first to enable native library load. - *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. - */ -public class OlmManager { - private static final String LOG_TAG = "OlmManager"; - - /** - * Constructor. - */ - public OlmManager() { - } - - static { - try { - java.lang.System.loadLibrary("olm"); - } catch(UnsatisfiedLinkError e) { - Log.e(LOG_TAG,"Exception loadLibrary() - Msg="+e.getMessage()); - } - } - - /** - * Provide the android library version - * @param context the context - * @return the library version - */ - public String getSdkOlmVersion(Context context) { - String gitVersion = context.getResources().getString(R.string.git_olm_revision); - String date = context.getResources().getString(R.string.git_olm_revision_date); - return gitVersion + "-" + date; - } - - /** - * Get the OLM lib version. - * @return the lib version as a string - */ - public String getOlmLibVersion(){ - return getOlmLibVersionJni(); - } - public native String getOlmLibVersionJni(); -} - diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java deleted file mode 100644 index 08db993..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -/** - * Message class used in Olm sessions to contain the encrypted data.
- * See {@link OlmSession#decryptMessage(OlmMessage)} and {@link OlmSession#encryptMessage(String)}. - *
Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. - */ -public class OlmMessage { - /** PRE KEY message type (used to establish new Olm session) **/ - public final static int MESSAGE_TYPE_PRE_KEY = 0; - /** normal message type **/ - public final static int MESSAGE_TYPE_MESSAGE = 1; - - /** the encrypted message **/ - public String mCipherText; - - /** defined by {@link #MESSAGE_TYPE_MESSAGE} or {@link #MESSAGE_TYPE_PRE_KEY}**/ - public long mType; -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java deleted file mode 100644 index 0481824..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright 2017 OpenMarket Ltd - * Copyright 2017 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - - -import android.text.TextUtils; -import android.util.Log; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -/** - * Class used to create an outbound a Megolm session.
- * To send a first message in an encrypted room, the client should start a new outbound Megolm session. - * The session ID and the session key must be shared with each device in the room within. - * - *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. - */ -public class OlmOutboundGroupSession extends CommonSerializeUtils implements Serializable { - private static final long serialVersionUID = -3133097431283604416L; - private static final String LOG_TAG = "OlmOutboundGroupSession"; - - /** Session Id returned by JNI.
- * This value uniquely identifies the native outbound group session instance. - */ - private transient long mNativeId; - - /** - * Constructor.
- * Create and save a new session native instance ID and - * initialise a new outbound group session.
- * @throws OlmException constructor failure - */ - public OlmOutboundGroupSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, e.getMessage()); - } - } - - /** - * Create the corresponding OLM outbound group session in native side.
- * An exception is thrown if the operation fails. - * Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native session instance identifier (see {@link #mNativeId}) - */ - private native long createNewSessionJni(); - - /** - * Release native session and invalid its JAVA reference counter part.
- * Public API for {@link #releaseSessionJni()}. - */ - public void releaseSession() { - if (0 != mNativeId) { - releaseSessionJni(); - } - mNativeId = 0; - } - - /** - * Destroy the corresponding OLM outbound group session native object.
- * This method must ALWAYS be called when this JAVA instance - * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #createNewSessionJni()}. - */ - private native void releaseSessionJni(); - - /** - * Return true the object resources have been released.
- * @return true the object resources have been released - */ - public boolean isReleased() { - return (0 == mNativeId); - } - - /** - * Get a base64-encoded identifier for this session. - * @return session identifier - * @throws OlmException the failure reason - */ - public String sessionIdentifier() throws OlmException { - try { - return new String(sessionIdentifierJni(), "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## sessionIdentifier() failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_IDENTIFIER, e.getMessage()); - } - } - - /** - * Return the session identifier. - * An exception is thrown if the operation fails. - * @return the session identifier - */ - private native byte[] sessionIdentifierJni(); - - /** - * Get the current message index for this session.
- * Each message is sent with an increasing index, this - * method returns the index for the next message. - * @return current session index - */ - public int messageIndex() { - return messageIndexJni(); - } - - /** - * Get the current message index for this session.
- * Each message is sent with an increasing index, this - * method returns the index for the next message. - * An exception is thrown if the operation fails. - * @return current session index - */ - private native int messageIndexJni(); - - /** - * Get the base64-encoded current ratchet key for this session.
- * Each message is sent with a different ratchet key. This method returns the - * ratchet key that will be used for the next message. - * @return outbound session key - * @exception OlmException the failure reason - */ - public String sessionKey() throws OlmException { - try { - return new String(sessionKeyJni(), "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## sessionKey() failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY, e.getMessage()); - } - } - - /** - * Return the session key. - * An exception is thrown if the operation fails. - * @return the session key - */ - private native byte[] sessionKeyJni(); - - /** - * Encrypt some plain-text message.
- * The message given as parameter is encrypted and returned as the return value. - * @param aClearMsg message to be encrypted - * @return the encrypted message - * @exception OlmException the encryption failure reason - */ - public String encryptMessage(String aClearMsg) throws OlmException { - String retValue = null; - - if (!TextUtils.isEmpty(aClearMsg)) { - try { - byte[] encryptedBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8")); - - if (null != encryptedBuffer) { - retValue = new String(encryptedBuffer , "UTF-8"); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## encryptMessage() failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_ENCRYPT_MESSAGE, e.getMessage()); - } - } - - return retValue; - } - - /** - * Encrypt a bytes buffer messages. - * An exception is thrown if the operation fails. - * @param aClearMsgBuffer the message to encode - * @return the encoded message - */ - private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); - - //============================================================================================================== - // Serialization management - //============================================================================================================== - - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serialize(aOutStream); - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws Exception exception - */ - private void readObject(ObjectInputStream aInStream) throws Exception { - deserialize(aInStream); - } - - /** - * Return the current outbound group session as a base64 byte buffers.
- * The session is serialized and encrypted with aKey. - * In case of failure, an error human readable - * description is provide in aErrorMsg. - * @param aKey encryption key - * @param aErrorMsg error message description - * @return pickled base64 bytes buffer if operation succeed, null otherwise - */ - @Override - protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { - byte[] pickleRetValue = null; - - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serialize(): invalid parameter - aErrorMsg=null"); - } else if (null == aKey) { - aErrorMsg.append("Invalid input parameters in serialize()"); - } else { - try { - pickleRetValue = serializeJni(aKey); - } catch (Exception e) { - Log.e(LOG_TAG,"## serialize(): failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return pickleRetValue; - } - - /** - * JNI counter part of {@link #serialize(byte[], StringBuffer)}. - * An exception is thrown if the operation fails. - * @param aKey encryption key - * @return the serialized session - */ - private native byte[] serializeJni(byte[] aKey); - - /** - * Loads an account from a pickled base64 string.
- * See {@link #serialize(byte[], StringBuffer)} - * @param aSerializedData pickled account in a base64 bytes buffer - * @param aKey key used to encrypted - * @exception Exception the exception - */ - @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - String errorMsg = null; - - try { - if ((null == aSerializedData) || (null == aKey)) { - Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg = "invalid input parameters"; - } else { - mNativeId = deserializeJni(aSerializedData, aKey); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg = e.getMessage(); - } - - if (!TextUtils.isEmpty(errorMsg)) { - releaseSession(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); - } - } - - /** - * Allocate a new session and initialize it with the serialisation data.
- * An exception is thrown if the operation fails. - * @param aSerializedData the session serialisation buffer - * @param aKey the key used to encrypt the serialized account data - * @return the deserialized session - **/ - private native long deserializeJni(byte[] aSerializedData, byte[] aKey); - -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java deleted file mode 100644 index da2e963..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java +++ /dev/null @@ -1,445 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.text.TextUtils; -import android.util.Log; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.ObjectOutputStream; -import java.io.Serializable; - -/** - * Session class used to create Olm sessions in conjunction with {@link OlmAccount} class.
- * Olm session is used to encrypt data between devices, especially to create Olm group sessions (see {@link OlmOutboundGroupSession} and {@link OlmInboundGroupSession}).
- * To establish an Olm session with Bob, Alice calls {@link #initOutboundSession(OlmAccount, String, String)} with Bob's identity and onetime keys. Then Alice generates an encrypted PRE_KEY message ({@link #encryptMessage(String)}) - * used by Bob to open the Olm session in his side with {@link #initOutboundSession(OlmAccount, String, String)}. - * From this step on, messages can be exchanged by using {@link #encryptMessage(String)} and {@link #decryptMessage(OlmMessage)}. - *

Detailed implementation guide is available at Implementing End-to-End Encryption in Matrix clients. - */ -public class OlmSession extends CommonSerializeUtils implements Serializable { - private static final long serialVersionUID = -8975488639186976419L; - private static final String LOG_TAG = "OlmSession"; - - /** Session Id returned by JNI. - * This value uniquely identifies the native session instance. - **/ - private transient long mNativeId; - - public OlmSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, e.getMessage()); - } - } - - /** - * Create an OLM session in native side.
- * Do not forget to call {@link #releaseSession()} when JAVA side is done. - * @return native account instance identifier or throw an exception. - */ - private native long createNewSessionJni(); - - /** - * Getter on the session ID. - * @return native session ID - */ - long getOlmSessionId(){ - return mNativeId; - } - - /** - * Destroy the corresponding OLM session native object.
- * This method must ALWAYS be called when this JAVA instance - * is destroyed (ie. garbage collected) to prevent memory leak in native side. - * See {@link #createNewSessionJni()}. - */ - private native void releaseSessionJni(); - - /** - * Release native session and invalid its JAVA reference counter part.
- * Public API for {@link #releaseSessionJni()}. - */ - public void releaseSession() { - if (0 != mNativeId) { - releaseSessionJni(); - } - mNativeId = 0; - } - - /** - * Return true the object resources have been released.
- * @return true the object resources have been released - */ - public boolean isReleased() { - return (0 == mNativeId); - } - - /** - * Creates a new out-bound session for sending messages to a recipient - * identified by an identity key and a one time key.
- * @param aAccount the account to associate with this session - * @param aTheirIdentityKey the identity key of the recipient - * @param aTheirOneTimeKey the one time key of the recipient - * @exception OlmException the failure reason - */ - public void initOutboundSession(OlmAccount aAccount, String aTheirIdentityKey, String aTheirOneTimeKey) throws OlmException { - if ((null == aAccount) || TextUtils.isEmpty(aTheirIdentityKey) || TextUtils.isEmpty(aTheirOneTimeKey)) { - Log.e(LOG_TAG, "## initOutboundSession(): invalid input parameters"); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, "invalid input parameters"); - } else { - try { - initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aTheirOneTimeKey.getBytes("UTF-8")); - } catch (Exception e) { - Log.e(LOG_TAG, "## initOutboundSession(): " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_OUTBOUND_SESSION, e.getMessage()); - } - } - } - - /** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message.
The recipient is defined as the entity - * with whom the session is established. - * An exception is thrown if the operation fails. - * @param aOlmAccountId account instance - * @param aTheirIdentityKey the identity key of the recipient - * @param aTheirOneTimeKey the one time key of the recipient - **/ - private native void initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey); - - /** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message ({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}).
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * @param aAccount the account to associate with this session - * @param aPreKeyMsg PRE KEY message - * @exception OlmException the failure reason - */ - public void initInboundSession(OlmAccount aAccount, String aPreKeyMsg) throws OlmException { - if ((null == aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ - Log.e(LOG_TAG, "## initInboundSession(): invalid input parameters"); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, "invalid input parameters"); - } else { - try { - initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg.getBytes("UTF-8")); - } catch (Exception e) { - Log.e(LOG_TAG, "## initInboundSession(): " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION, e.getMessage()); - } - } - } - - /** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message.
- * An exception is thrown if the operation fails. - * @param aOlmAccountId account instance - * @param aOneTimeKeyMsg PRE_KEY message - */ - private native void initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg); - - /** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message based on the sender identity key.
- * Public API for {@link #initInboundSessionFromIdKeyJni(long, byte[], byte[])}. - * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * This method must only be called the first time a pre-key message is received from an inbound session. - * @param aAccount the account to associate with this session - * @param aTheirIdentityKey the sender identity key - * @param aPreKeyMsg PRE KEY message - * @exception OlmException the failure reason - */ - public void initInboundSessionFrom(OlmAccount aAccount, String aTheirIdentityKey, String aPreKeyMsg) throws OlmException { - if ( (null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ - Log.e(LOG_TAG, "## initInboundSessionFrom(): invalid input parameters"); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, "invalid input parameters"); - } else { - try { - initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey.getBytes("UTF-8"), aPreKeyMsg.getBytes("UTF-8")); - } catch (Exception e) { - Log.e(LOG_TAG, "## initInboundSessionFrom(): " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_INIT_INBOUND_SESSION_FROM, e.getMessage()); - } - } - } - - /** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message based on the recipient identity key.
- * An exception is thrown if the operation fails. - * @param aOlmAccountId account instance - * @param aTheirIdentityKey the identity key of the recipient - * @param aOneTimeKeyMsg encrypted message - */ - private native void initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); - - /** - * Get the session identifier.
Will be the same for both ends of the - * conversation. The session identifier is returned as a String object. - * Session Id sample: "session_id":"M4fOVwD6AABrkTKl" - * Public API for {@link #getSessionIdentifierJni()}. - * @return the session ID - * @exception OlmException the failure reason - */ - public String sessionIdentifier() throws OlmException { - try { - byte[] buffer = getSessionIdentifierJni(); - - if (null != buffer) { - return new String(buffer, "UTF-8"); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## sessionIdentifier(): " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SESSION_IDENTIFIER, e.getMessage()); - } - - return null; - } - - /** - * Get the session identifier for this session. - * An exception is thrown if the operation fails. - * @return the session identifier - */ - private native byte[] getSessionIdentifierJni(); - - /** - * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session.
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * Public API for {@link #matchesInboundSessionJni(byte[])}. - * @param aOneTimeKeyMsg PRE KEY message - * @return true if the one time key matches. - */ - public boolean matchesInboundSession(String aOneTimeKeyMsg) { - boolean retCode = false; - - try { - retCode = matchesInboundSessionJni(aOneTimeKeyMsg.getBytes("UTF-8")); - } catch (Exception e) { - Log.e(LOG_TAG, "## matchesInboundSession(): failed " + e.getMessage()); - } - - return retCode; - } - - /** - * Checks if the PRE_KEY message is for this in-bound session.
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * An exception is thrown if the operation fails. - * @param aOneTimeKeyMsg PRE KEY message - * @return true if the PRE_KEY message matches - */ - private native boolean matchesInboundSessionJni(byte[] aOneTimeKeyMsg); - - /** - * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session based on the sender identity key.
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * Public API for {@link #matchesInboundSessionJni(byte[])}. - * @param aTheirIdentityKey the sender identity key - * @param aOneTimeKeyMsg PRE KEY message - * @return this if operation succeed, null otherwise - */ - public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) { - boolean retCode = false; - - try { - retCode = matchesInboundSessionFromIdKeyJni(aTheirIdentityKey.getBytes("UTF-8"), aOneTimeKeyMsg.getBytes("UTF-8")); - } catch (Exception e) { - Log.e(LOG_TAG, "## matchesInboundSessionFrom(): failed " + e.getMessage()); - } - - return retCode; - } - - /** - * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * An exception is thrown if the operation fails. - * @param aTheirIdentityKey the identity key of the sender - * @param aOneTimeKeyMsg PRE KEY message - * @return true if the PRE_KEY message matches. - */ - private native boolean matchesInboundSessionFromIdKeyJni(byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); - - /** - * Encrypt a message using the session.
- * The encrypted message is returned in a OlmMessage object. - * Public API for {@link #encryptMessageJni(byte[], OlmMessage)}. - * @param aClearMsg message to encrypted - * @return the encrypted message - * @exception OlmException the failure reason - */ - public OlmMessage encryptMessage(String aClearMsg) throws OlmException { - if (null == aClearMsg) { - return null; - } - - OlmMessage encryptedMsgRetValue = new OlmMessage(); - - try { - byte[] encryptedMessageBuffer = encryptMessageJni(aClearMsg.getBytes("UTF-8"), encryptedMsgRetValue); - - if (null != encryptedMessageBuffer) { - encryptedMsgRetValue.mCipherText = new String(encryptedMessageBuffer, "UTF-8"); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## encryptMessage(): failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_ENCRYPT_MESSAGE, e.getMessage()); - } - - return encryptedMsgRetValue; - } - - /** - * Encrypt a message using the session.
- * An exception is thrown if the operation fails. - * @param aClearMsg clear text message - * @param aEncryptedMsg ciphered message - * @return the encrypted message - */ - private native byte[] encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); - - /** - * Decrypt a message using the session.
- * The encrypted message is given as a OlmMessage object. - * @param aEncryptedMsg message to decrypt - * @return the decrypted message - * @exception OlmException the failure reason - */ - public String decryptMessage(OlmMessage aEncryptedMsg) throws OlmException { - if (null == aEncryptedMsg) { - return null; - } - - try { - return new String(decryptMessageJni(aEncryptedMsg), "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## decryptMessage(): failed " + e.getMessage()); - throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage()); - } - } - /** - * Decrypt a message using the session.
- * An exception is thrown if the operation fails. - * @param aEncryptedMsg message to decrypt - * @return the decrypted message - */ - private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg); - - //============================================================================================================== - // Serialization management - //============================================================================================================== - - /** - * Kick off the serialization mechanism. - * @param aOutStream output stream for serializing - * @throws IOException exception - */ - private void writeObject(ObjectOutputStream aOutStream) throws IOException { - serialize(aOutStream); - } - - /** - * Kick off the deserialization mechanism. - * @param aInStream input stream - * @throws IOException exception - * @throws ClassNotFoundException exception - */ - private void readObject(ObjectInputStream aInStream) throws Exception { - deserialize(aInStream); - } - - /** - * Return a session as a bytes buffer.
- * The account is serialized and encrypted with aKey. - * In case of failure, an error human readable - * description is provide in aErrorMsg. - * @param aKey encryption key - * @param aErrorMsg error message description - * @return session as a bytes buffer - */ - @Override - protected byte[] serialize(byte[] aKey, StringBuffer aErrorMsg) { - byte[] pickleRetValue = null; - - // sanity check - if(null == aErrorMsg) { - Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); - } else if (null == aKey) { - aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); - } else { - aErrorMsg.setLength(0); - try { - pickleRetValue = serializeJni(aKey); - } catch (Exception e) { - Log.e(LOG_TAG,"## serializeDataWithKey(): failed " + e.getMessage()); - aErrorMsg.append(e.getMessage()); - } - } - - return pickleRetValue; - } - - /** - * Serialize and encrypt session instance.
- * An exception is thrown if the operation fails. - * @param aKeyBuffer key used to encrypt the serialized account data - * @return the serialised account as bytes buffer. - **/ - private native byte[] serializeJni(byte[] aKeyBuffer); - - /** - * Loads an account from a pickled base64 string.
- * See {@link #serialize(byte[], StringBuffer)} - * @param aSerializedData pickled account in a base64 string format - * @param aKey key used to encrypted - */ - @Override - protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - String errorMsg = null; - - try { - if ((null == aSerializedData) || (null == aKey)) { - Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); - errorMsg = "invalid input parameters"; - } else { - mNativeId = deserializeJni(aSerializedData, aKey); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); - errorMsg = e.getMessage(); - } - - if (!TextUtils.isEmpty(errorMsg)) { - releaseSession(); - throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); - } - } - /** - * Allocate a new session and initialize it with the serialisation data.
- * An exception is thrown if the operation fails. - * @param aSerializedData the session serialisation buffer - * @param aKey the key used to encrypt the serialized account data - * @return the deserialized session - **/ - private native long deserializeJni(byte[] aSerializedData, byte[] aKey); -} - diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java deleted file mode 100644 index bf9ef90..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2017 OpenMarket Ltd - * Copyright 2017 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.matrix.olm; - -import android.text.TextUtils; -import android.util.Log; - -import org.json.JSONObject; - -import java.security.SecureRandom; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -/** - * Olm SDK helper class. - */ -public class OlmUtility { - private static final String LOG_TAG = "OlmUtility"; - - public static final int RANDOM_KEY_SIZE = 32; - - /** Instance Id returned by JNI. - * This value uniquely identifies this utility instance. - **/ - private long mNativeId; - - public OlmUtility() throws OlmException { - initUtility(); - } - - /** - * Create a native utility instance. - * To be called before any other API call. - * @exception OlmException the exception - */ - private void initUtility() throws OlmException { - try { - mNativeId = createUtilityJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_UTILITY_CREATION, e.getMessage()); - } - } - - private native long createUtilityJni(); - - /** - * Release native instance.
- * Public API for {@link #releaseUtilityJni()}. - */ - public void releaseUtility() { - if (0 != mNativeId) { - releaseUtilityJni(); - } - mNativeId = 0; - } - private native void releaseUtilityJni(); - - /** - * Verify an ed25519 signature.
- * An exception is thrown if the operation fails. - * @param aSignature the base64-encoded message signature to be checked. - * @param aFingerprintKey the ed25519 key (fingerprint key) - * @param aMessage the signed message - * @exception OlmException the failure reason - */ - public void verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage) throws OlmException { - String errorMessage; - - try { - if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { - Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); - errorMessage = "JAVA sanity check failure - invalid input parameters"; - } else { - errorMessage = verifyEd25519SignatureJni(aSignature.getBytes("UTF-8"), aFingerprintKey.getBytes("UTF-8"), aMessage.getBytes("UTF-8")); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## verifyEd25519Signature(): failed " + e.getMessage()); - errorMessage = e.getMessage(); - } - - if (!TextUtils.isEmpty(errorMessage)) { - throw new OlmException(OlmException.EXCEPTION_CODE_UTILITY_VERIFY_SIGNATURE, errorMessage); - } - } - - /** - * Verify an ed25519 signature. - * Return a human readable error message in case of verification failure. - * @param aSignature the base64-encoded message signature to be checked. - * @param aFingerprintKey the ed25519 key - * @param aMessage the signed message - * @return null if validation succeed, the error message string if operation failed - */ - private native String verifyEd25519SignatureJni(byte[] aSignature, byte[] aFingerprintKey, byte[] aMessage); - - /** - * Compute the hash(SHA-256) value of the string given in parameter(aMessageToHash).
- * The hash value is the returned by the method. - * @param aMessageToHash message to be hashed - * @return hash value if operation succeed, null otherwise - */ - public String sha256(String aMessageToHash) { - String hashRetValue = null; - - if (null != aMessageToHash) { - try { - hashRetValue = new String(sha256Jni(aMessageToHash.getBytes("UTF-8")), "UTF-8"); - } catch (Exception e) { - Log.e(LOG_TAG, "## sha256(): failed " + e.getMessage()); - } - } - - return hashRetValue; - } - - /** - * Compute the digest (SHA 256) for the message passed in parameter.
- * The digest value is the function return value. - * An exception is thrown if the operation fails. - * @param aMessage the message - * @return digest of the message. - **/ - private native byte[] sha256Jni(byte[] aMessage); - - /** - * Helper method to compute a string based on random integers. - * @return bytes buffer containing randoms integer values - */ - public static byte[] getRandomKey() { - SecureRandom secureRandom = new SecureRandom(); - byte[] buffer = new byte[RANDOM_KEY_SIZE]; - secureRandom.nextBytes(buffer); - - // the key is saved as string - // so avoid the UTF8 marker bytes - for(int i = 0; i < RANDOM_KEY_SIZE; i++) { - buffer[i] = (byte)(buffer[i] & 0x7F); - } - return buffer; - } - - /** - * Return true the object resources have been released.
- * @return true the object resources have been released - */ - public boolean isReleased() { - return (0 == mNativeId); - } - - /** - * Build a string-string dictionary from a jsonObject.
- * @param jsonObject the object to parse - * @return the map - */ - public static Map toStringMap(JSONObject jsonObject) { - if (null != jsonObject) { - HashMap map = new HashMap<>(); - Iterator keysItr = jsonObject.keys(); - while(keysItr.hasNext()) { - String key = keysItr.next(); - try { - Object value = jsonObject.get(key); - - if (value instanceof String) { - map.put(key, (String) value); - } else { - Log.e(LOG_TAG, "## toStringMap(): unexpected type " + value.getClass()); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## toStringMap(): failed " + e.getMessage()); - } - } - - return map; - } - - return null; - } - - /** - * Build a string-string dictionary of string dictionary from a jsonObject.
- * @param jsonObject the object to parse - * @return the map - */ - public static Map> toStringMapMap(JSONObject jsonObject) { - if (null != jsonObject) { - HashMap> map = new HashMap<>(); - - Iterator keysItr = jsonObject.keys(); - while(keysItr.hasNext()) { - String key = keysItr.next(); - try { - Object value = jsonObject.get(key); - - if (value instanceof JSONObject) { - map.put(key, toStringMap((JSONObject) value)); - } else { - Log.e(LOG_TAG, "## toStringMapMap(): unexpected type " + value.getClass()); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## toStringMapMap(): failed " + e.getMessage()); - } - } - - return map; - } - - return null; - } -} - diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk deleted file mode 100644 index ffe1f67..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk +++ /dev/null @@ -1,59 +0,0 @@ -LOCAL_PATH := $(call my-dir) -include $(CLEAR_VARS) - -LOCAL_MODULE := olm -MAJOR := 2 -MINOR := 0 -PATCH := 0 -OLM_VERSION := $(MAJOR).$(MINOR).$(PATCH) -SRC_ROOT_DIR := ../../../../../../.. - -$(info LOCAL_PATH=$(LOCAL_PATH)) -$(info SRC_ROOT_DIR=$(SRC_ROOT_DIR)) -$(info OLM_VERSION=$(OLM_VERSION)) - -LOCAL_CPPFLAGS+= -std=c++11 -Wall -LOCAL_CONLYFLAGS+= -std=c99 -LOCAL_CFLAGS+= -DOLMLIB_VERSION_MAJOR=$(MAJOR) \ --DOLMLIB_VERSION_MINOR=$(MINOR) \ --DOLMLIB_VERSION_PATCH=$(PATCH) - -#LOCAL_CFLAGS+= -DNDK_DEBUG - -LOCAL_C_INCLUDES+= $(LOCAL_PATH)/$(SRC_ROOT_DIR)/include/ \ -$(LOCAL_PATH)/$(SRC_ROOT_DIR)/lib - -$(info LOCAL_C_INCLUDES=$(LOCAL_C_INCLUDES)) - -LOCAL_SRC_FILES := $(SRC_ROOT_DIR)/src/account.cpp \ -$(SRC_ROOT_DIR)/src/base64.cpp \ -$(SRC_ROOT_DIR)/src/cipher.cpp \ -$(SRC_ROOT_DIR)/src/crypto.cpp \ -$(SRC_ROOT_DIR)/src/memory.cpp \ -$(SRC_ROOT_DIR)/src/message.cpp \ -$(SRC_ROOT_DIR)/src/olm.cpp \ -$(SRC_ROOT_DIR)/src/pickle.cpp \ -$(SRC_ROOT_DIR)/src/ratchet.cpp \ -$(SRC_ROOT_DIR)/src/session.cpp \ -$(SRC_ROOT_DIR)/src/utility.cpp \ -$(SRC_ROOT_DIR)/src/ed25519.c \ -$(SRC_ROOT_DIR)/src/error.c \ -$(SRC_ROOT_DIR)/src/inbound_group_session.c \ -$(SRC_ROOT_DIR)/src/megolm.c \ -$(SRC_ROOT_DIR)/src/outbound_group_session.c \ -$(SRC_ROOT_DIR)/src/pickle_encoding.c \ -$(SRC_ROOT_DIR)/lib/crypto-algorithms/sha256.c \ -$(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \ -$(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \ -olm_account.cpp \ -olm_session.cpp \ -olm_jni_helper.cpp \ -olm_inbound_group_session.cpp \ -olm_outbound_group_session.cpp \ -olm_utility.cpp \ -olm_manager.cpp - -LOCAL_LDLIBS := -llog - -include $(BUILD_SHARED_LIBRARY) - diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk deleted file mode 100644 index 6516f5e..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk +++ /dev/null @@ -1,3 +0,0 @@ -APP_PLATFORM := android-16 -APP_ABI := arm64-v8a armeabi-v7a armeabi x86_64 x86 -APP_STL := gnustl_static \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp deleted file mode 100644 index 40081ac..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp +++ /dev/null @@ -1,687 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_account.h" - -using namespace AndroidOlmSdk; - -/** - * Init memory allocation for account creation. - * @return valid memory allocation, NULL otherwise - **/ -OlmAccount* initializeAccountMemory() -{ - size_t accountSize = olm_account_size(); - OlmAccount* accountPtr = (OlmAccount*)malloc(accountSize); - - if (accountPtr) - { - // init account object - accountPtr = olm_account(accountPtr); - LOGD("## initializeAccountMemory(): success - OLM account size=%lu",static_cast(accountSize)); - } - else - { - LOGE("## initializeAccountMemory(): failure - OOM"); - } - - return accountPtr; -} - -/** - * Create a new account and return it to JAVA side.
- * Since a C prt is returned as a jlong, special care will be taken - * to make the cast (OlmAccount* => jlong) platform independent. - * @return the initialized OlmAccount* instance or throw an exception if fails - **/ -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - OlmAccount *accountPtr = initializeAccountMemory(); - - // init account memory allocation - if (!accountPtr) - { - LOGE("## initNewAccount(): failure - init account OOM"); - errorMessage = "init account OOM"; - } - else - { - // get random buffer size - size_t randomSize = olm_create_account_random_length(accountPtr); - - LOGD("## initNewAccount(): randomSize=%lu", static_cast(randomSize)); - - uint8_t *randomBuffPtr = NULL; - size_t accountRetCode; - - // allocate random buffer - if ((0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) - { - LOGE("## initNewAccount(): failure - random buffer init"); - errorMessage = "random buffer init"; - } - else - { - // create account - accountRetCode = olm_create_account(accountPtr, (void*)randomBuffPtr, randomSize); - - if (accountRetCode == olm_error()) - { - LOGE("## initNewAccount(): failure - account creation failed Msg=%s", olm_account_last_error(accountPtr)); - errorMessage = olm_account_last_error(accountPtr); - } - - LOGD("## initNewAccount(): success - OLM account created"); - LOGD("## initNewAccount(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); - } - - if (randomBuffPtr) - { - memset(randomBuffPtr, 0, randomSize); - free(randomBuffPtr); - } - } - - if (errorMessage) - { - // release the allocated data - if (accountPtr) - { - olm_clear_account(accountPtr); - free(accountPtr); - } - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)accountPtr; -} -/** - * Release the account allocation made by initializeAccountMemory().
- * This method MUST be called when java counter part account instance is done. - */ -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## releaseAccountJni(): IN"); - - OlmAccount* accountPtr = getAccountInstanceId(env, thiz); - - if (!accountPtr) - { - LOGE(" ## releaseAccountJni(): failure - invalid Account ptr=NULL"); - } - else - { - LOGD(" ## releaseAccountJni(): accountPtr=%p",accountPtr); - olm_clear_account(accountPtr); - - LOGD(" ## releaseAccountJni(): IN"); - // even if free(NULL) does not crash, logs are performed for debug purpose - free(accountPtr); - LOGD(" ## releaseAccountJni(): OUT"); - } -} - -// ********************************************************************* -// ************************* IDENTITY KEYS API ************************* -// ********************************************************************* - -/** - * Get identity keys: Ed25519 fingerprint key and Curve25519 identity key.
- * The keys are returned in the byte array. - * @return the identity keys or throw an exception if it fails - **/ -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - jbyteArray byteArrayRetValue = NULL; - OlmAccount* accountPtr = getAccountInstanceId(env, thiz); - - if (!accountPtr) - { - LOGE("## identityKeys(): failure - invalid Account ptr=NULL"); - errorMessage = "invalid Account ptr"; - } - else - { - LOGD("## identityKeys(): accountPtr =%p", accountPtr); - - // identity keys allocation - size_t identityKeysLength = olm_account_identity_keys_length(accountPtr); - uint8_t *identityKeysBytesPtr = (uint8_t*)malloc(identityKeysLength); - - if (!identityKeysBytesPtr) - { - LOGE("## identityKeys(): failure - identity keys array OOM"); - errorMessage = "identity keys array OOM"; - } - else - { - // retrieve key pairs in identityKeysBytesPtr - size_t keysResult = olm_account_identity_keys(accountPtr, identityKeysBytesPtr, identityKeysLength); - - if (keysResult == olm_error()) - { - errorMessage = (const char *)olm_account_last_error(accountPtr); - LOGE("## identityKeys(): failure - error getting identity keys Msg=%s", errorMessage); - } - else - { - // allocate the byte array to be returned to java - byteArrayRetValue = env->NewByteArray(identityKeysLength); - - if (!byteArrayRetValue) - { - LOGE("## identityKeys(): failure - return byte array OOM"); - errorMessage = "byte array OOM"; - } - else - { - env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, identityKeysLength, (const jbyte*)identityKeysBytesPtr); - LOGD("## identityKeys(): success - result=%lu", static_cast(keysResult)); - } - } - - free(identityKeysBytesPtr); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return byteArrayRetValue; -} - -// ********************************************************************* -// ************************* ONE TIME KEYS API ************************* -// ********************************************************************* - -/** - * Get the public parts of the unpublished "one time keys" for the account.
- * The returned data is a JSON-formatted object with the single property - * curve25519, which is itself an object mapping key id to - * base64-encoded Curve25519 key.
- * @return byte array containing the one time keys or throw an exception if it fails - */ -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz) -{ - OlmAccount* accountPtr = getAccountInstanceId(env, thiz); - size_t maxKeys = -1; - - if (!accountPtr) - { - LOGE("## maxOneTimeKey(): failure - invalid Account ptr=NULL"); - } - else - { - maxKeys = olm_account_max_number_of_one_time_keys(accountPtr); - } - - LOGD("## maxOneTimeKey(): Max keys=%lu", static_cast(maxKeys)); - - return (jlong)maxKeys; -} - -/** - * Generate "one time keys". - * An exception is thrown if the operation fails. - * @param aNumberOfKeys number of keys to generate - **/ -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) -{ - const char* errorMessage = NULL; - OlmAccount *accountPtr = getAccountInstanceId(env, thiz); - - if (!accountPtr) - { - LOGE("## generateOneTimeKeysJni(): failure - invalid Account ptr"); - errorMessage = "invalid Account ptr"; - } - else - { - // keys memory allocation - size_t randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys); - LOGD("## generateOneTimeKeysJni(): randomLength=%lu", static_cast(randomLength)); - - uint8_t *randomBufferPtr = NULL; - - if ((0 != randomLength) && !setRandomInBuffer(env, &randomBufferPtr, randomLength)) - { - LOGE("## generateOneTimeKeysJni(): failure - random buffer init"); - errorMessage = "random buffer init"; - } - else - { - LOGD("## generateOneTimeKeysJni(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys); - - // retrieve key pairs in keysBytesPtr - size_t result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength); - - if (result == olm_error()) - { - errorMessage = olm_account_last_error(accountPtr); - LOGE("## generateOneTimeKeysJni(): failure - error generating one time keys Msg=%s", errorMessage); - } - else - { - LOGD("## generateOneTimeKeysJni(): success - result=%lu", static_cast(result)); - } - } - - - if (randomBufferPtr) - { - memset(randomBufferPtr, 0, randomLength); - free(randomBufferPtr); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } -} - -/** - * Get "one time keys".
- * Return the public parts of the unpublished "one time keys" for the account - * @return a valid byte array if operation succeed, null otherwise - **/ -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - jbyteArray byteArrayRetValue = NULL; - OlmAccount* accountPtr = getAccountInstanceId(env, thiz); - - LOGD("## oneTimeKeysJni(): IN"); - - if (!accountPtr) - { - LOGE("## oneTimeKeysJni(): failure - invalid Account ptr"); - errorMessage = "invalid Account ptr"; - } - else - { - // keys memory allocation - size_t keysLength = olm_account_one_time_keys_length(accountPtr); - uint8_t *keysBytesPtr = (uint8_t *)malloc(keysLength*sizeof(uint8_t)); - - if (!keysBytesPtr) - { - LOGE("## oneTimeKeysJni(): failure - one time keys array OOM"); - errorMessage = "one time keys array OOM"; - } - else - { - // retrieve key pairs in keysBytesPtr - size_t keysResult = olm_account_one_time_keys(accountPtr, keysBytesPtr, keysLength); - - if (keysResult == olm_error()) { - LOGE("## oneTimeKeysJni(): failure - error getting one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); - errorMessage = (const char *)olm_account_last_error(accountPtr); - } - else - { - // allocate the byte array to be returned to java - byteArrayRetValue = env->NewByteArray(keysLength); - - if (!byteArrayRetValue) - { - LOGE("## oneTimeKeysJni(): failure - return byte array OOM"); - errorMessage = "return byte array OOM"; - } - else - { - env->SetByteArrayRegion(byteArrayRetValue, 0/*offset*/, keysLength, (const jbyte*)keysBytesPtr); - LOGD("## oneTimeKeysJni(): success"); - } - } - - free(keysBytesPtr); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return byteArrayRetValue; -} - -/** - * Remove the "one time keys" that the session used from the account. - * An exception is thrown if the operation fails. - * @param aNativeOlmSessionId session instance - **/ -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) -{ - const char* errorMessage = NULL; - OlmAccount* accountPtr = NULL; - OlmSession* sessionPtr = (OlmSession*)aNativeOlmSessionId; - - if (!sessionPtr) - { - LOGE("## removeOneTimeKeysJni(): failure - invalid session ptr"); - errorMessage = "invalid session ptr"; - } - else if (!(accountPtr = getAccountInstanceId(env, thiz))) - { - LOGE("## removeOneTimeKeysJni(): failure - invalid account ptr"); - errorMessage = "invalid account ptr"; - } - else - { - size_t result = olm_remove_one_time_keys(accountPtr, sessionPtr); - - if (result == olm_error()) - { // the account doesn't have any matching "one time keys".. - LOGW("## removeOneTimeKeysJni(): failure - removing one time keys Msg=%s", olm_account_last_error(accountPtr)); - errorMessage = (const char *)olm_account_last_error(accountPtr); - } - else - { - LOGD("## removeOneTimeKeysJni(): success"); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } -} - -/** - * Mark the current set of "one time keys" as being published. - * An exception is thrown if the operation fails. - **/ -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - OlmAccount* accountPtr = getAccountInstanceId(env, thiz); - - if (!accountPtr) - { - LOGE("## markOneTimeKeysAsPublishedJni(): failure - invalid account ptr"); - errorMessage = "invalid account ptr"; - } - else - { - size_t result = olm_account_mark_keys_as_published(accountPtr); - - if (result == olm_error()) - { - LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",(const char *)olm_account_last_error(accountPtr)); - errorMessage = (const char *)olm_account_last_error(accountPtr); - } - else - { - LOGD("## markOneTimeKeysAsPublishedJni(): success - retCode=%lu",static_cast(result)); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } -} - -/** - * Sign a message with the ed25519 key (fingerprint) for this account.
- * The signed message is returned by the function. - * @param aMessage message to sign - * @return the signed message, null otherwise - **/ -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) -{ - const char* errorMessage = NULL; - OlmAccount* accountPtr = NULL; - jbyteArray signedMsgRetValueBuffer = NULL; - - if (!aMessage) - { - LOGE("## signMessageJni(): failure - invalid aMessage param"); - errorMessage = "invalid aMessage param"; - } - else if (!(accountPtr = getAccountInstanceId(env, thiz))) - { - LOGE("## signMessageJni(): failure - invalid account ptr"); - errorMessage = "invalid account ptr"; - } - else - { - int messageLength = env->GetArrayLength(aMessage); - jbyte* messageToSign = env->GetByteArrayElements(aMessage, NULL); - - // signature memory allocation - size_t signatureLength = olm_account_signature_length(accountPtr); - void* signedMsgPtr = malloc(signatureLength * sizeof(uint8_t)); - - if (!signedMsgPtr) - { - LOGE("## signMessageJni(): failure - signature allocation OOM"); - errorMessage = "signature allocation OOM"; - } - else - { - // sign message - size_t resultSign = olm_account_sign(accountPtr, - (void*)messageToSign, - (size_t)messageLength, - signedMsgPtr, - signatureLength); - - if (resultSign == olm_error()) - { - LOGE("## signMessageJni(): failure - error signing message Msg=%s",(const char *)olm_account_last_error(accountPtr)); - errorMessage = (const char *)olm_account_last_error(accountPtr); - } - else - { - LOGD("## signMessageJni(): success - retCode=%lu signatureLength=%lu", static_cast(resultSign), static_cast(signatureLength)); - - signedMsgRetValueBuffer = env->NewByteArray(signatureLength); - env->SetByteArrayRegion(signedMsgRetValueBuffer, 0 , signatureLength, (jbyte*)signedMsgPtr); - } - - free(signedMsgPtr); - } - - // release messageToSign - if (messageToSign) - { - env->ReleaseByteArrayElements(aMessage, messageToSign, JNI_ABORT); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return signedMsgRetValueBuffer; -} - -/** - * Serialize and encrypt account instance.
- * @param aKeyBuffer key used to encrypt the serialized account data - * @return the serialised account as bytes buffer. - **/ -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - jbyteArray pickledDataRetValue = 0; - jbyte* keyPtr = NULL; - OlmAccount* accountPtr = NULL; - - LOGD("## serializeJni(): IN"); - - if (!aKeyBuffer) - { - LOGE(" ## serializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!(accountPtr = getAccountInstanceId(env, thiz))) - { - LOGE(" ## serializeJni(): failure - invalid account ptr"); - errorMessage = "invalid account ptr"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, NULL))) - { - LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "keyPtr JNI allocation OOM"; - } - else - { - size_t pickledLength = olm_pickle_account_length(accountPtr); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - - void* pickledPtr = malloc(pickledLength * sizeof(uint8_t)); - - if (!pickledPtr) - { - LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); - errorMessage = "pickledPtr buffer OOM"; - } - else - { - size_t result = olm_pickle_account(accountPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_account_last_error(accountPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_account() Msg=%s", errorMessage); - } - else - { - LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); - pickledDataRetValue = env->NewByteArray(pickledLength); - env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength, (jbyte*)pickledPtr); - } - - free(pickledPtr); - } - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return pickledDataRetValue; -} - -/** - * Allocate a new account and initialise it with the serialisation data.
- * @param aSerializedDataBuffer the account serialisation buffer - * @param aKeyBuffer the key used to encrypt the serialized account data - * @return the deserialised account - **/ -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - - OlmAccount* accountPtr = NULL; - - jbyte* keyPtr = NULL; - jbyte* pickledPtr = NULL; - - LOGD("## deserializeJni(): IN"); - - if (!aKeyBuffer) - { - LOGE(" ## deserializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!aSerializedDataBuffer) - { - LOGE(" ## deserializeJni(): failure - invalid serialized data"); - errorMessage = "invalid serialized data"; - } - else if (!(accountPtr = initializeAccountMemory())) - { - LOGE(" ## deserializeJni(): failure - account failure OOM"); - errorMessage = "account failure OOM"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "keyPtr JNI allocation OOM"; - } - else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); - errorMessage = "pickledPtr JNI allocation OOM"; - } - else - { - size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%.*s", static_cast (pickledLength), (char const *)pickledPtr); - - size_t result = olm_unpickle_account(accountPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_account_last_error(accountPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); - } - else - { - LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); - } - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (pickledPtr) - { - env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); - } - - if (errorMessage) - { - if (accountPtr) - { - olm_clear_account(accountPtr); - free(accountPtr); - } - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)accountPtr; -} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h deleted file mode 100644 index 42b2c2a..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2017 OpenMarket Ltd - * Copyright 2017 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _OMLACCOUNT_H -#define _OMLACCOUNT_H - -#include "olm_jni.h" -#include "olm/olm.h" - -#define OLM_ACCOUNT_FUNC_DEF(func_name) FUNC_DEF(OlmAccount,func_name) -#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name) - -#ifdef __cplusplus -extern "C" { -#endif - -// account creation/destruction -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz); - -// identity keys -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz); - -// one time keys -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz); -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); -JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); - -// signing -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage); - -// serialization -JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer); -JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp deleted file mode 100644 index 23910bb..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_inbound_group_session.h" - -using namespace AndroidOlmSdk; - -/** - * Release the session allocation made by initializeInboundGroupSessionMemory().
- * This method MUST be called when java counter part account instance is done. - */ -JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) -{ - OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env,thiz); - - LOGD("## releaseSessionJni(): InBound group session IN"); - - if (!sessionPtr) - { - LOGE("## releaseSessionJni(): failure - invalid inbound group session instance"); - } - else - { - LOGD(" ## releaseSessionJni(): sessionPtr=%p", sessionPtr); -#ifdef ENABLE_JNI_LOG - size_t retCode = olm_clear_inbound_group_session(sessionPtr); - LOGD(" ## releaseSessionJni(): clear_inbound_group_session=%lu",static_cast(retCode)); -#else - olm_clear_inbound_group_session(sessionPtr); -#endif - - LOGD(" ## releaseSessionJni(): free IN"); - free(sessionPtr); - LOGD(" ## releaseSessionJni(): free OUT"); - } -} - -/** - * Initialize a new inbound group session and return it to JAVA side.
- * Since a C prt is returned as a jlong, special care will be taken - * to make the cast (OlmInboundGroupSession* => jlong) platform independent. - * @param aSessionKeyBuffer session key from an outbound session - * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. - **/ -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) -{ - const char* errorMessage = NULL; - OlmInboundGroupSession* sessionPtr = NULL; - jbyte* sessionKeyPtr = NULL; - size_t sessionSize = olm_inbound_group_session_size(); - - LOGD("## createNewSessionJni(): inbound group session IN"); - - if (!sessionSize) - { - LOGE(" ## createNewSessionJni(): failure - inbound group session size = 0"); - errorMessage = "inbound group session size = 0"; - } - else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) - { - LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); - errorMessage = "inbound group session OOM"; - } - else if (!aSessionKeyBuffer) - { - LOGE(" ## createNewSessionJni(): failure - invalid aSessionKey"); - errorMessage = "invalid aSessionKey"; - } - else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) - { - LOGE(" ## createNewSessionJni(): failure - session key JNI allocation OOM"); - errorMessage = "Session key JNI allocation OOM"; - } - else - { - sessionPtr = olm_inbound_group_session(sessionPtr); - - size_t sessionKeyLength = (size_t)env->GetArrayLength(aSessionKeyBuffer); - LOGD(" ## createNewSessionJni(): sessionKeyLength=%lu", static_cast(sessionKeyLength)); - - size_t sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); - - if (sessionResult == olm_error()) - { - errorMessage = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## createNewSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); - } - else - { - LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); - } - } - - if (sessionKeyPtr) - { - env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - if (errorMessage) - { - // release the allocated session - if (sessionPtr) - { - olm_clear_inbound_group_session(sessionPtr); - free(sessionPtr); - } - - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)sessionPtr; -} - -/** - * Get a base64-encoded identifier for this inbound group session. - * An exception is thrown if the operation fails. - * @return the base64-encoded identifier - */ -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); - jbyteArray returnValue = 0; - - LOGD("## sessionIdentifierJni(): inbound group session IN"); - - if (!sessionPtr) - { - LOGE(" ## sessionIdentifierJni(): failure - invalid inbound group session instance"); - errorMessage = "invalid inbound group session instance"; - } - else - { - // get the size to alloc - size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr); - LOGD(" ## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); - - uint8_t *sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)); - - if (!sessionIdPtr) - { - LOGE(" ## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM"); - errorMessage = "inbound group session identifier allocation OOM"; - } - else - { - size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - - if (result == olm_error()) - { - errorMessage = (const char *)olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## sessionIdentifierJni(): failure - get inbound group session identifier failure Msg=%s",(const char *)olm_inbound_group_session_last_error(sessionPtr)); - } - else - { - LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); - - returnValue = env->NewByteArray(result); - env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); - } - - free(sessionIdPtr); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return returnValue; -} - -/** - * Decrypt a message. - * An exception is thrown if the operation fails. - * @param aEncryptedMsg the encrypted message - * @param aDecryptMessageResult the decryptMessage information - * @return the decrypted message - */ -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult) -{ - jbyteArray decryptedMsgBuffer = 0; - const char* errorMessage = NULL; - - OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); - jbyte *encryptedMsgPtr = NULL; - jclass indexObjJClass = 0; - jfieldID indexMsgFieldId; - - LOGD("## decryptMessageJni(): inbound group session IN"); - - if (!sessionPtr) - { - LOGE(" ## decryptMessageJni(): failure - invalid inbound group session ptr=NULL"); - errorMessage = "invalid inbound group session ptr=NULL"; - } - else if (!aEncryptedMsgBuffer) - { - LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); - errorMessage = "invalid encrypted message"; - } - else if (!aDecryptionResult) - { - LOGE(" ## decryptMessageJni(): failure - invalid index object"); - errorMessage = "invalid index object"; - } - else if (!(encryptedMsgPtr = env->GetByteArrayElements(aEncryptedMsgBuffer, 0))) - { - LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); - errorMessage = "encrypted message JNI allocation OOM"; - } - else if (!(indexObjJClass = env->GetObjectClass(aDecryptionResult))) - { - LOGE("## decryptMessageJni(): failure - unable to get index class"); - errorMessage = "unable to get index class"; - } - else if (!(indexMsgFieldId = env->GetFieldID(indexObjJClass,"mIndex","J"))) - { - LOGE("## decryptMessageJni(): failure - unable to get index type field"); - errorMessage = "unable to get index type field"; - } - else - { - // get encrypted message length - size_t encryptedMsgLength = (size_t)env->GetArrayLength(aEncryptedMsgBuffer); - uint8_t *tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); - - // create a dedicated temp buffer to be used in next Olm API calls - if (!tempEncryptedPtr) - { - LOGE(" ## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM"); - errorMessage = "tempEncryptedPtr allocation OOM"; - } - else - { - memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD(" ## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%.*s",static_cast(encryptedMsgLength), static_cast(encryptedMsgLength), encryptedMsgPtr); - - // get max plaintext length - size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr, - tempEncryptedPtr, - encryptedMsgLength); - if (maxPlainTextLength == olm_error()) - { - errorMessage = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s", errorMessage); - } - else - { - LOGD(" ## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); - - uint32_t messageIndex = 0; - - // allocate output decrypted message - uint8_t *plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); - - // decrypt, but before reload encrypted buffer (previous one was destroyed) - memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - size_t plaintextLength = olm_group_decrypt(sessionPtr, - tempEncryptedPtr, - encryptedMsgLength, - plainTextMsgPtr, - maxPlainTextLength, - &messageIndex); - if (plaintextLength == olm_error()) - { - errorMessage = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## decryptMessageJni(): failure - olm_group_decrypt Msg=%s", errorMessage); - } - else - { - // update index - env->SetLongField(aDecryptionResult, indexMsgFieldId, (jlong)messageIndex); - - decryptedMsgBuffer = env->NewByteArray(plaintextLength); - env->SetByteArrayRegion(decryptedMsgBuffer, 0 , plaintextLength, (jbyte*)plainTextMsgPtr); - - LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); - } - - if (plainTextMsgPtr) - { - memset(plainTextMsgPtr, 0, maxPlainTextLength*sizeof(uint8_t)); - free(plainTextMsgPtr); - } - } - - if (tempEncryptedPtr) - { - free(tempEncryptedPtr); - } - } - } - - // free alloc - if (encryptedMsgPtr) - { - env->ReleaseByteArrayElements(aEncryptedMsgBuffer, encryptedMsgPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return decryptedMsgBuffer; -} - - -/** - * Serialize and encrypt session instance into a base64 string.
- * An exception is thrown if the operation fails. - * @param aKeyBuffer key used to encrypt the serialized session data - * @return a base64 string if operation succeed, null otherwise - **/ -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - - jbyteArray pickledDataRet = 0; - jbyte* keyPtr = NULL; - OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env, thiz); - - LOGD("## inbound group session serializeJni(): IN"); - - if (!sessionPtr) - { - LOGE(" ## serializeJni(): failure - invalid session ptr"); - errorMessage = "invalid session ptr"; - } - else if (!aKeyBuffer) - { - LOGE(" ## serializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "keyPtr JNI allocation OOM"; - } - else - { - size_t pickledLength = olm_pickle_inbound_group_session_length(sessionPtr); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu", static_cast(pickledLength), static_cast(keyLength)); - - void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); - - if (!pickledPtr) - { - LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); - errorMessage = "pickledPtr buffer OOM"; - } - else - { - size_t result = olm_pickle_inbound_group_session(sessionPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s", errorMessage); - } - else - { - LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); - - pickledDataRet = env->NewByteArray(pickledLength); - env->SetByteArrayRegion(pickledDataRet, 0 , pickledLength, (jbyte*)pickledPtr); - } - - free(pickledPtr); - } - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return pickledDataRet; -} - -/** - * Allocate a new session and initialize it with the serialisation data.
- * An exception is thrown if the operation fails. - * @param aSerializedData the session serialisation buffer - * @param aKey the key used to encrypt the serialized account data - * @return the deserialized session - **/ -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - - OlmInboundGroupSession* sessionPtr = NULL; - size_t sessionSize = olm_inbound_group_session_size(); - jbyte* keyPtr = NULL; - jbyte* pickledPtr = NULL; - - LOGD("## deserializeJni(): IN"); - - if (!sessionSize) - { - LOGE(" ## deserializeJni(): failure - inbound group session size = 0"); - errorMessage = "inbound group session size = 0"; - } - else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) - { - LOGE(" ## deserializeJni(): failure - session failure OOM"); - errorMessage = "session failure OOM"; - } - else if (!aKeyBuffer) - { - LOGE(" ## deserializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!aSerializedDataBuffer) - { - LOGE(" ## deserializeJni(): failure - serialized data"); - errorMessage = "serialized data"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "keyPtr JNI allocation OOM"; - } - else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); - errorMessage = "pickledPtr JNI allocation OOM"; - } - else - { - sessionPtr = olm_inbound_group_session(sessionPtr); - - size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%.*s", static_cast(pickledLength), (char const *)pickledPtr); - - size_t result = olm_unpickle_inbound_group_session(sessionPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_inbound_group_session() Msg=%s", errorMessage); - } - else - { - LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); - } - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (pickledPtr) - { - env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); - } - - if (errorMessage) - { - if (sessionPtr) - { - olm_clear_inbound_group_session(sessionPtr); - free(sessionPtr); - } - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)sessionPtr; -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h deleted file mode 100644 index 00990dd..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _OMLINBOUND_GROUP_SESSION_H -#define _OMLINBOUND_GROUP_SESSION_H - -#include "olm_jni.h" -#include "olm/olm.h" -#include "olm/inbound_group_session.h" - -#define OLM_INBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmInboundGroupSession,func_name) - -#ifdef __cplusplus -extern "C" { -#endif - -// session creation/destruction -JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); - -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex); - -// serialization -JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h deleted file mode 100644 index e6a49e2..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _OMLJNI_H -#define _OMLJNI_H - -#include -#include -#include -#include -#include -#include - - -#define TAG "OlmJniNative" - -/* logging macros */ -//#define ENABLE_JNI_LOG - -#ifdef NDK_DEBUG - #warning NDK_DEBUG is defined! -#endif - -#ifdef ENABLE_JNI_LOG - #warning ENABLE_JNI_LOG is defined! -#endif - -#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) - -#ifdef ENABLE_JNI_LOG - #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) - #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) -#else - #define LOGD(...) - #define LOGW(...) -#endif - -#define FUNC_DEF(class_name,func_name) JNICALL Java_org_matrix_olm_##class_name##_##func_name - -namespace AndroidOlmSdk -{ - -} - - -#ifdef __cplusplus -extern "C" { -#endif - -// internal helper functions -bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize); - -struct OlmSession* getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -struct OlmAccount* getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -struct OlmInboundGroupSession* getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -struct OlmOutboundGroupSession* getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); -struct OlmUtility* getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject); - -#ifdef __cplusplus -} -#endif - - -#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp deleted file mode 100644 index a1f5c59..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_jni_helper.h" -#include "olm/olm.h" -#include - -using namespace AndroidOlmSdk; - -/** -* Init a buffer with a given number of random values. -* @param aBuffer2Ptr the buffer to be initialized -* @param aRandomSize the number of random values to apply -* @return true if operation succeed, false otherwise -**/ -bool setRandomInBuffer(JNIEnv *env, uint8_t **aBuffer2Ptr, size_t aRandomSize) -{ - bool retCode = false; - int bufferLen = aRandomSize*sizeof(uint8_t); - - if (!aBuffer2Ptr) - { - LOGE("## setRandomInBuffer(): failure - aBuffer=NULL"); - } - else if (!aRandomSize) - { - LOGE("## setRandomInBuffer(): failure - random size=0"); - } - else if (!(*aBuffer2Ptr = (uint8_t*)malloc(bufferLen))) - { - LOGE("## setRandomInBuffer(): failure - alloc mem OOM"); - } - else - { - LOGD("## setRandomInBuffer(): randomSize=%lu",static_cast(aRandomSize)); - - // use the secureRandom class - jclass cls = env->FindClass("java/security/SecureRandom"); - - if (cls) - { - jobject newObj = 0; - jmethodID constructor = env->GetMethodID(cls, "", "()V"); - jmethodID nextByteMethod = env->GetMethodID(cls, "nextBytes", "([B)V"); - - if (constructor) - { - newObj = env->NewObject(cls, constructor); - jbyteArray tempByteArray = env->NewByteArray(bufferLen); - - if (newObj && tempByteArray) - { - env->CallVoidMethod(newObj, nextByteMethod, tempByteArray); - - if (!env->ExceptionOccurred()) - { - jbyte* buffer = env->GetByteArrayElements(tempByteArray, NULL); - - if (buffer) - { - memcpy(*aBuffer2Ptr, buffer, bufferLen); - retCode = true; - - // clear tempByteArray to hide sensitive data. - memset(buffer, 0, bufferLen); - env->SetByteArrayRegion(tempByteArray, 0, bufferLen, buffer); - - // ensure that the buffer is released - env->ReleaseByteArrayElements(tempByteArray, buffer, JNI_ABORT); - } - } - } - - if (tempByteArray) - { - env->DeleteLocalRef(tempByteArray); - } - - if (newObj) - { - env->DeleteLocalRef(newObj); - } - } - } - - // debug purpose - /*for(int i = 0; i < aRandomSize; i++) - { - LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]); - }*/ - } - - return retCode; -} - -/** -* Read the instance ID of the calling object. -* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @param aCallingClass java calling class name -* @return the related instance ID -**/ -jlong getInstanceId(JNIEnv* aJniEnv, jobject aJavaObject, const char *aCallingClass) -{ - jlong instanceId = 0; - - if (aJniEnv) - { - jclass requiredClass = aJniEnv->FindClass(aCallingClass); - jclass loaderClass = 0; - - if (requiredClass && (JNI_TRUE != aJniEnv->IsInstanceOf(aJavaObject, requiredClass))) - { - LOGE("## getInstanceId() failure - invalid instance of"); - } - else if ((loaderClass = aJniEnv->GetObjectClass(aJavaObject))) - { - jfieldID instanceIdField = aJniEnv->GetFieldID(loaderClass, "mNativeId", "J"); - - if (instanceIdField) - { - instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField); - LOGD("## getInstanceId(): read from java instanceId=%lld",instanceId); - } - else - { - LOGE("## getInstanceId() ERROR! GetFieldID=null"); - } - - aJniEnv->DeleteLocalRef(loaderClass); - } - else - { - LOGE("## getInstanceId() ERROR! GetObjectClass=null"); - } - } - else - { - LOGE("## getInstanceId() ERROR! aJniEnv=NULL"); - } - - LOGD("## getInstanceId() success - instanceId=%p (jlong)(intptr_t)instanceId=%lld",(void*)instanceId, (jlong)(intptr_t)instanceId); - - return instanceId; -} - -/** -* Read the account instance ID of the calling object. -* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the related OlmAccount. -**/ -struct OlmAccount* getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - return (struct OlmAccount*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_ACCOUNT); -} - -/** -* Read the session instance ID of the calling object (aJavaObject).
-* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the related OlmSession. -**/ -struct OlmSession* getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - return (struct OlmSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_SESSION); -} - -/** -* Read the inbound group session instance ID of the calling object (aJavaObject).
-* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the related OlmInboundGroupSession. -**/ -struct OlmInboundGroupSession* getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - return (struct OlmInboundGroupSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_INBOUND_GROUP_SESSION); -} - -/** -* Read the outbound group session instance ID of the calling object (aJavaObject).
-* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the related OlmOutboundGroupSession -**/ -struct OlmOutboundGroupSession* getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - return (struct OlmOutboundGroupSession*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_OUTBOUND_GROUP_SESSION); -} - -/** -* Read the utility instance ID of the calling object (aJavaObject).
-* @param aJniEnv pointer pointing on the JNI function table -* @param aJavaObject reference to the object on which the method is invoked -* @return the related OlmUtility -**/ -struct OlmUtility* getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) -{ - return (struct OlmUtility*)getInstanceId(aJniEnv, aJavaObject, CLASS_OLM_UTILITY); -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h deleted file mode 100644 index a181b32..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_jni.h" - -// constant strings -namespace AndroidOlmSdk -{ - static const char *CLASS_OLM_INBOUND_GROUP_SESSION = "org/matrix/olm/OlmInboundGroupSession"; - static const char *CLASS_OLM_OUTBOUND_GROUP_SESSION = "org/matrix/olm/OlmOutboundGroupSession"; - static const char *CLASS_OLM_SESSION = "org/matrix/olm/OlmSession"; - static const char *CLASS_OLM_ACCOUNT = "org/matrix/olm/OlmAccount"; - static const char *CLASS_OLM_UTILITY = "org/matrix/olm/OlmUtility"; -} diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp deleted file mode 100644 index 8ee0df7..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_manager.h" - -using namespace AndroidOlmSdk; - -JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv* env, jobject thiz) -{ - uint8_t majorVer=0, minorVer=0, patchVer=0; - jstring returnValueStr=0; - char buff[150]; - - olm_get_library_version(&majorVer, &minorVer, &patchVer); - LOGD("## getOlmLibVersionJni(): Major=%d Minor=%d Patch=%d", majorVer, minorVer, patchVer); - - snprintf(buff, sizeof(buff), "%d.%d.%d", majorVer, minorVer, patchVer); - returnValueStr = env->NewStringUTF((const char*)buff); - - return returnValueStr; -} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h deleted file mode 100644 index 5fb6da2..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_manager.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _OMLMANAGER_H -#define _OMLMANAGER_H - -#include "olm_jni.h" -#include "olm/olm.h" - -#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name) - -#ifdef __cplusplus -extern "C" { -#endif - -JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersionJni)(JNIEnv *env, jobject thiz); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp deleted file mode 100644 index a821709..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_outbound_group_session.h" - -using namespace AndroidOlmSdk; - -/** - * Release the session allocation made by initializeOutboundGroupSessionMemory().
- * This method MUST be called when java counter part account instance is done. - * - */ -JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## releaseSessionJni(): OutBound group session IN"); - - OlmOutboundGroupSession* sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - - if (!sessionPtr) - { - LOGE(" ## releaseSessionJni(): failure - invalid outbound group session instance"); - } - else - { - LOGD(" ## releaseSessionJni(): sessionPtr=%p",sessionPtr); - -#ifdef ENABLE_JNI_LOG - size_t retCode = olm_clear_outbound_group_session(sessionPtr); - LOGD(" ## releaseSessionJni(): clear_outbound_group_session=%lu",static_cast(retCode)); -#else - olm_clear_outbound_group_session(sessionPtr); -#endif - - LOGD(" ## releaseSessionJni(): free IN"); - free(sessionPtr); - LOGD(" ## releaseSessionJni(): free OUT"); - } -} - -/** - * Initialize a new outbound group session and return it to JAVA side.
- * Since a C prt is returned as a jlong, special care will be taken - * to make the cast (OlmOutboundGroupSession* => jlong) platform independent. - * @return the initialized OlmOutboundGroupSession* instance or throw an exception - **/ -JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - - OlmOutboundGroupSession* sessionPtr = NULL; - size_t sessionSize = 0; - - LOGD("## createNewSessionJni(): outbound group session IN"); - sessionSize = olm_outbound_group_session_size(); - - if (0 == sessionSize) - { - LOGE(" ## createNewSessionJni(): failure - outbound group session size = 0"); - errorMessage = "outbound group session size = 0"; - } - else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) - { - LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); - errorMessage = "outbound group session OOM"; - } - else - { - sessionPtr = olm_outbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); - - // compute random buffer - size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); - uint8_t *randomBuffPtr = NULL; - - LOGW(" ## createNewSessionJni(): randomLength=%lu",static_cast(randomLength)); - - if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) - { - LOGE(" ## createNewSessionJni(): failure - random buffer init"); - errorMessage = "random buffer init"; - } - else - { - if (0 == randomLength) - { - LOGW(" ## createNewSessionJni(): random buffer is not required"); - } - - size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); - - if (sessionResult == olm_error()) { - errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## createNewSessionJni(): failure - init outbound session creation Msg=%s", errorMessage); - } - else - { - LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); - } - - // clear the random buffer - memset(randomBuffPtr, 0, randomLength); - free(randomBuffPtr); - } - } - - if (errorMessage) - { - if (sessionPtr) - { - olm_clear_outbound_group_session(sessionPtr); - free(sessionPtr); - } - - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)sessionPtr; -} - -/** - * Return the session identifier. - * An exception is thrown if the operation fails. - * @return the session identifier - */ -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## sessionIdentifierJni(): outbound group session IN"); - - const char* errorMessage = NULL; - OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - jbyteArray returnValue = 0; - - if (!sessionPtr) - { - LOGE(" ## sessionIdentifierJni(): failure - invalid outbound group session instance"); - errorMessage = "invalid outbound group session instance"; - } - else - { - // get the size to alloc - size_t lengthSessionId = olm_outbound_group_session_id_length(sessionPtr); - LOGD(" ## sessionIdentifierJni(): outbound group session lengthSessionId=%lu",static_cast(lengthSessionId)); - - uint8_t *sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t)); - - if (!sessionIdPtr) - { - LOGE(" ## sessionIdentifierJni(): failure - outbound identifier allocation OOM"); - errorMessage = "outbound identifier allocation OOM"; - } - else - { - size_t result = olm_outbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - - if (result == olm_error()) - { - errorMessage = reinterpret_cast(olm_outbound_group_session_last_error(sessionPtr)); - LOGE(" ## sessionIdentifierJni(): failure - outbound group session identifier failure Msg=%s", errorMessage); - } - else - { - returnValue = env->NewByteArray(result); - env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); - - LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId= %.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionIdPtr)); - } - - // free alloc - free(sessionIdPtr); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return returnValue; -} - - -/** - * Get the current message index for this session.
- * Each message is sent with an increasing index, this - * method returns the index for the next message. - * An exception is thrown if the operation fails. - * @return current session index - */ -JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz) -{ - OlmOutboundGroupSession *sessionPtr = NULL; - jint indexRetValue = 0; - - LOGD("## messageIndexJni(): IN"); - - if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) - { - LOGE(" ## messageIndexJni(): failure - invalid outbound group session instance"); - } - else - { - indexRetValue = static_cast(olm_outbound_group_session_message_index(sessionPtr)); - } - - LOGD(" ## messageIndexJni(): success - index=%d",indexRetValue); - - return indexRetValue; -} - -/** - * Return the session key. - * An exception is thrown if the operation fails. - * @return the session key - */ -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## sessionKeyJni(): outbound group session IN"); - - const char* errorMessage = NULL; - OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - jbyteArray returnValue = 0; - - if (!sessionPtr) - { - LOGE(" ## sessionKeyJni(): failure - invalid outbound group session instance"); - errorMessage = "invalid outbound group session instance"; - } - else - { - // get the size to alloc - size_t sessionKeyLength = olm_outbound_group_session_key_length(sessionPtr); - LOGD(" ## sessionKeyJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); - - uint8_t *sessionKeyPtr = (uint8_t*)malloc(sessionKeyLength*sizeof(uint8_t)); - - if (!sessionKeyPtr) - { - LOGE(" ## sessionKeyJni(): failure - session key allocation OOM"); - errorMessage = "session key allocation OOM"; - } - else - { - size_t result = olm_outbound_group_session_key(sessionPtr, sessionKeyPtr, sessionKeyLength); - - if (result == olm_error()) - { - errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## sessionKeyJni(): failure - session key failure Msg=%s", errorMessage); - } - else - { - LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionKeyPtr)); - - returnValue = env->NewByteArray(result); - env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionKeyPtr); - } - - // free alloc - free(sessionKeyPtr); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return returnValue; -} - -/** - * Encrypt a bytes buffer messages. - * An exception is thrown if the operation fails. - * @param aClearMsgBuffer the message to encode - * @return the encoded message - */ -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) -{ - LOGD("## encryptMessageJni(): IN"); - - const char* errorMessage = NULL; - jbyteArray encryptedMsgRet = 0; - - OlmOutboundGroupSession *sessionPtr = NULL; - jbyte* clearMsgPtr = NULL; - - if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) - { - LOGE(" ## encryptMessageJni(): failure - invalid outbound group session ptr=NULL"); - errorMessage = "invalid outbound group session ptr=NULL"; - } - else if (!aClearMsgBuffer) - { - LOGE(" ## encryptMessageJni(): failure - invalid clear message"); - errorMessage = "invalid clear message"; - } - else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, NULL))) - { - LOGE(" ## encryptMessageJni(): failure - clear message JNI allocation OOM"); - errorMessage = "clear message JNI allocation OOM"; - } - else - { - // get clear message length - size_t clearMsgLength = (size_t)env->GetArrayLength(aClearMsgBuffer); - LOGD(" ## encryptMessageJni(): clearMsgLength=%lu",static_cast(clearMsgLength)); - - // compute max encrypted length - size_t encryptedMsgLength = olm_group_encrypt_message_length(sessionPtr,clearMsgLength); - uint8_t *encryptedMsgPtr = (uint8_t*)malloc(encryptedMsgLength*sizeof(uint8_t)); - - if (!encryptedMsgPtr) - { - LOGE(" ## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); - errorMessage = "encryptedMsgPtr buffer OOM"; - } - else - { - LOGD(" ## encryptMessageJni(): estimated encryptedMsgLength=%lu",static_cast(encryptedMsgLength)); - - size_t encryptedLength = olm_group_encrypt(sessionPtr, - (uint8_t*)clearMsgPtr, - clearMsgLength, - encryptedMsgPtr, - encryptedMsgLength); - - - if (encryptedLength == olm_error()) - { - errorMessage = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## encryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s", errorMessage); - } - else - { - LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%.*s",static_cast(encryptedLength), static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); - - encryptedMsgRet = env->NewByteArray(encryptedLength); - env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedLength, (jbyte*)encryptedMsgPtr); - } - - free(encryptedMsgPtr); - } - } - - // free alloc - if (clearMsgPtr) - { - env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return encryptedMsgRet; -} - -/** - * Serialize and encrypt session instance into a base64 string.
- * An exception is thrown if the operation fails. - * @param aKey key used to encrypt the serialized session data - * @return a base64 string if operation succeed, null otherwise - **/ -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - jbyteArray returnValue = 0; - - jbyte* keyPtr = NULL; - OlmOutboundGroupSession* sessionPtr = NULL; - - LOGD("## outbound group session serializeJni(): IN"); - - if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) - { - LOGE(" ## serializeJni(): failure - invalid session ptr"); - errorMessage = "invalid session ptr"; - } - else if (!aKeyBuffer) - { - LOGE(" ## serializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "keyPtr JNI allocation OOM"; - } - else - { - size_t pickledLength = olm_pickle_outbound_group_session_length(sessionPtr); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - - void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); - - if(!pickledPtr) - { - LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); - errorMessage = "pickledPtr buffer OOM"; - } - else - { - size_t result = olm_pickle_outbound_group_session(sessionPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_outbound_group_session() Msg=%s", errorMessage); - } - else - { - LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(result), static_cast(pickledPtr)); - - returnValue = env->NewByteArray(pickledLength); - env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); - } - } - - free(pickledPtr); - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return returnValue; -} - -/** - * Allocate a new session and initialize it with the serialisation data.
- * An exception is thrown if the operation fails. - * @param aSerializedData the session serialisation buffer - * @param aKey the key used to encrypt the serialized account data - * @return the deserialized session - **/ -JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - size_t sessionSize = olm_outbound_group_session_size(); - OlmOutboundGroupSession* sessionPtr = NULL; - - jbyte* keyPtr = NULL; - jbyte* pickledPtr = NULL; - - LOGD("## deserializeJni(): IN"); - - if (!sessionSize) - { - LOGE(" ## deserializeJni(): failure - outbound group session size = 0"); - errorMessage = "outbound group session size = 0"; - } - else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) - { - LOGE(" ## deserializeJni(): failure - session failure OOM"); - errorMessage = "session failure OOM"; - } - else if (!aKeyBuffer) - { - LOGE(" ## deserializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!aSerializedDataBuffer) - { - LOGE(" ## deserializeJni(): failure - serialized data"); - errorMessage = "invalid serialized data"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "keyPtr JNI allocation OOM"; - } - else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); - errorMessage = "pickledPtr JNI allocation OOM"; - } - else - { - sessionPtr = olm_outbound_group_session(sessionPtr); - size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%.*s", static_cast(pickledLength), (char const *)pickledPtr); - - size_t result = olm_unpickle_outbound_group_session(sessionPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_outbound_group_session() Msg=%s", errorMessage); - } - else - { - LOGD(" ## deserializeJni(): success - result=%lu ", static_cast(result)); - } - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (pickledPtr) - { - env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); - } - - if (errorMessage) - { - if (sessionPtr) - { - olm_clear_outbound_group_session(sessionPtr); - free(sessionPtr); - } - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)sessionPtr; -} - diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h deleted file mode 100644 index f6abba2..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _OMLOUTBOUND_GROUP_SESSION_H -#define _OMLOUTBOUND_GROUP_SESSION_H - -#include "olm_jni.h" -#include "olm/olm.h" -#include "olm/outbound_group_session.h" - -#define OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmOutboundGroupSession,func_name) - -#ifdef __cplusplus -extern "C" { -#endif - -// session creation/destruction -JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); - -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); - -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer); - -// serialization -JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp deleted file mode 100644 index 5ca49db..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp +++ /dev/null @@ -1,961 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_session.h" - -using namespace AndroidOlmSdk; - -/** -* Init memory allocation for a session creation.
-* Make sure releaseSessionJni() is called when one is done with the session instance. -* @return valid memory allocation, NULL otherwise -**/ -OlmSession* initializeSessionMemory() -{ - size_t sessionSize = olm_session_size(); - OlmSession* sessionPtr = (OlmSession*)malloc(sessionSize); - - if (sessionPtr) - { - // init session object - sessionPtr = olm_session(sessionPtr); - LOGD("## initializeSessionMemory(): success - OLM session size=%lu",static_cast(sessionSize)); - } - else - { - LOGE("## initializeSessionMemory(): failure - OOM"); - } - - return sessionPtr; -} - -JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## createNewSessionJni(): IN"); - OlmSession* accountPtr = initializeSessionMemory(); - - if (!accountPtr) - { - LOGE("## initNewAccount(): failure - init session OOM"); - env->ThrowNew(env->FindClass("java/lang/Exception"), "init session OOM"); - } - else - { - LOGD(" ## createNewSessionJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); - } - - return (jlong)(intptr_t)accountPtr; -} - -JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) -{ - LOGD("## releaseSessionJni(): IN"); - OlmSession* sessionPtr = getSessionInstanceId(env, thiz); - - if (!sessionPtr) - { - LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL"); - } - else - { - olm_clear_session(sessionPtr); - - // even if free(NULL) does not crash, logs are performed for debug purpose - free(sessionPtr); - } -} - -// ********************************************************************* -// ********************** OUTBOUND SESSION ***************************** -// ********************************************************************* -/** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message.
The recipient is defined as the entity - * with whom the session is established. - * @param aOlmAccountId account instance - * @param aTheirIdentityKey the identity key of the recipient - * @param aTheirOneTimeKey the one time key of the recipient or an exception is thrown - **/ -JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) -{ - OlmSession* sessionPtr = getSessionInstanceId(env, thiz); - const char* errorMessage = NULL; - OlmAccount* accountPtr = NULL; - - if (!sessionPtr) - { - LOGE("## initOutboundSessionJni(): failure - invalid Session ptr=NULL"); - errorMessage = "invalid Session ptr=NULL"; - } - else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) - { - LOGE("## initOutboundSessionJni(): failure - invalid Account ptr=NULL"); - errorMessage = "invalid Account ptr=NULL"; - } - else if (!aTheirIdentityKeyBuffer || !aTheirOneTimeKeyBuffer) - { - LOGE("## initOutboundSessionJni(): failure - invalid keys"); - errorMessage = "invalid keys"; - } - else - { - size_t randomSize = olm_create_outbound_session_random_length(sessionPtr); - uint8_t *randomBuffPtr = NULL; - - LOGD("## initOutboundSessionJni(): randomSize=%lu",static_cast(randomSize)); - - if ( (0 != randomSize) && !setRandomInBuffer(env, &randomBuffPtr, randomSize)) - { - LOGE("## initOutboundSessionJni(): failure - random buffer init"); - errorMessage = "random buffer init"; - } - else - { - jbyte* theirIdentityKeyPtr = NULL; - jbyte* theirOneTimeKeyPtr = NULL; - - // convert identity & one time keys to C strings - if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) - { - LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM"); - errorMessage = "identityKey JNI allocation OOM"; - } - else if (!(theirOneTimeKeyPtr = env->GetByteArrayElements(aTheirOneTimeKeyBuffer, 0))) - { - LOGE("## initOutboundSessionJni(): failure - one time Key JNI allocation OOM"); - errorMessage = "one time Key JNI allocation OOM"; - } - else - { - size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); - size_t theirOneTimeKeyLength = (size_t)env->GetArrayLength(aTheirOneTimeKeyBuffer); - LOGD("## initOutboundSessionJni(): identityKey=%.*s oneTimeKey=%.*s", static_cast(theirIdentityKeyLength), theirIdentityKeyPtr, static_cast(theirOneTimeKeyLength), theirOneTimeKeyPtr); - - size_t sessionResult = olm_create_outbound_session(sessionPtr, - accountPtr, - theirIdentityKeyPtr, - theirIdentityKeyLength, - theirOneTimeKeyPtr, - theirOneTimeKeyLength, - (void*)randomBuffPtr, - randomSize); - if (sessionResult == olm_error()) { - errorMessage = (const char *)olm_session_last_error(sessionPtr); - LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s", errorMessage); - } - else - { - LOGD("## initOutboundSessionJni(): success - result=%lu", static_cast(sessionResult)); - } - } - - if (theirIdentityKeyPtr) - { - env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); - } - - if (theirOneTimeKeyPtr) - { - env->ReleaseByteArrayElements(aTheirOneTimeKeyBuffer, theirOneTimeKeyPtr, JNI_ABORT); - } - - if (randomBuffPtr) - { - memset(randomBuffPtr, 0, randomSize); - free(randomBuffPtr); - } - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } -} - - -// ********************************************************************* -// *********************** INBOUND SESSION ***************************** -// ********************************************************************* -/** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message.
- * An exception is thrown if the operation fails. - * @param aOlmAccountId account instance - * @param aOneTimeKeyMsg PRE_KEY message - */ -JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsgBuffer) -{ - const char* errorMessage = NULL; - OlmSession *sessionPtr = getSessionInstanceId(env,thiz); - OlmAccount *accountPtr = NULL; - size_t sessionResult; - - if (!sessionPtr) - { - LOGE("## initInboundSessionJni(): failure - invalid Session ptr=NULL"); - errorMessage = "invalid Session ptr=NULL"; - } - else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) - { - LOGE("## initInboundSessionJni(): failure - invalid Account ptr=NULL"); - errorMessage = "invalid Account ptr=NULL"; - } - else if (!aOneTimeKeyMsgBuffer) - { - LOGE("## initInboundSessionJni(): failure - invalid message"); - errorMessage = "invalid message"; - } - else - { - jbyte* messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0); - - if (!messagePtr) - { - LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM"); - errorMessage = "message JNI allocation OOM"; - } - else - { - size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); - LOGD("## initInboundSessionJni(): messageLength=%lu message=%.*s", static_cast(messageLength), static_cast(messageLength), messagePtr); - - sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength); - - if (sessionResult == olm_error()) - { - errorMessage = olm_session_last_error(sessionPtr); - LOGE("## initInboundSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); - } - else - { - LOGD("## initInboundSessionJni(): success - result=%lu", static_cast(sessionResult)); - } - - // free local alloc - env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } -} - -/** - * Create a new in-bound session for sending/receiving messages from an - * incoming PRE_KEY message based on the recipient identity key.
- * An exception is thrown if the operation fails. - * @param aOlmAccountId account instance - * @param aTheirIdentityKey the identity key of the recipient - * @param aOneTimeKeyMsg encrypted message - */ -JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) -{ - const char* errorMessage = NULL; - - OlmSession *sessionPtr = getSessionInstanceId(env, thiz); - OlmAccount *accountPtr = NULL; - jbyte *messagePtr = NULL; - jbyte *theirIdentityKeyPtr = NULL; - size_t sessionResult; - - if (!sessionPtr) - { - LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); - errorMessage = "invalid Session ptr=NULL"; - } - else if (!(accountPtr = (OlmAccount*)aOlmAccountId)) - { - LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid Account ptr=NULL"); - errorMessage = "invalid Account ptr=NULL"; - } - else if (!aTheirIdentityKeyBuffer) - { - LOGE("## initInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); - errorMessage = "invalid theirIdentityKey"; - } - else if (!aOneTimeKeyMsgBuffer) - { - LOGE("## initInboundSessionJni(): failure - invalid one time key message"); - errorMessage = "invalid invalid one time key message"; - } - else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) - { - LOGE("## initInboundSessionFromIdKeyJni(): failure - message JNI allocation OOM"); - errorMessage = "message JNI allocation OOM"; - } - else if(!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) - { - LOGE("## initInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); - errorMessage = "theirIdentityKey JNI allocation OOM"; - } - else - { - size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); - size_t theirIdentityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); - - LOGD("## initInboundSessionFromIdKeyJni(): message=%.*s messageLength=%lu", static_cast(messageLength), messagePtr, static_cast(messageLength)); - - sessionResult = olm_create_inbound_session_from(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, (void*)messagePtr , messageLength); - if (sessionResult == olm_error()) - { - errorMessage = (const char *)olm_session_last_error(sessionPtr); - LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s", errorMessage); - } - else - { - LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(sessionResult)); - } - } - - // free local alloc - if (messagePtr) - { - env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); - } - - if (theirIdentityKeyPtr) - { - env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } -} - -/** - * Checks if the PRE_KEY message is for this in-bound session.
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * @param aOneTimeKeyMsg PRE KEY message - * @return true if the PRE_KEY message matches - */ -JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) -{ - jboolean retCode = JNI_FALSE; - OlmSession *sessionPtr = getSessionInstanceId(env, thiz); - jbyte *messagePtr = NULL; - - if (!sessionPtr) - { - LOGE("## matchesInboundSessionJni(): failure - invalid Session ptr=NULL"); - } - else if (!aOneTimeKeyMsgBuffer) - { - LOGE("## matchesInboundSessionJni(): failure - invalid one time key message"); - } - else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) - { - LOGE("## matchesInboundSessionJni(): failure - one time key JNI allocation OOM"); - } - else - { - size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); - - size_t matchResult = olm_matches_inbound_session(sessionPtr, (void*)messagePtr , messageLength); - //if(matchResult == olm_error()) { - // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 - if (matchResult != 1) { - LOGE("## matchesInboundSessionJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); - } - else - { - retCode = JNI_TRUE; - LOGD("## matchesInboundSessionJni(): success - result=%lu", static_cast(matchResult)); - } - } - - // free local alloc - if (messagePtr) - { - env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); - } - - return retCode; -} - -/** - * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
- * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). - * @param aTheirIdentityKey the identity key of the sender - * @param aOneTimeKeyMsg PRE KEY message - * @return true if the PRE_KEY message matches. - */ -JNIEXPORT jboolean JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) -{ - jboolean retCode = JNI_FALSE; - OlmSession *sessionPtr = getSessionInstanceId(env, thiz); - jbyte *messagePtr = NULL; - jbyte *theirIdentityKeyPtr = NULL; - - if (!sessionPtr) - { - LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid Session ptr=NULL"); - } - else if (!aTheirIdentityKeyBuffer) - { - LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid theirIdentityKey"); - } - else if (!(theirIdentityKeyPtr = env->GetByteArrayElements(aTheirIdentityKeyBuffer, 0))) - { - LOGE("## matchesInboundSessionFromIdKeyJni(): failure - theirIdentityKey JNI allocation OOM"); - } - else if (!aOneTimeKeyMsgBuffer) - { - LOGE("## matchesInboundSessionFromIdKeyJni(): failure - invalid one time key message"); - } - else if (!(messagePtr = env->GetByteArrayElements(aOneTimeKeyMsgBuffer, 0))) - { - LOGE("## matchesInboundSessionFromIdKeyJni(): failure - one time key JNI allocation OOM"); - } - else - { - size_t identityKeyLength = (size_t)env->GetArrayLength(aTheirIdentityKeyBuffer); - size_t messageLength = (size_t)env->GetArrayLength(aOneTimeKeyMsgBuffer); - size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength); - - //if(matchResult == olm_error()) { - // for now olm_matches_inbound_session() returns 1 when it succeeds, otherwise 1- or 0 - if (matchResult != 1) - { - LOGE("## matchesInboundSessionFromIdKeyJni(): failure - no match Msg=%s",(const char *)olm_session_last_error(sessionPtr)); - } - else - { - retCode = JNI_TRUE; - LOGD("## matchesInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(matchResult)); - } - } - - // free local alloc - if (theirIdentityKeyPtr) - { - env->ReleaseByteArrayElements(aTheirIdentityKeyBuffer, theirIdentityKeyPtr, JNI_ABORT); - } - - if (messagePtr) - { - env->ReleaseByteArrayElements(aOneTimeKeyMsgBuffer, messagePtr, JNI_ABORT); - } - - return retCode; -} - -/** - * Encrypt a message using the session.
- * An exception is thrown if the operation fails. - * @param aClearMsg clear text message - * @param [out] aEncryptedMsg ciphered message - * @return the encrypted message - */ -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer, jobject aEncryptedMsg) -{ - jbyteArray encryptedMsgRet = 0; - const char* errorMessage = NULL; - - OlmSession *sessionPtr = getSessionInstanceId(env, thiz); - jbyte *clearMsgPtr = NULL; - jclass encryptedMsgJClass = 0; - jfieldID typeMsgFieldId; - - LOGD("## encryptMessageJni(): IN "); - - if (!sessionPtr) - { - LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL"); - errorMessage = "invalid Session ptr=NULL"; - } - else if (!aClearMsgBuffer) - { - LOGE("## encryptMessageJni(): failure - invalid clear message"); - errorMessage = "invalid clear message"; - } - else if (!aEncryptedMsg) - { - LOGE("## encryptMessageJni(): failure - invalid encrypted message"); - } - else if (!(clearMsgPtr = env->GetByteArrayElements(aClearMsgBuffer, 0))) - { - LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM"); - errorMessage = "clear message JNI allocation OOM"; - } - else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) - { - LOGE("## encryptMessageJni(): failure - unable to get crypted message class"); - errorMessage = "unable to get crypted message class"; - } - else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) - { - LOGE("## encryptMessageJni(): failure - unable to get message type field"); - errorMessage = "unable to get message type field"; - } - else - { - // get message type - size_t messageType = olm_encrypt_message_type(sessionPtr); - uint8_t *randomBuffPtr = NULL; - - // compute random buffer - // Note: olm_encrypt_random_length() can return 0, which means - // it just does not need new random data to encrypt a new message - size_t randomLength = olm_encrypt_random_length(sessionPtr); - - LOGD("## encryptMessageJni(): randomLength=%lu", static_cast(randomLength)); - - if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) - { - LOGE("## encryptMessageJni(): failure - random buffer init"); - errorMessage = "random buffer init"; - } - else - { - // alloc buffer for encrypted message - size_t clearMsgLength = (size_t)env->GetArrayLength(aClearMsgBuffer); - size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength); - - void *encryptedMsgPtr = malloc(encryptedMsgLength*sizeof(uint8_t)); - - if (!encryptedMsgPtr) - { - LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM"); - errorMessage = "encryptedMsgPtr buffer OOM"; - } - else - { - if (0 == randomLength) - { - LOGW("## encryptMessageJni(): random buffer is not required"); - } - - LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu clearMsgLength=%lu encryptedMsgLength=%lu",static_cast(messageType),static_cast(randomLength), static_cast(clearMsgLength), static_cast(encryptedMsgLength)); - // encrypt message - size_t result = olm_encrypt(sessionPtr, - (void const *)clearMsgPtr, - clearMsgLength, - randomBuffPtr, - randomLength, - encryptedMsgPtr, - encryptedMsgLength); - if (result == olm_error()) - { - errorMessage = (const char *)olm_session_last_error(sessionPtr); - LOGE("## encryptMessageJni(): failure - Msg=%s", errorMessage); - } - else - { - // update message type: PRE KEY or normal - env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType); - - encryptedMsgRet = env->NewByteArray(encryptedMsgLength); - env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedMsgLength, (jbyte*)encryptedMsgPtr); - - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%.*s", static_cast(result), static_cast(messageType), static_cast(result), (const char*)encryptedMsgPtr); - } - - free(encryptedMsgPtr); - } - - memset(randomBuffPtr, 0, randomLength); - free(randomBuffPtr); - } - } - - // free alloc - if (clearMsgPtr) - { - env->ReleaseByteArrayElements(aClearMsgBuffer, clearMsgPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return encryptedMsgRet; -} - -/** - * Decrypt a message using the session.
- * An exception is thrown if the operation fails. - * @param aEncryptedMsg message to decrypt - * @return decrypted message if operation succeed - */ -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg) -{ - const char* errorMessage = NULL; - - jbyteArray decryptedMsgRet = 0; - - jclass encryptedMsgJClass = 0; - jstring encryptedMsgJstring = 0; // <= obtained from encryptedMsgFieldId - // field IDs - jfieldID encryptedMsgFieldId; - jfieldID typeMsgFieldId; - // ptrs - OlmSession *sessionPtr = getSessionInstanceId(env, thiz); - const char *encryptedMsgPtr = NULL; // <= obtained from encryptedMsgJstring - uint8_t *plainTextMsgPtr = NULL; - char *tempEncryptedPtr = NULL; - - LOGD("## decryptMessageJni(): IN - OlmSession"); - - if (!sessionPtr) - { - LOGE("## decryptMessageJni(): failure - invalid Session ptr=NULL"); - errorMessage = "invalid Session ptr=NULL"; - } - else if (!aEncryptedMsg) - { - LOGE("## decryptMessageJni(): failure - invalid encrypted message"); - errorMessage = "invalid encrypted message"; - } - else if (!(encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg))) - { - LOGE("## decryptMessageJni(): failure - unable to get encrypted message class"); - errorMessage = "unable to get encrypted message class"; - } - else if (!(encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;"))) - { - LOGE("## decryptMessageJni(): failure - unable to get message field"); - errorMessage = "unable to get message field"; - } - else if (!(typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J"))) - { - LOGE("## decryptMessageJni(): failure - unable to get message type field"); - errorMessage = "unable to get message type field"; - } - else if (!(encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId))) - { - LOGE("## decryptMessageJni(): failure - JNI encrypted object "); - errorMessage = "JNI encrypted object"; - } - else if (!(encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0))) - { - LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); - errorMessage = "encrypted message JNI allocation OOM"; - } - else - { - // get message type - size_t encryptedMsgType = (size_t)env->GetLongField(aEncryptedMsg, typeMsgFieldId); - // get encrypted message length - size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(encryptedMsgJstring); - - // create a dedicated temp buffer to be used in next Olm API calls - tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t))); - memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - LOGD("## decryptMessageJni(): MsgType=%lu encryptedMsgLength=%lu encryptedMsg=%.*s",static_cast(encryptedMsgType),static_cast(encryptedMsgLength), static_cast(encryptedMsgLength), encryptedMsgPtr); - - // get max plaintext length - size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr, - static_cast(encryptedMsgType), - static_cast(tempEncryptedPtr), - encryptedMsgLength); - // Note: tempEncryptedPtr is destroyed by olm_decrypt_max_plaintext_length() - - if (maxPlainTextLength == olm_error()) - { - errorMessage = (const char *)olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt_max_plaintext_length Msg=%s", errorMessage); - } - else - { - LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",static_cast(maxPlainTextLength)); - - // allocate output decrypted message - plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t))); - - // decrypt, but before reload encrypted buffer (previous one was destroyed) - memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength); - size_t plaintextLength = olm_decrypt(sessionPtr, - encryptedMsgType, - (void*)tempEncryptedPtr, - encryptedMsgLength, - plainTextMsgPtr, - maxPlainTextLength); - if (plaintextLength == olm_error()) - { - errorMessage = (const char *)olm_session_last_error(sessionPtr); - LOGE("## decryptMessageJni(): failure - olm_decrypt Msg=%s", errorMessage); - } - else - { - decryptedMsgRet = env->NewByteArray(plaintextLength); - env->SetByteArrayRegion(decryptedMsgRet, 0 , plaintextLength, (jbyte*)plainTextMsgPtr); - - LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast(plaintextLength)); - } - } - } - - // free alloc - if (encryptedMsgPtr) - { - env->ReleaseStringUTFChars(encryptedMsgJstring, encryptedMsgPtr); - } - - if (tempEncryptedPtr) - { - free(tempEncryptedPtr); - } - - if (plainTextMsgPtr) - { - free(plainTextMsgPtr); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return decryptedMsgRet; -} - -/** - * Get the session identifier for this session. - * An exception is thrown if the operation fails. - * @return the session identifier - */ -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - jbyteArray returnValue = 0; - - LOGD("## getSessionIdentifierJni(): IN "); - - OlmSession *sessionPtr = getSessionInstanceId(env, thiz); - - if (!sessionPtr) - { - LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL"); - errorMessage = "invalid Session ptr=NULL"; - } - else - { - // get the size to alloc to contain the id - size_t lengthSessionId = olm_session_id_length(sessionPtr); - LOGD("## getSessionIdentifierJni(): lengthSessionId=%lu",static_cast(lengthSessionId)); - - void *sessionIdPtr = malloc(lengthSessionId*sizeof(uint8_t)); - - if (!sessionIdPtr) - { - LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM"); - errorMessage = "identifier allocation OOM"; - } - else - { - size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId); - - if (result == olm_error()) - { - errorMessage = (const char *)olm_session_last_error(sessionPtr); - LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s", errorMessage); - } - else - { - LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); - - returnValue = env->NewByteArray(result); - env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); - } - - free(sessionIdPtr); - } - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return returnValue; -} - -/** - * Serialize and encrypt session instance.
- * An exception is thrown if the operation fails. - * @param aKeyBuffer key used to encrypt the serialized account data - * @return the serialised account as bytes buffer. - **/ -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - jbyteArray returnValue = 0; - - jbyte* keyPtr = NULL; - OlmSession* sessionPtr = getSessionInstanceId(env, thiz); - - LOGD("## serializeJni(): IN"); - - if (!sessionPtr) - { - LOGE(" ## serializeJni(): failure - invalid session ptr"); - errorMessage = "invalid session ptr"; - } - else if (!aKeyBuffer) - { - LOGE(" ## serializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "ikeyPtr JNI allocation OOM"; - } - else - { - size_t pickledLength = olm_pickle_session_length(sessionPtr); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - - void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); - - if (!pickledPtr) - { - LOGE(" ## serializeJni(): failure - pickledPtr buffer OOM"); - errorMessage = "pickledPtr buffer OOM"; - } - else - { - size_t result = olm_pickle_session(sessionPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_session_last_error(sessionPtr); - LOGE(" ## serializeJni(): failure - olm_pickle_session() Msg=%s", errorMessage); - } - else - { - LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); - - returnValue = env->NewByteArray(pickledLength); - env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); - } - - free(pickledPtr); - } - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return returnValue; -} - -/** - * Allocate a new session and initialize it with the serialisation data.
- * An exception is thrown if the operation fails. - * @param aSerializedData the session serialisation buffer - * @param aKey the key used to encrypt the serialized account data - * @return the deserialized session - **/ -JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) -{ - const char* errorMessage = NULL; - OlmSession* sessionPtr = initializeSessionMemory(); - jbyte* keyPtr = NULL; - jbyte* pickledPtr = NULL; - - LOGD("## deserializeJni(): IN"); - - if (!sessionPtr) - { - LOGE(" ## deserializeJni(): failure - session failure OOM"); - errorMessage = "session failure OOM"; - } - else if (!aKeyBuffer) - { - LOGE(" ## deserializeJni(): failure - invalid key"); - errorMessage = "invalid key"; - } - else if (!aSerializedDataBuffer) - { - LOGE(" ## deserializeJni(): failure - serialized data"); - errorMessage = "serialized data"; - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); - errorMessage = "keyPtr JNI allocation OOM"; - } - else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) - { - LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); - errorMessage = "pickledPtr JNI allocation OOM"; - } - else - { - size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - LOGD(" ## deserializeJni(): pickled=%.*s",static_cast(pickledLength), (char const *)pickledPtr); - - size_t result = olm_unpickle_session(sessionPtr, - (void const *)keyPtr, - keyLength, - (void*)pickledPtr, - pickledLength); - if (result == olm_error()) - { - errorMessage = olm_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); - } - else - { - LOGD(" ## initJni(): success - result=%lu ", static_cast(result)); - } - } - - // free alloc - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (pickledPtr) - { - env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); - } - - if (errorMessage) - { - if (sessionPtr) - { - olm_clear_session(sessionPtr); - free(sessionPtr); - } - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } - - return (jlong)(intptr_t)sessionPtr; -} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h deleted file mode 100644 index b8cdd2f..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _OMLSESSION_H -#define _OMLSESSION_H - -#include "olm_jni.h" -#include "olm/olm.h" - -#define OLM_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmSession,func_name) - -#ifdef __cplusplus -extern "C" { -#endif - -// session creation/destruction -JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); - -// outbound session -JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aTheirOneTimeKey); - -// inbound sessions: establishment based on PRE KEY message -JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aOneTimeKeyMsg); -JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); - -// match inbound sessions: based on PRE KEY message -JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); -JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); - -// encrypt/decrypt -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); - -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); - -// serialization -JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp deleted file mode 100644 index f6fe719..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "olm_utility.h" - -using namespace AndroidOlmSdk; - -OlmUtility* initializeUtilityMemory() -{ - size_t utilitySize = olm_utility_size(); - OlmUtility* utilityPtr = (OlmUtility*)malloc(utilitySize); - - if (utilityPtr) - { - utilityPtr = olm_utility(utilityPtr); - LOGD("## initializeUtilityMemory(): success - OLM utility size=%lu",static_cast(utilitySize)); - } - else - { - LOGE("## initializeUtilityMemory(): failure - OOM"); - } - - return utilityPtr; -} - -JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(createUtilityJni)(JNIEnv *env, jobject thiz) -{ - OlmUtility* utilityPtr = initializeUtilityMemory(); - - LOGD("## createUtilityJni(): IN"); - - // init account memory allocation - if (!utilityPtr) - { - LOGE(" ## createUtilityJni(): failure - init OOM"); - env->ThrowNew(env->FindClass("java/lang/Exception"), "init OOM"); - } - else - { - LOGD(" ## createUtilityJni(): success"); - } - - return (jlong)(intptr_t)utilityPtr; -} - - -JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz) -{ - OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); - - LOGD("## releaseUtilityJni(): IN"); - - if (!utilityPtr) - { - LOGE("## releaseUtilityJni(): failure - utility ptr=NULL"); - } - else - { - olm_clear_utility(utilityPtr); - free(utilityPtr); - } -} - - -/** - * Verify an ed25519 signature. - * @param aSignature the base64-encoded message signature to be checked. - * @param aKey the ed25519 key (fingerprint key) - * @param aMessage the message which was signed - * @return 0 if validation succeed, an error message string if operation failed - */ -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignatureBuffer, jbyteArray aKeyBuffer, jbyteArray aMessageBuffer) -{ - jstring errorMessageRetValue = 0; - OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); - jbyte* signaturePtr = NULL; - jbyte* keyPtr = NULL; - jbyte* messagePtr = NULL; - - LOGD("## verifyEd25519SignatureJni(): IN"); - - if (!utilityPtr) - { - LOGE(" ## verifyEd25519SignatureJni(): failure - invalid utility ptr=NULL"); - } - else if (!aSignatureBuffer || !aKeyBuffer || !aMessageBuffer) - { - LOGE(" ## verifyEd25519SignatureJni(): failure - invalid input parameters "); - } - else if (!(signaturePtr = env->GetByteArrayElements(aSignatureBuffer, 0))) - { - LOGE(" ## verifyEd25519SignatureJni(): failure - signature JNI allocation OOM"); - } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) - { - LOGE(" ## verifyEd25519SignatureJni(): failure - key JNI allocation OOM"); - } - else if (!(messagePtr = env->GetByteArrayElements(aMessageBuffer, 0))) - { - LOGE(" ## verifyEd25519SignatureJni(): failure - message JNI allocation OOM"); - } - else - { - size_t signatureLength = (size_t)env->GetArrayLength(aSignatureBuffer); - size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); - size_t messageLength = (size_t)env->GetArrayLength(aMessageBuffer); - LOGD(" ## verifyEd25519SignatureJni(): signatureLength=%lu keyLength=%lu messageLength=%lu",static_cast(signatureLength),static_cast(keyLength),static_cast(messageLength)); - LOGD(" ## verifyEd25519SignatureJni(): key=%.*s", static_cast(keyLength), keyPtr); - - size_t result = olm_ed25519_verify(utilityPtr, - (void const *)keyPtr, - keyLength, - (void const *)messagePtr, - messageLength, - (void*)signaturePtr, - signatureLength); - if (result == olm_error()) { - const char *errorMsgPtr = olm_utility_last_error(utilityPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); - LOGE("## verifyEd25519SignatureJni(): failure - olm_ed25519_verify Msg=%s",errorMsgPtr); - } - else - { - LOGD("## verifyEd25519SignatureJni(): success - result=%lu", static_cast(result)); - } - } - - // free alloc - if (signaturePtr) - { - env->ReleaseByteArrayElements(aSignatureBuffer, signaturePtr, JNI_ABORT); - } - - if (keyPtr) - { - env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); - } - - if (messagePtr) - { - env->ReleaseByteArrayElements(aMessageBuffer, messagePtr, JNI_ABORT); - } - - return errorMessageRetValue; -} - -/** - * Compute the digest (SHA 256) for the message passed in parameter.
- * The digest value is the function return value. - * An exception is thrown if the operation fails. - * @param aMessage the message - * @return digest of the message. - **/ -JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHashBuffer) -{ - jbyteArray sha256Ret = 0; - - OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); - jbyte* messagePtr = NULL; - - LOGD("## sha256Jni(): IN"); - - if (!utilityPtr) - { - LOGE(" ## sha256Jni(): failure - invalid utility ptr=NULL"); - } - else if(!aMessageToHashBuffer) - { - LOGE(" ## sha256Jni(): failure - invalid message parameters "); - } - else if(!(messagePtr = env->GetByteArrayElements(aMessageToHashBuffer, 0))) - { - LOGE(" ## sha256Jni(): failure - message JNI allocation OOM"); - } - else - { - // get lengths - size_t messageLength = (size_t)env->GetArrayLength(aMessageToHashBuffer); - size_t hashLength = olm_sha256_length(utilityPtr); - void* hashValuePtr = malloc((hashLength)*sizeof(uint8_t)); - - if (!hashValuePtr) - { - LOGE("## sha256Jni(): failure - hash value allocation OOM"); - } - else - { - size_t result = olm_sha256(utilityPtr, - (void const *)messagePtr, - messageLength, - (void *)hashValuePtr, - hashLength); - if (result == olm_error()) - { - LOGE("## sha256Jni(): failure - hash creation Msg=%s",(const char *)olm_utility_last_error(utilityPtr)); - } - else - { - LOGD("## sha256Jni(): success - result=%lu hashValue=%.*s",static_cast(result), static_cast(result), (char*)hashValuePtr); - sha256Ret = env->NewByteArray(result); - env->SetByteArrayRegion(sha256Ret, 0 , result, (jbyte*)hashValuePtr); - } - - free(hashValuePtr); - } - } - - if (messagePtr) - { - env->ReleaseByteArrayElements(aMessageToHashBuffer, messagePtr, JNI_ABORT); - } - - return sha256Ret; -} \ No newline at end of file diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h deleted file mode 100644 index de4b290..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef _OMLUTILITY_H -#define _OMLUTILITY_H - -#include "olm_jni.h" -#include "olm/olm.h" - -#define OLM_UTILITY_FUNC_DEF(func_name) FUNC_DEF(OlmUtility,func_name) - - -#ifdef __cplusplus -extern "C" { -#endif -JNIEXPORT jlong OLM_UTILITY_FUNC_DEF(createUtilityJni)(JNIEnv *env, jobject thiz); -JNIEXPORT void OLM_UTILITY_FUNC_DEF(releaseUtilityJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, jobject thiz, jbyteArray aSignature, jbyteArray aKey, jbyteArray aMessage); -JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHash); -#ifdef __cplusplus -} -#endif - - - -#endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml b/java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml deleted file mode 100644 index 93bea1d..0000000 --- a/java/android/OlmLibSdk/olm-sdk/src/main/res/values/strings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - OlmSdk - diff --git a/java/android/OlmLibSdk/settings.gradle b/java/android/OlmLibSdk/settings.gradle deleted file mode 100644 index d11302c..0000000 --- a/java/android/OlmLibSdk/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':olm-sdk' -- cgit v1.2.3