From eeb210f733924d9c48e82c66e53f0630f05d894e Mon Sep 17 00:00:00 2001 From: ylecollen Date: Tue, 10 Jan 2017 11:40:57 +0100 Subject: [PATCH] -> Check the function descriptions -> Update the deserialization methods (the jni methods create an object instance before deserializing them. --- .../main/java/org/matrix/olm/OlmAccount.java | 158 +++++--------- .../java/org/matrix/olm/OlmException.java | 4 +- .../matrix/olm/OlmInboundGroupSession.java | 106 ++++------ .../matrix/olm/OlmOutboundGroupSession.java | 104 ++++----- .../main/java/org/matrix/olm/OlmSession.java | 130 ++++++++---- .../main/java/org/matrix/olm/OlmUtility.java | 79 ++++++- .../olm-sdk/src/main/jni/olm_account.cpp | 118 +++++++---- .../olm-sdk/src/main/jni/olm_account.h | 8 +- .../main/jni/olm_inbound_group_session.cpp | 199 ++++++++++-------- .../src/main/jni/olm_inbound_group_session.h | 6 +- .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h | 5 - .../main/jni/olm_outbound_group_session.cpp | 155 ++++++++------ .../src/main/jni/olm_outbound_group_session.h | 3 +- .../olm-sdk/src/main/jni/olm_session.cpp | 93 +++++--- .../olm-sdk/src/main/jni/olm_session.h | 6 +- .../olm-sdk/src/main/jni/olm_utility.cpp | 11 +- 16 files changed, 679 insertions(+), 506 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 6c1caf0..9ebaaf1 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 @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,8 +26,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; /** @@ -62,9 +60,21 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { private transient long mNativeId; public OlmAccount() throws OlmException { - createNewAccount(); + try { + mNativeId = createNewAccountJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); + } } + /** + * Create 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* to jlong) platform independent. + * @return the initialized OlmAccount* instance or throw an exception if fails + **/ + private native long createNewAccountJni(); + /** * Getter on the account ID. * @return native account ID @@ -92,26 +102,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ private native void releaseAccountJni(); - /** - * Create and initialize a native account instance.
- * To be called before any other API call. - * @exception OlmException the failure reason - */ - private void createNewAccount() throws OlmException { - try { - mNativeId = createNewAccountJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_ACCOUNT_CREATION, e.getMessage()); - } - } - - /** - * Create an OLM account in native side.
- * Do not forget to call {@link #releaseAccount()} when JAVA side is done. - * @return native account instance identifier (see {@link #mNativeId}) - */ - private native long createNewAccountJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -146,7 +136,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if (null != identityKeysBuffer) { try { identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer, "UTF-8")); - //Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString()); } catch (Exception e) { Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage()); } @@ -154,14 +143,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null"); } - return toStringMap(identityKeysJsonObj); + return OlmUtility.toStringMap(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 + * @return the identity keys or throw an exception if it fails */ private native byte[] identityKeysJni(); @@ -173,6 +162,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return maxOneTimeKeysJni(); } + /** + * Return the largest number of "one time keys" this account can store. + * @return the max number of "one time keys", -1 otherwise + */ private native long maxOneTimeKeysJni(); /** @@ -190,6 +183,12 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } + /** + * Generate a number of new one time keys.
If total number of keys stored + * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded. + * An exception is thrown if the operation fails.
+ * @param aNumberOfKeys number of keys to generate + */ private native void generateOneTimeKeysJni(int aNumberOfKeys); /** @@ -221,7 +220,6 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if( null != oneTimeKeysBuffer) { try { oneTimeKeysJsonObj = new JSONObject(new String(oneTimeKeysBuffer, "UTF-8")); - //Log.d(LOG_TAG, "## oneTimeKeys(): OneTime Json keys=" + oneTimeKeysJsonObj.toString()); } catch (Exception e) { Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage()); } @@ -229,7 +227,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null"); } - return toStringMapMap(oneTimeKeysJsonObj); + return OlmUtility.toStringMapMap(oneTimeKeysJsonObj); } /** @@ -237,7 +235,7 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { * 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 + * @return byte array containing the one time keys or throw an exception if it fails */ private native byte[] oneTimeKeysJni(); @@ -252,7 +250,8 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { if (null != aSession) { try { - res = (removeOneTimeKeysJni(aSession.getOlmSessionId()) >= 0); + removeOneTimeKeysJni(aSession.getOlmSessionId()); + res = true; Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result=" + res); } catch (Exception e) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_REMOVE_ONE_TIME_KEYS, e.getMessage()); @@ -264,10 +263,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { /** * Remove the "one time keys" that the session used from the account. + * An exception is thrown if the operation fails. * @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 */ - private native int removeOneTimeKeysJni(long aNativeOlmSessionId); + private native void removeOneTimeKeysJni(long aNativeOlmSessionId); /** * Marks the current set of "one time keys" as being published. @@ -281,6 +280,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } + /** + * Marks the current set of "one time keys" as being published. + * An exception is thrown if the operation fails. + */ private native void markOneTimeKeysAsPublishedJni(); /** @@ -312,69 +315,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return result; } + /** + * Sign a message with the ed25519 fingerprint key for this account.
+ * The signed message is returned by the method. + * @param aMessage message to sign + * @return the signed message + */ private native byte[] signMessageJni(byte[] aMessage); - /** - * Build a string-string dictionary from a jsonObject.
- * @param jsonObject the object to parse - * @return the map - */ - private static Map toStringMap(JSONObject jsonObject) { - if (null != jsonObject) { - HashMap map = new HashMap<>(); - Iterator keysItr = jsonObject.keys(); - while(keysItr.hasNext()) { - String key = keysItr.next(); - try { - Object value = jsonObject.get(key); - - if (value instanceof String) { - map.put(key, (String) value); - } else { - Log.e(LOG_TAG, "## toStringMap(): unexpected type " + value.getClass()); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## toStringMap(): failed " + e.getMessage()); - } - } - - return map; - } - - return null; - } - - /** - * Build a string-string dictionary of string dictionary from a jsonObject.
- * @param jsonObject the object to parse - * @return the map - */ - private static Map> toStringMapMap(JSONObject jsonObject) { - if (null != jsonObject) { - HashMap> map = new HashMap<>(); - - Iterator keysItr = jsonObject.keys(); - while(keysItr.hasNext()) { - String key = keysItr.next(); - try { - Object value = jsonObject.get(key); - - if (value instanceof JSONObject) { - map.put(key, toStringMap((JSONObject) value)); - } else { - Log.e(LOG_TAG, "## toStringMapMap(): unexpected type " + value.getClass()); - } - } catch (Exception e) { - Log.e(LOG_TAG, "## toStringMapMap(): failed " + e.getMessage()); - } - } - - return map; - } - - return null; - } - //============================================================================================================== // Serialization management //============================================================================================================== @@ -428,7 +376,12 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native byte[] serializeJni(byte[] aKey); + /** + * Serialize and encrypt account instance.
+ * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ + private native byte[] serializeJni(byte[] aKeyBuffer); /** * Loads an account from a pickled bytes buffer.
@@ -439,15 +392,14 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewAccount(); - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -460,5 +412,11 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } - private native String deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); + /** + * Allocate a new account and initialize it with the serialisation data.
+ * @param aSerializedDataBuffer the account serialisation buffer + * @param aKeyBuffer the key used to encrypt the serialized account data + * @return the deserialized account + **/ + private native long deserializeJni(byte[] aSerializedDataBuffer, byte[] aKeyBuffer); } 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 93a2425..b0b1a6a 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 @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. 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 index 09e5276..571bddb 100644 --- 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 @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,6 @@ package org.matrix.olm; - import android.text.TextUtils; import android.util.Log; @@ -55,16 +54,32 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * Constructor.
* Create and save a new native session instance ID and start a new inbound group session. - * The session key parameter is retrieved from an outbound group session - * See {@link #createNewSession()} and {@link #initInboundGroupSession(String)} + * The session key parameter is retrieved from an outbound group session. * @param aSessionKey session key * @throws OlmException constructor failure */ public OlmInboundGroupSession(String aSessionKey) throws OlmException { - createNewSession(); - initInboundGroupSession(aSessionKey); + if (TextUtils.isEmpty(aSessionKey)) { + Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); + } else { + try { + mNativeId = createNewSessionJni(aSessionKey.getBytes("UTF-8")); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); + } + } } + /** + * 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* to jlong) platform independent. + * @param aSessionKeyBuffer session key from an outbound session + * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. + **/ + private native long createNewSessionJni(byte[] aSessionKeyBuffer); + /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. @@ -80,30 +95,10 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri * 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 #createNewSessionJni()}. + * See {@link #createNewSessionJni(byte[])}. */ private native void releaseSessionJni(); - /** - * Create and save the session native instance ID.
- * To be called before any other API call. - * @exception OlmException the failure reason - */ - private void createNewSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_INBOUND_GROUP_SESSION, e.getMessage()); - } - } - - /** - * 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 #mNativeId}) - */ - private native long createNewSessionJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -112,28 +107,6 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return (0 == mNativeId); } - /** - * Start a new inbound group session.
- * The session key parameter is retrieved from an outbound group session - * see {@link OlmOutboundGroupSession#sessionKey()} - * @param aSessionKey session key - * @exception OlmException the failure reason - */ - private void initInboundGroupSession(String aSessionKey) throws OlmException { - if (TextUtils.isEmpty(aSessionKey)) { - Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); - } else { - try { - initInboundGroupSessionJni(aSessionKey.getBytes("UTF-8")); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); - } - } - } - - private native void initInboundGroupSessionJni(byte[] aSessionKeyBuffer); - /** * Retrieve the base64-encoded identifier for this inbound group session. * @return the session ID @@ -148,6 +121,11 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } } + /** + * Get a base64-encoded identifier for this inbound group session. + * An exception is thrown if the operation fails. + * @return the base64-encoded identifier + */ private native byte[] sessionIdentifierJni(); /** @@ -174,6 +152,13 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri return result; } + /** + * Decrypt a message. + * An exception is thrown if the operation fails. + * @param aEncryptedMsg the encrypted message + * @param aDecryptMessageResult the decryptMessage informaton + * @return the decrypted message + */ private native byte[] decryptMessageJni(byte[] aEncryptedMsg, DecryptMessageResult aDecryptMessageResult); //============================================================================================================== @@ -232,7 +217,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri /** * JNI counter part of {@link #serialize(byte[], StringBuffer)}. * @param aKey encryption key - * @return pickled base64 string if operation succeed, null otherwise + * @return the serialized session */ private native byte[] serializeJni(byte[] aKey); @@ -244,16 +229,14 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewSession(); - - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -267,10 +250,11 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri } /** - * JNI counter part of {@link #deserialize(byte[], byte[])}. - * @param aSerializedData pickled session in a base64 sbytes buffer - * @param aKey key used to encrypted in {@link #serialize(byte[], StringBuffer)} - * @return null if operation succeed, an error message if operation failed - */ - private native String deserializeJni(byte[] aSerializedData, byte[] aKey); + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); } 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 index d26b9b6..0481824 100644 --- 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 @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -46,14 +46,24 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser * Constructor.
* Create and save a new session native instance ID and * initialise a new outbound group session.
- * See {@link #createNewSession()} and {@link #initOutboundGroupSession()} * @throws OlmException constructor failure */ public OlmOutboundGroupSession() throws OlmException { - createNewSession(); - initOutboundGroupSession(); + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, e.getMessage()); + } } + /** + * Create the corresponding OLM outbound group session in native side.
+ * An exception is thrown if the operation fails. + * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native session instance identifier (see {@link #mNativeId}) + */ + private native long createNewSessionJni(); + /** * Release native session and invalid its JAVA reference counter part.
* Public API for {@link #releaseSessionJni()}. @@ -73,27 +83,6 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ private native void releaseSessionJni(); - /** - * Create and save the session native instance ID. - * Wrapper for {@link #createNewSessionJni()}.
- * To be called before any other API call. - * @exception OlmException the exception. - */ - private void createNewSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_CREATE_OUTBOUND_GROUP_SESSION, e.getMessage()); - } - } - - /** - * 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 #mNativeId}) - */ - private native long createNewSessionJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -102,20 +91,6 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return (0 == mNativeId); } - /** - * Start a new outbound group session.
- * @exception OlmException the failre reason - */ - private void initOutboundGroupSession() throws OlmException { - try { - initOutboundGroupSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION, e.getMessage()); - } - } - - private native void initOutboundGroupSessionJni(); - /** * Get a base64-encoded identifier for this session. * @return session identifier @@ -130,6 +105,11 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } } + /** + * Return the session identifier. + * An exception is thrown if the operation fails. + * @return the session identifier + */ private native byte[] sessionIdentifierJni(); /** @@ -141,6 +121,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser public int messageIndex() { return messageIndexJni(); } + + /** + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * An exception is thrown if the operation fails. + * @return current session index + */ private native int messageIndexJni(); /** @@ -159,6 +147,11 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } } + /** + * Return the session key. + * An exception is thrown if the operation fails. + * @return the session key + */ private native byte[] sessionKeyJni(); /** @@ -186,8 +179,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return retValue; } - private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); + /** + * Encrypt a bytes buffer messages. + * An exception is thrown if the operation fails. + * @param aClearMsgBuffer the message to encode + * @return the encoded message + */ + private native byte[] encryptMessageJni(byte[] aClearMsgBuffer); //============================================================================================================== // Serialization management @@ -240,8 +239,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser return pickleRetValue; } - private native byte[] serializeJni(byte[] aKey); + /** + * JNI counter part of {@link #serialize(byte[], StringBuffer)}. + * An exception is thrown if the operation fails. + * @param aKey encryption key + * @return the serialized session + */ + private native byte[] serializeJni(byte[] aKey); /** * Loads an account from a pickled base64 string.
@@ -252,16 +257,14 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewSession(); - - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -274,6 +277,13 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser } } - private native String deserializeJni(byte[] aSerializedData, byte[] aKey); + /** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); } 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 92cc110..da2e963 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 @@ -43,9 +43,20 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { private transient long mNativeId; public OlmSession() throws OlmException { - createNewSession(); + try { + mNativeId = createNewSessionJni(); + } catch (Exception e) { + throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, e.getMessage()); + } } + /** + * Create an OLM session in native side.
+ * Do not forget to call {@link #releaseSession()} when JAVA side is done. + * @return native account instance identifier or throw an exception. + */ + private native long createNewSessionJni(); + /** * Getter on the session ID. * @return native session ID @@ -73,28 +84,6 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { mNativeId = 0; } - /** - * 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()}. - * @exception OlmException the exception - */ - private void createNewSession() throws OlmException { - try { - mNativeId = createNewSessionJni(); - } catch (Exception e) { - throw new OlmException(OlmException.EXCEPTION_CODE_INIT_SESSION_CREATION, e.getMessage()); - } - } - - /** - * 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 #mNativeId}) - */ - private native long createNewSessionJni(); - /** * Return true the object resources have been released.
* @return true the object resources have been released @@ -125,6 +114,15 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } } + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
The recipient is defined as the entity + * with whom the session is established. + * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient + **/ private native void initOutboundSessionJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aTheirOneTimeKey); /** @@ -149,6 +147,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } } + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aOneTimeKeyMsg PRE_KEY message + */ private native void initInboundSessionJni(long aOlmAccountId, byte[] aOneTimeKeyMsg); /** @@ -176,6 +181,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { } } + /** + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message based on the recipient identity key.
+ * An exception is thrown if the operation fails. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aOneTimeKeyMsg encrypted message + */ private native void initInboundSessionFromIdKeyJni(long aOlmAccountId, byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); /** @@ -201,6 +214,11 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return null; } + /** + * Get the session identifier for this session. + * An exception is thrown if the operation fails. + * @return the session identifier + */ private native byte[] getSessionIdentifierJni(); /** @@ -208,13 +226,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * Public API for {@link #matchesInboundSessionJni(byte[])}. * @param aOneTimeKeyMsg PRE KEY message - * @return this if operation succeed, null otherwise + * @return true if the one time key matches. */ public boolean matchesInboundSession(String aOneTimeKeyMsg) { boolean retCode = false; try { - retCode = (0 == matchesInboundSessionJni(aOneTimeKeyMsg.getBytes("UTF-8"))); + retCode = matchesInboundSessionJni(aOneTimeKeyMsg.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG, "## matchesInboundSession(): failed " + e.getMessage()); } @@ -222,8 +240,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return retCode; } - private native int matchesInboundSessionJni(byte[] aOneTimeKeyMsg); - + /** + * Checks if the PRE_KEY message is for this in-bound session.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * An exception is thrown if the operation fails. + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches + */ + private native boolean matchesInboundSessionJni(byte[] aOneTimeKeyMsg); /** * Checks if the PRE_KEY({@link OlmMessage#MESSAGE_TYPE_PRE_KEY}) message is for this in-bound session based on the sender identity key.
@@ -237,7 +261,7 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { boolean retCode = false; try { - retCode = (0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey.getBytes("UTF-8"), aOneTimeKeyMsg.getBytes("UTF-8"))); + retCode = matchesInboundSessionFromIdKeyJni(aTheirIdentityKey.getBytes("UTF-8"), aOneTimeKeyMsg.getBytes("UTF-8")); } catch (Exception e) { Log.e(LOG_TAG, "## matchesInboundSessionFrom(): failed " + e.getMessage()); } @@ -245,8 +269,15 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return retCode; } - private native int matchesInboundSessionFromIdKeyJni(byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); - + /** + * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
+ * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). + * An exception is thrown if the operation fails. + * @param aTheirIdentityKey the identity key of the sender + * @param aOneTimeKeyMsg PRE KEY message + * @return true if the PRE_KEY message matches. + */ + private native boolean matchesInboundSessionFromIdKeyJni(byte[] aTheirIdentityKey, byte[] aOneTimeKeyMsg); /** * Encrypt a message using the session.
@@ -277,6 +308,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return encryptedMsgRetValue; } + /** + * Encrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aClearMsg clear text message + * @param aEncryptedMsg ciphered message + * @return the encrypted message + */ private native byte[] encryptMessageJni(byte[] aClearMsg, OlmMessage aEncryptedMsg); /** @@ -298,7 +336,12 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { throw new OlmException(OlmException.EXCEPTION_CODE_SESSION_DECRYPT_MESSAGE, e.getMessage()); } } - + /** + * Decrypt a message using the session.
+ * An exception is thrown if the operation fails. + * @param aEncryptedMsg message to decrypt + * @return the decrypted message + */ private native byte[] decryptMessageJni(OlmMessage aEncryptedMsg); //============================================================================================================== @@ -354,7 +397,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { return pickleRetValue; } - private native byte[] serializeJni(byte[] aKey); + + /** + * Serialize and encrypt session instance.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ + private native byte[] serializeJni(byte[] aKeyBuffer); /** * Loads an account from a pickled base64 string.
@@ -364,16 +414,14 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { */ @Override protected void deserialize(byte[] aSerializedData, byte[] aKey) throws Exception { - createNewSession(); - - String errorMsg; + String errorMsg = null; try { if ((null == aSerializedData) || (null == aKey)) { Log.e(LOG_TAG, "## deserialize(): invalid input parameters"); errorMsg = "invalid input parameters"; } else { - errorMsg = deserializeJni(aSerializedData, aKey); + mNativeId = deserializeJni(aSerializedData, aKey); } } catch (Exception e) { Log.e(LOG_TAG, "## deserialize() failed " + e.getMessage()); @@ -385,7 +433,13 @@ public class OlmSession extends CommonSerializeUtils implements Serializable { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_DESERIALIZATION, errorMsg); } } - - private native String deserializeJni(byte[] aSerializedData, byte[] aKey); + /** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ + private native long deserializeJni(byte[] aSerializedData, byte[] aKey); } diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index 32a5830..12f3663 100644 --- a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,12 @@ package org.matrix.olm; import android.text.TextUtils; import android.util.Log; +import org.json.JSONObject; + import java.security.SecureRandom; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; /** * Olm SDK helper class. @@ -108,7 +113,6 @@ public class OlmUtility { */ private native String verifyEd25519SignatureJni(byte[] aSignature, byte[] aFingerprintKey, byte[] aMessage); - /** * Compute the hash(SHA-256) value of the string given in parameter(aMessageToHash).
* The hash value is the returned by the method. @@ -129,9 +133,15 @@ public class OlmUtility { return hashRetValue; } + /** + * Compute the digest (SHA 256) for the message passed in parameter.
+ * The digest value is the function return value. + * An exception is thrown if the operation fails. + * @param aMessage the message + * @return digest of the message. + **/ private native byte[] sha256Jni(byte[] aMessage); - /** * Helper method to compute a string based on random integers. * @return bytes buffer containing randoms integer values @@ -156,5 +166,66 @@ public class OlmUtility { public boolean isReleased() { return (0 == mNativeId); } + + /** + * Build a string-string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + public static Map toStringMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap map = new HashMap<>(); + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof String) { + map.put(key, (String) value); + } else { + Log.e(LOG_TAG, "## toStringMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } + + /** + * Build a string-string dictionary of string dictionary from a jsonObject.
+ * @param jsonObject the object to parse + * @return the map + */ + public static Map> toStringMapMap(JSONObject jsonObject) { + if (null != jsonObject) { + HashMap> map = new HashMap<>(); + + Iterator keysItr = jsonObject.keys(); + while(keysItr.hasNext()) { + String key = keysItr.next(); + try { + Object value = jsonObject.get(key); + + if (value instanceof JSONObject) { + map.put(key, toStringMap((JSONObject) value)); + } else { + Log.e(LOG_TAG, "## toStringMapMap(): unexpected type " + value.getClass()); + } + } catch (Exception e) { + Log.e(LOG_TAG, "## toStringMapMap(): failed " + e.getMessage()); + } + } + + return map; + } + + return null; + } } 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 30828d9..6e62f50 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 @@ -20,9 +20,9 @@ using namespace AndroidOlmSdk; /** -* Init memory allocation for account creation. -* @return valid memory allocation, NULL otherwise -**/ + * Init memory allocation for account creation. + * @return valid memory allocation, NULL otherwise + **/ OlmAccount* initializeAccountMemory() { size_t accountSize = olm_account_size(); @@ -43,11 +43,11 @@ OlmAccount* initializeAccountMemory() } /** -* Create 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 independent. -* @return the initialized OlmAccount* instance -**/ + * Create 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 independent. + * @return the initialized OlmAccount* instance or throw an exception if fails + **/ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -98,6 +98,12 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject t if (errorMessage) { + // release the allocated data + if (accountPtr) + { + olm_clear_account(accountPtr); + free(accountPtr); + } env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } @@ -106,7 +112,6 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(createNewAccountJni)(JNIEnv *env, jobject t /** * Release the account allocation made by initializeAccountMemory().
* This method MUST be called when java counter part account instance is done. - * */ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz) { @@ -133,11 +138,12 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz // ********************************************************************* // ************************* IDENTITY KEYS API ************************* // ********************************************************************* + /** -* Get identity keys: Ed25519 fingerprint key and Curve25519 identity key.
-* The keys are returned in the byte array. -* @return a valid byte array if operation succeed, null otherwise -**/ + * Get identity keys: Ed25519 fingerprint key and Curve25519 identity key.
+ * The keys are returned in the byte array. + * @return the identity keys or throw an exception if it fails + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -204,10 +210,14 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(identityKeysJni)(JNIEnv *env, jobject // ********************************************************************* // ************************* ONE TIME KEYS API ************************* // ********************************************************************* + /** - * Get the maximum number of "one time keys" the account can store. - * -**/ + * 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 or throw an exception if it fails + */ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz) { OlmAccount* accountPtr = getAccountInstanceId(env, thiz); @@ -229,8 +239,9 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(maxOneTimeKeysJni)(JNIEnv *env, jobject thi /** * Generate "one time keys". + * An exception is thrown if the operation fails. * @param aNumberOfKeys number of keys to generate -**/ + **/ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys) { const char* errorMessage = NULL; @@ -289,7 +300,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject * Get "one time keys".
* Return the public parts of the unpublished "one time keys" for the account * @return a valid byte array if operation succeed, null otherwise -**/ + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -354,14 +365,12 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t /** * Remove the "one time keys" that the session used from the account. - * Return the public parts of the unpublished "one time keys" for the account + * An exception is thrown if the operation fails. * @param aNativeOlmSessionId session instance - * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise -**/ -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) + **/ +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId) { const char* errorMessage = NULL; - jint retCode = ERROR_CODE_KO; OlmAccount* accountPtr = NULL; OlmSession* sessionPtr = (OlmSession*)aNativeOlmSessionId; @@ -370,7 +379,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t LOGE("## removeOneTimeKeysJni(): failure - invalid session ptr"); errorMessage = "invalid session ptr"; } - else if(!(accountPtr = getAccountInstanceId(env, thiz))) + else if (!(accountPtr = getAccountInstanceId(env, thiz))) { LOGE("## removeOneTimeKeysJni(): failure - invalid account ptr"); errorMessage = "invalid account ptr"; @@ -381,12 +390,11 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t if (result == olm_error()) { // the account doesn't have any matching "one time keys".. - LOGW("## removeOneTimeKeysJni(): failure - removing one time keys Msg=%s",(const char *)olm_account_last_error(accountPtr)); + LOGW("## removeOneTimeKeysJni(): failure - removing one time keys Msg=%s", olm_account_last_error(accountPtr)); errorMessage = (const char *)olm_account_last_error(accountPtr); } else { - retCode = ERROR_CODE_OK; LOGD("## removeOneTimeKeysJni(): success"); } } @@ -395,13 +403,12 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject t { env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } - - return retCode; } /** * Mark the current set of "one time keys" as being published. -**/ + * An exception is thrown if the operation fails. + **/ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -438,7 +445,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, * The signed message is returned by the function. * @param aMessage message to sign * @return the signed message, null otherwise -**/ + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aMessage) { const char* errorMessage = NULL; @@ -510,10 +517,10 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t } /** -* Serialize and encrypt account instance into a base64 string.
-* @param aKeyBuffer key used to encrypt the serialized account data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt account instance.
+ * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -544,7 +551,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## serializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); - void *pickledPtr = malloc(pickledLength*sizeof(uint8_t)); + void* pickledPtr = malloc(pickledLength * sizeof(uint8_t)); if (!pickledPtr) { @@ -565,7 +572,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi } else { - LOGD(" ## serializeJni(): success - result=%lu pickled starts with = %10s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); pickledDataRetValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(pickledDataRetValue, 0 , pickledLength, (jbyte*)pickledPtr); } @@ -588,11 +595,18 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi return pickledDataRetValue; } - -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new account and initialise it with the serialisation data.
+ * @param aSerializedDataBuffer the account serialisation buffer + * @param aKeyBuffer the key used to encrypt the serialized account data + * @return the deserialised account + **/ +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { + const char* errorMessage = NULL; + OlmAccount* accountPtr = NULL; - jstring errorMessageRetValue = 0; + jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; @@ -601,22 +615,27 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { - LOGE(" ## deserializeJni(): failure - serialized data"); + LOGE(" ## deserializeJni(): failure - invalid serialized data"); + errorMessage = "invalid serialized data"; } - else if (!(accountPtr = getAccountInstanceId(env, thiz))) + else if (!(accountPtr = initializeAccountMemory())) { LOGE(" ## deserializeJni(): failure - account failure OOM"); + errorMessage = "account failure OOM"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { @@ -632,9 +651,8 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_account_last_error(accountPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_account_last_error(accountPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); } else { @@ -653,5 +671,15 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (accountPtr) + { + olm_clear_account(accountPtr); + free(accountPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)accountPtr; } \ No newline at end of file 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 2bfb39c..42b2c2a 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 @@ -1,6 +1,6 @@ /* - * Copyright 2016 OpenMarket Ltd - * Copyright 2016 Vector Creations Ltd + * Copyright 2017 OpenMarket Ltd + * Copyright 2017 Vector Creations Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -39,7 +39,7 @@ 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(maxOneTimeKeysJni)(JNIEnv *env, jobject thiz); JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeysJni)(JNIEnv *env, jobject thiz, jint aNumberOfKeys); -JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); +JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId); JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz); // signing @@ -47,7 +47,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject t // serialization JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer); -JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); +JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer); #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 index a2b1624..14e338b 100644 --- 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 @@ -22,7 +22,6 @@ using namespace AndroidOlmSdk; /** * 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) { @@ -51,103 +50,91 @@ JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env } /** -* 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(createNewSessionJni)(JNIEnv *env, jobject thiz) + * 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. + * @param aSessionKeyBuffer session key from an outbound session + * @return the initialized OlmInboundGroupSession* instance or throw an exception it fails. + **/ +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) { const char* errorMessage = NULL; OlmInboundGroupSession* sessionPtr = NULL; - size_t sessionSize = 0; + jbyte* sessionKeyPtr = NULL; + size_t sessionSize = olm_inbound_group_session_size(); LOGD("## createNewSessionJni(): inbound group session IN"); - sessionSize = olm_inbound_group_session_size(); if (!sessionSize) { LOGE(" ## createNewSessionJni(): failure - inbound group session size = 0"); errorMessage = "inbound group session size = 0"; } - else if ((sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) - { - sessionPtr = olm_inbound_group_session(sessionPtr); - LOGD(" ## createNewSessionJni(): success - inbound group session size=%lu",static_cast(sessionSize)); - } - else + else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) { LOGE(" ## createNewSessionJni(): failure - inbound group session OOM"); errorMessage = "inbound group session OOM"; } + else if (!aSessionKeyBuffer) + { + LOGE(" ## createNewSessionJni(): failure - invalid aSessionKey"); + errorMessage = "invalid aSessionKey"; + } + else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) + { + LOGE(" ## createNewSessionJni(): failure - session key JNI allocation OOM"); + errorMessage = "Session key JNI allocation OOM"; + } + else + { + sessionPtr = olm_inbound_group_session(sessionPtr); + + size_t sessionKeyLength = (size_t)env->GetArrayLength(aSessionKeyBuffer); + LOGD(" ## createNewSessionJni(): sessionKeyLength=%lu", static_cast(sessionKeyLength)); + + size_t sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); + + if (sessionResult == olm_error()) + { + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## createNewSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); + } + else + { + LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); + } + } + + if (sessionKeyPtr) + { + env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); + } if (errorMessage) { env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } + if (errorMessage) + { + // release the allocated session + if (sessionPtr) + { + olm_clear_inbound_group_session(sessionPtr); + free(sessionPtr); + } + + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + return (jlong)(intptr_t)sessionPtr; } /** - * Create a new in-bound session.
- * @param aSessionKey session key from an outbound session + * Get a base64-encoded identifier for this inbound group session. + * An exception is thrown if the operation fails. + * @return the base64-encoded identifier */ -JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer) -{ - const char* errorMessage = NULL; - OlmInboundGroupSession *sessionPtr = getInboundGroupSessionInstanceId(env, thiz); - jbyte* sessionKeyPtr = NULL; - size_t sessionResult; - - LOGD("## initInboundGroupSessionJni(): inbound group session IN"); - - if (!sessionPtr) - { - LOGE(" ## initInboundGroupSessionJni(): failure - invalid inbound group session instance"); - errorMessage = "invalid inbound group session instance"; - } - else if (!aSessionKeyBuffer) - { - LOGE(" ## initInboundGroupSessionJni(): failure - invalid aSessionKey"); - errorMessage = "invalid aSessionKey"; - } - else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) - { - LOGE(" ## initInboundGroupSessionJni(): failure - session key JNI allocation OOM"); - errorMessage = "Session key JNI allocation OOM"; - } - else - { - size_t sessionKeyLength = (size_t)env->GetArrayLength(aSessionKeyBuffer); - LOGD(" ## initInboundGroupSessionJni(): sessionKeyLength=%lu",static_cast(sessionKeyLength)); - - sessionResult = olm_init_inbound_group_session(sessionPtr, (const uint8_t*)sessionKeyPtr, sessionKeyLength); - if (sessionResult == olm_error()) { - errorMessage = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## initInboundGroupSessionJni(): failure - init inbound session creation Msg=%s", errorMessage); - } - else - { - LOGD(" ## initInboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); - } - } - - // free local alloc - if (sessionKeyPtr) - { - env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); - } - - if (errorMessage) - { - env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); - } -} - -/** -* Get a base64-encoded identifier for this inbound group session. -*/ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -185,7 +172,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN } else { - LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId starts with =%10s",static_cast(result), (char*)sessionIdPtr); + LOGD(" ## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); @@ -203,7 +190,13 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JN return returnValue; } - +/** + * Decrypt a message. + * An exception is thrown if the operation fails. + * @param aEncryptedMsg the encrypted message + * @param aDecryptMessageResult the decryptMessage information + * @return the decrypted message + */ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsgBuffer, jobject aDecryptionResult) { jbyteArray decryptedMsgBuffer = 0; @@ -335,10 +328,11 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEn /** -* Serialize and encrypt session instance into a base64 string.
-* @param aKeyBuffer key used to encrypt the serialized session data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt session instance into a base64 string.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized session data + * @return a base64 string if operation succeed, null otherwise + **/ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -391,7 +385,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en } else { - LOGD(" ## serializeJni(): success - result=%lu pickled starts with %10s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(pickledLength), static_cast(pickledPtr)); pickledDataRet = env->NewByteArray(pickledLength); env->SetByteArrayRegion(pickledDataRet, 0 , pickledLength, (jbyte*)pickledPtr); @@ -415,38 +409,58 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en return pickledDataRet; } - -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { - OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env, thiz); - jstring errorMessageRetValue = 0; + const char* errorMessage = NULL; + + OlmInboundGroupSession* sessionPtr = NULL; + size_t sessionSize = olm_inbound_group_session_size(); jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); - if (!sessionPtr) + if (!sessionSize) + { + LOGE(" ## deserializeJni(): failure - inbound group session size = 0"); + errorMessage = "inbound group session size = 0"; + } + else if (!(sessionPtr = (OlmInboundGroupSession*)malloc(sessionSize))) { LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; } else if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "serialized data"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { + sessionPtr = olm_inbound_group_session(sessionPtr); + size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); @@ -459,9 +473,8 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_inbound_group_session() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_inbound_group_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_inbound_group_session() Msg=%s", errorMessage); } else { @@ -480,5 +493,15 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_inbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; } 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 index a631acf..00990dd 100644 --- 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 @@ -30,16 +30,14 @@ extern "C" { // session creation/destruction JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); -JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aSessionKeyBuffer); JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aEncryptedMsg, jobject aDecryptIndex); // serialization JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); - +JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } 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 73a529d..e6a49e2 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 @@ -53,12 +53,7 @@ namespace AndroidOlmSdk { - // Error codes definition - static const int ERROR_CODE_OK = 0; - static const int ERROR_CODE_KO = -1; - // constants - static const int ACCOUNT_CREATION_RANDOM_MODULO = 256; } 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 index 7330a20..689f1b4 100644 --- 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 @@ -52,13 +52,15 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *en } /** -* 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 -**/ + * 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 or throw an exception + **/ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz) { + const char* errorMessage = NULL; + OlmOutboundGroupSession* sessionPtr = NULL; size_t sessionSize = 0; @@ -68,65 +70,45 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv if (0 == sessionSize) { LOGE(" ## createNewSessionJni(): failure - outbound group session size = 0"); + errorMessage = "outbound group session size = 0"; } - else if ((sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) + else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) + { + LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); + errorMessage = "outbound group session OOM"; + } + else { sessionPtr = olm_outbound_group_session(sessionPtr); LOGD(" ## createNewSessionJni(): success - outbound group session size=%lu",static_cast(sessionSize)); - } - else - { - LOGE(" ## createNewSessionJni(): failure - outbound group session OOM"); - } - return (jlong)(intptr_t)sessionPtr; -} - -/** - * Start a new outbound session.
- */ -JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz) -{ - const char* errorMessage = NULL; - - LOGD("## initOutboundGroupSessionJni(): IN"); - - OlmOutboundGroupSession *sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz); - - if (!sessionPtr) - { - LOGE(" ## initOutboundGroupSessionJni(): failure - invalid outbound group session instance"); - errorMessage = "invalid outbound group session instance"; - } - else - { // compute random buffer size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr); uint8_t *randomBuffPtr = NULL; - LOGW(" ## initOutboundGroupSessionJni(): randomLength=%lu",static_cast(randomLength)); + LOGW(" ## createNewSessionJni(): randomLength=%lu",static_cast(randomLength)); if ((0 != randomLength) && !setRandomInBuffer(env, &randomBuffPtr, randomLength)) { - LOGE(" ## initOutboundGroupSessionJni(): failure - random buffer init"); + LOGE(" ## createNewSessionJni(): failure - random buffer init"); errorMessage = "random buffer init"; } else { if (0 == randomLength) { - LOGW(" ## initOutboundGroupSessionJni(): random buffer is not required"); + LOGW(" ## createNewSessionJni(): random buffer is not required"); } size_t sessionResult = olm_init_outbound_group_session(sessionPtr, randomBuffPtr, randomLength); if (sessionResult == olm_error()) { errorMessage = (const char *)olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## initOutboundGroupSessionJni(): failure - init outbound session creation Msg=%s", errorMessage); + LOGE(" ## createNewSessionJni(): failure - init outbound session creation Msg=%s", errorMessage); } else { - LOGD(" ## initOutboundGroupSessionJni(): success - result=%lu", static_cast(sessionResult)); + LOGD(" ## createNewSessionJni(): success - result=%lu", static_cast(sessionResult)); } // clear the random buffer @@ -137,13 +119,23 @@ JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)( if (errorMessage) { + if (sessionPtr) + { + olm_clear_outbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } + + return (jlong)(intptr_t)sessionPtr; } /** -* Get a base64-encoded identifier for this outbound group session. -*/ + * Return the session identifier. + * An exception is thrown if the operation fails. + * @return the session identifier + */ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz) { LOGD("## sessionIdentifierJni(): outbound group session IN"); @@ -184,7 +176,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); - LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId starts with %10s",static_cast(result), reinterpret_cast(sessionIdPtr)); + LOGD(" ## sessionIdentifierJni(): success - outbound group session identifier result=%lu sessionId= %.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionIdPtr)); } // free alloc @@ -202,11 +194,12 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(J /** -* Get the current message index for this session.
-* Each message is sent with an increasing index, this -* method returns the index for the next message. -* @return current session index -*/ + * Get the current message index for this session.
+ * Each message is sent with an increasing index, this + * method returns the index for the next message. + * An exception is thrown if the operation fails. + * @return current session index + */ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz) { OlmOutboundGroupSession *sessionPtr = NULL; @@ -229,8 +222,10 @@ JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, } /** -* Get the base64-encoded current ratchet key for this session.
-*/ + * Return the session key. + * An exception is thrown if the operation fails. + * @return the session key + */ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz) { LOGD("## sessionKeyJni(): outbound group session IN"); @@ -268,7 +263,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * } else { - LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey starts with %10s",static_cast(result), reinterpret_cast(sessionKeyPtr)); + LOGD(" ## sessionKeyJni(): success - outbound group session key result=%lu sessionKey=%.*s",static_cast(result), static_cast(result), reinterpret_cast(sessionKeyPtr)); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionKeyPtr); @@ -287,6 +282,12 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv * return returnValue; } +/** + * Encrypt a bytes buffer messages. + * An exception is thrown if the operation fails. + * @param aClearMsgBuffer the message to encode + * @return the encoded message + */ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsgBuffer) { LOGD("## encryptMessageJni(): IN"); @@ -345,7 +346,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE } else { - LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%10s",static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); + LOGD(" ## encryptMessageJni(): encrypted returnedLg=%lu plainTextMsgPtr=%.*s",static_cast(encryptedLength), static_cast(encryptedLength), reinterpret_cast(encryptedMsgPtr)); encryptedMsgRet = env->NewByteArray(encryptedLength); env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedLength, (jbyte*)encryptedMsgPtr); @@ -369,12 +370,12 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE return encryptedMsgRet; } - /** -* Serialize and encrypt session instance into a base64 string.
-* @param aKey key used to encrypt the serialized session data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt session instance into a base64 string.
+ * An exception is thrown if the operation fails. + * @param aKey key used to encrypt the serialized session data + * @return a base64 string if operation succeed, null otherwise + **/ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -427,7 +428,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e } else { - LOGD(" ## serializeJni(): success - result=%lu pickled starts with %10s", static_cast(result), static_cast(pickledPtr)); + LOGD(" ## serializeJni(): success - result=%lu pickled=%.*s", static_cast(result), static_cast(result), static_cast(pickledPtr)); returnValue = env->NewByteArray(pickledLength); env->SetByteArrayRegion(returnValue, 0 , pickledLength, (jbyte*)pickledPtr); @@ -451,38 +452,57 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e return returnValue; } - -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { + const char* errorMessage = NULL; + size_t sessionSize = olm_outbound_group_session_size(); OlmOutboundGroupSession* sessionPtr = NULL; - jstring errorMessageRetValue = 0; + jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); - if (!(sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz))) + if (!sessionSize) + { + LOGE(" ## deserializeJni(): failure - outbound group session size = 0"); + errorMessage = "outbound group session size = 0"; + } + else if (!(sessionPtr = (OlmOutboundGroupSession*)malloc(sessionSize))) { LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; } else if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "invalid serialized data"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { + sessionPtr = olm_outbound_group_session(sessionPtr); size_t pickledLength = (size_t)env->GetArrayLength(aSerializedDataBuffer); size_t keyLength = (size_t)env->GetArrayLength(aKeyBuffer); LOGD(" ## deserializeJni(): pickledLength=%lu keyLength=%lu",static_cast(pickledLength), static_cast(keyLength)); @@ -495,9 +515,8 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *en pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_outbound_group_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_outbound_group_session() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_outbound_group_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_outbound_group_session() Msg=%s", errorMessage); } else { @@ -516,6 +535,16 @@ JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *en env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_outbound_group_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; } 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 index fb3bf87..f6abba2 100644 --- 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 @@ -32,7 +32,6 @@ extern "C" { JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *env, jobject thiz); -JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(messageIndexJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionKeyJni)(JNIEnv *env, jobject thiz); @@ -41,7 +40,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(encryptMessageJni)(JNIE // serialization JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); +JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } 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 d6ede41..034e0e8 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 @@ -83,13 +83,13 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz // ********************** OUTBOUND SESSION ***************************** // ********************************************************************* /** -* Create a new in-bound session for sending/receiving messages from an -* incoming PRE_KEY message.
The recipient is defined as the entity -* with whom the session is established. -* @param aOlmAccountId account instance -* @param aTheirIdentityKey the identity key of the recipient -* @param aTheirOneTimeKey the one time key of the recipient -**/ + * Create a new in-bound session for sending/receiving messages from an + * incoming PRE_KEY message.
The recipient is defined as the entity + * with whom the session is established. + * @param aOlmAccountId account instance + * @param aTheirIdentityKey the identity key of the recipient + * @param aTheirOneTimeKey the one time key of the recipient or an exception is thrown + **/ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aTheirOneTimeKeyBuffer) { OlmSession* sessionPtr = getSessionInstanceId(env, thiz); @@ -193,6 +193,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initOutboundSessionJni)(JNIEnv *env, jobject /** * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY message.
+ * An exception is thrown if the operation fails. * @param aOlmAccountId account instance * @param aOneTimeKeyMsg PRE_KEY message */ @@ -258,6 +259,7 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject /** * Create a new in-bound session for sending/receiving messages from an * incoming PRE_KEY message based on the recipient identity key.
+ * An exception is thrown if the operation fails. * @param aOlmAccountId account instance * @param aTheirIdentityKey the identity key of the recipient * @param aOneTimeKeyMsg encrypted message @@ -342,11 +344,11 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, * Checks if the PRE_KEY message is for this in-bound session.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aOneTimeKeyMsg PRE KEY message - * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + * @return true if the PRE_KEY message matches */ -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsgBuffer) { - jint retCode = ERROR_CODE_KO; + jboolean retCode = JNI_FALSE; OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *messagePtr = NULL; @@ -374,7 +376,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje } else { - retCode = ERROR_CODE_OK; + retCode = JNI_TRUE; LOGD("## matchesInboundSessionJni(): success - result=%lu", static_cast(matchResult)); } } @@ -388,17 +390,16 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobje return retCode; } - /** * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.
* This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY). * @param aTheirIdentityKey the identity key of the sender * @param aOneTimeKeyMsg PRE KEY message - * @return ERROR_CODE_OK if match, ERROR_CODE_KO otherwise + * @return true if the PRE_KEY message matches. */ -JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) +JNIEXPORT jboolean JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKeyBuffer, jbyteArray aOneTimeKeyMsgBuffer) { - jint retCode = ERROR_CODE_KO; + jboolean retCode = JNI_FALSE; OlmSession *sessionPtr = getSessionInstanceId(env, thiz); jbyte *messagePtr = NULL; jbyte *theirIdentityKeyPtr = NULL; @@ -437,7 +438,7 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J } else { - retCode = ERROR_CODE_OK; + retCode = JNI_TRUE; LOGD("## matchesInboundSessionFromIdKeyJni(): success - result=%lu", static_cast(matchResult)); } } @@ -456,9 +457,9 @@ JNIEXPORT jint JNICALL OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(J return retCode; } - /** * Encrypt a message using the session.
+ * An exception is thrown if the operation fails. * @param aClearMsg clear text message * @param [out] aEncryptedMsg ciphered message * @return the encrypted message @@ -564,7 +565,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec encryptedMsgRet = env->NewByteArray(encryptedMsgLength); env->SetByteArrayRegion(encryptedMsgRet, 0 , encryptedMsgLength, (jbyte*)encryptedMsgPtr); - LOGD("## encryptMessageJni(): success - result=%lu Type=%lu utfLength=%lu encryptedMsg starts with %10s", static_cast(result), static_cast(messageType), static_cast((size_t)env->GetStringUTFLength(encryptedJstring)), (const char*)encryptedMsgPtr); + LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%.*s", static_cast(result), static_cast(messageType), static_cast(result), (const char*)encryptedMsgPtr); } free(encryptedMsgPtr); @@ -590,6 +591,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobjec /** * Decrypt a message using the session.
+ * An exception is thrown if the operation fails. * @param aEncryptedMsg message to decrypt * @return decrypted message if operation succeed */ @@ -725,11 +727,11 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobjec return decryptedMsgRet; } - /** -* Get the session identifier for this session. -* @return the session identifier if operation succeed, null otherwise -*/ + * Get the session identifier for this session. + * An exception is thrown if the operation fails. + * @return the session identifier + */ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz) { const char* errorMessage = NULL; @@ -768,7 +770,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, } else { - LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId= starts with %10s",static_cast(result), (char*)sessionIdPtr); + LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%.*s",static_cast(result), static_cast(result), (char*)sessionIdPtr); returnValue = env->NewByteArray(result); env->SetByteArrayRegion(returnValue, 0 , result, (jbyte*)sessionIdPtr); @@ -786,12 +788,12 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, return returnValue; } - /** -* Serialize and encrypt session instance into a base64 string.
-* @param aKey key used to encrypt the serialized session data -* @return a base64 string if operation succeed, null otherwise -**/ + * Serialize and encrypt session instance.
+ * An exception is thrown if the operation fails. + * @param aKeyBuffer key used to encrypt the serialized account data + * @return the serialised account as bytes buffer. + **/ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKeyBuffer) { const char* errorMessage = NULL; @@ -868,10 +870,17 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi return returnValue; } -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) +/** + * Allocate a new session and initialize it with the serialisation data.
+ * An exception is thrown if the operation fails. + * @param aSerializedData the session serialisation buffer + * @param aKey the key used to encrypt the serialized account data + * @return the deserialized session + **/ +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedDataBuffer, jbyteArray aKeyBuffer) { - OlmSession* sessionPtr = getSessionInstanceId(env, thiz); - jstring errorMessageRetValue = 0; + const char* errorMessage = NULL; + OlmSession* sessionPtr = initializeSessionMemory(); jbyte* keyPtr = NULL; jbyte* pickledPtr = NULL; @@ -880,22 +889,27 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz if (!sessionPtr) { LOGE(" ## deserializeJni(): failure - session failure OOM"); + errorMessage = "session failure OOM"; } else if (!aKeyBuffer) { LOGE(" ## deserializeJni(): failure - invalid key"); + errorMessage = "invalid key"; } else if (!aSerializedDataBuffer) { LOGE(" ## deserializeJni(): failure - serialized data"); + errorMessage = "serialized data"; } else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); + errorMessage = "keyPtr JNI allocation OOM"; } else if (!(pickledPtr = env->GetByteArrayElements(aSerializedDataBuffer, 0))) { LOGE(" ## deserializeJni(): failure - pickledPtr JNI allocation OOM"); + errorMessage = "pickledPtr JNI allocation OOM"; } else { @@ -911,9 +925,8 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz pickledLength); if (result == olm_error()) { - const char *errorMsgPtr = olm_session_last_error(sessionPtr); - LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s",errorMsgPtr); - errorMessageRetValue = env->NewStringUTF(errorMsgPtr); + errorMessage = olm_session_last_error(sessionPtr); + LOGE(" ## deserializeJni(): failure - olm_unpickle_account() Msg=%s", errorMessage); } else { @@ -932,5 +945,15 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz env->ReleaseByteArrayElements(aSerializedDataBuffer, pickledPtr, JNI_ABORT); } - return errorMessageRetValue; + if (errorMessage) + { + if (sessionPtr) + { + olm_clear_session(sessionPtr); + free(sessionPtr); + } + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return (jlong)(intptr_t)sessionPtr; } \ 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 01cf96c..b8cdd2f 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 @@ -39,8 +39,8 @@ JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionJni)(JNIEnv *env, jobject JNIEXPORT void OLM_SESSION_FUNC_DEF(initInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // match inbound sessions: based on PRE KEY message -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); -JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionJni)(JNIEnv *env, jobject thiz, jbyteArray aOneTimeKeyMsg); +JNIEXPORT jboolean OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *env, jobject thiz, jbyteArray aTheirIdentityKey, jbyteArray aOneTimeKeyMsg); // encrypt/decrypt JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jbyteArray aClearMsg, jobject aEncryptedMsg); @@ -50,7 +50,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, // serialization JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thiz, jbyteArray aKey); -JNIEXPORT jstring OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); +JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, jbyteArray aSerializedData, jbyteArray aKey); #ifdef __cplusplus } 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 b26cfae..c4ac9fd 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 @@ -162,11 +162,12 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j } /** -* Compute the digest (SHA 256) for the message passed in parameter.
-* The digest value is the function return value. -* @param aMessage -* @return digest of the message if operation succeed, null otherwise -**/ + * Compute the digest (SHA 256) for the message passed in parameter.
+ * The digest value is the function return value. + * An exception is thrown if the operation fails. + * @param aMessage the message + * @return digest of the message. + **/ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, jbyteArray aMessageToHashBuffer) { jbyteArray sha256Ret = 0;