First commit adding Olm Lib for Android
- Add Android Studio project
This commit is contained in:
parent
3136826e02
commit
5573d3ab23
18 changed files with 2102 additions and 1 deletions
23
java/android/OlmLibSdk/build.gradle
Normal file
23
java/android/OlmLibSdk/build.gradle
Normal 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
|
||||||
|
}
|
19
java/android/OlmLibSdk/gradle.properties
Normal file
19
java/android/OlmLibSdk/gradle.properties
Normal 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
160
java/android/OlmLibSdk/gradlew
vendored
Normal 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
90
java/android/OlmLibSdk/gradlew.bat
vendored
Normal 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
|
72
java/android/OlmLibSdk/olm-sdk/build.gradle
Normal file
72
java/android/OlmLibSdk/olm-sdk/build.gradle
Normal 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'
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
11
java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml
Normal file
11
java/android/OlmLibSdk/olm-sdk/src/main/AndroidManifest.xml
Normal 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>
|
|
@ -26,7 +26,10 @@ public class OlmAccount {
|
||||||
|
|
||||||
// JSON keys used in the JSON objects returned by JNI
|
// JSON keys used in the JSON objects returned by JNI
|
||||||
public static String JSON_KEY_ONE_TIME_KEY = "curve25519";
|
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_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 **/
|
/** instance unique identifier, used in JNI to match the corresponding native class **/
|
||||||
private int mJavaInstanceId;
|
private int mJavaInstanceId;
|
||||||
|
@ -99,7 +102,7 @@ public class OlmAccount {
|
||||||
private native byte[] identityKeysJni();
|
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()}.
|
* Public API for {@link #identityKeysJni()}.
|
||||||
* @return identity keys in JSON array format if operation succeed, null otherwise
|
* @return identity keys in JSON array format if operation succeed, null otherwise
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
52
java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
Normal file
52
java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
Normal 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)
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
APP_PLATFORM := android-21
|
||||||
|
APP_ABI := arm64-v8a #armeabi-v7a armeabi x86 x86_64
|
||||||
|
APP_STL := gnustl_static
|
491
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
Normal file
491
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
Normal 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;
|
||||||
|
}
|
34
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h
Normal file
34
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h
Normal 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
|
46
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h
Normal file
46
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h
Normal 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
|
476
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
Normal file
476
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
Normal 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;
|
||||||
|
}
|
38
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
Normal file
38
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
Normal 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
|
1
java/android/OlmLibSdk/settings.gradle
Normal file
1
java/android/OlmLibSdk/settings.gradle
Normal file
|
@ -0,0 +1 @@
|
||||||
|
include ':olm-sdk'
|
Loading…
Reference in a new issue