aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorpedroGitt <pedro.contreiras@amdocs.com>2016-10-05 18:25:09 +0200
committerpedroGitt <pedro.contreiras@amdocs.com>2016-10-05 18:25:09 +0200
commit5573d3ab23de21b93b1ecc50d4fce96b02a42886 (patch)
tree96cab6aeb25b6ed60ea1ab27757e29c00b013b79 /java
parent3136826e02ee379858ff5a1c3aa9140f0136e813 (diff)
First commit adding Olm Lib for Android
- Add Android Studio project
Diffstat (limited to 'java')
-rw-r--r--java/android/OlmLibSdk/build.gradle23
-rw-r--r--java/android/OlmLibSdk/gradle.properties19
-rw-r--r--java/android/OlmLibSdk/gradlew160
-rw-r--r--java/android/OlmLibSdk/gradlew.bat90
-rw-r--r--java/android/OlmLibSdk/olm-sdk/build.gradle72
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java223
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml11
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java5
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmManager.java32
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java327
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk52
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/jni/Application.mk3
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp491
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h34
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h46
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp476
-rw-r--r--java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h38
-rw-r--r--java/android/OlmLibSdk/settings.gradle1
18 files changed, 2102 insertions, 1 deletions
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 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.matrix.olm">
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:supportsRtl="true">
+
+ </application>
+
+</manifest>
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.<br>
+ * Return the identity keys (identity & fingerprint keys) in a JSON array.<br>
* 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.<br>
+ * 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.<br>
+ * 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()}.<br>
+ * 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.<br>
+ * 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.<br>
+ * 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.<br>
+ * 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!.<br>
+ * 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.<br>
+ * 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.<br> 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).<br>
+ * 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.<br>
+ * 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.<br> 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.<br>
+ * The returned data is a JSON-formatted object with the single property
+ * <tt>curve25519</tt>, 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.<br>
+ * 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().<br>
+ * 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.<br>
+* 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<randomSize;i++)
+ {
+ randomBuffPtr[i] = (std::uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO);;
+ }
+
+ // create account
+ accountRetCode = olm_create_account(accountPtr, randomBuffPtr, randomSize);
+ if(accountRetCode == olm_error()) {
+ const char *errorMsgPtr = olm_account_last_error(accountPtr);
+ LOGE("## initNewAccount(): failure - account creation failed Msg=%s", errorMsgPtr);
+ }
+
+ free(randomBuffPtr);
+ LOGD("## initNewAccount(): success - OLM account created");
+ LOGD("## initNewAccount(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr);
+ }
+ }
+
+ return (jlong)(intptr_t)accountPtr;
+}
+
+// *********************************************************************
+// ************************* IDENTITY KEYS API *************************
+// *********************************************************************
+/**
+* Get identity keys: Ed25519 fingerprint key and Curve25519 identity key.<br>
+* 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 <cstdlib>
+#include <cstdio>
+#include <string>
+#include <sstream>
+#include <map>
+#include <jni.h>
+#include <android/log.h>
+
+#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.<br>
+* 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.<br> 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.<br>
+ * @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.<br>
+ * @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.<br>
+ * 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.<br>
+ * 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'