First commit adding Olm Lib for Android

- Add Android Studio project
release-v2.2.0
pedroGitt 2016-10-05 18:25:09 +02:00
parent 3136826e02
commit 5573d3ab23
18 changed files with 2102 additions and 1 deletions

View File

@ -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
}

View File

@ -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

160
java/android/OlmLibSdk/gradlew vendored Normal file
View File

@ -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 "$@"

90
java/android/OlmLibSdk/gradlew.bat vendored Normal file
View File

@ -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

View File

@ -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'
}

View File

@ -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();
}
}

View File

@ -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>

View File

@ -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
*/

View File

@ -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();
}

View File

@ -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();
}
}

View File

@ -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)

View File

@ -0,0 +1,3 @@
APP_PLATFORM := android-21
APP_ABI := arm64-v8a #armeabi-v7a armeabi x86 x86_64
APP_STL := gnustl_static

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -0,0 +1 @@
include ':olm-sdk'