From 655c841cc3720d1bb9892d60a2d7ca136c90cfbd Mon Sep 17 00:00:00 2001 From: pedroGitt 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 --- java/android/OlmLibSdk/olm-sdk/build.gradle | 24 ++- .../java/org/matrix/olm/OlmAccountTest.java | 16 +- .../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 ++ 11 files changed, 353 insertions(+), 176 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') 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 - */ - 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).
- * 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.
+ * 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.
- * 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.
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 + * 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[] oneTimeKeysJni(); + public OlmMessage encryptMessage(String aClearMsg) { + OlmMessage encryptedMsgRetValue = new OlmMessage(); - /** - * 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"); + 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;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