From fb87d8feee14b36a76d8022e2b742a6c1d65d0f0 Mon Sep 17 00:00:00 2001 From: pedroGitt Date: Fri, 21 Oct 2016 18:09:20 +0200 Subject: Serialization for OlmAccount and OlmSession OK --- .../src/main/java/org/matrix/olm/OlmAccount.java | 35 ++-- .../src/main/java/org/matrix/olm/OlmException.java | 2 + .../src/main/java/org/matrix/olm/OlmSession.java | 174 ++++++++++++++++---- .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp | 15 ++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 14 ++ .../olm-sdk/src/main/jni/olm_jni_helper.cpp | 95 +++++++++++ .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 176 ++++++++++++++++++++- .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h | 5 + 8 files changed, 465 insertions(+), 51 deletions(-) (limited to 'java/android/OlmLibSdk/olm-sdk/src/main') 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.
+ * 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.
+ * 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; } /** @@ -92,6 +201,29 @@ public class OlmSession implements Serializable { private native long initNewSessionJni(); + /** + * Create a native account instance without any initialization.
+ * Since the account is left uninitialized, this + * method is intended to be used in the serialization mechanism (see {@link #readObject(ObjectInputStream)}).
+ * 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.
+ * 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.
@@ -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 aGetLengthFunc, + olmPickleFuncPtr aGetPickleFunc, + olmLastErrorFuncPtr 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 using olmPickleLengthFuncPtr = size_t (*)(T); +template using olmPickleFuncPtr = size_t (*)(T, void const *, size_t, void *, size_t); +template using olmLastErrorFuncPtr = const char* (*)(T); + +template +jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr aGetLengthFunc, + olmPickleFuncPtr aGetPickleFunc, + olmLastErrorFuncPtr 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 +jstring serializeDataWithKey(JNIEnv *env, jobject thiz, + jstring aKey, + jobject aErrorMsg, + olmPickleLengthFuncPtr aGetLengthFunc, + olmPickleFuncPtr aGetPickleFunc, + olmLastErrorFuncPtr 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(pickledPtr))[pickledLength] = static_cast('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(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.
+* @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(pickledPtr))[pickledLength] = static_cast('\0'); + pickledDataRetValue = env->NewStringUTF((const char*)pickledPtr); + LOGD(" ## serializeDataWithKeyJni(): success - result=%lu pickled=%s", result, static_cast(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 -- cgit v1.2.3