diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
index ec1d49c..ad875c5 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
@@ -152,9 +152,8 @@ public class OlmAccountTest {
long sessionId = olmSession.getOlmSessionId();
assertTrue(0 != sessionId);
- int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(sessionId);
- // no one time key has been use in the session, so removeOneTimeKeysForSession() returns an error
- assertTrue(0 != sessionRetCode);
+ int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(olmSession);
+ assertTrue(0 == sessionRetCode);
olmSession.releaseSession();
sessionId = olmSession.getOlmSessionId();
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java
new file mode 100644
index 0000000..482ae0f
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupTest.java
@@ -0,0 +1,95 @@
+package org.matrix.olm;
+
+import android.support.test.runner.AndroidJUnit4;
+import android.util.Log;
+
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+@RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class OlmGroupTest {
+ private static final String LOG_TAG = "OlmSessionTest";
+
+ private static OlmManager mOlmManager;
+
+ @BeforeClass
+ public static void setUpClass(){
+ // load native lib
+ mOlmManager = new OlmManager();
+
+ String version = mOlmManager.getOlmLibVersion();
+ assertNotNull(version);
+ Log.d(LOG_TAG, "## setUpClass(): lib version="+version);
+ }
+
+ @Test
+ public void test00AliceToBob() {
+ // TBD
+ }
+
+ /**
+ * Basic test:
+ * - alice creates an account
+ * - bob creates an account
+ * - alice creates an outbound group session
+ * - bob creates an inbound group session with alice's outbound session key
+ * - alice encrypts a message with its session
+ * - bob decrypts the encrypted message with its session
+ */
+ //@Test
+ public void test01AliceToBob() {
+ // creates alice outbound session
+ OlmOutboundGroupSession aliceOutboundSession = new OlmOutboundGroupSession();
+
+ // test accounts creation
+ String aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier();
+ assertNotNull(aliceSessionIdentifier);
+ assertTrue(aliceSessionIdentifier.length()>0);
+
+ String aliceOutboundSessionKey = aliceOutboundSession.sessionKey();
+ assertNotNull(aliceOutboundSessionKey);
+ assertTrue(aliceOutboundSessionKey.length()>0);
+
+ long messageIndex = aliceOutboundSession.messageIndex();
+ assertTrue(0==messageIndex);
+
+ String clearMessage = "Hello!";
+ String encryptedMessage = aliceOutboundSession.encryptMessage(clearMessage);
+ assertNotNull(encryptedMessage);
+
+ messageIndex = aliceOutboundSession.messageIndex();
+ assertTrue(1==messageIndex);
+
+ assertTrue(encryptedMessage.length()>=0);
+
+ OlmInboundGroupSession bobInboundSession = new OlmInboundGroupSession();
+ bobInboundSession.initInboundGroupSessionWithSessionKey(aliceOutboundSessionKey);
+ // check session identifiers are equals
+ aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier();
+ String bobSessionIdentifier = aliceOutboundSession.sessionIdentifier();
+ assertTrue(aliceSessionIdentifier.equals(bobSessionIdentifier ));
+
+ String decryptedMessage = bobInboundSession.decryptMessage(encryptedMessage);
+ assertTrue(decryptedMessage.equals(bobSessionIdentifier ));
+ }
+
+ //@Test
+ public void test02InboundGroupSession() {
+ // creates alice outbound session
+ OlmInboundGroupSession aliceInboundSession = new OlmInboundGroupSession();
+
+ // test session identifier
+ String sessionIdentifier = aliceInboundSession.sessionIdentifier();
+ assertNotNull(sessionIdentifier);
+ assertTrue(sessionIdentifier.length()>0);
+ }
+
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
index 0b8e6b4..6056466 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmSessionTest.java
@@ -105,7 +105,7 @@ public class OlmSessionTest {
assertTrue(clearMsg.equals(decryptedMsg));
// clean objects..
- assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId()));
+ assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
// release accounts
bobAccount.releaseAccount();
aliceAccount.releaseAccount();
@@ -191,7 +191,7 @@ public class OlmSessionTest {
// MESSAGE COMPARISON: decrypted vs encrypted
assertTrue(helloClearMsg.equals(decryptedMsg01));
- assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId()));
+ assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
// BACK/FORTH MESSAGE COMPARISON
String clearMsg1 = "Hello I'm Bob!";
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java
index 963f0a4..95a6eb5 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java
@@ -21,7 +21,9 @@ import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
-public class OlmAccount {
+import java.io.Serializable;
+
+public class OlmAccount implements Serializable {
private static final String LOG_TAG = "OlmAccount";
// JSON keys used in the JSON objects returned by JNI
@@ -67,7 +69,6 @@ public class OlmAccount {
/**
* Create the corresponding OLM account in native side.
- * The return value is a long casted C ptr on the OlmAccount.
* Do not forget to call {@link #releaseAccount()} when JAVA side is done.
* @return native account instance identifier (see {@link #mNativeOlmAccountId})
*/
@@ -87,14 +88,6 @@ public class OlmAccount {
return retCode;
}
- /**
- * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
- * Keys are Base64 encoded.
- * These keys must be published on the server.
- * @return byte array containing the identity keys if operation succeed, null otherwise
- */
- private native byte[] identityKeysJni();
-
/**
* Return the identity keys (identity & fingerprint keys) in a JSON array.
* Public API for {@link #identityKeysJni()}.
@@ -123,6 +116,13 @@ public class OlmAccount {
return identityKeysJsonObj;
}
+ /**
+ * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).
+ * Keys are Base64 encoded.
+ * These keys must be published on the server.
+ * @return byte array containing the identity keys if operation succeed, null otherwise
+ */
+ private native byte[] identityKeysJni();
/**
* Return the largest number of "one time keys" this account can store.
@@ -139,15 +139,6 @@ public class OlmAccount {
*/
public native int generateOneTimeKeys(int aNumberOfKeys);
- /**
- * Get the public parts of the unpublished "one time keys" for the account.
- * The returned data is a JSON-formatted object with the single property
- * curve25519, which is itself an object mapping key id to
- * base64-encoded Curve25519 key.
- * @return byte array containing the one time keys if operation succeed, null otherwise
- */
- private native byte[] oneTimeKeysJni();
-
/**
* Return the "one time keys" in a JSON array.
* The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}
@@ -181,24 +172,61 @@ public class OlmAccount {
return identityKeysJsonObj;
}
+ /**
+ * Get the public parts of the unpublished "one time keys" for the account.
+ * The returned data is a JSON-formatted object with the single property
+ * curve25519, which is itself an object mapping key id to
+ * base64-encoded Curve25519 key.
+ * @return byte array containing the one time keys if operation succeed, null otherwise
+ */
+ private native byte[] oneTimeKeysJni();
+ /**
+ * Remove the "one time keys" that the session used from the account.
+ * @param aSession session instance
+ * @return 0 if operation succeed, -1 otherwise
+ */
+ public int removeOneTimeKeysForSession(OlmSession aSession) {
+ int retCode = 0;
+
+ if(null != aSession) {
+ int result = removeOneTimeKeysForSessionJni(aSession.getOlmSessionId());
+ Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result="+result);
+ if(-1 == result) {
+ retCode = -1;
+ }
+ }
+
+ return retCode;
+ }
/**
* Remove the "one time keys" that the session used from the account.
* @param aNativeOlmSessionId native session instance identifier
* @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed
*/
- public native int removeOneTimeKeysForSession(long aNativeOlmSessionId);
+ private native int removeOneTimeKeysForSessionJni(long aNativeOlmSessionId);
/**
* Marks the current set of "one time keys" as being published.
* @return 0 if operation succeed, -1 otherwise
*/
- public native int markOneTimeKeysAsPublished();
+ public int markOneTimeKeysAsPublished() {
+ return markOneTimeKeysAsPublishedJni();
+ }
+ private native int markOneTimeKeysAsPublishedJni();
/**
* Sign a message with the ed25519 fingerprint key for this account.
* @param aMessage message to sign
* @return the signed message if operation succeed, null otherwise
*/
- public native String signMessage(String aMessage);
+ public String signMessage(String aMessage){
+ return signMessageJni(aMessage);
+ }
+ private native String signMessageJni(String aMessage);
+
+ // TODO missing API: initWithSerializedData
+ // TODO missing API: serializeDataWithKey
+ // TODO missing API: initWithCoder
+ // TODO missing API: encodeWithCoder
}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
new file mode 100644
index 0000000..53ef7a3
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java
@@ -0,0 +1,126 @@
+/**
+ * Created by pedrocon on 13/10/2016.
+ */
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.olm;
+
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.io.Serializable;
+
+public class OlmInboundGroupSession implements Serializable {
+
+ private static final String LOG_TAG = "OlmInboundGroupSession";
+
+ /** session raw pointer value returned by JNI.
+ * this value uniquely identifies the native inbound group session instance.
+ */
+ private long mNativeOlmInboundGroupSessionId;
+
+
+ public OlmInboundGroupSession() {
+ initNewSession();
+ }
+
+ /**
+ * Getter on the native inbound group session ID.
+ * @return native inbound group session ID
+ */
+ public long getOlmInboundGroupSessionId(){
+ return mNativeOlmInboundGroupSessionId;
+ }
+
+ /**
+ * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}.
+ * To be called before any other API call.
+ */
+ public void releaseSession(){
+ releaseSessionJni();
+
+ mNativeOlmInboundGroupSessionId = 0;
+ }
+
+ /**
+ * Destroy the corresponding OLM inbound group session native object.
+ * This method must ALWAYS be called when this JAVA instance
+ * is destroyed (ie. garbage collected) to prevent memory leak in native side.
+ * See {@link #initNewSessionJni()}.
+ */
+ private native void releaseSessionJni();
+
+ /**
+ * Create and save the session native instance ID.
+ * Wrapper for {@link #initNewSessionJni()}.
+ * To be called before any other API call.
+ * @return true if init succeed, false otherwise.
+ */
+ private boolean initNewSession() {
+ boolean retCode = false;
+ if(0 != (mNativeOlmInboundGroupSessionId = initNewSessionJni())){
+ retCode = true;
+ }
+ return retCode;
+ }
+
+ /**
+ * Create the corresponding OLM inbound group session in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done.
+ * @return native session instance identifier (see {@link #mNativeOlmInboundGroupSessionId})
+ */
+ private native long initNewSessionJni();
+
+ /**
+ * Creates a new inbound group session.
+ * The session key parameter is retrieved from a outbound group session.
+ * @param aSessionKey session key
+ * @return 0 if operation succeed, -1 otherwise
+ */
+ public int initInboundGroupSessionWithSessionKey(String aSessionKey) {
+ int retCode = -1;
+
+ if(TextUtils.isEmpty(aSessionKey)){
+ Log.e(LOG_TAG, "## initInboundGroupSessionWithSessionKey(): invalid session key");
+ } else {
+ retCode = initInboundGroupSessionWithSessionKeyJni(aSessionKey);
+ }
+
+ return retCode;
+ }
+ private native int initInboundGroupSessionWithSessionKeyJni(String aSessionKey);
+
+
+ public String sessionIdentifier() {
+ return sessionIdentifierJni();
+ }
+ private native String sessionIdentifierJni();
+
+
+ public String decryptMessage(String aEncryptedMsg) {
+ return decryptMessageJni(aEncryptedMsg);
+ }
+ private native String decryptMessageJni(String aEncryptedMsg);
+
+
+ // TODO missing API: initWithSerializedData
+ // TODO missing API: serializeDataWithKey
+ // TODO missing API: initWithCoder
+ // TODO missing API: encodeWithCoder
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
new file mode 100644
index 0000000..63c0c36
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.olm;
+
+
+import android.text.TextUtils;
+import android.util.Log;
+
+public class OlmOutboundGroupSession {
+ private static final String LOG_TAG = "OlmOutboundGroupSession";
+
+ /** session raw pointer value returned by JNI.
+ * this value uniquely identifies the native inbound group session instance.
+ */
+ private long mNativeOlmOutboundGroupSessionId;
+
+ public OlmOutboundGroupSession() {
+ initNewSession();
+ }
+
+ /**
+ * Getter on the native outbound group session ID.
+ * @return native outbound group session ID
+ */
+ public long getOlmInboundGroupSessionId(){
+ return mNativeOlmInboundGroupSessionId;
+ }
+
+ /**
+ * Release native session and invalid its JAVA reference counter part.
+ * Public API for {@link #releaseSessionJni()}.
+ * To be called before any other API call.
+ */
+ public void releaseSession(){
+ releaseSessionJni();
+
+ mNativeOlmOutboundGroupSessionId = 0;
+ }
+
+ /**
+ * Destroy the corresponding OLM outbound group session native object.
+ * This method must ALWAYS be called when this JAVA instance
+ * is destroyed (ie. garbage collected) to prevent memory leak in native side.
+ * See {@link #initNewSessionJni()}.
+ */
+ private native void releaseSessionJni();
+
+ /**
+ * Create and save the session native instance ID.
+ * Wrapper for {@link #initNewSessionJni()}.
+ * To be called before any other API call.
+ * @return true if init succeed, false otherwise.
+ */
+ private boolean initNewSession() {
+ boolean retCode = false;
+ if(0 != (mNativeOlmOutboundGroupSessionId = initNewSessionJni())){
+ retCode = true;
+ }
+ return retCode;
+ }
+
+ /**
+ * Create the corresponding OLM outbound group session in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done.
+ * @return native session instance identifier (see {@link #mNativeOlmOutboundGroupSessionId})
+ */
+ private native long initNewSessionJni();
+
+
+ /**
+ * Creates a new outbound group session.
+ * The session key parameter is retrieved from a outbound group session.
+ * @return 0 if operation succeed, -1 otherwise
+ */
+ public int initOutboundGroupSession() {
+ return initOutboundGroupSessionJni();
+ }
+ public native int initOutboundGroupSessionJni();
+
+
+
+
+ public String sessionIdentifier() {
+ String retValue = null;
+ //retValue = sessionIdentifierJni();
+
+ return retValue;
+ }
+ public native String sessionIdentifierJni();
+
+
+
+
+ public long messageIndex() {
+ long retValue =0;
+ //retValue = messageIndexJni();
+
+ return retValue;
+ }
+ private native long messageIndexJni();
+
+
+
+
+ public String sessionKey() {
+ String retValue = null;
+ //retValue = sessionKeyJni();
+
+ return retValue;
+ }
+ private native String sessionKeyJni();
+
+
+ public String encryptMessage(String aClearMsg) {
+ String retValue = null;
+ //retValue = encryptMessageJni(aClearMsg);
+
+ return retValue;
+ }
+ private native String encryptMessageJni(String aClearMsg);
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
index fc1f76f..2df5ea7 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmSession.java
@@ -19,7 +19,9 @@ package org.matrix.olm;
import android.text.TextUtils;
import android.util.Log;
-public class OlmSession {
+import java.io.Serializable;
+
+public class OlmSession implements Serializable {
private static final String LOG_TAG = "OlmSession";
/** session raw pointer value (OlmSession*) returned by JNI.
@@ -85,7 +87,6 @@ public class OlmSession {
/**
* Create the corresponding OLM session in native side.
- * The return value is a long casted C ptr on the OlmSession.
* Do not forget to call {@link #releaseSession()} when JAVA side is done.
* @return native session instance identifier (see {@link #mNativeOlmSessionId})
*/
@@ -159,6 +160,7 @@ public class OlmSession {
* @param aTheirIdentityKey the sender identity key
* @param aOneTimeKeyMsg PRE KEY message
* @return this if operation succeed, null otherwise
+ * TODO unit test missing: initInboundSessionWithAccountFrom
*/
public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aOneTimeKeyMsg) {
OlmSession retObj=null;
@@ -198,6 +200,7 @@ public class OlmSession {
* Public API for {@link #matchesInboundSessionJni(String)}.
* @param aOneTimeKeyMsg PRE KEY message
* @return this if operation succeed, null otherwise
+ * TODO unit test missing: matchesInboundSession
*/
public boolean matchesInboundSession(String aOneTimeKeyMsg) {
boolean retCode = false;
@@ -218,6 +221,7 @@ public class OlmSession {
* @param aTheirIdentityKey the sender identity key
* @param aOneTimeKeyMsg PRE KEY message
* @return this if operation succeed, null otherwise
+ * TODO unit test missing: matchesInboundSessionFrom
*/
public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) {
boolean retCode = false;
@@ -261,5 +265,10 @@ public class OlmSession {
}
private native String decryptMessageJni(OlmMessage aEncryptedMsg);
+
+ // TODO missing API: initWithSerializedData
+ // TODO missing API: serializeDataWithKey
+ // TODO missing API: initWithCoder
+ // TODO missing API: encodeWithCoder
}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
index 26a6a90..01c0dc9 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
@@ -45,7 +45,8 @@ $(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \
$(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \
olm_account.cpp \
olm_session.cpp \
-olm_utility.cpp
+olm_utility.cpp \
+olm_inbound_group_session.cpp
LOCAL_LDLIBS := -llog
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
index 2a5ab6f..ba15c13 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
@@ -19,7 +19,7 @@
/**
* Init memory allocation for account creation.
-* @return valid memory alocation, NULL otherwise
+* @return valid memory allocation, NULL otherwise
**/
OlmAccount* initializeAccountMemory()
{
@@ -68,7 +68,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz
/**
* Initialize a new account and return it to JAVA side.
* Since a C prt is returned as a jlong, special care will be taken
-* to make the cast (OlmAccount* => jlong) platform independant.
+* to make the cast (OlmAccount* => jlong) platform independent.
* @return the initialized OlmAccount* instance if init succeed, NULL otherwise
**/
JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz)
@@ -308,7 +308,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t
* @param aNativeOlmSessionId session instance
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS if no matching keys, ERROR_CODE_KO otherwise
**/
-JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId)
+JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId)
{
jint retCode = ERROR_CODE_KO;
OlmAccount* accountPtr = NULL;
@@ -317,11 +317,11 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo
if(NULL == sessionPtr)
{
- LOGE("## removeOneTimeKeysForSession(): failure - invalid session ptr");
+ LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid session ptr");
}
else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz)))
{
- LOGE("## removeOneTimeKeysForSession(): failure - invalid account ptr");
+ LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid account ptr");
}
else
{
@@ -329,14 +329,14 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo
if(result == olm_error())
{ // the account doesn't have any matching "one time keys"..
const char *errorMsgPtr = olm_account_last_error(accountPtr);
- LOGW("## removeOneTimeKeysForSession(): failure - removing one time keys Msg=%s",errorMsgPtr);
+ LOGW("## removeOneTimeKeysForSessionJni(): failure - removing one time keys Msg=%s",errorMsgPtr);
retCode = ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS;
}
else
{
retCode = ERROR_CODE_OK;
- LOGD("## removeOneTimeKeysForSession(): success");
+ LOGD("## removeOneTimeKeysForSessionJni(): success");
}
}
@@ -347,7 +347,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo
* Mark the current set of "one time keys" as being published.
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
**/
-JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz)
+JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz)
{
jint retCode = ERROR_CODE_OK;
OlmAccount* accountPtr = NULL;
@@ -355,7 +355,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job
if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz)))
{
- LOGE("## markOneTimeKeysPublished(): failure - invalid account ptr");
+ LOGE("## markOneTimeKeysAsPublishedJni(): failure - invalid account ptr");
retCode = ERROR_CODE_KO;
}
else
@@ -364,12 +364,12 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job
if(result == olm_error())
{
const char *errorMsgPtr = olm_account_last_error(accountPtr);
- LOGW("## markOneTimeKeysPublished(): failure - Msg=%s",errorMsgPtr);
+ LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",errorMsgPtr);
retCode = ERROR_CODE_KO;
}
else
{
- LOGD("## markOneTimeKeysPublished(): success - retCode=%ld",result);
+ LOGD("## markOneTimeKeysAsPublishedJni(): success - retCode=%ld",result);
}
}
@@ -382,7 +382,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job
* @param aMessage message to sign
* @return the signed message, null otherwise
**/
-JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage)
+JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage)
{
OlmAccount* accountPtr = NULL;
size_t signatureLength;
@@ -392,11 +392,11 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j
if(NULL == aMessage)
{
- LOGE("## signMessage(): failure - invalid aMessage param");
+ LOGE("## signMessageJni(): failure - invalid aMessage param");
}
else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz)))
{
- LOGE("## signMessage(): failure - invalid account ptr");
+ LOGE("## signMessageJni(): failure - invalid account ptr");
}
else
{
@@ -404,7 +404,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j
const char* messageToSign = env->GetStringUTFChars(aMessage, 0);
if(NULL == messageToSign)
{
- LOGE("## signMessage(): failure - message JNI allocation OOM");
+ LOGE("## signMessageJni(): failure - message JNI allocation OOM");
}
else
{
@@ -414,22 +414,26 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j
signatureLength = olm_account_signature_length(accountPtr);
if(NULL == (signedMsgPtr = (void*)malloc(signatureLength*sizeof(uint8_t))))
{
- LOGE("## signMessage(): failure - signature allocation OOM");
+ LOGE("## signMessageJni(): failure - signature allocation OOM");
}
else
{ // sign message
- resultSign = olm_account_sign(accountPtr, (void*)messageToSign, (size_t)messageLength, signedMsgPtr, signatureLength);
+ resultSign = olm_account_sign(accountPtr,
+ (void*)messageToSign,
+ (size_t)messageLength,
+ signedMsgPtr,
+ signatureLength);
if(resultSign == olm_error())
{
const char *errorMsgPtr = olm_account_last_error(accountPtr);
- LOGE("## signMessage(): failure - error signing message Msg=%s",errorMsgPtr);
+ LOGE("## signMessageJni(): failure - error signing message Msg=%s",errorMsgPtr);
}
else
- { // convert to jstring
- // TODO check how UTF conversion can impact the content?
- // why not consider return jbyteArray? and convert in JAVA side..
+ {
+ // TODO check if signedMsgPtr needs to be null ended: signedMsgPtr[resultSign]='\0'
+ // convert to jstring
signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8
- LOGD("## signMessage(): success - retCode=%ld",resultSign);
+ LOGD("## signMessageJni(): success - retCode=%ld",resultSign);
}
free(signedMsgPtr);
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h
index 23c9687..63ec3ef 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.h
@@ -18,6 +18,7 @@
#define _OMLACCOUNT_H
#include "olm_jni.h"
+#include "olm/olm.h"
#define OLM_ACCOUNT_FUNC_DEF(func_name) FUNC_DEF(OlmAccount,func_name)
#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name)
@@ -39,11 +40,11 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject
JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeys)(JNIEnv *env, jobject thiz);
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys);
-JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId);
-JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz);
+JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId);
+JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz);
// signing
-JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage);
+JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage);
#ifdef __cplusplus
}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp
new file mode 100644
index 0000000..43e9e20
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.cpp
@@ -0,0 +1,262 @@
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "olm_inbound_group_session.h"
+#include "olm_utility.h"
+
+
+/**
+ * Release the session allocation made by initializeInboundGroupSessionMemory().
+ * This method MUST be called when java counter part account instance is done.
+ *
+ */
+JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz)
+{
+ OlmInboundGroupSession* sessionPtr = NULL;
+
+ LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr);
+
+ if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## releaseSessionJni(): failure - invalid inbound group session instance");
+ }
+ else
+ {
+ size_t retCode = olm_clear_inbound_group_session(sessionPtr);
+ LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode);
+
+ LOGD("## releaseSessionJni(): IN");
+ free(sessionPtr);
+ LOGD("## releaseSessionJni(): OUT");
+ }
+}
+
+/**
+* Initialize a new inbound group session and return it to JAVA side.
+* Since a C prt is returned as a jlong, special care will be taken
+* to make the cast (OlmInboundGroupSession* => jlong) platform independent.
+* @return the initialized OlmInboundGroupSession* instance if init succeed, NULL otherwise
+**/
+JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz)
+{
+ OlmInboundGroupSession* sessionPtr = NULL;
+ size_t sessionSize = olm_inbound_group_session_size();
+
+ if(0 == sessionSize)
+ {
+ LOGE("## initNewSessionJni(): failure - inbound group session size = 0");
+ }
+ else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize)))
+ {
+ sessionPtr = olm_inbound_group_session(sessionPtr);
+ LOGD("## initNewSessionJni(): success - inbound group session size=%lu",sessionSize);
+ }
+ else
+ {
+ LOGE("## initNewSessionJni(): failure - inbound group session OOM");
+ }
+
+ return (jlong)(intptr_t)sessionPtr;
+}
+
+/**
+ * Create a new in-bound session.
+ * @param aSessionKey session key from an outbound session
+ * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
+ */
+JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey)
+{
+ jint retCode = ERROR_CODE_KO;
+ OlmInboundGroupSession *sessionPtr = NULL;
+ const uint8_t *sessionKeyPtr = NULL;
+ size_t sessionResult;
+
+ if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance");
+ }
+ else if(0 == aSessionKey)
+ {
+ LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey");
+ }
+ else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0)))
+ {
+ LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM");
+ }
+ else
+ {
+ size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey);
+ LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength);
+
+ sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength);
+ if(sessionResult == olm_error()) {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ retCode = ERROR_CODE_OK;
+ LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
+ }
+ }
+
+ // free local alloc
+ if(NULL!= sessionKeyPtr)
+ {
+ env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr);
+ }
+
+ return retCode;
+}
+
+
+JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz)
+{
+ OlmInboundGroupSession *sessionPtr = NULL;
+ uint8_t *sessionIdPtr = NULL;
+ jstring returnValueStr=0;
+
+ // get the size to alloc to contain the id
+ size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr);
+
+ if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance");
+ }
+ else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t))))
+ {
+ LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM");
+ }
+ else
+ {
+ size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId);
+ if (result == olm_error())
+ {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ // update length
+ sessionIdPtr[result] = static_cast('\0');
+
+ LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr);
+ returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
+ }
+ free(sessionIdPtr);
+ }
+
+ return returnValueStr;
+}
+
+JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg)
+{
+ jstring decryptedMsgRetValue = 0;
+ OlmInboundGroupSession *sessionPtr = NULL;
+ const char *encryptedMsgPtr = NULL;
+ uint8_t *plainTextMsgPtr = NULL;
+ uint8_t *tempEncryptedPtr = NULL;
+
+ LOGD("## decryptMessageJni(): IN");
+
+ if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL");
+ }
+ else if(0 == aEncryptedMsg)
+ {
+ LOGE("## decryptMessageJni(): failure - invalid clear message");
+ }
+ else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0)))
+ {
+ LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM");
+ }
+ else
+ {
+ // get encrypted message length
+ size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg);
+
+ // create a dedicated temp buffer to be used in next Olm API calls
+ if(NULL == (tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t)))))
+ {
+ LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM");
+ }
+ else
+ {
+ memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
+ LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr);
+
+ // get max plaintext length
+ size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr,
+ tempEncryptedPtr,
+ encryptedMsgLength);
+ if(maxPlainTextLength == olm_error())
+ {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength);
+
+ // allocate output decrypted message
+ plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t)));
+
+ // decrypt, but before reload encrypted buffer (previous one was destroyed)
+ memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
+ size_t plaintextLength = olm_group_decrypt(sessionPtr,
+ tempEncryptedPtr,
+ encryptedMsgLength,
+ plainTextMsgPtr,
+ maxPlainTextLength);
+ if(plaintextLength == olm_error())
+ {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ // update decrypted buffer size
+ plainTextMsgPtr[plaintextLength] = static_cast('\0');
+
+ LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr);
+ decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr);
+ }
+ }
+ }
+ }
+
+ // free alloc
+ if(NULL != encryptedMsgPtr)
+ {
+ env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr);
+ }
+
+ if(NULL != tempEncryptedPtr)
+ {
+ free(tempEncryptedPtr);
+ }
+
+ if(NULL != plainTextMsgPtr)
+ {
+ free(plainTextMsgPtr);
+ }
+
+ return decryptedMsgRetValue;
+}
+
+
+
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h
new file mode 100644
index 0000000..1eb8238
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_inbound_group_session.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _OMLINBOUND_GROUP_SESSION_H
+#define _OMLINBOUND_GROUP_SESSION_H
+
+#include "olm_jni.h"
+#include "olm/olm.h"
+#include "olm/inbound_group_session.h"
+
+#define OLM_INBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmInboundGroupSession,func_name)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// session creation/destruction
+JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz);
+JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz);
+
+JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey);
+JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz);
+JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h
index 38269f9..8f1555d 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h
@@ -25,7 +25,6 @@
#include
#include
-#include "olm/olm.h"
#define TAG "OlmJniNative"
@@ -54,11 +53,4 @@ static const int ERROR_CODE_KO = -1;
// constants
static const int ACCOUNT_CREATION_RANDOM_MODULO = 256;
-
-typedef struct _AccountContext
-{
- OlmAccount* mAccountPtr;
- _AccountContext(): mAccountPtr(NULL){}
-} AccountContext;
-
#endif
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp
new file mode 100644
index 0000000..40af39d
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.cpp
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "olm_outbound_group_session.h"
+#include "olm_utility.h"
+
+
+/**
+ * Release the session allocation made by initializeOutboundGroupSessionMemory().
+ * This method MUST be called when java counter part account instance is done.
+ *
+ */
+JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz)
+{
+ OlmOutboundGroupSession* sessionPtr = NULL;
+
+ LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr);
+
+ if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## releaseSessionJni(): failure - invalid inbound group session instance");
+ }
+ else
+ {
+ size_t retCode = olm_clear_outbound_group_session(sessionPtr);
+ LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode);
+
+ LOGD("## releaseSessionJni(): IN");
+ free(sessionPtr);
+ LOGD("## releaseSessionJni(): OUT");
+ }
+}
+
+/**
+* Initialize a new outbound group session and return it to JAVA side.
+* Since a C prt is returned as a jlong, special care will be taken
+* to make the cast (OlmOutboundGroupSession* => jlong) platform independent.
+* @return the initialized OlmOutboundGroupSession* instance if init succeed, NULL otherwise
+**/
+JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz)
+{
+ OlmOutboundGroupSession* sessionPtr = NULL;
+ size_t sessionSize = olm_outbound_group_session_size();
+
+ if(0 == sessionSize)
+ {
+ LOGE("## initNewSessionJni(): failure - outbound group session size = 0");
+ }
+ else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize)))
+ {
+ sessionPtr = olm_outbound_group_session(sessionPtr);
+ LOGD("## initNewSessionJni(): success - outbound group session size=%lu",sessionSize);
+ }
+ else
+ {
+ LOGE("## initNewSessionJni(): failure - outbound group session OOM");
+ }
+
+ return (jlong)(intptr_t)sessionPtr;
+}
+
+/**
+ * Create a new outbound session.
+ * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
+ */
+JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz)
+{
+ jint retCode = ERROR_CODE_KO;
+ OlmOutboundGroupSession *sessionPtr = NULL;
+ uint8_t *randomBuffPtr = NULL;
+ size_t sessionResult;
+
+ if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## initOutboundGroupSessionJni(): failure - invalid inbound group session instance");
+ }
+ else
+ {
+ // compute random buffer
+ size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr);
+
+ if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength))
+ {
+ LOGE("## initOutboundGroupSessionJni(): failure - random buffer init");
+ }
+ else
+ {
+ if(0==randomLength)
+ {
+ LOGW("## initOutboundGroupSessionJni(): random buffer is not required");
+ }
+
+ size_t sessionResult = olm_init_outbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength);
+ if(sessionResult == olm_error()) {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ retCode = ERROR_CODE_OK;
+ LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
+ }
+
+
+ }
+ }
+
+
+ else if(0 == aSessionKey)
+ {
+ LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey");
+ }
+ else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0)))
+ {
+ LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM");
+ }
+ else
+ {
+ size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey);
+ LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength);
+
+ sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength);
+ if(sessionResult == olm_error()) {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ retCode = ERROR_CODE_OK;
+ LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
+ }
+ }
+
+ // free local alloc
+ if(NULL!= sessionKeyPtr)
+ {
+ env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr);
+ }
+
+ return retCode;
+}
+
+
+JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz)
+{
+ OlmInboundGroupSession *sessionPtr = NULL;
+ uint8_t *sessionIdPtr = NULL;
+ jstring returnValueStr=0;
+
+ // get the size to alloc to contain the id
+ size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr);
+
+ if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance");
+ }
+ else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t))))
+ {
+ LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM");
+ }
+ else
+ {
+ size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId);
+ if (result == olm_error())
+ {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ // update length
+ sessionIdPtr[result] = static_cast('\0');
+
+ LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr);
+ returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
+ }
+ free(sessionIdPtr);
+ }
+
+ return returnValueStr;
+}
+
+JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg)
+{
+ jstring decryptedMsgRetValue = 0;
+ OlmInboundGroupSession *sessionPtr = NULL;
+ const char *encryptedMsgPtr = NULL;
+ uint8_t *plainTextMsgPtr = NULL;
+ uint8_t *tempEncryptedPtr = NULL;
+
+ LOGD("## decryptMessageJni(): IN");
+
+ if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
+ {
+ LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL");
+ }
+ else if(0 == aEncryptedMsg)
+ {
+ LOGE("## decryptMessageJni(): failure - invalid clear message");
+ }
+ else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0)))
+ {
+ LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM");
+ }
+ else
+ {
+ // get encrypted message length
+ size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg);
+
+ // create a dedicated temp buffer to be used in next Olm API calls
+ if(NULL == (tempEncryptedPtr = static_cast(malloc(encryptedMsgLength*sizeof(uint8_t)))))
+ {
+ LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM");
+ }
+ else
+ {
+ memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
+ LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr);
+
+ // get max plaintext length
+ size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr,
+ tempEncryptedPtr,
+ encryptedMsgLength);
+ if(maxPlainTextLength == olm_error())
+ {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength);
+
+ // allocate output decrypted message
+ plainTextMsgPtr = static_cast(malloc(maxPlainTextLength*sizeof(uint8_t)));
+
+ // decrypt, but before reload encrypted buffer (previous one was destroyed)
+ memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
+ size_t plaintextLength = olm_group_decrypt(sessionPtr,
+ tempEncryptedPtr,
+ encryptedMsgLength,
+ plainTextMsgPtr,
+ maxPlainTextLength);
+ if(plaintextLength == olm_error())
+ {
+ const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
+ LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr);
+ }
+ else
+ {
+ // update decrypted buffer size
+ plainTextMsgPtr[plaintextLength] = static_cast('\0');
+
+ LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr);
+ decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr);
+ }
+ }
+ }
+ }
+
+ // free alloc
+ if(NULL != encryptedMsgPtr)
+ {
+ env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr);
+ }
+
+ if(NULL != tempEncryptedPtr)
+ {
+ free(tempEncryptedPtr);
+ }
+
+ if(NULL != plainTextMsgPtr)
+ {
+ free(plainTextMsgPtr);
+ }
+
+ return decryptedMsgRetValue;
+}
+
+
+
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h
new file mode 100644
index 0000000..1270dc2
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_outbound_group_session.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _OMLOUTBOUND_GROUP_SESSION_H
+#define _OMLOUTBOUND_GROUP_SESSION_H
+
+#include "olm_jni.h"
+#include "olm/olm.h"
+#include "olm/outbound_group_session.h"
+
+#define OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmOutboundGroupSession,func_name)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// session creation/destruction
+JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz);
+JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz);
+
+JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz, jstring aSessionKey);
+JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz);
+JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
index d33ab72..435540c 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp
@@ -458,7 +458,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
}
else if(0 == aEncryptedMsg)
{
- LOGE("## encryptMessageJni(): failure - invalid clear message");
+ LOGE("## encryptMessageJni(): failure - invalid encrypted message");
}
else if(NULL == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0)))
{
@@ -587,11 +587,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t
}
else if(0 == aEncryptedMsg)
{
- LOGE("## decryptMessageJni(): failure - invalid clear message");
+ LOGE("## decryptMessageJni(): failure - invalid encrypted message");
}
else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg)))
{
- LOGE("## decryptMessageJni(): failure - unable to get crypted message class");
+ LOGE("## decryptMessageJni(): failure - unable to get encrypted message class");
}
else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;")))
{
@@ -644,7 +644,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
size_t plaintextLength = olm_decrypt(sessionPtr,
encryptedMsgType,
- (void*)encryptedMsgPtr,
+ (void*)tempEncryptedPtr,
encryptedMsgLength,
plainTextMsgPtr,
maxPlainTextLength);
@@ -717,7 +717,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job
}
else
{
- // update decrypted buffer size
+ // update length
(static_cast(sessionIdPtr))[result] = static_cast('\0');
LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr);
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
index babb3bd..f79dcaa 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_session.h
@@ -18,6 +18,7 @@
#define _OMLSESSION_H
#include "olm_jni.h"
+#include "olm/olm.h"
#define OLM_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmSession,func_name)
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
index c27fe7c..bd920fe 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
@@ -101,7 +101,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
}
/**
-* Read the account instance ID of the calling object (aJavaObject).
+* Read the session instance ID of the calling object (aJavaObject).
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
@@ -139,3 +139,83 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
//LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId);
return instanceId;
}
+
+
+/**
+* Read the inbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table
+* @param aJavaObject reference to the object on which the method is invoked
+* @return the instance ID if read succeed, -1 otherwise.
+**/
+jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
+{
+ jlong instanceId=-1;
+ jfieldID instanceIdField;
+ jclass loaderClass;
+
+ if(NULL!=aJniEnv)
+ {
+ if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
+ {
+ if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J")))
+ {
+ instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
+ aJniEnv->DeleteLocalRef(loaderClass);
+ }
+ else
+ {
+ LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
+ }
+ }
+ else
+ {
+ LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
+ }
+ }
+ else
+ {
+ LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
+ }
+
+ return instanceId;
+}
+
+
+/**
+* Read the outbound group session instance ID of the calling object (aJavaObject).
+* @param aJniEnv pointer pointing on the JNI function table
+* @param aJavaObject reference to the object on which the method is invoked
+* @return the instance ID if read succeed, -1 otherwise.
+**/
+jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
+{
+ jlong instanceId=-1;
+ jfieldID instanceIdField;
+ jclass loaderClass;
+
+ if(NULL!=aJniEnv)
+ {
+ if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
+ {
+ if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J")))
+ {
+ instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
+ aJniEnv->DeleteLocalRef(loaderClass);
+ }
+ else
+ {
+ LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
+ }
+ }
+ else
+ {
+ LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
+ }
+ }
+ else
+ {
+ LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
+ }
+
+ return instanceId;
+}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
index bf35955..b16e915 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
@@ -25,6 +25,7 @@ extern "C" {
bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize);
jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
+jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
#ifdef __cplusplus
}