Temp commit.. adding group session API in progress

This commit is contained in:
pedroGitt 2016-10-13 19:21:01 +02:00
parent 147df845d0
commit 57ec6fff88
19 changed files with 1182 additions and 69 deletions

View file

@ -152,9 +152,8 @@ public class OlmAccountTest {
long sessionId = olmSession.getOlmSessionId();
assertTrue(0 != sessionId);
int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(sessionId);
// no one time key has been use in the session, so removeOneTimeKeysForSession() returns an error
assertTrue(0 != sessionRetCode);
int sessionRetCode = mOlmAccount.removeOneTimeKeysForSession(olmSession);
assertTrue(0 == sessionRetCode);
olmSession.releaseSession();
sessionId = olmSession.getOlmSessionId();

View file

@ -0,0 +1,95 @@
package org.matrix.olm;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import org.junit.BeforeClass;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.MethodSorters;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
@RunWith(AndroidJUnit4.class)
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class OlmGroupTest {
private static final String LOG_TAG = "OlmSessionTest";
private static OlmManager mOlmManager;
@BeforeClass
public static void setUpClass(){
// load native lib
mOlmManager = new OlmManager();
String version = mOlmManager.getOlmLibVersion();
assertNotNull(version);
Log.d(LOG_TAG, "## setUpClass(): lib version="+version);
}
@Test
public void test00AliceToBob() {
// TBD
}
/**
* Basic test:
* - alice creates an account
* - bob creates an account
* - alice creates an outbound group session
* - bob creates an inbound group session with alice's outbound session key
* - alice encrypts a message with its session
* - bob decrypts the encrypted message with its session
*/
//@Test
public void test01AliceToBob() {
// creates alice outbound session
OlmOutboundGroupSession aliceOutboundSession = new OlmOutboundGroupSession();
// test accounts creation
String aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier();
assertNotNull(aliceSessionIdentifier);
assertTrue(aliceSessionIdentifier.length()>0);
String aliceOutboundSessionKey = aliceOutboundSession.sessionKey();
assertNotNull(aliceOutboundSessionKey);
assertTrue(aliceOutboundSessionKey.length()>0);
long messageIndex = aliceOutboundSession.messageIndex();
assertTrue(0==messageIndex);
String clearMessage = "Hello!";
String encryptedMessage = aliceOutboundSession.encryptMessage(clearMessage);
assertNotNull(encryptedMessage);
messageIndex = aliceOutboundSession.messageIndex();
assertTrue(1==messageIndex);
assertTrue(encryptedMessage.length()>=0);
OlmInboundGroupSession bobInboundSession = new OlmInboundGroupSession();
bobInboundSession.initInboundGroupSessionWithSessionKey(aliceOutboundSessionKey);
// check session identifiers are equals
aliceSessionIdentifier = aliceOutboundSession.sessionIdentifier();
String bobSessionIdentifier = aliceOutboundSession.sessionIdentifier();
assertTrue(aliceSessionIdentifier.equals(bobSessionIdentifier ));
String decryptedMessage = bobInboundSession.decryptMessage(encryptedMessage);
assertTrue(decryptedMessage.equals(bobSessionIdentifier ));
}
//@Test
public void test02InboundGroupSession() {
// creates alice outbound session
OlmInboundGroupSession aliceInboundSession = new OlmInboundGroupSession();
// test session identifier
String sessionIdentifier = aliceInboundSession.sessionIdentifier();
assertNotNull(sessionIdentifier);
assertTrue(sessionIdentifier.length()>0);
}
}

View file

@ -105,7 +105,7 @@ public class OlmSessionTest {
assertTrue(clearMsg.equals(decryptedMsg));
// clean objects..
assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId()));
assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
// release accounts
bobAccount.releaseAccount();
aliceAccount.releaseAccount();
@ -191,7 +191,7 @@ public class OlmSessionTest {
// MESSAGE COMPARISON: decrypted vs encrypted
assertTrue(helloClearMsg.equals(decryptedMsg01));
assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession.getOlmSessionId()));
assertTrue(0==bobAccount.removeOneTimeKeysForSession(bobSession));
// BACK/FORTH MESSAGE COMPARISON
String clearMsg1 = "Hello I'm Bob!";

View file

