diff --git a/java/android/OlmLibSdk/olm-sdk/build.gradle b/java/android/OlmLibSdk/olm-sdk/build.gradle
index 96eaaf7..2f92151 100644
--- a/java/android/OlmLibSdk/olm-sdk/build.gradle
+++ b/java/android/OlmLibSdk/olm-sdk/build.gradle
@@ -24,9 +24,16 @@ android {
jni.srcDirs = []
}
- task ndkBuildNative(type: Exec, description: 'NDK building..') {
+ task ndkBuildNativeRelease(type: Exec, description: 'NDK building..') {
+ println 'ndkBuildNativeRelease starts..'
workingDir file('src/main')
- commandLine getNdkBuildCmd() //, '-B', 'NDK_DEBUG=1'
+ commandLine getNdkBuildCmd(), 'NDK_DEBUG=0'
+ }
+
+ task ndkBuildNativeDebug(type: Exec, description: 'NDK building..') {
+ println 'ndkBuildNativeDebug starts..'
+ workingDir file('src/main')
+ commandLine getNdkBuildCmd(), 'NDK_DEBUG=1'
}
task cleanNative(type: Exec, description: 'Clean NDK build') {
@@ -34,10 +41,21 @@ android {
commandLine getNdkBuildCmd(), 'clean'
}
- tasks.withType(JavaCompile) {
+ /*tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuildNative
+ }*/
+
+ tasks.withType(JavaCompile) {
+ compileTask -> if (compileTask.name.startsWith('compileDebugJava')) {
+ println 'test compile: Debug'
+ compileTask.dependsOn ndkBuildNativeDebug
+ } else if (compileTask.name.startsWith('compileReleaseJava')) {
+ println 'test compile: Release'
+ compileTask.dependsOn ndkBuildNativeRelease
+ }
}
+
clean.dependsOn cleanNative
}
diff --git a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
index 061c79d..f592aa4 100644
--- a/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
+++ b/java/android/OlmLibSdk/olm-sdk/src/androidTest/java/org/matrix/olm/OlmAccountTest.java
@@ -55,7 +55,6 @@ public class OlmAccountTest {
}
}
-
@After
public void tearDown() {
// TBD
@@ -63,30 +62,25 @@ public class OlmAccountTest {
@Test
public void test1CreateAccount() {
- Log.d(LOG_TAG,"## testInitNewAccount");
mOlmAccount = new OlmAccount();
assertNotNull(mOlmAccount);
}
@Test
public void test2InitNewAccount() {
- Log.d(LOG_TAG,"## testInitNewAccount");
assertTrue(mOlmAccount.initNewAccount());
mIsAccountCreated = true;
}
@Test
public void test3GetOlmAccountId() {
- Log.d(LOG_TAG,"## testGetOlmAccountId");
-
long olmNativeInstance = mOlmAccount.getOlmAccountId();
+ Log.d(LOG_TAG,"## testGetOlmAccountId olmNativeInstance="+olmNativeInstance);
assertTrue(0!=olmNativeInstance);
}
@Test
public void test4IdentityKeys() {
- Log.d(LOG_TAG,"## testIdentityKeys");
-
JSONObject identityKeysJson = mOlmAccount.identityKeys();
assertNotNull(identityKeysJson);
Log.d(LOG_TAG,"## testIdentityKeys Keys="+identityKeysJson);
@@ -115,8 +109,6 @@ public class OlmAccountTest {
//****************************************************
@Test
public void test5MaxOneTimeKeys() {
- Log.d(LOG_TAG,"## testMaxOneTimeKeys");
-
long maxOneTimeKeys = mOlmAccount.maxOneTimeKeys();
Log.d(LOG_TAG,"## testMaxOneTimeKeys(): maxOneTimeKeys="+maxOneTimeKeys);
@@ -125,14 +117,12 @@ public class OlmAccountTest {
@Test
public void test6GenerateOneTimeKeys() {
- Log.d(LOG_TAG,"## testGenerateOneTimeKeys");
int retValue = mOlmAccount.generateOneTimeKeys(GENERATION_ONE_TIME_KEYS_NUMBER);
assertTrue(0==retValue);
}
@Test
public void test7OneTimeKeysJsonFormat() {
- Log.d(LOG_TAG,"## test7OneTimeKeysJsonFormat");
int oneTimeKeysCount = 0;
JSONObject generatedKeysJsonObj;
JSONObject oneTimeKeysJson = mOlmAccount.oneTimeKeys();
@@ -169,8 +159,6 @@ public class OlmAccountTest {
@Test
public void test8MarkOneTimeKeysAsPublished() {
- Log.d(LOG_TAG,"## testMarkOneTimeKeysAsPublished");
-
int retCode = mOlmAccount.markOneTimeKeysAsPublished();
// if OK => retCode=0
assertTrue(0 == retCode);
@@ -178,8 +166,6 @@ public class OlmAccountTest {
@Test
public void test9SignMessage() {
- Log.d(LOG_TAG,"## testMarkOneTimeKeysAsPublished");
-
String clearMsg = "String to be signed by olm";
String signedMsg = mOlmAccount.signMessage(clearMsg);
assertNotNull(signedMsg);
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!.
+ * incoming PRE_KEY message based on the sender identity key.
* 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.
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.
@@ -194,129 +206,43 @@ public class OlmSession {
/**
- * Get the session identifier.
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
+ * 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).
+ * Public API for {@link #matchesInboundSessionJni(String)}.
+ * @param aTheirIdentityKey the sender identity key
+ * @param aOneTimeKeyMsg PRE KEY message
+ * @return this if operation succeed, null otherwise
*/
- public String sessionIdentifier() {
- return getSessionIdentifierJni();
+ public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) {
+ boolean retCode = false;
+
+ if(0 == matchesInboundSessionFromIdKeyJni(aTheirIdentityKey, aOneTimeKeyMsg)){
+ retCode = true;
+ }
+ return retCode;
}
- 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;
-*/
+ private native int matchesInboundSessionFromIdKeyJni(String aTheirIdentityKey, String aOneTimeKeyMsg);
/**
- * 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
+ * Encrypt a message using the session.
+ * Public API for {@link #encryptMessageJni(String, OlmMessage)}.
+ * @param aClearMsg message to encrypted
+ * @return the encrypted message if operation succeed, null otherwise
*/
- private native byte[] identityKeysJni();
+ public OlmMessage encryptMessage(String aClearMsg) {
+ OlmMessage encryptedMsgRetValue = new OlmMessage();
- /**
- * Return the identity keys in a JSON array.
- * 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 != encryptMessageJni(aClearMsg, encryptedMsgRetValue)){
+ encryptedMsgRetValue = null;
}
- return identityKeysJsonObj;
+ return encryptedMsgRetValue;
}
- /**
- * 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 encryptMessageJni(String aClearMsg, OlmMessage aEncryptedMsg);
- /**
- * 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.
- * @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.
- * 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.
- * These keys must be published on the server.
- * @return byte array containing the one time keys if operation succeed, null otherwise
- */
- private native byte[] oneTimeKeysJni();
-
- /**
- * Return the "one time keys" in a JSON array.
- * 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");
- }
-
- return identityKeysJsonObj;
- }
-
- /**
- * 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);
-
- /**
- * 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;iGetStringUTFChars(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.
* @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.
+ * 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