From 655c841cc3720d1bb9892d60a2d7ca136c90cfbd Mon Sep 17 00:00:00 2001
From: pedroGitt <pedro.contreiras@amdocs.com>
Date: Thu, 6 Oct 2016 19:55:03 +0200
Subject: - Update Unit tests for OlmAccount  - new file olm_utility.cpp to
 have a stand alone function to initialize/alloc a random buffer  - new class
 OlmMessage  - complete OlmSession API with encryptMessage()  - comments
 review  - OlmAccount unit tests are green  - new gradle to compile the shared
 lib according to debug mode

---
 .../src/main/java/org/matrix/olm/OlmMessage.java   |  30 ++++
 .../src/main/java/org/matrix/olm/OlmSession.java   | 146 +++++------------
 .../OlmLibSdk/olm-sdk/src/main/jni/Android.mk      |   3 +-
 .../OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp |  56 +++----
 .../OlmLibSdk/olm-sdk/src/main/jni/olm_jni.h       |   2 +-
 .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.cpp | 174 ++++++++++++++++++---
 .../OlmLibSdk/olm-sdk/src/main/jni/olm_session.h   |   2 +
 .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp |  60 +++++++
 .../OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h   |  16 ++
 9 files changed, 331 insertions(+), 158 deletions(-)
 create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java
 create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
 create mode 100644 java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h

(limited to 'java/android/OlmLibSdk/olm-sdk/src/main')

diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java
new file mode 100644
index 0000000..047db97
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/java/org/matrix/olm/OlmMessage.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.matrix.olm;
+
+public class OlmMessage {
+    /** PRE KEY message type (used to establish new Olm session) **/
+    public final static int MESSAGE_TYPE_PRE_KEY = 0;
+    /** normal message type **/
+    public final static int MESSAGE_TYPE_MESSAGE = 1;
+
+    /** the encrypted message (ie. )**/
+    public String mCipherText;
+
+    /** defined by {@link #MESSAGE_TYPE_MESSAGE} or {@link #MESSAGE_TYPE_PRE_KEY}**/
+    public long mType;
+}
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 28324da..24a4215 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
@@ -146,12 +146,12 @@ public class OlmSession {
 
     /**
      * Create a new in-bound session for sending/receiving messages from an
-     * incoming PRE_KEY message based on the sender identity key TODO TBC!.<br>
+     * incoming PRE_KEY message based on the sender identity key.<br>
      * Public API for {@link #initInboundSessionFromIdKeyJni(long, String, String)}.
      * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY).
      * @param aAccount the account to associate with this session
      * @param aTheirIdentityKey the sender identity key
-     * @param aOneTimeKeyMsg PRE KEY message TODO TBC
+     * @param aOneTimeKeyMsg PRE KEY message
      * @return this if operation succeed, null otherwise
      */
     public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aOneTimeKeyMsg) {
@@ -173,6 +173,18 @@ public class OlmSession {
 
     private native int initInboundSessionFromIdKeyJni(long aOlmAccountId, String aTheirIdentityKey, String aOneTimeKeyMsg);
 
+    /**
+     * Get the session identifier.<br> Will be the same for both ends of the
+     * conversation. The session identifier is returned as a String object.
+     * Session Id sample: "session_id":"M4fOVwD6AABrkTKl"
+     * Public API for {@link #getSessionIdentifierJni()}.
+     * @return the session ID as a String if operation succeed, null otherwise
+     */
+    public String sessionIdentifier() {
+        return getSessionIdentifierJni();
+    }
+
+    private native String getSessionIdentifierJni();
 
     /**
      * Checks if the PRE_KEY message is for this in-bound session.<br>
@@ -194,129 +206,43 @@ public class OlmSession {
 
 
     /**
-     * Get the session identifier.<br> Will be the same for both ends of the
-     * conversation. The session identifier is returned as a String object.
-     * Session Id sample: "session_id":"M4fOVwD6AABrkTKl"
-     * Public API for {@link #getSessionIdentifierJni()}.
-     * @return the session ID as a String if operation succeed, null otherwise
-     */
-    public String sessionIdentifier() {
-        return getSessionIdentifierJni();
-    }
-
-    private native String getSessionIdentifierJni();
-
-/*
-- (BOOL) matchesInboundSession:(NSString*)oneTimeKeyMessage;
-- (BOOL) matchesInboundSessionFrom:(NSString*)theirIdentityKey oneTimeKeyMessage:(NSString *)oneTimeKeyMessage;
-
-// UTF-8 plaintext -> base64 ciphertext
-- (OLMMessage*) encryptMessage:(NSString*)message;
-
-// base64 ciphertext -> UTF-8 plaintext
-- (NSString*) decryptMessage:(OLMMessage*)message;
-*/
-
-
-    /**
-     * Get the public identity keys (Ed25519 fingerprint key and Curve25519 identity key).<br>
-     * Keys are Base64 encoded.
-     * These keys must be published on the server.
-     * @return byte array containing the identity keys if operation succeed, null otherwise
+     * Checks if the PRE_KEY message is for this in-bound session based on the sender identity key.<br>
+     * This API may be used to process a "m.room.encrypted" event when type = 1 (PRE_KEY).
+     * Public API for {@link #matchesInboundSessionJni(String)}.
+     * @param aTheirIdentityKey the sender identity key
+     * @param aOneTimeKeyMsg PRE KEY message
+     * @return this if operation succeed, null otherwise
      */
-    private native byte[] identityKeysJni();
+    public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) {
+        boolean retCode = false;
 
-    /**
-     * Return the identity keys in a JSON array.<br>
-     * Public API for {@link #identityKeysJni()}.
-     * @return identity keys in JSON array format if operation succeed, null otherwise
-     */
-    public JSONObject identityKeys() {
-        JSONObject identityKeysJsonObj = null;
-        byte identityKeysBuffer[];
-
-        if( null != (identityKeysBuffer = identityKeysJni())) {
-            try {
-                identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer));
-                Log.d(LOG_TAG, "## identityKeys(): Identity Json keys=" + identityKeysJsonObj.toString());
-            } catch (JSONException e) {
-                identityKeysJsonObj = null;
-                Log.e(LOG_TAG, "## identityKeys(): Exception - Msg=" + e.getMessage());
-            }
-        } else {
-            Log.e(LOG_TAG, "## identityKeys(): Failure - identityKeysJni()=null");
+        if(0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey, aOneTimeKeyMsg)){
+            retCode = true;
         }
-
-        return identityKeysJsonObj;
+        return retCode;
     }
 
-    /**
-     * Return the largest number of "one time keys" this account can store.
-     * @return the max number of "one time keys", -1 otherwise
-     */
-    public native long maxOneTimeKeys();
+    private native int matchesInboundSessionFromIdKeyJni(String aTheirIdentityKey, String aOneTimeKeyMsg);
 
-    /**
-     * Generate a number of new one time keys.<br> If total number of keys stored
-     * by this account exceeds {@link #maxOneTimeKeys()}, the old keys are discarded.
-     * @param aNumberOfKeys number of keys to generate
-     * @return 0 if operation succeed, -1 otherwise
-     */
-    public native int generateOneTimeKeys(int aNumberOfKeys);
 
     /**
-     * Get the public parts of the unpublished "one time keys" for the account.<br>
-     * The returned data is a JSON-formatted object with the single property
-     * <tt>curve25519</tt>, which is itself an object mapping key id to
-     * base64-encoded Curve25519 key.
-     * These keys must be published on the server.
-     * @return byte array containing the one time keys if operation succeed, null otherwise
+     * Encrypt a message using the session.<br>
+     * Public API for {@link #encryptMessageJni(String, OlmMessage)}.
+     * @param aClearMsg message to encrypted
+     * @return the encrypted message if operation succeed, null otherwise
      */