@ -21,7 +21,9 @@ import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
public class OlmAccount {
import java.io.Serializable;
public class OlmAccount implements Serializable {
private static final String LOG_TAG = "OlmAccount";
// JSON keys used in the JSON objects returned by JNI
@ -67,7 +69,6 @@ public class OlmAccount {
/**
* Create the corresponding OLM account in native side.<br>
* The return value is a long casted C ptr on the OlmAccount.
* Do not forget to call {@link #releaseAccount()} when JAVA side is done.
* @return native account instance identifier (see {@link #mNativeOlmAccountId})
*/
@ -87,14 +88,6 @@ public class OlmAccount {
return retCode;
}
/**
* 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
*/
private native byte[] identityKeysJni();
/**
* Return the identity keys (identity & fingerprint keys) in a JSON array.<br>
* Public API for {@link #identityKeysJni()}.<br>
@ -123,6 +116,13 @@ public class OlmAccount {
return identityKeysJsonObj;
}
/**
* 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
*/
private native byte[] identityKeysJni();
/**
* Return the largest number of "one time keys" this account can store.
@ -139,15 +139,6 @@ public class OlmAccount {
*/
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.<br>
* @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.<br>
* The number of "one time keys", is specified by {@link #generateOneTimeKeys(int)}<br>
@ -181,24 +172,61 @@ public class OlmAccount {
return identityKeysJsonObj;
}
/**
* 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.<br>
* @return byte array containing the one time keys if operation succeed, null otherwise
*/
private native byte[] oneTimeKeysJni();
/**
* Remove the "one time keys" that the session used from the account.
* @param aSession session instance
* @return 0 if operation succeed, -1 otherwise
*/
public int removeOneTimeKeysForSession(OlmSession aSession) {
int retCode = 0;
if(null != aSession) {
int result = removeOneTimeKeysForSessionJni(aSession.getOlmSessionId());
Log.d(LOG_TAG,"## removeOneTimeKeysForSession(): result="+result);
if(-1 == result) {
retCode = -1;
}
}
return retCode;
}
/**
* 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 removeOneTimeKeysForSessionJni(long aNativeOlmSessionId);
/**
* Marks the current set of "one time keys" as being published.
* @return 0 if operation succeed, -1 otherwise
*/
public native int markOneTimeKeysAsPublished();
public int markOneTimeKeysAsPublished() {
return markOneTimeKeysAsPublishedJni();
}
private native int markOneTimeKeysAsPublishedJni();
/**
* 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);
public String signMessage(String aMessage){
return signMessageJni(aMessage);
}
private native String signMessageJni(String aMessage);
// TODO missing API: initWithSerializedData
// TODO missing API: serializeDataWithKey
// TODO missing API: initWithCoder
// TODO missing API: encodeWithCoder
}

View file

@ -0,0 +1,126 @@
/**
* Created by pedrocon on 13/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.
*/
package org.matrix.olm;
import android.text.TextUtils;
import android.util.Log;
import java.io.Serializable;
public class OlmInboundGroupSession implements Serializable {
private static final String LOG_TAG = "OlmInboundGroupSession";
/** session raw pointer value returned by JNI.<br>
* this value uniquely identifies the native inbound group session instance.
*/
private long mNativeOlmInboundGroupSessionId;
public OlmInboundGroupSession() {
initNewSession();
}
/**
* Getter on the native inbound group session ID.
* @return native inbound group session ID
*/
public long getOlmInboundGroupSessionId(){
return mNativeOlmInboundGroupSessionId;
}
/**
* Release native session and invalid its JAVA reference counter part.<br>
* Public API for {@link #releaseSessionJni()}.
* To be called before any other API call.
*/
public void releaseSession(){
releaseSessionJni();
mNativeOlmInboundGroupSessionId = 0;
}
/**
* Destroy the corresponding OLM inbound group session native object.<br>
* This method must ALWAYS be called when this JAVA instance
* is destroyed (ie. garbage collected) to prevent memory leak in native side.
* See {@link #initNewSessionJni()}.
*/
private native void releaseSessionJni();
/**
* Create and save the session native instance ID.
* Wrapper for {@link #initNewSessionJni()}.<br>
* To be called before any other API call.
* @return true if init succeed, false otherwise.
*/
private boolean initNewSession() {
boolean retCode = false;
if(0 != (mNativeOlmInboundGroupSessionId = initNewSessionJni())){
retCode = true;
}
return retCode;
}
/**
* Create the corresponding OLM inbound group session in native side.<br>
* Do not forget to call {@link #releaseSession()} when JAVA side is done.
* @return native session instance identifier (see {@link #mNativeOlmInboundGroupSessionId})
*/
private native long initNewSessionJni();
/**
* Creates a new inbound group session.<br>
* The session key parameter is retrieved from a outbound group session.
* @param aSessionKey session key
* @return 0 if operation succeed, -1 otherwise
*/
public int initInboundGroupSessionWithSessionKey(String aSessionKey) {
int retCode = -1;
if(TextUtils.isEmpty(aSessionKey)){
Log.e(LOG_TAG, "## initInboundGroupSessionWithSessionKey(): invalid session key");
} else {
retCode = initInboundGroupSessionWithSessionKeyJni(aSessionKey);
}
return retCode;
}
private native int initInboundGroupSessionWithSessionKeyJni(String aSessionKey);
public String sessionIdentifier() {
return sessionIdentifierJni();
}
private native String sessionIdentifierJni();
public String decryptMessage(String aEncryptedMsg) {
return decryptMessageJni(aEncryptedMsg);
}
private native String decryptMessageJni(String aEncryptedMsg);
// TODO missing API: initWithSerializedData
// TODO missing API: serializeDataWithKey
// TODO missing API: initWithCoder
// TODO missing API: encodeWithCoder
}

View file

@ -0,0 +1,135 @@
/*
* 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;
import android.text.TextUtils;
import android.util.Log;
public class OlmOutboundGroupSession {
private static final String LOG_TAG = "OlmOutboundGroupSession";
/** session raw pointer value returned by JNI.<br>
* this value uniquely identifies the native inbound group session instance.
*/
private long mNativeOlmOutboundGroupSessionId;
public OlmOutboundGroupSession() {
initNewSession();
}
/**
* Getter on the native outbound group session ID.
* @return native outbound group session ID
*/
public long getOlmInboundGroupSessionId(){
return mNativeOlmInboundGroupSessionId;
}
/**
* Release native session and invalid its JAVA reference counter part.<br>
* Public API for {@link #releaseSessionJni()}.
* To be called before any other API call.
*/
public void releaseSession(){
releaseSessionJni();
mNativeOlmOutboundGroupSessionId = 0;
}
/**
* Destroy the corresponding OLM outbound group session native object.<br>
* This method must ALWAYS be called when this JAVA instance
* is destroyed (ie. garbage collected) to prevent memory leak in native side.
* See {@link #initNewSessionJni()}.
*/
private native void releaseSessionJni();
/**
* Create and save the session native instance ID.
* Wrapper for {@link #initNewSessionJni()}.<br>
* To be called before any other API call.
* @return true if init succeed, false otherwise.
*/
private boolean initNewSession() {
boolean retCode = false;
if(0 != (mNativeOlmOutboundGroupSessionId = initNewSessionJni())){
retCode = true;
}
return retCode;
}
/**
* Create the corresponding OLM outbound group session in native side.<br>
* Do not forget to call {@link #releaseSession()} when JAVA side is done.
* @return native session instance identifier (see {@link #mNativeOlmOutboundGroupSessionId})
*/
private native long initNewSessionJni();
/**
* Creates a new outbound group session.<br>
* The session key parameter is retrieved from a outbound group session.
* @return 0 if operation succeed, -1 otherwise
*/
public int initOutboundGroupSession() {
return initOutboundGroupSessionJni();
}
public native int initOutboundGroupSessionJni();
public String sessionIdentifier() {
String retValue = null;
//retValue = sessionIdentifierJni();
return retValue;
}
public native String sessionIdentifierJni();
public long messageIndex() {
long retValue =0;
//retValue = messageIndexJni();
return retValue;
}
private native long messageIndexJni();
public String sessionKey() {
String retValue = null;
//retValue = sessionKeyJni();
return retValue;
}
private native String sessionKeyJni();
public String encryptMessage(String aClearMsg) {
String retValue = null;
//retValue = encryptMessageJni(aClearMsg);
return retValue;
}
private native String encryptMessageJni(String aClearMsg);
}

View file

@ -19,7 +19,9 @@ package org.matrix.olm;
import android.text.TextUtils;
import android.util.Log;
public class OlmSession {
import java.io.Serializable;
public class OlmSession implements Serializable {
private static final String LOG_TAG = "OlmSession";
/** session raw pointer value (OlmSession*) returned by JNI.
@ -85,7 +87,6 @@ public class OlmSession {
/**
* Create the corresponding OLM session in native side.<br>
* The return value is a long casted C ptr on the OlmSession.
* Do not forget to call {@link #releaseSession()} when JAVA side is done.
* @return native session instance identifier (see {@link #mNativeOlmSessionId})
*/
@ -159,6 +160,7 @@ public class OlmSession {
* @param aTheirIdentityKey the sender identity key
* @param aOneTimeKeyMsg PRE KEY message
* @return this if operation succeed, null otherwise
* TODO unit test missing: initInboundSessionWithAccountFrom
*/
public OlmSession initInboundSessionWithAccountFrom(OlmAccount aAccount, String aTheirIdentityKey, String aOneTimeKeyMsg) {
OlmSession retObj=null;
@ -198,6 +200,7 @@ public class OlmSession {
* Public API for {@link #matchesInboundSessionJni(String)}.
* @param aOneTimeKeyMsg PRE KEY message
* @return this if operation succeed, null otherwise
* TODO unit test missing: matchesInboundSession
*/
public boolean matchesInboundSession(String aOneTimeKeyMsg) {
boolean retCode = false;
@ -218,6 +221,7 @@ public class OlmSession {
* @param aTheirIdentityKey the sender identity key
* @param aOneTimeKeyMsg PRE KEY message
* @return this if operation succeed, null otherwise
* TODO unit test missing: matchesInboundSessionFrom
*/
public boolean matchesInboundSessionFrom(String aTheirIdentityKey, String aOneTimeKeyMsg) {
boolean retCode = false;
@ -261,5 +265,10 @@ public class OlmSession {
}
private native String decryptMessageJni(OlmMessage aEncryptedMsg);
// TODO missing API: initWithSerializedData
// TODO missing API: serializeDataWithKey
// TODO missing API: initWithCoder
// TODO missing API: encodeWithCoder
}

View file

@ -45,7 +45,8 @@ $(SRC_ROOT_DIR)/lib/crypto-algorithms/aes.c \
$(SRC_ROOT_DIR)/lib/curve25519-donna/curve25519-donna.c \
olm_account.cpp \
olm_session.cpp \
olm_utility.cpp
olm_utility.cpp \
olm_inbound_group_session.cpp
LOCAL_LDLIBS := -llog

View file

@ -19,7 +19,7 @@
/**
* Init memory allocation for account creation.
* @return valid memory alocation, NULL otherwise
* @return valid memory allocation, NULL otherwise
**/
OlmAccount* initializeAccountMemory()
{
@ -68,7 +68,7 @@ JNIEXPORT void OLM_ACCOUNT_FUNC_DEF(releaseAccountJni)(JNIEnv *env, jobject thiz
/**
* Initialize a new account and return it to JAVA side.<br>
* Since a C prt is returned as a jlong, special care will be taken
* to make the cast (OlmAccount* => jlong) platform independant.
* to make the cast (OlmAccount* => jlong) platform independent.
* @return the initialized OlmAccount* instance if init succeed, NULL otherwise
**/
JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thiz)
@ -308,7 +308,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(oneTimeKeysJni)(JNIEnv *env, jobject t
* @param aNativeOlmSessionId session instance
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS if no matching keys, ERROR_CODE_KO otherwise
**/
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId)
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId)
{
jint retCode = ERROR_CODE_KO;
OlmAccount* accountPtr = NULL;
@ -317,11 +317,11 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo
if(NULL == sessionPtr)
{
LOGE("## removeOneTimeKeysForSession(): failure - invalid session ptr");
LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid session ptr");
}
else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz)))
{
LOGE("## removeOneTimeKeysForSession(): failure - invalid account ptr");
LOGE("## removeOneTimeKeysForSessionJni(): failure - invalid account ptr");
}
else
{
@ -329,14 +329,14 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo
if(result == olm_error())
{ // the account doesn't have any matching "one time keys"..
const char *errorMsgPtr = olm_account_last_error(accountPtr);
LOGW("## removeOneTimeKeysForSession(): failure - removing one time keys Msg=%s",errorMsgPtr);
LOGW("## removeOneTimeKeysForSessionJni(): failure - removing one time keys Msg=%s",errorMsgPtr);
retCode = ERROR_CODE_NO_MATCHING_ONE_TIME_KEYS;
}
else
{
retCode = ERROR_CODE_OK;
LOGD("## removeOneTimeKeysForSession(): success");
LOGD("## removeOneTimeKeysForSessionJni(): success");
}
}
@ -347,7 +347,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jo
* Mark the current set of "one time keys" as being published.
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
**/
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz)
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz)
{
jint retCode = ERROR_CODE_OK;
OlmAccount* accountPtr = NULL;
@ -355,7 +355,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job
if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz)))
{
LOGE("## markOneTimeKeysPublished(): failure - invalid account ptr");
LOGE("## markOneTimeKeysAsPublishedJni(): failure - invalid account ptr");
retCode = ERROR_CODE_KO;
}
else
@ -364,12 +364,12 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job
if(result == olm_error())
{
const char *errorMsgPtr = olm_account_last_error(accountPtr);
LOGW("## markOneTimeKeysPublished(): failure - Msg=%s",errorMsgPtr);
LOGW("## markOneTimeKeysAsPublishedJni(): failure - Msg=%s",errorMsgPtr);
retCode = ERROR_CODE_KO;
}
else
{
LOGD("## markOneTimeKeysPublished(): success - retCode=%ld",result);
LOGD("## markOneTimeKeysAsPublishedJni(): success - retCode=%ld",result);
}
}
@ -382,7 +382,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, job
* @param aMessage message to sign
* @return the signed message, null otherwise
**/
JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage)
JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage)
{
OlmAccount* accountPtr = NULL;
size_t signatureLength;
@ -392,11 +392,11 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j
if(NULL == aMessage)
{
LOGE("## signMessage(): failure - invalid aMessage param");
LOGE("## signMessageJni(): failure - invalid aMessage param");
}
else if(NULL == (accountPtr = (OlmAccount*)getAccountInstanceId(env,thiz)))
{
LOGE("## signMessage(): failure - invalid account ptr");
LOGE("## signMessageJni(): failure - invalid account ptr");
}
else
{
@ -404,7 +404,7 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j
const char* messageToSign = env->GetStringUTFChars(aMessage, 0);
if(NULL == messageToSign)
{
LOGE("## signMessage(): failure - message JNI allocation OOM");
LOGE("## signMessageJni(): failure - message JNI allocation OOM");
}
else
{
@ -414,22 +414,26 @@ JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, j
signatureLength = olm_account_signature_length(accountPtr);
if(NULL == (signedMsgPtr = (void*)malloc(signatureLength*sizeof(uint8_t))))
{
LOGE("## signMessage(): failure - signature allocation OOM");
LOGE("## signMessageJni(): failure - signature allocation OOM");
}
else
{ // sign message
resultSign = olm_account_sign(accountPtr, (void*)messageToSign, (size_t)messageLength, signedMsgPtr, signatureLength);
resultSign = olm_account_sign(accountPtr,
(void*)messageToSign,
(size_t)messageLength,
signedMsgPtr,
signatureLength);
if(resultSign == olm_error())
{
const char *errorMsgPtr = olm_account_last_error(accountPtr);
LOGE("## signMessage(): failure - error signing message Msg=%s",errorMsgPtr);
LOGE("## signMessageJni(): failure - error signing message Msg=%s",errorMsgPtr);
}
else
{ // convert to jstring
// TODO check how UTF conversion can impact the content?
// why not consider return jbyteArray? and convert in JAVA side..
{
// TODO check if signedMsgPtr needs to be null ended: signedMsgPtr[resultSign]='\0'
// convert to jstring
signedMsgRetValue = env->NewStringUTF((const char*)signedMsgPtr); // UTF8
LOGD("## signMessage(): success - retCode=%ld",resultSign);
LOGD("## signMessageJni(): success - retCode=%ld",resultSign);
}
free(signedMsgPtr);

View file

@ -18,6 +18,7 @@
#define _OMLACCOUNT_H
#include "olm_jni.h"
#include "olm/olm.h"
#define OLM_ACCOUNT_FUNC_DEF(func_name) FUNC_DEF(OlmAccount,func_name)
#define OLM_MANAGER_FUNC_DEF(func_name) FUNC_DEF(OlmManager,func_name)
@ -39,11 +40,11 @@ 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(maxOneTimeKeys)(JNIEnv *env, jobject thiz);
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject thiz, jint aNumberOfKeys);
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSession)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId);
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublished)(JNIEnv *env, jobject thiz);
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(removeOneTimeKeysForSessionJni)(JNIEnv *env, jobject thiz, jlong aNativeOlmSessionId);
JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(markOneTimeKeysAsPublishedJni)(JNIEnv *env, jobject thiz);
// signing
JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessage)(JNIEnv *env, jobject thiz, jstring aMessage);
JNIEXPORT jstring OLM_ACCOUNT_FUNC_DEF(signMessageJni)(JNIEnv *env, jobject thiz, jstring aMessage);
#ifdef __cplusplus
}

View file

@ -0,0 +1,262 @@
/*
* 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_inbound_group_session.h"
#include "olm_utility.h"
/**
* Release the session allocation made by initializeInboundGroupSessionMemory().<br>
* 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)
{
OlmInboundGroupSession* sessionPtr = NULL;
LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr);
if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## releaseSessionJni(): failure - invalid inbound group session instance");
}
else
{
size_t retCode = olm_clear_inbound_group_session(sessionPtr);
LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode);
LOGD("## releaseSessionJni(): IN");
free(sessionPtr);
LOGD("## releaseSessionJni(): OUT");
}
}
/**
* Initialize a new inbound group session and return it to JAVA side.<br>
* 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(initNewSessionJni)(JNIEnv *env, jobject thiz)
{
OlmInboundGroupSession* sessionPtr = NULL;
size_t sessionSize = olm_inbound_group_session_size();
if(0 == sessionSize)
{
LOGE("## initNewSessionJni(): failure - inbound group session size = 0");
}
else if(NULL != (sessionPtr=(OlmInboundGroupSession*)malloc(sessionSize)))
{
sessionPtr = olm_inbound_group_session(sessionPtr);
LOGD("## initNewSessionJni(): success - inbound group session size=%lu",sessionSize);
}
else
{
LOGE("## initNewSessionJni(): failure - inbound group session OOM");
}
return (jlong)(intptr_t)sessionPtr;
}
/**
* Create a new in-bound session.<br>
* @param aSessionKey session key from an outbound session
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
*/
JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey)
{
jint retCode = ERROR_CODE_KO;
OlmInboundGroupSession *sessionPtr = NULL;
const uint8_t *sessionKeyPtr = NULL;
size_t sessionResult;
if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid inbound group session instance");
}
else if(0 == aSessionKey)
{
LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey");
}
else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0)))
{
LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM");
}
else
{
size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey);
LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength);
sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength);
if(sessionResult == olm_error()) {
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr);
}
else
{
retCode = ERROR_CODE_OK;
LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
}
}
// free local alloc
if(NULL!= sessionKeyPtr)
{
env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr);
}
return retCode;
}
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz)
{
OlmInboundGroupSession *sessionPtr = NULL;
uint8_t *sessionIdPtr = NULL;
jstring returnValueStr=0;
// get the size to alloc to contain the id
size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr);
if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance");
}
else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t))))
{
LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM");
}
else
{
size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId);
if (result == olm_error())
{
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr);
}
else
{
// update length
sessionIdPtr[result] = static_cast<char>('\0');
LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr);
returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
}
free(sessionIdPtr);
}
return returnValueStr;
}
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg)
{
jstring decryptedMsgRetValue = 0;
OlmInboundGroupSession *sessionPtr = NULL;
const char *encryptedMsgPtr = NULL;
uint8_t *plainTextMsgPtr = NULL;
uint8_t *tempEncryptedPtr = NULL;
LOGD("## decryptMessageJni(): IN");
if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL");
}
else if(0 == aEncryptedMsg)
{
LOGE("## decryptMessageJni(): failure - invalid clear message");
}
else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0)))
{
LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM");
}
else
{
// get encrypted message length
size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg);
// create a dedicated temp buffer to be used in next Olm API calls
if(NULL == (tempEncryptedPtr = static_cast<uint8_t*>(malloc(encryptedMsgLength*sizeof(uint8_t)))))
{
LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM");
}
else
{
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr);
// get max plaintext length
size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr,
tempEncryptedPtr,
encryptedMsgLength);
if(maxPlainTextLength == olm_error())
{
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr);
}
else
{
LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength);
// allocate output decrypted message
plainTextMsgPtr = static_cast<uint8_t*>(malloc(maxPlainTextLength*sizeof(uint8_t)));
// decrypt, but before reload encrypted buffer (previous one was destroyed)
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
size_t plaintextLength = olm_group_decrypt(sessionPtr,
tempEncryptedPtr,
encryptedMsgLength,
plainTextMsgPtr,
maxPlainTextLength);
if(plaintextLength == olm_error())
{
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr);
}
else
{
// update decrypted buffer size
plainTextMsgPtr[plaintextLength] = static_cast<char>('\0');
LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr);
decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr);
}
}
}
}
// free alloc
if(NULL != encryptedMsgPtr)
{
env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr);
}
if(NULL != tempEncryptedPtr)
{
free(tempEncryptedPtr);
}
if(NULL != plainTextMsgPtr)
{
free(plainTextMsgPtr);
}
return decryptedMsgRetValue;
}

