diff options
Diffstat (limited to 'java/android/OlmLibSdk')
11 files changed, 760 insertions, 66 deletions
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 385fc0a..6c1cbf3 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 @@ -42,7 +42,7 @@ public class OlmAccountTest { private static OlmAccount mOlmAccount; private static OlmManager mOlmManager; private boolean mIsAccountCreated; - final String FILE_NAME = "SerialTestFile"; + private final String FILE_NAME = "SerialTestFile"; @BeforeClass public static void setUpClass(){ @@ -170,7 +170,12 @@ public class OlmAccountTest { @Test public void test10RemoveOneTimeKeysForSession() { - OlmSession olmSession = new OlmSession(); + OlmSession olmSession = null; + try { + olmSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } long sessionId = olmSession.getOlmSessionId(); assertTrue(0 != sessionId); @@ -230,16 +235,16 @@ public class OlmAccountTest { try { Context context = getInstrumentation().getContext(); - context.getFilesDir(); + //context.getFilesDir(); fileOutput = context.openFileOutput(FILE_NAME, Context.MODE_PRIVATE); - // serialize + // serialize account objectOutput = new ObjectOutputStream(fileOutput); objectOutput.writeObject(accountRef); objectOutput.flush(); objectOutput.close(); - // deserialize + // deserialize account FileInputStream fileInput = context.openFileInput(FILE_NAME); ObjectInputStream objectInput = new ObjectInputStream(fileInput); accountDeserial = (OlmAccount) objectInput.readObject(); @@ -262,7 +267,6 @@ public class OlmAccountTest { accountRef.releaseAccount(); accountDeserial.releaseAccount(); } - catch (FileNotFoundException e) { Log.e(LOG_TAG, "## test13Serialization(): Exception FileNotFoundException Msg=="+e.getMessage()); } @@ -278,7 +282,6 @@ public class OlmAccountTest { catch (Exception e) { Log.e(LOG_TAG, "## test13Serialization(): Exception Msg==" + e.getMessage()); } - } diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java index fc3c1f0..e488ae0 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java +++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmGroupSessionTest.java @@ -1,5 +1,6 @@ package org.matrix.olm; +import android.content.Context; import android.support.test.runner.AndroidJUnit4; import android.text.TextUtils; import android.util.Log; @@ -11,6 +12,14 @@ import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; + +import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -19,6 +28,7 @@ import static org.junit.Assert.assertTrue; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class OlmGroupSessionTest { private static final String LOG_TAG = "OlmSessionTest"; + private final String FILE_NAME_SERIAL_SESSION = "SerialGroupSession"; private static OlmManager mOlmManager; private static OlmOutboundGroupSession mAliceOutboundGroupSession; @@ -141,4 +151,66 @@ public class OlmGroupSessionTest { // release group sessions mBobInboundGroupSession.releaseSession(); } + + + @Test + public void test14SerializeOutboundSession() { + OlmOutboundGroupSession outboundGroupSessionRef=null; + OlmOutboundGroupSession outboundGroupSessionSerial=null; + + // alice creates OUTBOUND GROUP SESSION + try { + outboundGroupSessionRef = new OlmOutboundGroupSession(); + } catch (OlmException e) { + assertTrue("Exception in OlmOutboundGroupSession, Exception code=" + e.getExceptionCode(), false); + } + + assertNotNull(outboundGroupSessionRef); + + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(outboundGroupSessionRef); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + outboundGroupSessionSerial = (OlmOutboundGroupSession) objectInput.readObject(); + objectInput.close(); + + // get sessions IDs + String sessionKeyRef = outboundGroupSessionRef.sessionKey(); + String sessionKeySerial = outboundGroupSessionSerial.sessionKey(); + + // session ID sanity check + assertFalse(TextUtils.isEmpty(sessionKeyRef)); + assertFalse(TextUtils.isEmpty(sessionKeySerial)); + + // session IDs comparison + assertTrue(sessionKeyRef.equals(sessionKeySerial)); + } + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + } + + } + + } 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 4d7c5b0..8fd2744 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 @@ -1,5 +1,6 @@ package org.matrix.olm; +import android.content.Context; import android.support.test.runner.AndroidJUnit4; import android.util.Log; @@ -11,8 +12,15 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.MethodSorters; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.util.Iterator; +import static android.support.test.InstrumentationRegistry.getInstrumentation; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; @@ -20,6 +28,7 @@ import static org.junit.Assert.assertTrue; @FixMethodOrder(MethodSorters.NAME_ASCENDING) public class OlmSessionTest { private static final String LOG_TAG = "OlmSessionTest"; + private final String FILE_NAME_SERIAL_SESSION = "SerialSession"; private static OlmManager mOlmManager; @@ -86,11 +95,16 @@ public class OlmSessionTest { } assertNotNull(bobOneTimeKey); } catch (JSONException e) { - assertTrue("Exception MSg="+e.getMessage(), false); + assertTrue("Exception Msg="+e.getMessage(), false); } // CREATE ALICE SESSION - OlmSession aliceSession = new OlmSession(); + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob @@ -101,7 +115,12 @@ public class OlmSessionTest { Log.d(LOG_TAG,"## test01AliceToBob(): encryptedMsg="+encryptedMsgToBob.mCipherText); // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = new OlmSession(); + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=bobSession.getOlmSessionId()); assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedMsgToBob.mCipherText)); String decryptedMsg = bobSession.decryptMessage(encryptedMsgToBob); @@ -173,6 +192,7 @@ public class OlmSessionTest { Iterator<String> generatedKeysIt = generatedKeys.keys(); if(generatedKeysIt.hasNext()) { + // return first otk bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); } assertNotNull(bobOneTimeKey); @@ -181,7 +201,12 @@ public class OlmSessionTest { } // CREATE ALICE SESSION - OlmSession aliceSession = new OlmSession(); + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=aliceSession.getOlmSessionId()); // CREATE ALICE OUTBOUND SESSION and encrypt message to bob @@ -192,7 +217,12 @@ public class OlmSessionTest { assertNotNull(encryptedAliceToBobMsg1); // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = new OlmSession(); + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=bobSession.getOlmSessionId()); assertNotNull(bobSession.initInboundSessionWithAccount(bobAccount, encryptedAliceToBobMsg1.mCipherText)); @@ -210,6 +240,7 @@ public class OlmSessionTest { String clearMsg2 = "Isn't life grand?"; String clearMsg3 = "Let's go to the opera."; + // bob encrypts messages OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); assertNotNull(encryptedMsg1); OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); @@ -217,6 +248,7 @@ public class OlmSessionTest { OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); assertNotNull(encryptedMsg3); + // alice decrypts bob's messages String decryptedMsg1 = aliceSession.decryptMessage(encryptedMsg1); assertNotNull(decryptedMsg1); String decryptedMsg2 = aliceSession.decryptMessage(encryptedMsg2); @@ -224,6 +256,7 @@ public class OlmSessionTest { String decryptedMsg3 = aliceSession.decryptMessage(encryptedMsg3); assertNotNull(decryptedMsg3); + // comparison tests assertTrue(clearMsg1.equals(decryptedMsg1)); assertTrue(clearMsg2.equals(decryptedMsg2)); assertTrue(clearMsg3.equals(decryptedMsg3)); @@ -235,6 +268,7 @@ public class OlmSessionTest { aliceSession.releaseSession(); } + @Test public void test03AliceBobSessionId() { // creates alice & bob accounts @@ -252,11 +286,22 @@ public class OlmSessionTest { assertTrue(0!=aliceAccount.getOlmAccountId()); // CREATE ALICE SESSION - OlmSession aliceSession = new OlmSession(); + + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } assertTrue(0!=aliceSession.getOlmSessionId()); - // CREATE BOB INBOUND SESSION and decrypt message from alice - OlmSession bobSession = new OlmSession(); + // CREATE ALICE SESSION + OlmSession bobSession = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + e.printStackTrace(); + } assertTrue(0!=bobSession.getOlmSessionId()); String aliceSessionId = aliceSession.sessionIdentifier(); @@ -268,4 +313,164 @@ public class OlmSessionTest { // must be the same for both ends of the conversation assertTrue(aliceSessionId.equals(bobSessionId)); } + + // ******************************************************** + // ************* SERIALIZATION TEST *********************** + // ******************************************************** + /** + * Same as test02AliceToBobBackAndForth() but alice's session + * is serialized and de-serialized before performing the final + * comparison (encrypt vs ) + */ + @Test + public void test03SessionSerialization() { + final int ONE_TIME_KEYS_NUMBER = 1; + String bobIdentityKey = null; + String bobOneTimeKey=null; + OlmAccount aliceAccount = null; + OlmAccount bobAccount = null; + OlmSession aliceSessionDeserial; + + // creates alice & bob accounts + try { + aliceAccount = new OlmAccount(); + bobAccount = new OlmAccount(); + } catch (OlmException e) { + assertTrue(e.getMessage(),false); + } + + // 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()) { + // return first otk + bobOneTimeKey = generatedKeys.getString(generatedKeysIt.next()); + } + assertNotNull(bobOneTimeKey); + } catch (JSONException e) { + assertTrue("Exception MSg="+e.getMessage(), false); + } + + // CREATE ALICE SESSION + OlmSession aliceSession = null; + try { + aliceSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + 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 = null; + try { + bobSession = new OlmSession(); + } catch (OlmException e) { + assertTrue("Exception Msg="+e.getMessage(), false); + } + 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)); + + // BACK/FORTH MESSAGE COMPARISON + String clearMsg1 = "Hello I'm Bob!"; + String clearMsg2 = "Isn't life grand?"; + String clearMsg3 = "Let's go to the opera."; + + // bob encrypts messages + OlmMessage encryptedMsg1 = bobSession.encryptMessage(clearMsg1); + assertNotNull(encryptedMsg1); + OlmMessage encryptedMsg2 = bobSession.encryptMessage(clearMsg2); + assertNotNull(encryptedMsg2); + OlmMessage encryptedMsg3 = bobSession.encryptMessage(clearMsg3); + assertNotNull(encryptedMsg3); + + // serialize alice session + Context context = getInstrumentation().getContext(); + try { + FileOutputStream fileOutput = context.openFileOutput(FILE_NAME_SERIAL_SESSION, Context.MODE_PRIVATE); + ObjectOutputStream objectOutput = new ObjectOutputStream(fileOutput); + objectOutput.writeObject(aliceSession); + objectOutput.flush(); + objectOutput.close(); + + // deserialize session + FileInputStream fileInput = context.openFileInput(FILE_NAME_SERIAL_SESSION); + ObjectInputStream objectInput = new ObjectInputStream(fileInput); + aliceSessionDeserial = (OlmSession) objectInput.readObject(); + objectInput.close(); + + // test deserialize return value + assertNotNull(aliceSessionDeserial); + + // de-serialized alice session decrypts bob's messages + String decryptedMsg1 = aliceSessionDeserial.decryptMessage(encryptedMsg1); + assertNotNull(decryptedMsg1); + String decryptedMsg2 = aliceSessionDeserial.decryptMessage(encryptedMsg2); + assertNotNull(decryptedMsg2); + String decryptedMsg3 = aliceSessionDeserial.decryptMessage(encryptedMsg3); + assertNotNull(decryptedMsg3); + + // comparison tests + assertTrue(clearMsg1.equals(decryptedMsg1)); + assertTrue(clearMsg2.equals(decryptedMsg2)); + assertTrue(clearMsg3.equals(decryptedMsg3)); + + // clean objects.. + bobAccount.releaseAccount(); + aliceAccount.releaseAccount(); + bobSession.releaseSession(); + aliceSession.releaseSession(); + aliceSessionDeserial.releaseSession(); + } + catch (FileNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception FileNotFoundException Msg=="+e.getMessage()); + } + catch (ClassNotFoundException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception ClassNotFoundException Msg==" + e.getMessage()); + } + catch (IOException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception IOException Msg==" + e.getMessage()); + } + /*catch (OlmException e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception OlmException Msg==" + e.getMessage()); + }*/ + catch (Exception e) { + Log.e(LOG_TAG, "## test03SessionSerialization(): Exception Msg==" + e.getMessage()); + } + } } 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 61b6c52..8d19a0c 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 @@ -31,8 +31,6 @@ import java.util.Random; public class OlmAccount implements Serializable { private static final long serialVersionUID = 3497486121598434824L; private static final String LOG_TAG = "OlmAccount"; - private static final int RANDOM_KEY_SIZE = 32; - private static final int RANDOM_RANGE = 256; // JSON keys used in the JSON objects returned by JNI /** As well as the identity key, each device creates a number of Curve25519 key pairs which are @@ -63,24 +61,17 @@ public class OlmAccount implements Serializable { } } - private String getRandomKey() { - String keyRetValue; - Random rand = new Random(); - StringBuilder strBuilder = new StringBuilder(); - - for(int i = 0; i< OlmAccount.RANDOM_KEY_SIZE; i++) { - strBuilder.append(rand.nextInt(RANDOM_RANGE)); - } - keyRetValue = strBuilder.toString(); - - return keyRetValue; - } - + /** + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException + * @throws OlmException + */ private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { aOutStream.defaultWriteObject(); // generate serialization key - String key = getRandomKey(); + String key = OlmUtility.getRandomKey(); // compute pickle string StringBuffer errorMsg = new StringBuffer(); @@ -94,6 +85,13 @@ public class OlmAccount implements Serializable { } } + /** + * Kick off the deserialization mechanism. + * @param aInStream + * @throws IOException + * @throws ClassNotFoundException + * @throws OlmException + */ private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { aInStream.defaultReadObject(); StringBuffer errorMsg = new StringBuffer(); @@ -379,9 +377,4 @@ public class OlmAccount implements Serializable { 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/OlmException.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index b83e77c..280dce1 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -30,6 +30,7 @@ public class OlmException extends Exception { public static final int EXCEPTION_CODE_SESSION_SERIALIZATION = 6; public static final int EXCEPTION_CODE_SESSION_DESERIALIZATION = 7; public static final int EXCEPTION_CODE_INIT_ACCOUNT_CREATION = 8; + public static final int EXCEPTION_CODE_INIT_SESSION_CREATION = 9; // exception human readable messages public static final String EXCEPTION_MSG_NEW_OUTBOUND_GROUP_SESSION = "failed to create a new outbound group Session"; @@ -40,6 +41,7 @@ public class OlmException extends Exception { public static final String EXCEPTION_MSG_INIT_ACCOUNT_DESERIALIZATION = "initWithSerializedData() failure"; public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid deserialized parameters"; public static final String EXCEPTION_MSG_INIT_ACCOUNT_CREATION = "Account constructor failure"; + public static final String EXCEPTION_MSG_INIT_SESSION_CREATION = "Session constructor failure"; /** exception code to be taken from: {@link #EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION} * {@link #EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION} {@link #EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION}**/ 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 8574f95..ca74352 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,37 +19,146 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.Serializable; public class OlmSession implements Serializable { + private static final long serialVersionUID = -8975488639186976419L; 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; + private transient long mNativeOlmSessionId; - /** account instance associated with this session. **/ - private OlmAccount mOlmAccount; - public OlmSession() { - initNewSession(); + public OlmSession() throws OlmException { + if(!initNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, OlmException.EXCEPTION_MSG_INIT_SESSION_CREATION); + } } /** - * Getter on the session ID. - * @return native session ID + * Kick off the serialization mechanism. + * @param aOutStream output stream for serializing + * @throws IOException + * @throws OlmException */ - public long getOlmSessionId(){ - return mNativeOlmSessionId; + private void writeObject(ObjectOutputStream aOutStream) throws IOException, OlmException { + aOutStream.defaultWriteObject(); + + // generate serialization key + String key = OlmUtility.getRandomKey(); + + // compute pickle string + StringBuffer errorMsg = new StringBuffer(); + String pickledData = serializeDataWithKey(key, errorMsg); + + if(null == pickledData) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_SERIALIZATION, String.valueOf(errorMsg)); + } else { + aOutStream.writeObject(key); + aOutStream.writeObject(pickledData); + } } /** + * Kick off the deserialization mechanism. + * @param aInStream + * @throws IOException + * @throws ClassNotFoundException + * @throws OlmException + */ + private void readObject(ObjectInputStream aInStream) throws IOException, ClassNotFoundException, OlmException { + aInStream.defaultReadObject(); + StringBuffer errorMsg = new StringBuffer(); + + String key = (String) aInStream.readObject(); + String pickledData = (String) aInStream.readObject(); + + if(TextUtils.isEmpty(key)) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" key"); + + } else if(TextUtils.isEmpty(pickledData)) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION+" pickle"); + + } else if(!createNewSession()) { + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, OlmException.EXCEPTION_MSG_INIT_NEW_ACCOUNT_DESERIALIZATION); + + } else if(!initWithSerializedData(pickledData, key, errorMsg)) { + releaseSession(); // prevent memory leak + throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DESERIALIZATION, String.valueOf(errorMsg)); + + } else { + Log.d(LOG_TAG,"## readObject(): success"); + } + } + + /** + * Return an account as a base64 string.<br> + * The account is serialized and encrypted with aKey. + * In case of failure, an error human readable + * description is provide in aErrorMsg. + * @param aKey encryption key + * @param aErrorMsg error message description + * @return pickled base64 string if operation succeed, null otherwise + */ + private String serializeDataWithKey(String aKey, StringBuffer aErrorMsg) { + String pickleRetValue = null; + + // sanity check + if(null == aErrorMsg) { + Log.e(LOG_TAG,"## serializeDataWithKey(): invalid parameter - aErrorMsg=null"); + } else if(TextUtils.isEmpty(aKey)) { + aErrorMsg.append("Invalid input parameters in serializeDataWithKey()"); + } else { + aErrorMsg.setLength(0); + pickleRetValue = serializeDataWithKeyJni(aKey, aErrorMsg); + } + + return pickleRetValue; + } + private native String serializeDataWithKeyJni(String aKey, StringBuffer aErrorMsg); + + + /** + * Loads an account from a pickled base64 string.<br> + * See {@link #serializeDataWithKey(String, StringBuffer)} + * @param aSerializedData pickled account in a base64 string format + * @param aKey key used to encrypted + * @param aErrorMsg error message description + * @return true if operation succeed, false otherwise + */ + private boolean initWithSerializedData(String aSerializedData, String aKey, StringBuffer aErrorMsg) { + boolean retCode = false; + String jniError; + + if(null == aErrorMsg) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input error parameter"); + } else { + aErrorMsg.setLength(0); + + if (TextUtils.isEmpty(aSerializedData) || TextUtils.isEmpty(aKey)) { + Log.e(LOG_TAG, "## initWithSerializedData(): invalid input parameters"); + } else if (null == (jniError = initWithSerializedDataJni(aSerializedData, aKey))) { + retCode = true; + } else { + aErrorMsg.append(jniError); + } + } + + return retCode; + } + private native String initWithSerializedDataJni(String aSerializedData, String aKey); + + /** * Getter on the session ID. * @return native session ID */ - public OlmAccount getOlmAccountId(){ - return mOlmAccount; + public long getOlmSessionId(){ + return mNativeOlmSessionId; } /** @@ -93,6 +202,29 @@ public class OlmSession implements Serializable { /** + * Create a native account instance without any initialization.<br> + * Since the account is left uninitialized, this + * method is intended to be used in the serialization mechanism (see {@link #readObject(ObjectInputStream)}).<br> + * Public wrapper for {@link #createNewSessionJni()}. + * @return true if init succeed, false otherwise. + */ + private boolean createNewSession() { + boolean retCode = false; + if(0 != (mNativeOlmSessionId = createNewSessionJni())){ + retCode = true; + } + return retCode; + } + + /** + * Create an OLM account in native side.<br> + * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native account instance identifier (see {@link #mNativeOlmSessionId}) + */ + private native long createNewSessionJni(); + + + /** * 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)}. @@ -107,10 +239,7 @@ public class OlmSession implements Serializable { 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)) { + if(0 == initOutboundSessionJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aTheirOneTimeKey)) { retObj = this; } } @@ -136,10 +265,7 @@ public class OlmSession implements Serializable { if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - // set the account of this session - mOlmAccount = aAccount; - - if( 0 == initInboundSessionJni(mOlmAccount.getOlmAccountId(), aPreKeyMsg)) { + if( 0 == initInboundSessionJni(aAccount.getOlmAccountId(), aPreKeyMsg)) { retObj = this; } } @@ -168,10 +294,7 @@ public class OlmSession implements Serializable { if((null==aAccount) || TextUtils.isEmpty(aPreKeyMsg)){ Log.e(LOG_TAG, "## initInboundSessionWithAccount(): invalid input parameters"); } else { - // set the account of this session - mOlmAccount = aAccount; - - if(0 == initInboundSessionFromIdKeyJni(mOlmAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg)){ + if(0 == initInboundSessionFromIdKeyJni(aAccount.getOlmAccountId(), aTheirIdentityKey, aPreKeyMsg)){ retObj = this; } } @@ -265,10 +388,5 @@ public class OlmSession implements Serializable { } 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/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp index 6f2e6ee..fd3a977 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 @@ -18,6 +18,13 @@ using namespace AndroidOlmSdk; +/*jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr<OlmAccount*> aGetLengthFunc, + olmPickleFuncPtr<OlmAccount*> aGetPickleFunc, + olmLastErrorFuncPtr<OlmAccount*> aGetLastErrorFunc);*/ + /** * Init memory allocation for account creation. * @return valid memory allocation, NULL otherwise @@ -487,6 +494,14 @@ JNIEXPORT jstring OLM_MANAGER_FUNC_DEF(getOlmLibVersion)(JNIEnv* env, jobject th **/ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) { + /*jstring pickledDataRetValue = serializeDataWithKey(env,thiz, + aKey, + aErrorMsg, + olm_pickle_account_length, + olm_pickle_account, + olm_account_last_error); + return pickledDataRetValue;*/ + jstring pickledDataRetValue = 0; jclass errorMsgJClass = 0; jmethodID errorMsgMethodId = 0; 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 70267ff..2e31bff 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 @@ -55,6 +55,20 @@ namespace AndroidOlmSdk static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; } + +// function pointer templates +template<typename T> using olmPickleLengthFuncPtr = size_t (*)(T); +template<typename T> using olmPickleFuncPtr = size_t (*)(T, void const *, size_t, void *, size_t); +template<typename T> using olmLastErrorFuncPtr = const char* (*)(T); + +template <typename T> +jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr<T> aGetLengthFunc, + olmPickleFuncPtr<T> aGetPickleFunc, + olmLastErrorFuncPtr<T> aGetLastErrorFunc); + #ifdef __cplusplus extern "C" { #endif diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp index b8dcbd1..174739c 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp +++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_jni_helper.cpp @@ -18,6 +18,7 @@ */ #include "olm_jni_helper.h" +#include "olm/olm.h" using namespace AndroidOlmSdk; @@ -288,3 +289,97 @@ jlong getUtilityInstanceId(JNIEnv* aJniEnv, jobject aJavaObject) return instanceId; } + +template <typename T> +jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr<T> aGetLengthFunc, + olmPickleFuncPtr<T> aGetPickleFunc, + olmLastErrorFuncPtr<T> aGetLastErrorFunc) +{ + jstring pickledDataRetValue = 0; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *keyPtr = NULL; + void *pickledPtr = NULL; + T accountPtr = NULL; + + LOGD("## serializeDataWithKeyJni(): IN"); + + if(NULL == (accountPtr = (T)getAccountInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid account ptr"); + } + else if(0 == aKey) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + } + else if(0 == aErrorMsg) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = aGetLengthFunc(accountPtr); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + + if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + } + else + { + size_t result = aGetPickleFunc(accountPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = aGetLastErrorFunc(accountPtr); + LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_account() Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } + } + else + { + // build success output + (static_cast<char*>(pickledPtr))[pickledLength] = static_cast<char>('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast<char*>(pickledPtr)); + } + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + free(pickledPtr); + } + + return pickledDataRetValue; +}
\ No newline at end of file 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 22316cb..3422fee 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 @@ -41,6 +41,16 @@ OlmSession* initializeSessionMemory() return sessionPtr; } + +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) +{ + LOGD("## createNewSessionJni(): IN"); + OlmSession* accountPtr = initializeSessionMemory(); + + LOGD(" ## createNewSessionJni(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr); + return (jlong)(intptr_t)accountPtr; +} + JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz) { OlmSession* sessionPtr = NULL; @@ -687,8 +697,6 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t } - - /** * Get the session identifier for this session. * @return the session identifier if operation succeed, null otherwise @@ -739,3 +747,167 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job return returnValueStr; } + +/** +* Serialize and encrypt session instance into a base64 string.<br> +* @param aKey key used to encrypt the serialized session data +* @param[out] aErrorMsg error message set if operation failed +* @return a base64 string if operation succeed, null otherwise +**/ +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg) +{ + jstring pickledDataRetValue = 0; + jclass errorMsgJClass = 0; + jmethodID errorMsgMethodId = 0; + jstring errorJstring = 0; + const char *keyPtr = NULL; + void *pickledPtr = NULL; + OlmSession* sessionPtr = NULL; + + LOGD("## serializeDataWithKeyJni(): IN"); + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid session ptr"); + } + else if(0 == aKey) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid key"); + } + else if(0 == aErrorMsg) + { + LOGE(" ## serializeDataWithKeyJni(): failure - invalid error object"); + } + else if(0 == (errorMsgJClass = env->GetObjectClass(aErrorMsg))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error class"); + } + else if(0 == (errorMsgMethodId = env->GetMethodID(errorMsgJClass, "append", "(Ljava/lang/String;)Ljava/lang/StringBuffer;"))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - unable to get error method ID"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - keyPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = olm_pickle_session_length(sessionPtr); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## serializeDataWithKeyJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## serializeDataWithKeyJni(): key=%s",(char const *)keyPtr); + + if(NULL == (pickledPtr = (void*)malloc((pickledLength+1)*sizeof(uint8_t)))) + { + LOGE(" ## serializeDataWithKeyJni(): failure - pickledPtr buffer OOM"); + } + else + { + size_t result = olm_pickle_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE(" ## serializeDataWithKeyJni(): failure - olm_pickle_session() Msg=%s",errorMsgPtr); + + if(0 != (errorJstring = env->NewStringUTF(errorMsgPtr))) + { + env->CallObjectMethod(aErrorMsg, errorMsgMethodId, errorJstring); + } + } + else + { + // build success output + (static_cast<char*>(pickledPtr))[pickledLength] = static_cast<char>('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast<char*>(pickledPtr)); + } + } + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + free(pickledPtr); + } + + return pickledDataRetValue; +} + + +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey) +{ + OlmSession* sessionPtr = NULL; + jstring errorMessageRetValue = 0; + const char *keyPtr = NULL; + const char *pickledPtr = NULL; + + LOGD("## initWithSerializedDataJni(): IN"); + + if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz))) + { + LOGE(" ## initWithSerializedDataJni(): failure - session failure OOM"); + } + else if(0 == aKey) + { + LOGE(" ## initWithSerializedDataJni(): failure - invalid key"); + } + else if(0 == aSerializedData) + { + LOGE(" ## initWithSerializedDataJni(): failure - serialized data"); + } + else if(NULL == (keyPtr = env->GetStringUTFChars(aKey, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - keyPtr JNI allocation OOM"); + } + else if(NULL == (pickledPtr = env->GetStringUTFChars(aSerializedData, 0))) + { + LOGE(" ## initWithSerializedDataJni(): failure - pickledPtr JNI allocation OOM"); + } + else + { + size_t pickledLength = (size_t)env->GetStringUTFLength(aSerializedData); + size_t keyLength = (size_t)env->GetStringUTFLength(aKey); + LOGD(" ## initWithSerializedDataJni(): pickledLength=%lu keyLength=%lu",pickledLength, keyLength); + LOGD(" ## initWithSerializedDataJni(): key=%s",(char const *)keyPtr); + LOGD(" ## initWithSerializedDataJni(): pickled=%s",(char const *)pickledPtr); + + size_t result = olm_unpickle_session(sessionPtr, + (void const *)keyPtr, + keyLength, + (void*)pickledPtr, + pickledLength); + if(result == olm_error()) + { + const char *errorMsgPtr = olm_session_last_error(sessionPtr); + LOGE(" ## initWithSerializedDataJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); + errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + } + else + { + LOGD(" ## initWithSerializedDataJni(): success - result=%lu ", result); + } + + } + + // free alloc + if(NULL != keyPtr) + { + env->ReleaseStringUTFChars(aKey, keyPtr); + } + + if(NULL != pickledPtr) + { + env->ReleaseStringUTFChars(aSerializedData, pickledPtr); + } + + return errorMessageRetValue; +}
\ No newline at end of file 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 f79dcaa..a08b775 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 @@ -29,6 +29,7 @@ extern "C" { // session creation/destruction JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); // outbound session JNIEXPORT jint OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aTheirIdentityKey, jstring aTheirOneTimeKey); @@ -47,6 +48,10 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); +// serialization +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); +JNIEXPORT jstring OLM_SESSION_FUNC_DEF(initWithSerializedDataJni)(JNIEnv *env, jobject thiz, jstring aSerializedData, jstring aKey); + #ifdef __cplusplus } #endif |