-    private native byte[] oneTimeKeysJni();
+    public OlmMessage encryptMessage(String aClearMsg) {
+        OlmMessage encryptedMsgRetValue = new OlmMessage();
 
-    /**
-     * Return the "one time keys" in a JSON array.<br>
-     * Public API for {@link #oneTimeKeysJni()}.
-     * @return one time keys in JSON array format if operation succeed, null otherwise
-     */
-    public JSONObject oneTimeKeys() {
-        byte identityKeysBuffer[];
-        JSONObject identityKeysJsonObj = null;
-
-        if( null != (identityKeysBuffer = oneTimeKeysJni())) {
-            try {
-                identityKeysJsonObj = new JSONObject(new String(identityKeysBuffer));
-                Log.d(LOG_TAG, "## oneTimeKeys(): Identity Json keys=" + identityKeysJsonObj.toString());
-            } catch (JSONException e) {
-                identityKeysJsonObj = null;
-                Log.e(LOG_TAG, "## oneTimeKeys(): Exception - Msg=" + e.getMessage());
-            }
-        } else {
-            Log.e(LOG_TAG, "## oneTimeKeys(): Failure - identityKeysJni()=null");
+        if(0 != encryptMessageJni(aClearMsg, encryptedMsgRetValue)){
+            encryptedMsgRetValue = null;
         }
 
-        return identityKeysJsonObj;
+        return encryptedMsgRetValue;
     }
 
-    /**
-     * Remove the "one time keys" that the session used from the account.
-     * @param aNativeOlmSessionId native session instance identifier
-     * @return 0 if operation succeed, 1 if no matching keys in the sessions to be removed, -1 if operation failed
-     */
-    public native int removeOneTimeKeysForSession(long aNativeOlmSessionId);
+    private native int encryptMessageJni(String aClearMsg, OlmMessage aEncryptedMsg);
 
-    /**
-     * Marks the current set of "one time keys" as being published.
-     * @return 0 if operation succeed, -1 otherwise
-     */
-    public native int markOneTimeKeysAsPublished();
-
-    /**
-     * Sign a message with the ed25519 fingerprint key for this account.
-     * @param aMessage message to sign
-     * @return the signed message if operation succeed, null otherwise
-     */
-    public native String signMessage(String aMessage);
 
     @Override
     public String toString() {
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
index d59f916..26a6a90 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/Android.mk
@@ -44,7 +44,8 @@ $(SRC_ROOT_DIR)/lib/crypto-algorithms/sha256.c \
 $(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \
 $(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \
 olm_account.cpp \
-olm_session.cpp
+olm_session.cpp \
+olm_utility.cpp
 
 LOCAL_LDLIBS := -llog
 
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_account.cpp
index d8ee409..51c0ca8 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
@@ -15,7 +15,7 @@
  */
 
 #include "olm_account.h"
-
+#include "olm_utility.h"
 
 /**
 * Init memory allocation for account creation.
@@ -70,10 +70,10 @@ JNIEXPORT void JNICALL Java_org_matrix_olm_OlmAccount_releaseAccountJni(JNIEnv *
 **/
 JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv *env, jobject thiz)
 {
-    OlmAccount* accountPtr = NULL;
+    OlmAccount *accountPtr = NULL;
+    uint8_t *randomBuffPtr = NULL;
     size_t accountRetCode;
-    uint8_t* randomBuffPtr = NULL;
-    int randomSize;
+    size_t randomSize;
 
     // init account memory allocation
     if(NULL == (accountPtr = initializeAccountMemory()))
@@ -84,36 +84,34 @@ JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_initNewAccountJni(JNIEnv
     {
         // allocate random buffer
         randomSize = olm_create_account_random_length(accountPtr);
-        if(NULL == (randomBuffPtr = (std::uint8_t*)malloc(randomSize*sizeof(std::uint8_t))))
+        if(false == setRandomInBuffer(&randomBuffPtr, randomSize))
         {
-            LOGE("## initNewAccount(): failure - random buffer OOM");
+            LOGE("## initNewAccount(): failure - random buffer init");
         }
         else
-        {    // create random buffer
-            LOGD("## initNewAccount(): randomSize=%d",randomSize);
-
-            srand(time(NULL)); // init seed
-            for(int i=0;i<randomSize;i++)
-            {
-                randomBuffPtr[i] = (std::uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO);;
-            }
-
+        {
             // create account
-            accountRetCode = olm_create_account(accountPtr, randomBuffPtr, randomSize);
+            accountRetCode = olm_create_account(accountPtr, (void*)randomBuffPtr, randomSize);
             if(accountRetCode == olm_error()) {
                 const char *errorMsgPtr = olm_account_last_error(accountPtr);
                 LOGE("## initNewAccount(): failure - account creation failed Msg=%s", errorMsgPtr);
              }
 
-            free(randomBuffPtr);
             LOGD("## initNewAccount(): success - OLM account created");
             LOGD("## initNewAccount(): success - accountPtr=%p (jlong)(intptr_t)accountPtr=%lld",accountPtr,(jlong)(intptr_t)accountPtr);
         }
     }
 
+    if(NULL != randomBuffPtr)
+    {
+        free(randomBuffPtr);
+    }
+
     return (jlong)(intptr_t)accountPtr;
 }
 
+
+
 // *********************************************************************
 // ************************* IDENTITY KEYS API *************************
 // *********************************************************************
@@ -202,10 +200,10 @@ JNIEXPORT jlong JNICALL Java_org_matrix_olm_OlmAccount_maxOneTimeKeys(JNIEnv *en
 **/
 JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv *env, jobject thiz, jint aNumberOfKeys)
 {
-    OlmAccount* accountPtr = NULL;;
+    OlmAccount *accountPtr = NULL;
+    uint8_t *randomBufferPtr = NULL;
     jint retCode = ERROR_CODE_KO;
-    size_t length;
-    void* keysBytesPtr; // TODO check type: or uint8_t?
+    size_t randomLength;
     size_t result;
 
     LOGD("## generateOneTimeKeys(): accountPtr =%p aNumberOfKeys=%d",accountPtr, aNumberOfKeys);
@@ -216,15 +214,16 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv
     }
     else
     {   // keys memory allocation
-        length = olm_account_generate_one_time_keys_random_length(accountPtr, aNumberOfKeys);
-        LOGD("## generateOneTimeKeys(): randomLength=%ld", length);
-        if(NULL == (keysBytesPtr=(void*)malloc(length*sizeof(void*))))
+        randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, aNumberOfKeys);
+        LOGD("## generateOneTimeKeys(): randomLength=%ld", randomLength);
+
+        if(false == setRandomInBuffer(&randomBufferPtr, randomLength))
         {
-            LOGE("## generateOneTimeKeys(): failure - random allocation OOM");
+            LOGE("## generateOneTimeKeys(): failure - random buffer init");
         }
         else
         {   // retrieve key pairs in keysBytesPtr
-            result = olm_account_generate_one_time_keys(accountPtr, aNumberOfKeys, keysBytesPtr, length);
+            result = olm_account_generate_one_time_keys(accountPtr, aNumberOfKeys, (void*)randomBufferPtr, randomLength);
             if(result == olm_error()) {
                 const char *errorMsgPtr = olm_account_last_error(accountPtr);
                 LOGE("## generateOneTimeKeys(): failure - error generating one time keys Msg=%s",errorMsgPtr);
@@ -234,11 +233,14 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmAccount_generateOneTimeKeys(JNIEnv
                 retCode = ERROR_CODE_OK;
                 LOGD("## generateOneTimeKeys(): success - result=%ld", result);
             }
-
-            free(keysBytesPtr);
         }
     }
 
+    if(NULL != randomBufferPtr)
+    {
+        free(randomBufferPtr);
+    }
+
     return retCode;
 }
 
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 a504333..1e85cc1 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
@@ -34,7 +34,7 @@ static const int ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS = ERROR_CODE_OK+1;
 static const int ERROR_CODE_KO = -1;
 
 // constants
-static const int ACCOUNT_CREATION_RANDOM_MODULO = 500;
+static const int ACCOUNT_CREATION_RANDOM_MODULO = 256;
 
 
 typedef struct _AccountContext
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 22544d4..93b0658 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
@@ -15,6 +15,7 @@
  */
 
 #include "olm_session.h"
+#include "olm_utility.h"
 
 
 /**
@@ -95,7 +96,9 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI
     jint retCode = ERROR_CODE_KO;
     OlmSession* sessionPtr = NULL;
     OlmAccount* accountPtr = NULL;
-    void *randomBuffPtr;
+    const char* theirIdentityKeyPtr = NULL;
+    const char* theirOneTimeKeyPtr = NULL;
+    uint8_t *randomBuffPtr = NULL;
     size_t sessionResult;
 
     if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
@@ -113,15 +116,12 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI
     else
     {   // allocate random buffer
         size_t randomSize = olm_create_outbound_session_random_length(sessionPtr);
-        if(NULL == (randomBuffPtr = (void*)malloc(randomSize*sizeof(void*))))
+        if(false == setRandomInBuffer(&randomBuffPtr, randomSize))
         {
-            LOGE("## initOutboundSessionJni(): failure - random buffer OOM");
+            LOGE("## initOutboundSessionJni(): failure - random buffer init");
         }
         else
         {   // convert identity & one time keys to C strings
-            const char* theirIdentityKeyPtr = NULL;
-            const char* theirOneTimeKeyPtr = NULL;
-
             if(NULL == (theirIdentityKeyPtr = env->GetStringUTFChars(aTheirIdentityKey, 0)))
             {
                 LOGE("## initOutboundSessionJni(): failure - identityKey JNI allocation OOM");
@@ -136,7 +136,14 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI
                 int theirOneTimeKeyLength  = env->GetStringUTFLength(aTheirOneTimeKey);
                 LOGD("## initOutboundSessionJni(): identityKey=%s oneTimeKey=%s",theirIdentityKeyPtr,theirOneTimeKeyPtr);
 
-                sessionResult = olm_create_outbound_session(sessionPtr, accountPtr, theirIdentityKeyPtr, theirIdentityKeyLength, theirOneTimeKeyPtr, theirOneTimeKeyLength, randomBuffPtr, randomSize);
+                sessionResult = olm_create_outbound_session(sessionPtr,
+                                                            accountPtr,
+                                                            theirIdentityKeyPtr,
+                                                            theirIdentityKeyLength,
+                                                            theirOneTimeKeyPtr,
+                                                            theirOneTimeKeyLength,
+                                                            (void*)randomBuffPtr,
+                                                            randomSize);
                 if(sessionResult == olm_error()) {
                     const char *errorMsgPtr = olm_session_last_error(sessionPtr);
                     LOGE("## initOutboundSessionJni(): failure - session creation  Msg=%s",errorMsgPtr);
@@ -147,20 +154,25 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI
                     LOGD("## initOutboundSessionJni(): success - result=%ld", sessionResult);
                 }
             }
-
-            // free local alloc
-            free(randomBuffPtr);
-            if(NULL!= theirIdentityKeyPtr)
-            {
-                env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr);
-            }
-            if(NULL!= theirOneTimeKeyPtr)
-            {
-                env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr);
-            }
         }
     }
 
+     // **** free mem alloc ***
+     if(NULL!= randomBuffPtr)
+     {
+         free(randomBuffPtr);
+     }
+
+     if(NULL!= theirIdentityKeyPtr)
+     {
+         env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr);
+     }
+
+     if(NULL!= theirOneTimeKeyPtr)
+     {
+         env->ReleaseStringUTFChars(aTheirOneTimeKey, theirOneTimeKeyPtr);
+     }
+
     return retCode;
 }
 
@@ -172,7 +184,7 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initOutboundSessionJni(JNI
  * Create a new in-bound session for sending/receiving messages from an
  * incoming PRE_KEY message.<br>
  * @param aOlmAccountId account instance
- * @param aOneTimeKeyMsg PRE_KEY message TODO TBC
+ * @param aOneTimeKeyMsg PRE_KEY message
  * @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
  */
 JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionJni(JNIEnv *env, jobject thiz, jlong aOlmAccountId, jstring aOneTimeKeyMsg)
@@ -337,6 +349,12 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(J
         }
     }
 
+    // free local alloc
+    if(NULL!= messagePtr)
+    {
+     env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr);
+    }
+
     return retCode;
 }
 
@@ -392,10 +410,128 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromI
         }
     }
 