View file

@ -0,0 +1,43 @@
/*
* 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.
*/
#ifndef _OMLINBOUND_GROUP_SESSION_H
#define _OMLINBOUND_GROUP_SESSION_H
#include "olm_jni.h"
#include "olm/olm.h"
#include "olm/inbound_group_session.h"
#define OLM_INBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmInboundGroupSession,func_name)
#ifdef __cplusplus
extern "C" {
#endif
// session creation/destruction
JNIEXPORT void OLM_INBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey);
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -25,7 +25,6 @@
#include <jni.h>
#include <android/log.h>
#include "olm/olm.h"
#define TAG "OlmJniNative"
@ -54,11 +53,4 @@ static const int ERROR_CODE_KO = -1;
// constants
static const int ACCOUNT_CREATION_RANDOM_MODULO = 256;
typedef struct _AccountContext
{
OlmAccount* mAccountPtr;
_AccountContext(): mAccountPtr(NULL){}
} AccountContext;
#endif

View file

@ -0,0 +1,293 @@
/*
* 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_outbound_group_session.h"
#include "olm_utility.h"
/**
* Release the session allocation made by initializeOutboundGroupSessionMemory().<br>
* This method MUST be called when java counter part account instance is done.
*
*/
JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz)
{
OlmOutboundGroupSession* sessionPtr = NULL;
LOGD("## releaseSessionJni(): sessionPtr=%p",sessionPtr);
if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## releaseSessionJni(): failure - invalid inbound group session instance");
}
else
{
size_t retCode = olm_clear_outbound_group_session(sessionPtr);
LOGD("## releaseSessionJni(): clear_inbound_group_session=%lu",retCode);
LOGD("## releaseSessionJni(): IN");
free(sessionPtr);
LOGD("## releaseSessionJni(): OUT");
}
}
/**
* Initialize a new outbound group session and return it to JAVA side.<br>
* 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
**/
JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz)
{
OlmOutboundGroupSession* sessionPtr = NULL;
size_t sessionSize = olm_outbound_group_session_size();
if(0 == sessionSize)
{
LOGE("## initNewSessionJni(): failure - outbound group session size = 0");
}
else if(NULL != (sessionPtr=(OlmOutboundGroupSession*)malloc(sessionSize)))
{
sessionPtr = olm_outbound_group_session(sessionPtr);
LOGD("## initNewSessionJni(): success - outbound group session size=%lu",sessionSize);
}
else
{
LOGE("## initNewSessionJni(): failure - outbound group session OOM");
}
return (jlong)(intptr_t)sessionPtr;
}
/**
* Create a new outbound session.<br>
* @return ERROR_CODE_OK if operation succeed, ERROR_CODE_KO otherwise
*/
JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz)
{
jint retCode = ERROR_CODE_KO;
OlmOutboundGroupSession *sessionPtr = NULL;
uint8_t *randomBuffPtr = NULL;
size_t sessionResult;
if(NULL == (sessionPtr = (OlmOutboundGroupSession*)getOutboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## initOutboundGroupSessionJni(): failure - invalid inbound group session instance");
}
else
{
// compute random buffer
size_t randomLength = olm_init_outbound_group_session_random_length(sessionPtr);
if((0!=randomLength) && !setRandomInBuffer(&randomBuffPtr, randomLength))
{
LOGE("## initOutboundGroupSessionJni(): failure - random buffer init");
}
else
{
if(0==randomLength)
{
LOGW("## initOutboundGroupSessionJni(): random buffer is not required");
}
size_t sessionResult = olm_init_outbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength);
if(sessionResult == olm_error()) {
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr);
}
else
{
retCode = ERROR_CODE_OK;
LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
}
}
}
else if(0 == aSessionKey)
{
LOGE("## initInboundGroupSessionWithSessionKeyJni(): failure - invalid aSessionKey");
}
else if(NULL == (sessionKeyPtr = (const uint8_t *)env->GetStringUTFChars(aSessionKey, 0)))
{
LOGE("## initInboundSessionFromIdKeyJni(): failure - session key JNI allocation OOM");
}
else
{
size_t sessionKeyLength = (size_t)env->GetStringUTFLength(aSessionKey);
LOGD("## initInboundSessionFromIdKeyJni(): sessionKeyLength=%lu",sessionKeyLength);
sessionResult = olm_init_inbound_group_session(sessionPtr, sessionKeyPtr, sessionKeyLength);
if(sessionResult == olm_error()) {
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## initInboundSessionFromIdKeyJni(): failure - init inbound session creation Msg=%s",errorMsgPtr);
}
else
{
retCode = ERROR_CODE_OK;
LOGD("## initInboundSessionFromIdKeyJni(): success - result=%lu", sessionResult);
}
}
// free local alloc
if(NULL!= sessionKeyPtr)
{
env->ReleaseStringUTFChars(aSessionKey, (const char*)sessionKeyPtr);
}
return retCode;
}
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz)
{
OlmInboundGroupSession *sessionPtr = NULL;
uint8_t *sessionIdPtr = NULL;
jstring returnValueStr=0;
// get the size to alloc to contain the id
size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr);
if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## sessionIdentifierJni(): failure - invalid inbound group session instance");
}
else if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t))))
{
LOGE("## sessionIdentifierJni(): failure - identifier allocation OOM");
}
else
{
size_t result = olm_inbound_group_session_id(sessionPtr, sessionIdPtr, lengthSessionId);
if (result == olm_error())
{
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr);
}
else
{
// update length
sessionIdPtr[result] = static_cast<char>('\0');
LOGD("## sessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr);
returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
}
free(sessionIdPtr);
}
return returnValueStr;
}
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg)
{
jstring decryptedMsgRetValue = 0;
OlmInboundGroupSession *sessionPtr = NULL;
const char *encryptedMsgPtr = NULL;
uint8_t *plainTextMsgPtr = NULL;
uint8_t *tempEncryptedPtr = NULL;
LOGD("## decryptMessageJni(): IN");
if(NULL == (sessionPtr = (OlmInboundGroupSession*)getInboundGroupSessionInstanceId(env,thiz)))
{
LOGE("## decryptMessageJni(): failure - invalid inbound group session ptr=NULL");
}
else if(0 == aEncryptedMsg)
{
LOGE("## decryptMessageJni(): failure - invalid clear message");
}
else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0)))
{
LOGE("## decryptMessageJni(): failure - encrypted message JNI allocation OOM");
}
else
{
// get encrypted message length
size_t encryptedMsgLength = (size_t)env->GetStringUTFLength(aEncryptedMsg);
// create a dedicated temp buffer to be used in next Olm API calls
if(NULL == (tempEncryptedPtr = static_cast<uint8_t*>(malloc(encryptedMsgLength*sizeof(uint8_t)))))
{
LOGE("## decryptMessageJni(): failure - tempEncryptedPtr allocation OOM");
}
else
{
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
LOGD("## decryptMessageJni(): encryptedMsgLength=%lu encryptedMsg=%s",encryptedMsgLength,encryptedMsgPtr);
// get max plaintext length
size_t maxPlainTextLength = olm_group_decrypt_max_plaintext_length(sessionPtr,
tempEncryptedPtr,
encryptedMsgLength);
if(maxPlainTextLength == olm_error())
{
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## decryptMessageJni(): failure - olm_group_decrypt_max_plaintext_length Msg=%s",errorMsgPtr);
}
else
{
LOGD("## decryptMessageJni(): maxPlaintextLength=%lu",maxPlainTextLength);
// allocate output decrypted message
plainTextMsgPtr = static_cast<uint8_t*>(malloc(maxPlainTextLength*sizeof(uint8_t)));
// decrypt, but before reload encrypted buffer (previous one was destroyed)
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
size_t plaintextLength = olm_group_decrypt(sessionPtr,
tempEncryptedPtr,
encryptedMsgLength,
plainTextMsgPtr,
maxPlainTextLength);
if(plaintextLength == olm_error())
{
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## decryptMessageJni(): failure - olm_group_decrypt Msg=%s",errorMsgPtr);
}
else
{
// update decrypted buffer size
plainTextMsgPtr[plaintextLength] = static_cast<char>('\0');
LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",plaintextLength, (char*)plainTextMsgPtr);
decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr);
}
}
}
}
// free alloc
if(NULL != encryptedMsgPtr)
{
env->ReleaseStringUTFChars(aEncryptedMsg, encryptedMsgPtr);
}
if(NULL != tempEncryptedPtr)
{
free(tempEncryptedPtr);
}
if(NULL != plainTextMsgPtr)
{
free(plainTextMsgPtr);
}
return decryptedMsgRetValue;
}

