diff options
Diffstat (limited to 'java/android/OlmLibSdk/olm-sdk/src/main/java')
3 files changed, 162 insertions, 49 deletions
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 } |