+    // free local alloc
+    if(NULL!= theirIdentityKeyPtr)
+    {
+     env->ReleaseStringUTFChars(aTheirIdentityKey, theirIdentityKeyPtr);
+    }
+
+    if(NULL!= messagePtr)
+    {
+     env->ReleaseStringUTFChars(aOneTimeKeyMsg, messagePtr);
+    }
+
     return retCode;
 }
 
 
+/**
+ * Encrypt a message using the session. to a base64 ciphertext.<br>
+ * 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
+ */
+JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg)
+{
+    jint retCode = ERROR_CODE_KO;
+    OlmSession *sessionPtr = NULL;
+    const char *clearMsgPtr = NULL;
+    uint8_t *randomBuffPtr = NULL;
+    void *encryptedMsgPtr = NULL;
+    jclass encryptedMsgJClass;
+    jfieldID encryptedMsgFieldId;
+    jfieldID typeMsgFieldId;
+
+
+    if(NULL == (sessionPtr = (OlmSession*)getSessionInstanceId(env,thiz)))
+    {
+        LOGE("## encryptMessageJni(): failure - invalid Session ptr=NULL");
+    }
+    else if(0 == aClearMsg)
+    {
+        LOGE("## encryptMessageJni(): failure - invalid clear message");
+    }
+    else if(0 == aEncryptedMsg)
+    {
+        LOGE("## encryptMessageJni(): failure - invalid clear message");
+    }
+    else if(NULL == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0)))
+    {
+        LOGE("## encryptMessageJni(): failure - clear message JNI allocation OOM");
+    }
+    else if(0 == (encryptedMsgJClass = env->GetObjectClass(aEncryptedMsg)))
+    {
+        LOGE("## encryptMessageJni(): failure - unable to get crypted message class");
+    }
+    else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mCipherText","Ljava/lang/String;")))
+    {
+        LOGE("## encryptMessageJni(): failure - unable to get message field");
+    }
+    else if(0 == (typeMsgFieldId = env->GetFieldID(encryptedMsgJClass,"mType","I")))
+    {
+        LOGE("## encryptMessageJni(): failure - unable to get message type field");
+    }
+    else
+    {
+        // compute random buffer
+        size_t randomLength = olm_encrypt_random_length(sessionPtr);
+        if(false == setRandomInBuffer(&randomBuffPtr, randomLength))
+        {
+            LOGE("## encryptMessageJni(): failure - random buffer init");
+        }
+        else
+        {
+            // alloc buffer for encrypted message
+            size_t clearMsgLength = env->GetStringUTFLength(aClearMsg);
+            size_t encryptedMsgLength = olm_encrypt_message_length(sessionPtr, clearMsgLength);
+            if(NULL == (encryptedMsgPtr = (void*)malloc(encryptedMsgLength*sizeof(void*))))
+            {
+                LOGE("## encryptMessageJni(): failure - random buffer OOM");
+            }
+
+            size_t result = olm_encrypt(sessionPtr,
+                                        (void const *)clearMsgPtr,
+                                        clearMsgLength,
+                                        randomBuffPtr,
+                                        randomLength,
+                                        encryptedMsgPtr,
+                                        encryptedMsgLength);
+            if(result == olm_error())
+            {
+                const char *errorMsgPtr = olm_session_last_error(sessionPtr);
+                LOGE("## encryptMessageJni(): failure - Msg=%s",errorMsgPtr);
+            }
+            else
+            {
+                // update type: PRE KEY message or normal message
+                size_t messageType = olm_encrypt_message_type(sessionPtr);
+                env->SetLongField(aEncryptedMsg, typeMsgFieldId, (jlong)messageType);
+
+                // update message
+                jstring encryptedStr = env->NewStringUTF((const char*)encryptedMsgPtr);
+                env->SetObjectField(aEncryptedMsg, encryptedMsgFieldId, (jobject)encryptedStr);
+
+                retCode = ERROR_CODE_OK;
+                LOGD("## encryptMessageJni(): success - result=%lu Type=%lu encryptedMsg=%s", result, messageType, (const char*)encryptedMsgPtr);
+            }
+        }
+    }
+
+    // free alloc
+    if(NULL != clearMsgPtr)
+    {
+     env->ReleaseStringUTFChars(aClearMsg, clearMsgPtr);
+    }
+
+    if(NULL != randomBuffPtr)
+    {
+        free(randomBuffPtr);
+    }
+
+    return retCode;
+}
+
 /**
 * Get the session identifier for this session.
 * @return the session identifier if operation succeed, null otherwise
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 edd1012..8e162b0 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
@@ -24,6 +24,8 @@ JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_initInboundSessionFromIdKe
 JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionJni(JNIEnv *env, jobject thiz, jstring aOneTimeKeyMsg);
 JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_matchesInboundSessionFromIdKeyJni(JNIEnv *env, jobject thiz, jstring aTheirIdentityKey, jstring aOneTimeKeyMsg);
 
+JNIEXPORT jint JNICALL Java_org_matrix_olm_OlmSession_encryptMessageJni(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg);
+
 JNIEXPORT jstring JNICALL Java_org_matrix_olm_OlmSession_getSessionIdentifierJni(JNIEnv *env, jobject thiz);
 
 
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
new file mode 100644
index 0000000..9abd228
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.cpp
@@ -0,0 +1,60 @@
+/**
+ * Created by pedrocon on 06/10/2016.
+ */
+/*
+ * Copyright 2016 OpenMarket Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "olm_jni.h"
+#include "olm_utility.h"
+
+/**
+* Init a buffer with a given number of random values.
+* @param aBuffer2Ptr the buffer to be initialized
+* @param aRandomSize the number of random values to apply
+* @return true if operation succeed, false otherwise
+**/
+bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize)
+{
+    bool retCode = false;
+    if(NULL == aBuffer2Ptr)
+    {
+        LOGD("## setRandomInBuffer(): failure - aBuffer=NULL");
+    }
+    else if(0 == aRandomSize)
+    {
+        LOGD("## setRandomInBuffer(): failure - random size=0");
+    }
+    else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t))))
+    {
+        LOGD("## setRandomInBuffer(): failure - alloc mem OOM");
+    }
+    else
+    {
+        LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize);
+
+        srand(time(NULL)); // init seed
+        for(size_t i=0;i<aRandomSize;i++)
+        {
+            (*aBuffer2Ptr)[i] = (uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO);
+
+            // TODO debug purpose - remove asap
+            LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]);
+        }
+
+        retCode = true;
+    }
+    return retCode;
+}
\ No newline at end of file
diff --git a/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
new file mode 100644
index 0000000..bf29eed
--- /dev/null
+++ b/java/android/OlmLibSdk/olm-sdk/src/main/jni/olm_utility.h
@@ -0,0 +1,16 @@
+#ifndef _OMLUTILITY_H
+#define _OMLUTILITY_H
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
-- 
cgit v1.2.3-70-g09d2