View file

@ -0,0 +1,43 @@
/*
* 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.
*/
#ifndef _OMLOUTBOUND_GROUP_SESSION_H
#define _OMLOUTBOUND_GROUP_SESSION_H
#include "olm_jni.h"
#include "olm/olm.h"
#include "olm/outbound_group_session.h"
#define OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmOutboundGroupSession,func_name)
#ifdef __cplusplus
extern "C" {
#endif
// session creation/destruction
JNIEXPORT void OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(releaseSessionJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initNewSessionJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jint OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(initOutboundGroupSessionJni)(JNIEnv *env, jobject thiz, jstring aSessionKey);
JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jstring OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -458,7 +458,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
}
else if(0 == aEncryptedMsg)
{
LOGE("## encryptMessageJni(): failure - invalid clear message");
LOGE("## encryptMessageJni(): failure - invalid encrypted message");
}
else if(NULL == (clearMsgPtr = env->GetStringUTFChars(aClearMsg, 0)))
{
@ -587,11 +587,11 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t
}
else if(0 == aEncryptedMsg)
{
LOGE("## decryptMessageJni(): failure - invalid clear message");
LOGE("## decryptMessageJni(): failure - invalid encrypted message");
}
else if(0 == (encryptedMsgJclass = env->GetObjectClass(aEncryptedMsg)))
{
LOGE("## decryptMessageJni(): failure - unable to get crypted message class");
LOGE("## decryptMessageJni(): failure - unable to get encrypted message class");
}
else if(0 == (encryptedMsgFieldId = env->GetFieldID(encryptedMsgJclass,"mCipherText","Ljava/lang/String;")))
{
@ -644,7 +644,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t
memcpy(tempEncryptedPtr, encryptedMsgPtr, encryptedMsgLength);
size_t plaintextLength = olm_decrypt(sessionPtr,
encryptedMsgType,
(void*)encryptedMsgPtr,
(void*)tempEncryptedPtr,
encryptedMsgLength,
plainTextMsgPtr,
maxPlainTextLength);
@ -717,7 +717,7 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, job
}
else
{
// update decrypted buffer size
// update length
(static_cast<char*>(sessionIdPtr))[result] = static_cast<char>('\0');
LOGD("## getSessionIdentifierJni(): success - result=%lu sessionId=%s",result, (char*)sessionIdPtr);

View file

@ -18,6 +18,7 @@
#define _OMLSESSION_H
#include "olm_jni.h"
#include "olm/olm.h"
#define OLM_SESSION_FUNC_DEF(func_name) FUNC_DEF(OlmSession,func_name)

View file

@ -101,7 +101,7 @@ jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
}
/**
* Read the account instance ID of the calling object (aJavaObject).<br>
* Read the session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
@ -139,3 +139,83 @@ jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
//LOGD("## getSessionInstanceId() success - instanceId=%lld",instanceId);
return instanceId;
}
/**
* Read the inbound group session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
jlong instanceId=-1;
jfieldID instanceIdField;
jclass loaderClass;
if(NULL!=aJniEnv)
{
if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
{
if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmInboundGroupSessionId", "J")))
{
instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
aJniEnv->DeleteLocalRef(loaderClass);
}
else
{
LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
}
}
else
{
LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
}
}
else
{
LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
}
return instanceId;
}
/**
* Read the outbound group session instance ID of the calling object (aJavaObject).<br>
* @param aJniEnv pointer pointing on the JNI function table
* @param aJavaObject reference to the object on which the method is invoked
* @return the instance ID if read succeed, -1 otherwise.
**/
jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject)
{
jlong instanceId=-1;
jfieldID instanceIdField;
jclass loaderClass;
if(NULL!=aJniEnv)
{
if(0 != (loaderClass=aJniEnv->GetObjectClass(aJavaObject)))
{
if(0 != (instanceIdField=aJniEnv->GetFieldID(loaderClass, "mNativeOlmOutboundGroupSessionId", "J")))
{
instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
aJniEnv->DeleteLocalRef(loaderClass);
}
else
{
LOGD("## getSessionInstanceId() ERROR! GetFieldID=null");
}
}
else
{
LOGD("## getSessionInstanceId() ERROR! GetObjectClass=null");
}
}
else
{
LOGD("## getSessionInstanceId() ERROR! aJniEnv=NULL");
}
return instanceId;
}

View file

@ -25,6 +25,7 @@ extern "C" {
bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize);
jlong getSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
jlong getAccountInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
jlong getInboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
#ifdef __cplusplus
}