Merge remote-tracking branch 'origin/pedroc/android_e2e' into pedroc/android_e2e_dev
This commit is contained in:
commit
502de788f4
23 changed files with 2943 additions and 0 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
|
90
java/android/OlmLibSdk/olm-sdk/build.gradle
Normal file
90
java/android/OlmLibSdk/olm-sdk/build.gradle
Normal file
|
@ -0,0 +1,90 @@
|
|||
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 ndkBuildNativeRelease(type: Exec, description: 'NDK building..') {
|
||||
println 'ndkBuildNativeRelease starts..'
|
||||
workingDir file('src/main')
|
||||
commandLine getNdkBuildCmd(), 'NDK_DEBUG=0'
|
||||
}
|
||||
|
||||
task ndkBuildNativeDebug(type: Exec, description: 'NDK building..') {
|
||||
println 'ndkBuildNativeDebug starts..'
|
||||
workingDir file('src/main')
|
||||
commandLine getNdkBuildCmd(), 'NDK_DEBUG=1'
|
||||
}
|
||||
|
||||
task cleanNative(type: Exec, description: 'Clean NDK build') {
|
||||
workingDir file('src/main')
|
||||
commandLine getNdkBuildCmd(), 'clean'
|
||||
}
|
||||
|
||||
/*tasks.withType(JavaCompile) {
|
||||
compileTask -> compileTask.dependsOn ndkBuildNative
|
||||
}*/
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
compileTask -> if (compileTask.name.startsWith('compileDebugJava')) {
|
||||
println 'test compile: Debug'
|
||||
compileTask.dependsOn ndkBuildNativeDebug
|
||||
} else if (compileTask.name.startsWith('compileReleaseJava')) {
|
||||
println 'test compile: Release'
|
||||
compileTask.dependsOn ndkBuildNativeRelease
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
clean.dependsOn cleanNative
|
||||
|
||||
}
|
||||
|
||||
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,220 @@
|
|||
package org.matrix.olm;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
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;
|
||||
|
||||
@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 test01CreateReleaseAccount() {
|
||||
mOlmAccount = new OlmAccount();
|
||||
assertNotNull(mOlmAccount);
|
||||
|
||||
mOlmAccount.releaseAccount();
|
||||
assertTrue(0 == mOlmAccount.getOlmAccountId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test02CreateAccount() {
|
||||
mOlmAccount = new OlmAccount();
|
||||
assertNotNull(mOlmAccount);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test03InitNewAccount() {
|
||||
assertTrue(mOlmAccount.initNewAccount());
|
||||
mIsAccountCreated = true;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test04GetOlmAccountId() {
|
||||
long olmNativeInstance = mOlmAccount.getOlmAccountId();
|
||||
Log.d(LOG_TAG,"## testGetOlmAccountId olmNativeInstance="+olmNativeInstance);
|
||||
assertTrue(0!=olmNativeInstance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test05IdentityKeys() {
|
||||
JSONObject identityKeysJson = mOlmAccount.identityKeys();
|
||||
assertNotNull(identityKeysJson);
|
||||
Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson);
|
||||
|
||||
try {
|
||||
String fingerPrintKey = identityKeysJson.getString(OlmAccount.JSON_KEY_FINGER_PRINT_KEY);
|
||||
assertTrue("fingerprint key missing",!TextUtils.isEmpty(fingerPrintKey));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
assertTrue("Exception MSg="+e.getMessage(), false);
|
||||
}
|
||||
|
||||
try {
|
||||
String identityKey = identityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY);
|
||||
assertTrue("identity key missing",!TextUtils.isEmpty(identityKey));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
assertTrue("Exception MSg="+e.getMessage(), false);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//****************************************************
|
||||
//** ************** One time keys TESTS **************
|
||||
//****************************************************
|
||||
@Test
|
||||
public void test06MaxOneTimeKeys() {
|
||||
long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys();
|
||||
Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys);
|
||||
|
||||
assertTrue(maxOneTimeKeys>0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test07GenerateOneTimeKeys() {
|
||||
int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER);
|
||||
assertTrue(0==retValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test08OneTimeKeysJsonFormat() {
|
||||
int oneTimeKeysCount = 0;
|
||||
JSONObject generatedKeysJsonObj;
|
||||
JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys();
|
||||
assertNotNull(oneTimeKeysJson);
|
||||
|
||||
try {
|
||||
generatedKeysJsonObj = oneTimeKeysJson.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY);
|
||||
assertTrue(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", null!=generatedKeysJsonObj);
|
||||
|
||||
// test the count of the generated one time keys:
|
||||
Iterator<String> generatedKeysIt = generatedKeysJsonObj.keys();
|
||||
while(generatedKeysIt.hasNext()){
|
||||
generatedKeysIt.next();
|
||||
oneTimeKeysCount++;
|
||||
}
|
||||
assertTrue("Expected count="+GENERATION_ONE_TIME_KEYS_NUMBER+" found="+oneTimeKeysCount,GENERATION_ONE_TIME_KEYS_NUMBER==oneTimeKeysCount);
|
||||
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Exception MSg="+e.getMessage(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test10RemoveOneTimeKeysForSession() {
|
||||
OlmSession olmSession = new OlmSession();
|
||||
olmSession.initNewSession();
|
||||
long sessionId = olmSession.getOlmSessionId();
|
||||
assertTrue(0 != sessionId);
|
||||
|
||||
int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(sessionId);
|
||||
// no one time key has been use in the session, so removeOneTimeKeysForSession() returns an error
|
||||
assertTrue(0 != sessionRetCode);
|
||||
|
||||
olmSession.releaseSession();
|
||||
sessionId = olmSession.getOlmSessionId();
|
||||
assertTrue("sessionRetCode="+sessionRetCode,0 == sessionId);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test11MarkOneTimeKeysAsPublished() {
|
||||
int retCode = mOlmAccount.markOneTimeKeysAsPublished();
|
||||
// if OK => retCode=0
|
||||
assertTrue(0 == retCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test12SignMessage() {
|
||||
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 oneTimeKeysKeysJson = account.oneTimeKeys();
|
||||
Log.d(LOG_TAG, "## testJni(): oneTimeKeysKeysJson="+oneTimeKeysKeysJson.toString());
|
||||
|
||||
int asPublishedRetCode = account.markOneTimeKeysAsPublished();
|
||||
Log.d(LOG_TAG, "## testJni(): asPublishedRetCode="+asPublishedRetCode);
|
||||
|
||||
String clearMsg ="My clear message";
|
||||
String signedMsg = account.signMessage(clearMsg);
|
||||
Log.d(LOG_TAG, "## testJni(): signedMsg="+signedMsg);
|
||||
|
||||
account.releaseAccount();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
package org.matrix.olm;
|
||||
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
public class OlmSessionTest {
|
||||
private static final String LOG_TAG = "OlmSessionTest";
|
||||
|
||||
private static OlmManager mOlmManager;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpClass(){
|
||||
// load native lib
|
||||
mOlmManager = new OlmManager();
|
||||
|
||||
String version = mOlmManager.getOlmLibVersion();
|
||||
assertNotNull(version);
|
||||
Log.d(LOG_TAG, "## setUpClass(): lib version="+version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic test:
|
||||
* - alice creates an account
|
||||
* - bob creates an account
|
||||
* - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey)
|
||||
* - alice encrypts a message with its session
|
||||
* - bob creates an inbound session based on alice's encrypted message
|
||||
* - bob decrypts the encrypted message with its session
|
||||
*/
|
||||
@Test
|
||||
public void test01AliceToBob() {
|
||||
final int ONE_TIME_KEYS_NUMBER = 5;
|
||||
String bobIdentityKey = null;
|
||||
String bobOneTimeKey=null;
|
||||
|
||||
// creates alice & bob accounts
|
||||
OlmAccount aliceAccount = new OlmAccount();
|
||||
aliceAccount.initNewAccount();
|
||||
|
||||
OlmAccount bobAccount = new OlmAccount();
|
||||
bobAccount.initNewAccount();
|
||||
|
||||
// test accounts creation
|
||||
assertTrue(0!=bobAccount.getOlmAccountId());
|
||||
assertTrue(0!=aliceAccount.getOlmAccountId());
|
||||
|
||||
// get bob identity key
|
||||
JSONObject bobIdentityKeysJson = bobAccount.identityKeys();
|
||||
assertNotNull(bobIdentityKeysJson);
|
||||
try {
|
||||
bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY);
|
||||
assertTrue(null!=bobIdentityKey);
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Exception MSg="+e.getMessage(), false);
|
||||
}
|
||||
|
||||
// get bob one time keys
|
||||
assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
|
||||
JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys();
|
||||
assertNotNull(bobOneTimeKeysJsonObj);
|
||||
try {
|
||||
JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY);
|
||||
assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys);
|
||||
|
||||
Iterator<String> generatedKeysIt = generatedKeys.keys();
|
||||
if(generatedKeysIt.hasNext()) {
|
||||
bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next());
|
||||
}
|
||||
assertNotNull(bobOneTimeKey);
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Exception MSg="+e.getMessage(), false);
|
||||
}
|
||||
|
||||
// CREATE ALICE SESSION
|
||||
OlmSession aliceSession = new OlmSession();
|
||||
aliceSession.initNewSession();
|
||||
assertTrue(0!=aliceSession.getOlmSessionId());
|
||||
|
||||
// CREATE ALICE OUTBOUND SESSION and encrypt message to bob
|
||||
assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey));
|
||||
String clearMsg = "Heloo bob , this is alice!";
|
||||
OlmMessage encryptedMsgToBob = aliceSession.encryptMessage(clearMsg);
|
||||
assertNotNull(encryptedMsgToBob);
|
||||
Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText);
|
||||
|
||||
// CREATE BOB INBOUND SESSION and decrypt message from alice
|
||||
OlmSession bobSession = new OlmSession();
|
||||
bobSession.initNewSession();
|
||||
assertTrue(0!=bobSession.getOlmSessionId());
|
||||
assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText));
|
||||
String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob);
|
||||
assertNotNull(decryptedMsg);
|
||||
|
||||
// MESSAGE COMPARISON: decrypted vs encrypted
|
||||
assertTrue(clearMsg.equals(decryptedMsg));
|
||||
|
||||
// clean objects..
|
||||
assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId()));
|
||||
// release accounts
|
||||
bobAccount.releaseAccount();
|
||||
aliceAccount.releaseAccount();
|
||||
// release sessions
|
||||
bobSession.releaseSession();
|
||||
aliceSession.releaseSession();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Same as test01AliceToBob but with bob who's encrypting messages
|
||||
* to alice and alice decrypt them.<br>
|
||||
* - alice creates an account
|
||||
* - bob creates an account
|
||||
* - alice creates an outbound session with bob (bobIdentityKey & bobOneTimeKey)
|
||||
* - alice encrypts a message with its own session
|
||||
* - bob creates an inbound session based on alice's encrypted message
|
||||
* - bob decrypts the encrypted message with its own session
|
||||
* - bob encrypts messages with its own session
|
||||
* - alice decrypts bob's messages with its own message
|
||||
*/
|
||||
@Test
|
||||
public void test02AliceToBobBackAndForth() {
|
||||
final int ONE_TIME_KEYS_NUMBER = 1;
|
||||
String bobIdentityKey = null;
|
||||
String bobOneTimeKey=null;
|
||||
|
||||
// creates alice & bob accounts
|
||||
OlmAccount aliceAccount = new OlmAccount();
|
||||
aliceAccount.initNewAccount();
|
||||
|
||||
OlmAccount bobAccount = new OlmAccount();
|
||||
bobAccount.initNewAccount();
|
||||
|
||||
// test accounts creation
|
||||
assertTrue(0!=bobAccount.getOlmAccountId());
|
||||
assertTrue(0!=aliceAccount.getOlmAccountId());
|
||||
|
||||
// get bob identity key
|
||||
JSONObject bobIdentityKeysJson = bobAccount.identityKeys();
|
||||
assertNotNull(bobIdentityKeysJson);
|
||||
try {
|
||||
bobIdentityKey = bobIdentityKeysJson.getString(OlmAccount.JSON_KEY_IDENTITY_KEY);
|
||||
assertTrue(null!=bobIdentityKey);
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Exception MSg="+e.getMessage(), false);
|
||||
}
|
||||
|
||||
// get bob one time keys
|
||||
assertTrue(0==bobAccount.generateOneTimeKeys(ONE_TIME_KEYS_NUMBER));
|
||||
JSONObject bobOneTimeKeysJsonObj = bobAccount.oneTimeKeys();
|
||||
assertNotNull(bobOneTimeKeysJsonObj);
|
||||
try {
|
||||
JSONObject generatedKeys = bobOneTimeKeysJsonObj.getJSONObject(OlmAccount.JSON_KEY_ONE_TIME_KEY);
|
||||
assertNotNull(OlmAccount.JSON_KEY_ONE_TIME_KEY +" object is missing", generatedKeys);
|
||||
|
||||
Iterator<String> generatedKeysIt = generatedKeys.keys();
|
||||
if(generatedKeysIt.hasNext()) {
|
||||
bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next());
|
||||
}
|
||||
assertNotNull(bobOneTimeKey);
|
||||
} catch (JSONException e) {
|
||||
assertTrue("Exception MSg="+e.getMessage(), false);
|
||||
}
|
||||
|
||||
// CREATE ALICE SESSION
|
||||
OlmSession aliceSession = new OlmSession();
|
||||
aliceSession.initNewSession();
|
||||
assertTrue(0!=aliceSession.getOlmSessionId());
|
||||
|
||||
// CREATE ALICE OUTBOUND SESSION and encrypt message to bob
|
||||
assertNotNull(aliceSession.initOutboundSessionWithAccount(aliceAccount, bobIdentityKey, bobOneTimeKey));
|
||||
String helloClearMsg = "Hello I'm Alice!";
|
||||
|
||||
OlmMessage encryptedAliceToBobMsg1 = aliceSession.encryptMessage(helloClearMsg);
|
||||
assertNotNull(encryptedAliceToBobMsg1);
|
||||
|
||||
// CREATE BOB INBOUND SESSION and decrypt message from alice
|
||||
OlmSession bobSession = new OlmSession();
|
||||
bobSession.initNewSession();
|
||||
assertTrue(0!=bobSession.getOlmSessionId());
|
||||
assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText));
|
||||
|
||||
// DECRYPT MESSAGE FROM ALICE
|
||||
String decryptedMsg01 = bobSession.decryptMessage(encryptedAliceToBobMsg1);
|
||||
assertNotNull(decryptedMsg01);
|
||||
|
||||
// MESSAGE COMPARISON: decrypted vs encrypted
|
||||
assertTrue(helloClearMsg.equals(decryptedMsg01));
|
||||
|
||||
assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId()));
|
||||
|
||||
// BACK/FORTH MESSAGE COMPARISON
|
||||
String clearMsg1 = "Hello I'm Bob!";
|
||||
String clearMsg2 = "Isn't life grand?";
|
||||
String clearMsg3 = "Let's go to the opera.";
|
||||
|
||||
OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1);
|
||||
assertNotNull(encryptedMsg1);
|
||||
OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2);
|
||||
assertNotNull(encryptedMsg2);
|
||||
OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3);
|
||||
assertNotNull(encryptedMsg3);
|
||||
|
||||
String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1);
|
||||
assertNotNull(decryptedMsg1);
|
||||
String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2);
|
||||
assertNotNull(decryptedMsg2);
|
||||
String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3);
|
||||
assertNotNull(decryptedMsg3);
|
||||
|
||||
assertTrue(clearMsg1.equals(decryptedMsg1));
|
||||
assertTrue(clearMsg2.equals(decryptedMsg2));
|
||||
assertTrue(clearMsg3.equals(decryptedMsg3));
|
||||
|
||||
// clean objects..
|
||||
bobAccount.releaseAccount();
|
||||
aliceAccount.releaseAccount();
|
||||
bobSession.releaseSession();
|
||||
aliceSession.releaseSession();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test03AliceBobSessionId() {
|
||||
// creates alice & bob accounts
|
||||
OlmAccount aliceAccount = new OlmAccount();
|
||||
aliceAccount.initNewAccount();
|
||||
|
||||
OlmAccount bobAccount = new OlmAccount();
|
||||
bobAccount.initNewAccount();
|
||||
|
||||
// test accounts creation
|
||||
assertTrue(0!=bobAccount.getOlmAccountId());
|
||||
assertTrue(0!=aliceAccount.getOlmAccountId());
|
||||
|
||||
// CREATE ALICE SESSION
|
||||
OlmSession aliceSession = new OlmSession();
|
||||
aliceSession.initNewSession();
|
||||
assertTrue(0!=aliceSession.getOlmSessionId());
|
||||
|
||||
// CREATE BOB INBOUND SESSION and decrypt message from alice
|
||||
OlmSession bobSession = new OlmSession();
|
||||
bobSession.initNewSession();
|
||||
assertTrue(0!=bobSession.getOlmSessionId());
|
||||
|
||||
String aliceSessionId = aliceSession.sessionIdentifier();
|
||||
assertNotNull(aliceSessionId);
|
||||
|
||||
String bobSessionId = bobSession.sessionIdentifier();
|
||||
assertNotNull(bobSessionId);
|
||||
|
||||
// must be the same for both ends of the conversation
|
||||
assertTrue(aliceSessionId.equals(bobSessionId));
|
||||
}
|
||||
|
||||
}
|
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>
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.olm;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class OlmAccount {
|
||||
private static final String LOG_TAG = "OlmAccount";
|
||||
|
||||
// JSON keys used in the JSON objects returned by JNI
|
||||
public static final String JSON_KEY_ONE_TIME_KEY = "curve25519";
|
||||
public static final String JSON_KEY_IDENTITY_KEY = "curve25519";
|
||||
public static final String JSON_KEY_FINGER_PRINT_KEY = "ed25519";
|
||||
|
||||
/** account raw pointer value (OlmAccount*) returned by JNI.
|
||||
* this value identifies uniquely the native account instance.
|
||||
*/
|
||||
private long mNativeOlmAccountId;
|
||||
|
||||
public OlmAccount() {
|
||||
//initNewAccount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter on the account ID.
|
||||
* @return native account ID
|
||||
*/
|
||||
public long getOlmAccountId(){
|
||||
return mNativeOlmAccountId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the corresponding OLM account 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 #initNewAccountJni()}.
|
||||
*/
|
||||
private native void releaseAccountJni();
|
||||
|
||||
/**
|
||||
* Release native account and invalid its JAVA reference counter part.<br>
|
||||
* Public API for {@link #releaseAccountJni()}.
|
||||
* To be called before any other API call.
|
||||
*/
|
||||
public void releaseAccount(){
|
||||
releaseAccountJni();
|
||||
|
||||
mNativeOlmAccountId = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the corresponding OLM account in native side.<br>
|
||||
* The return value is a long casted C ptr on the OlmAccount.
|
||||
* Do not forget to call {@link #releaseAccount()} when JAVA side is done.
|
||||
* @return native account instance identifier (see {@link #mNativeOlmAccountId})
|
||||
*/
|
||||
private native long initNewAccountJni();
|
||||
|
||||
/**
|
||||
* Create and save the account native instance ID.
|
||||
* Wrapper for {@link #initNewAccountJni()}.<br>
|
||||
* To be called before any other API call.
|
||||
* @return true if init succeed, false otherwise.
|
||||
*/
|
||||
public boolean initNewAccount() {
|
||||
boolean retCode = false;
|
||||
if(0 != (mNativeOlmAccountId = initNewAccountJni())){
|
||||
retCode = true;
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).<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 (identity & fingerprint keys) in a JSON array.<br>
|
||||
* Public API for {@link #identityKeysJni()}.<br>
|
||||
* Ex:<tt>
|
||||
* {
|
||||
* "curve25519":"Vam++zZPMqDQM6ANKpO/uAl5ViJSHxV9hd+b0/fwRAg",
|
||||
* "ed25519":"+v8SOlOASFTMrX3MCKBM4iVnYoZ+JIjpNt1fi8Z9O2I"
|
||||
* }</tt>
|
||||
* @return identity keys in JSON array 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.<br>
|
||||
* The corresponding keys are retrieved by {@link #oneTimeKeys()}.
|
||||
* @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.<br>
|
||||
* @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>
|
||||
* The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}<br>
|
||||
* Ex:<tt>
|
||||
* { "curve25519":
|
||||
* {
|
||||
* "AAAABQ":"qefVZd8qvjOpsFzoKSAdfUnJVkIreyxWFlipCHjSQQg",
|
||||
* "AAAABA":"/X8szMU+p+lsTnr56wKjaLgjTMQQkCk8EIWEAilZtQ8",
|
||||
* "AAAAAw":"qxNxxFHzevFntaaPdT0fhhO7tc7pco4+xB/5VRG81hA",
|
||||
* }
|
||||
* }</tt><br>
|
||||
* Public API for {@link #oneTimeKeysJni()}.<br>
|
||||
* Note: these keys are to be published on the server.
|
||||
* @return one time keys in JSON array format if operation succeed, null otherwise
|
||||
*/
|
||||
public JSONObject oneTimeKeys() {
|
||||
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);
|
||||
}
|
|
@ -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,30 @@
|
|||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.olm;
|
||||
|
||||
public class OlmMessage {
|
||||
/** PRE KEY message type (used to establish new Olm session) **/
|
||||
public final static int MESSAGE_TYPE_PRE_KEY = 0;
|
||||
/** normal message type **/
|
||||
public final static int MESSAGE_TYPE_MESSAGE = 1;
|
||||
|
||||
/** the encrypted message (ie. )**/
|
||||
public String mCipherText;
|
||||
|
||||
/** defined by {@link #MESSAGE_TYPE_MESSAGE} or {@link #MESSAGE_TYPE_PRE_KEY}**/
|
||||
public long mType;
|
||||
}
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.matrix.olm;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter on the session ID.
|
||||
* @return native session ID
|
||||
*/
|
||||
public OlmAccount getOlmAccountId(){
|
||||
return mOlmAccount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
if(0 == 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
|
||||
* @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.<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
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
|
||||
/**
|
||||
* 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).
|
||||
* Public API for {@link #matchesInboundSessionJni(String)}.
|
||||
* @param aTheirIdentityKey the sender identity key
|
||||
* @param aOneTimeKeyMsg PRE KEY message
|
||||
* @return this if operation succeed, null otherwise
|
||||
*/
|
||||
public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) {
|
||||
boolean retCode = false;
|
||||
|
||||
if(0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey, aOneTimeKeyMsg)){
|
||||
retCode = true;
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
private native int matchesInboundSessionFromIdKeyJni(String aTheirIdentityKey, String aOneTimeKeyMsg);
|
||||
|
||||
|
||||
/**
|
||||
* Encrypt a message using the session.<br>
|
||||
* The encrypted message is returned in a OlmMessage object.
|
||||
* Public API for {@link #encryptMessageJni(String, OlmMessage)}.
|
||||
* @param aClearMsg message to encrypted
|
||||
* @return the encrypted message if operation succeed, null otherwise
|
||||
*/
|
||||
public OlmMessage encryptMessage(String aClearMsg) {
|
||||
OlmMessage encryptedMsgRetValue = new OlmMessage();
|
||||
|
||||
if(0 != encryptMessageJni(aClearMsg, encryptedMsgRetValue)){
|
||||
encryptedMsgRetValue = null;
|
||||
}
|
||||
|
||||
return encryptedMsgRetValue;
|
||||
}
|
||||
|
||||
private native int encryptMessageJni(String aClearMsg, OlmMessage aEncryptedMsg);
|
||||
|
||||
/**
|
||||
* Decrypt a message using the session.<br>
|
||||
* The encrypted message is given as a OlmMessage object.
|
||||
* @param aEncryptedMsg message to decrypt
|
||||
* @return the decrypted message if operation succeed, null otherwise
|
||||
*/
|
||||
public native String decryptMessage(OlmMessage aEncryptedMsg);
|
||||
}
|
||||
|
53
java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
Normal file
53
java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
Normal file
|
@ -0,0 +1,53 @@
|
|||
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 \
|
||||
olm_utility.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
|
462
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
Normal file
462
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
Normal file
|
@ -0,0 +1,462 @@
|
|||
/*
|
||||
* 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"
|
||||
#include "olm_utility.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 OLM_ACCOUNT_FUNC_DEF(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
|
||||
{
|
||||
olm_clear_account(accountPtr);
|
||||
|
||||
LOGD("## releaseAccountJni(): IN");
|
||||
// even if free(NULL) does not crash, logs are performed for debug purpose
|
||||
free(accountPtr);
|
||||
LOGD("## releaseAccountJni(): OUT");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a new account and return it to JAVA side.<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 OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
OlmAccount *accountPtr = NULL;
|
||||
uint8_t *randomBuffPtr = NULL;
|
||||
size_t accountRetCode;
|
||||
size_t 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(!setRandomInBuffer(&randomBuffPtr, randomSize))
|
||||
{
|
||||
LOGE("## initNewAccount(): failure - random buffer init");
|
||||
}
|
||||
else
|
||||
{
|
||||
// create account
|
||||
accountRetCode = olm_create_account(accountPtr, (void*)randomBuffPtr, randomSize);
|
||||
if(accountRetCode == olm_error()) {
|
||||
const char *errorMsgPtr = olm_account_last_error(accountPtr);
|
||||
LOGE("## initNewAccount(): failure - account creation failed Msg=%s", errorMsgPtr);
|
||||
}
|
||||
|
||||
LOGD("## initNewAccount(): success - OLM account created");
|
||||
LOGD("## initNewAccount(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr);
|
||||
}
|
||||
}
|
||||
|
||||
if(NULL != randomBuffPtr)
|
||||
{
|
||||
free(randomBuffPtr);
|
||||
}
|
||||
|
||||
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 OLM_ACCOUNT_FUNC_DEF(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(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 OLM_ACCOUNT_FUNC_DEF(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 OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys)
|
||||
{
|
||||
OlmAccount *accountPtr = NULL;
|
||||
uint8_t *randomBufferPtr = NULL;
|
||||
jint retCode = ERROR_CODE_KO;
|
||||
size_t randomLength;
|
||||
size_t result;
|
||||
|
||||
|
||||
if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz)))
|
||||
{
|
||||
LOGE("## generateOneTimeKeys(): failure - invalid Account ptr");
|
||||
}
|
||||
else
|
||||
{ // keys memory allocation
|
||||
randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys);
|
||||
LOGD("## generateOneTimeKeys(): randomLength=%ld", randomLength);
|
||||
|
||||
if(!setRandomInBuffer(&randomBufferPtr, randomLength))
|
||||
{
|
||||
LOGE("## generateOneTimeKeys(): failure - random buffer init");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## generateOneTimeKeys(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys);
|
||||
|
||||
// retrieve key pairs in keysBytesPtr
|
||||
result = olm_account_generate_one_time_keys(accountPtr, (size_t)aNumberOfKeys, (void*)randomBufferPtr, randomLength);
|
||||
if(result == olm_error()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(NULL != randomBufferPtr)
|
||||
{
|
||||
free(randomBufferPtr);
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "one time keys".<br>
|
||||
* Return the public parts of the unpublished "one time keys" for the account
|
||||
* @return a valid byte array if operation succeed, null otherwise
|
||||
**/
|
||||
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
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 OLM_ACCOUNT_FUNC_DEF(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 OLM_ACCOUNT_FUNC_DEF(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.<br>
|
||||
* The signed message is returned by the function.
|
||||
* @param aMessage message to sign
|
||||
* @return the signed message, null otherwise
|
||||
**/
|
||||
JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage)
|
||||
{
|
||||
OlmAccount* accountPtr = NULL;
|
||||
size_t signatureLength;
|
||||
void* signedMsgPtr;
|
||||
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 == (signedMsgPtr = (void*)malloc(signatureLength*sizeof(uint8_t))))
|
||||
{
|
||||
LOGE("## signMessage(): failure - signature allocation OOM");
|
||||
}
|
||||
else
|
||||
{ // sign message
|
||||
resultSign = olm_account_sign(accountPtr, (void*)messageToSign, (size_t)messageLength, signedMsgPtr, signatureLength);
|
||||
if(resultSign == olm_error())
|
||||
{
|
||||
const char *errorMsgPtr = olm_account_last_error(accountPtr);
|
||||
LOGE("## signMessage(): failure - error signing message Msg=%s",errorMsgPtr);
|
||||
}
|
||||
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*)signedMsgPtr); // UTF8
|
||||
LOGD("## signMessage(): success - retCode=%ld",resultSign);
|
||||
}
|
||||
|
||||
free(signedMsgPtr);
|
||||
}
|
||||
|
||||
// release messageToSign
|
||||
env->ReleaseStringUTFChars(aMessage, messageToSign);
|
||||
}
|
||||
}
|
||||
|
||||
return signedMsgRetValue;
|
||||
}
|
||||
|
||||
|
||||
JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(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;
|
||||
}
|
||||
|
||||
|
36
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h
Normal file
36
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef _OMLACCOUNT_H
|
||||
#define _OMLACCOUNT_H
|
||||
|
||||
#include "olm_jni.h"
|
||||
|
||||
#define OLM_ACCOUNT_FUNC_DEF(func_name) FUNC_DEF(OlmAccount,func_name)
|
||||
#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
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
|
48
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h
Normal file
48
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#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
|
||||
|
||||
#define FUNC_DEF(class_name,func_name) JNICALL Java_org_matrix_olm_##class_name##_##func_name
|
||||
|
||||
// Error codes definition
|
||||
static const int ERROR_CODE_OK = 0;
|
||||
static const int ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS = ERROR_CODE_OK+1;
|
||||
static const int ERROR_CODE_KO = -1;
|
||||
|
||||
// constants
|
||||
static const int ACCOUNT_CREATION_RANDOM_MODULO = 256;
|
||||
|
||||
|
||||
typedef struct _AccountContext
|
||||
{
|
||||
OlmAccount* mAccountPtr;
|
||||
_AccountContext(): mAccountPtr(NULL){}
|
||||
} AccountContext;
|
||||
|
||||
#endif
|
731
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
Normal file
731
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
Normal file
|
@ -0,0 +1,731 @@
|
|||
/*
|
||||
* 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"
|
||||
#include "olm_utility.h"
|
||||
|
||||
|
||||
/**
|
||||
* Init memory allocation for a session creation.<br>
|
||||
* Make sure releaseSessionJni() is called when one is done with the session instance.
|
||||
* @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 OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
OlmSession* sessionPtr = NULL;
|
||||
|
||||
if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
|
||||
{
|
||||
LOGE("## releaseSessionJni(): failure - invalid Session ptr=NULL");
|
||||
}
|
||||
else
|
||||
{
|
||||
olm_clear_session(sessionPtr);
|
||||
|
||||
LOGD("## releaseSessionJni(): IN");
|
||||
// even if free(NULL) does not crash, logs are performed for debug purpose
|
||||
free(sessionPtr);
|
||||
LOGD("## releaseSessionJni(): OUT");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 OLM_SESSION_FUNC_DEF(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 OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey)
|
||||
{
|
||||
jint retCode = ERROR_CODE_KO;
|
||||
OlmSession* sessionPtr = NULL;
|
||||
OlmAccount* accountPtr = NULL;
|
||||
const char* theirIdentityKeyPtr = NULL;
|
||||
const char* theirOneTimeKeyPtr = NULL;
|
||||
uint8_t *randomBuffPtr = NULL;
|
||||
size_t sessionResult;
|
||||
|
||||
if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
|
||||
{
|
||||
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((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize))
|
||||
{
|
||||
LOGE("## initOutboundSessionJni(): failure - random buffer init");
|
||||
}
|
||||
else
|
||||
{ // convert identity & one time keys to C strings
|
||||
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
|
||||
{
|
||||
size_t theirIdentityKeyLength = (size_t)env->GetStringUTFLength(aTheirIdentityKey);
|
||||
size_t theirOneTimeKeyLength = (size_t)env->GetStringUTFLength(aTheirOneTimeKey);
|
||||
LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr);
|
||||
|
||||
sessionResult = olm_create_outbound_session(sessionPtr,
|
||||
accountPtr,
|
||||
theirIdentityKeyPtr,
|
||||
theirIdentityKeyLength,
|
||||
theirOneTimeKeyPtr,
|
||||
theirOneTimeKeyLength,
|
||||
(void*)randomBuffPtr,
|
||||
randomSize);
|
||||
if(sessionResult == olm_error()) {
|
||||
const char *errorMsgPtr = olm_session_last_error(sessionPtr);
|
||||
LOGE("## initOutboundSessionJni(): failure - session creation Msg=%s",errorMsgPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
retCode = ERROR_CODE_OK;
|
||||
LOGD("## initOutboundSessionJni(): success - result=%ld", sessionResult);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// **** free mem alloc ***
|
||||
if(NULL!= randomBuffPtr)
|
||||
{
|
||||
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
|
||||
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
|
||||
*/
|
||||
JNIEXPORT jint OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg)
|
||||
{
|
||||
jint retCode = ERROR_CODE_KO;
|
||||
OlmSession *sessionPtr = NULL;
|
||||
OlmAccount *accountPtr = NULL;
|
||||
const char *messagePtr = NULL;
|
||||
size_t sessionResult;
|
||||
|
||||
if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
|
||||
{
|
||||
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("## initInboundSessionJni(): failure - invalid message");
|
||||
}
|
||||
else
|
||||
{ // convert message to C strings
|
||||
if(NULL == (messagePtr = env->GetStringUTFChars(aOneTimeKeyMsg, 0)))
|
||||
{
|
||||
LOGE("## initInboundSessionJni(): failure - message JNI allocation OOM");
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg);
|
||||
LOGD("## initInboundSessionJni(): messageLength=%d message=%s", messageLength, messagePtr);
|
||||
|
||||
sessionResult = olm_create_inbound_session(sessionPtr, accountPtr, (void*)messagePtr , messageLength);
|
||||
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 OLM_SESSION_FUNC_DEF(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("## initInboundSessionJni(): 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 = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg);
|
||||
size_t theirIdentityKeyLength = (size_t)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 OLM_SESSION_FUNC_DEF(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 = (size_t)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);
|
||||
}
|
||||
}
|
||||
|
||||
// free local alloc
|
||||
if(NULL!= messagePtr)
|
||||
{
|
||||
env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr);
|
||||
}
|
||||
|
||||
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 OLM_SESSION_FUNC_DEF(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 = (size_t)env->GetStringUTFLength(aTheirIdentityKey);
|
||||
size_t messageLength = (size_t)env->GetStringUTFLength(aOneTimeKeyMsg);
|
||||
|
||||
size_t matchResult = olm_matches_inbound_session_from(sessionPtr, (void const *)theirIdentityKeyPtr, identityKeyLength, (void*)messagePtr , messageLength);
|
||||
if(matchResult == olm_error()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// free local alloc
|
||||
if(NULL!= theirIdentityKeyPtr)
|
||||
{
|
||||
env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr);
|
||||
}
|
||||
|
||||
if(NULL!= messagePtr)
|
||||
{
|
||||
env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr);
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encrypt a message using the session.<br>
|
||||
* @param aClearMsg clear text message
|
||||
* @param [out] aEncryptedMsg ciphered message
|
||||
* @return ERROR_CODE_OK if encrypt operation succeed, ERROR_CODE_KO otherwise
|
||||
*/
|
||||
JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg)
|
||||
{
|
||||
jint retCode = ERROR_CODE_KO;
|
||||
OlmSession *sessionPtr = NULL;
|
||||
const char *clearMsgPtr = NULL;
|
||||
uint8_t *randomBuffPtr = NULL;
|
||||
void *encryptedMsgPtr = NULL;
|
||||
jclass encryptedMsgJClass = 0;
|
||||
jfieldID encryptedMsgFieldId;
|
||||
jfieldID typeMsgFieldId;
|
||||
|
||||
LOGD("## encryptMessageJni(): IN ");
|
||||
|
||||
if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL");
|
||||
}
|
||||
else if(0 == aClearMsg)
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - invalid clear message");
|
||||
}
|
||||
else if(0 == aEncryptedMsg)
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - invalid clear message");
|
||||
}
|
||||
else if(NULL == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0)))
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM");
|
||||
}
|
||||
else if(0 == (encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg)))
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - unable to get crypted message class");
|
||||
}
|
||||
else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;")))
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - unable to get message field");
|
||||
}
|
||||
else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","J")))
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - unable to get message type field");
|
||||
}
|
||||
else
|
||||
{
|
||||
// get message type
|
||||
size_t messageType = olm_encrypt_message_type(sessionPtr);
|
||||
|
||||
// compute random buffer
|
||||
// Note: olm_encrypt_random_length() can return 0, which means
|
||||
// it just does not need new random data to encrypt a new message
|
||||
size_t randomLength = olm_encrypt_random_length(sessionPtr);
|
||||
|
||||
if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength))
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - random buffer init");
|
||||
}
|
||||
else
|
||||
{
|
||||
// alloc buffer for encrypted message
|
||||
size_t clearMsgLength = (size_t)env->GetStringUTFLength(aClearMsg);
|
||||
size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength);
|
||||
if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(uint8_t))))
|
||||
{
|
||||
LOGE("## encryptMessageJni(): failure - encryptedMsgPtr buffer OOM");
|
||||
}
|
||||
else
|
||||
{
|
||||
if(0==randomLength)
|
||||
{
|
||||
LOGW("## encryptMessageJni(): random buffer is not required");
|
||||
}
|
||||
|
||||
LOGD("## encryptMessageJni(): messageType=%lu randomLength=%lu clearMsgLength=%lu encryptedMsgLength=%lu",messageType,randomLength, clearMsgLength, encryptedMsgLength);
|
||||
// encrypt message
|
||||
size_t result = olm_encrypt(sessionPtr,
|
||||
(void const *)clearMsgPtr,
|
||||
clearMsgLength,
|
||||
randomBuffPtr,
|
||||
randomLength,
|
||||
encryptedMsgPtr,
|
||||
encryptedMsgLength);
|
||||
if(result == olm_error())
|
||||
{
|
||||
const char *errorMsgPtr = olm_session_last_error(sessionPtr);
|
||||
LOGE("## encryptMessageJni(): failure - Msg=%s",errorMsgPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// update encrypted buffer size
|
||||
(static_cast<char*>(encryptedMsgPtr))[result] = static_cast<char>('\0');
|
||||
|
||||
// update message type: PRE KEY or normal
|
||||
env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType);
|
||||
|
||||
// update message: encryptedMsgPtr => encryptedJstring
|
||||
jstring encryptedJstring = env->NewStringUTF((const char*)encryptedMsgPtr);
|
||||
size_t encryptedUtfMsgLength = (size_t)env->GetStringUTFLength(encryptedJstring);
|
||||
env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedJstring);
|
||||
|
||||
retCode = ERROR_CODE_OK;
|
||||
LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg=%s", result, messageType, encryptedUtfMsgLength, (const char*)encryptedMsgPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free alloc
|
||||
if(NULL != clearMsgPtr)
|
||||
{
|
||||
env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr);
|
||||
}
|
||||
|
||||
if(NULL != randomBuffPtr)
|
||||
{
|
||||
free(randomBuffPtr);
|
||||
}
|
||||
|
||||
if(NULL != encryptedMsgPtr)
|
||||
{
|
||||
free(encryptedMsgPtr);
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decrypt a message using the session.<br>
|
||||
* @param aEncryptedMsg message to decrypt
|
||||
* @return decrypted message if operation succeed, null otherwise
|
||||
*/
|
||||
JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessage)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg)
|
||||
{
|
||||
jstring decryptedMsgRetValue = 0;
|
||||
jclass encryptedMsgJclass = 0;
|
||||
jstring encryptedMsgJstring = 0; // <= obtained from encryptedMsgFieldId
|
||||
// field IDs
|
||||
jfieldID encryptedMsgFieldId;
|
||||
jfieldID typeMsgFieldId;
|
||||
// ptrs
|
||||
OlmSession *sessionPtr = NULL;
|
||||
const char *encryptedMsgPtr = NULL; // <= obtained from encryptedMsgJstring
|
||||
void *plainTextMsgPtr = NULL;
|
||||
char *tempEncryptedPtr = NULL;
|
||||
|
||||
LOGD("## decryptMessage(): IN ");
|
||||
|
||||
if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
|
||||
{
|
||||
LOGE("## decryptMessage(): failure - invalid Session ptr=NULL");
|
||||
}
|
||||
else if(0 == aEncryptedMsg)
|
||||
{
|
||||
LOGE("## decryptMessage(): failure - invalid clear message");
|
||||
}
|
||||
else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg)))
|
||||
{
|
||||
LOGE("## decryptMessage(): failure - unable to get crypted message class");
|
||||
}
|
||||
else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;")))
|
||||
{
|
||||
LOGE("## decryptMessage(): failure - unable to get message field");
|
||||
}
|
||||
else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mType","J")))
|
||||
{
|
||||
LOGE("## decryptMessage(): failure - unable to get message type field");
|
||||
}
|
||||
else if(0 == (encryptedMsgJstring = (jstring)env->GetObjectField(aEncryptedMsg, encryptedMsgFieldId)))
|
||||
{
|
||||
LOGE("## decryptMessage(): failure - JNI encrypted object ");
|
||||
}
|
||||
else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(encryptedMsgJstring, 0)))
|
||||
{
|
||||
LOGE("## decryptMessage(): failure - encrypted message JNI allocation OOM");
|
||||
}
|
||||
else
|
||||
{
|
||||
// get message type
|
||||
size_t encryptedMsgType = (size_t)env->GetLongField(aEncryptedMsg, typeMsgFieldId);
|
||||
// get encrypted message length
|
||||
size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(encryptedMsgJstring);
|
||||
|
||||
// create a dedicated temp buffer to be used in next Olm API calls
|
||||
tempEncryptedPtr = static_cast<char*>(malloc(encryptedMsgLength*sizeof(uint8_t)));
|
||||
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
|
||||
LOGD("## decryptMessage(): MsgType=%ld encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgType,encryptedMsgLength,encryptedMsgPtr);
|
||||
|
||||
// get max plaintext length
|
||||
size_t maxPlainTextLength = olm_decrypt_max_plaintext_length(sessionPtr,
|
||||
static_cast<size_t>(encryptedMsgType),
|
||||
static_cast<void*>(tempEncryptedPtr),
|
||||
encryptedMsgLength);
|
||||
// Note: tempEncryptedPtr is destroyed by olm_decrypt_max_plaintext_length()
|
||||
|
||||
if(maxPlainTextLength == olm_error())
|
||||
{
|
||||
const char *errorMsgPtr = olm_session_last_error(sessionPtr);
|
||||
LOGE("## decryptMessage(): failure - olm_decrypt_max_plaintext_length Msg=%s",errorMsgPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## decryptMessage(): maxPlaintextLength=%lu",maxPlainTextLength);
|
||||
|
||||
// allocate output decrypted message
|
||||
plainTextMsgPtr = static_cast<void*>(malloc(maxPlainTextLength*sizeof(uint8_t)));
|
||||
|
||||
// decrypt, but before reload encrypted buffer (previous one was destroyed)
|
||||
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
|
||||
size_t plaintextLength = olm_decrypt(sessionPtr,
|
||||
encryptedMsgType,
|
||||
(void*)encryptedMsgPtr,
|
||||
encryptedMsgLength,
|
||||
plainTextMsgPtr,
|
||||
maxPlainTextLength);
|
||||
if(plaintextLength == olm_error())
|
||||
{
|
||||
const char *errorMsgPtr = olm_session_last_error(sessionPtr);
|
||||
LOGE("## decryptMessage(): failure - olm_decrypt Msg=%s",errorMsgPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// update decrypted buffer size
|
||||
(static_cast<char*>(plainTextMsgPtr))[plaintextLength] = static_cast<char>('\0');
|
||||
|
||||
LOGD("## decryptMessage(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, static_cast<char*>(plainTextMsgPtr));
|
||||
decryptedMsgRetValue = env->NewStringUTF(static_cast<const char*>(plainTextMsgPtr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// free alloc
|
||||
if(NULL != encryptedMsgPtr)
|
||||
{
|
||||
env->ReleaseStringUTFChars(encryptedMsgJstring, encryptedMsgPtr);
|
||||
}
|
||||
|
||||
if(NULL != tempEncryptedPtr)
|
||||
{
|
||||
free(tempEncryptedPtr);
|
||||
}
|
||||
|
||||
if(NULL != plainTextMsgPtr)
|
||||
{
|
||||
free(plainTextMsgPtr);
|
||||
}
|
||||
|
||||
return decryptedMsgRetValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the session identifier for this session.
|
||||
* @return the session identifier if operation succeed, null otherwise
|
||||
*/
|
||||
JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz)
|
||||
{
|
||||
OlmSession *sessionPtr = NULL;
|
||||
void *sessionIdPtr = NULL;
|
||||
jstring returnValueStr=0;
|
||||
|
||||
// get the size to alloc to contain the id
|
||||
size_t lengthSessionId = olm_session_id_length(sessionPtr);
|
||||
|
||||
if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
|
||||
{
|
||||
LOGE("## getSessionIdentifierJni(): failure - invalid Session ptr=NULL");
|
||||
}
|
||||
else if(NULL == (sessionIdPtr = (void*)malloc(lengthSessionId*sizeof(uint8_t))))
|
||||
{
|
||||
LOGE("## getSessionIdentifierJni(): failure - identifier allocation OOM");
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t result = olm_session_id(sessionPtr, sessionIdPtr, lengthSessionId);
|
||||
if (result == olm_error())
|
||||
{
|
||||
const char *errorMsgPtr = olm_session_last_error(sessionPtr);
|
||||
LOGE("## getSessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
// update decrypted buffer size
|
||||
(static_cast<char*>(sessionIdPtr))[result] = static_cast<char>('\0');
|
||||
|
||||
LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr);
|
||||
returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
|
||||
}
|
||||
free(sessionIdPtr);
|
||||
}
|
||||
|
||||
return returnValueStr;
|
||||
}
|
||||
|
37
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
Normal file
37
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#ifndef _OMLSESSION_H
|
||||
#define _OMLSESSION_H
|
||||
|
||||
#include "olm_jni.h"
|
||||
|
||||
#define OLM_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmSession,func_name)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// session creation/destruction
|
||||
JNIEXPORT void JNICALL Java_org_matrix_olm_OlmSession_releaseSessionJni(JNIEnv *env, jobject thiz);
|
||||
JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmSession_initNewSessionJni(JNIEnv *env, jobject thiz);
|
||||
|
||||
// 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);
|
||||
|
||||
// encrypt/decrypt
|
||||
JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg);
|
||||
JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_decryptMessage(JNIEnv *env, jobject thiz, jobject aEncryptedMsg);
|
||||
|
||||
JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
141
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
Normal file
141
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
/**
|
||||
* Created by pedrocon on 06/10/2016.
|
||||
*/
|
||||
/*
|
||||
* Copyright 2016 OpenMarket Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "olm_jni.h"
|
||||
#include "olm_utility.h"
|
||||
|
||||
/**
|
||||
* Init a buffer with a given number of random values.
|
||||
* @param aBuffer2Ptr the buffer to be initialized
|
||||
* @param aRandomSize the number of random values to apply
|
||||
* @return true if operation succeed, false otherwise
|
||||
**/
|
||||
bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize)
|
||||
{
|
||||
bool retCode = false;
|
||||
if(NULL == aBuffer2Ptr)
|
||||
{
|
||||
LOGD("## setRandomInBuffer(): failure - aBuffer=NULL");
|
||||
}
|
||||
else if(0 == aRandomSize)
|
||||
{
|
||||
LOGD("## setRandomInBuffer(): failure - random size=0");
|
||||
}
|
||||
else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t))))
|
||||
{
|
||||
LOGD("## setRandomInBuffer(): failure - alloc mem OOM");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize);
|
||||
|
||||
srand(time(NULL)); // init seed
|
||||
for(size_t i=0;i<aRandomSize;i++)
|
||||
{
|
||||
(*aBuffer2Ptr)[i] = (uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO);
|
||||
|
||||
// debug purpose
|
||||
//LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]);
|
||||
}
|
||||
|
||||
retCode = true;
|
||||
}
|
||||
return retCode;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read the account instance ID of the calling object.
|
||||
* @param aJniEnv pointer pointing on the JNI function table
|
||||
* @param aJavaObject reference to the object on which the method is invoked
|
||||
* @return the instance ID if operation succeed, -1 if instance ID was not found.
|
||||
**/
|
||||
jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
|
||||
{
|
||||
jlong instanceId=-1;
|
||||
jfieldID instanceIdField;
|
||||
jclass loaderClass;
|
||||
|
||||
if(NULL!=aJniEnv)
|
||||
{
|
||||
if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
|
||||
{
|
||||
if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmAccountId", "J")))
|
||||
{
|
||||
instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
|
||||
aJniEnv->DeleteLocalRef(loaderClass);
|
||||
LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## getAccountInstanceId() ERROR! GetFieldID=null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL");
|
||||
}
|
||||
LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId);
|
||||
return instanceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the account instance ID of the calling object (aJavaObject).<br>
|
||||
* @param aJniEnv pointer pointing on the JNI function table
|
||||
* @param aJavaObject reference to the object on which the method is invoked
|
||||
* @return the instance ID if read succeed, -1 otherwise.
|
||||
**/
|
||||
jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
|
||||
{
|
||||
jlong instanceId=-1;
|
||||
jfieldID instanceIdField;
|
||||
jclass loaderClass;
|
||||
|
||||
if(NULL!=aJniEnv)
|
||||
{
|
||||
if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
|
||||
{
|
||||
if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmSessionId", "J")))
|
||||
{
|
||||
instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
|
||||
aJniEnv->DeleteLocalRef(loaderClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
|
||||
}
|
||||
|
||||
//LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId);
|
||||
return instanceId;
|
||||
}
|
18
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
Normal file
18
java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef _OMLUTILITY_H
|
||||
#define _OMLUTILITY_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize);
|
||||
jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
|
||||
jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,3 @@
|
|||
<resources>
|
||||
<string name="app_name">OlmSdk</string>
|
||||
</resources>
|
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