Commit 10280995 authored by pedroGitt's avatar pedroGitt
Browse files

- Add inbound and outbound group sessions

- Modify constructors for inbound and outbound group sessions
- Add new Ecxception class
parent 57ec6fff
......@@ -34,19 +34,33 @@ public class OlmInboundGroupSession implements Serializable {
*/
private long mNativeOlmInboundGroupSessionId;
public OlmInboundGroupSession() {
initNewSession();
}
/**
* Getter on the native inbound group session ID.
* @return native inbound group session ID
*/
public long getOlmInboundGroupSessionId(){
public long getOlmInboundGroupSessionId() {
return mNativeOlmInboundGroupSessionId;
}
/**
* Constructor.<br>
* Create and save a new native session instance ID and start a new inbound group session.
* The session key parameter is retrieved from a outbound group session
* See {@link #initNewSession()} and {@link #initInboundGroupSessionWithSessionKey(String)}
* @param aSessionKey session key
* @throws OlmUtilsException
*/
public OlmInboundGroupSession(String aSessionKey) throws OlmUtilsException {
if(initNewSession()) {
if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) {
releaseSession();// prevent memory leak before throwing
throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION);
}
} else {
throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE);
}
}
/**
* Release native session and invalid its JAVA reference counter part.<br>
* Public API for {@link #releaseSessionJni()}.
......@@ -88,12 +102,13 @@ public class OlmInboundGroupSession implements Serializable {
private native long initNewSessionJni();
/**
* Creates a new inbound group session.<br>
* The session key parameter is retrieved from a outbound group session.
* Start a new inbound group session.<br>
* The session key parameter is retrieved from a outbound group session
* see {@link OlmOutboundGroupSession#sessionKey()}
* @param aSessionKey session key
* @return 0 if operation succeed, -1 otherwise
*/
public int initInboundGroupSessionWithSessionKey(String aSessionKey) {
private int initInboundGroupSessionWithSessionKey(String aSessionKey) {
int retCode = -1;
if(TextUtils.isEmpty(aSessionKey)){
......
......@@ -28,16 +28,30 @@ public class OlmOutboundGroupSession {
*/
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;
return mNativeOlmOutboundGroupSessionId;
}
/**
* Constructor.<br>
* Create and save a new session native instance ID and
* initialise a new outbound group session.<br>
* See {@link #initNewSession()} and {@link #initOutboundGroupSession()}
* @throws OlmUtilsException
*/
public OlmOutboundGroupSession() throws OlmUtilsException {
if(initNewSession()) {
if( 0 != initOutboundGroupSession()) {
releaseSession();// prevent memory leak before throwing
throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION);
}
} else {
throw new OlmUtilsException(OlmUtilsException.EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE);
}
}
/**
......@@ -45,9 +59,8 @@ public class OlmOutboundGroupSession {
* Public API for {@link #releaseSessionJni()}.
* To be called before any other API call.
*/
public void releaseSession(){
releaseSessionJni();
public void releaseSession() {
releaseSessionJni();
mNativeOlmOutboundGroupSessionId = 0;
}
......@@ -80,54 +93,66 @@ public class OlmOutboundGroupSession {
*/
private native long initNewSessionJni();
/**
* Creates a new outbound group session.<br>
* The session key parameter is retrieved from a outbound group session.
* Start a new outbound group session.<br>
* @return 0 if operation succeed, -1 otherwise
*/
public int initOutboundGroupSession() {
private int initOutboundGroupSession() {
return initOutboundGroupSessionJni();
}
public native int initOutboundGroupSessionJni();
private native int initOutboundGroupSessionJni();
/**
* Get a base64-encoded identifier for this session.
* @return session identifier if operation succeed, null otherwise.
*/
public String sessionIdentifier() {
String retValue = null;
//retValue = sessionIdentifierJni();
retValue = sessionIdentifierJni();
return retValue;
}
public native String sessionIdentifierJni();
private native String sessionIdentifierJni();
public long messageIndex() {
long retValue =0;
//retValue = messageIndexJni();
/**
* Get the current message index for this session.<br>
* Each message is sent with an increasing index, this
* method returns the index for the next message.
* @return current session index
*/
public int messageIndex() {
int retValue =0;
retValue = messageIndexJni();
return retValue;
}
private native long messageIndexJni();
private native int messageIndexJni();
/**
* Get the base64-encoded current ratchet key for this session.<br>
* Each message is sent with a different ratchet key. This method returns the
* ratchet key that will be used for the next message.
* @return outbound session key
*/
public String sessionKey() {
String retValue = null;
//retValue = sessionKeyJni();
retValue = sessionKeyJni();
return retValue;
}
private native String sessionKeyJni();
/**
* Encrypt some plain-text message.<br>
* @param aClearMsg message to be encrypted
* @return the encrypted message if operation succeed, null otherwise
*/
public String encryptMessage(String aClearMsg) {
String retValue = null;
//retValue = encryptMessageJni(aClearMsg);
if(!TextUtils.isEmpty(aClearMsg)) {
retValue = encryptMessageJni(aClearMsg);
}
return retValue;
}
......
/*
* 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 OlmUtilsException extends Exception {
// exception codes
public static final int EXCEPTION_CODE_INIT_NEW_SESSION_FAILURE = 0;
public static final int EXCEPTION_CODE_INIT_OUTBOUND_GROUP_SESSION = 1;
public static final int EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION = 2;
private final int mCode;
public OlmUtilsException(int aExceptionCode) {
super();
mCode = aExceptionCode;
}
public int getExceptionCode() {
return mCode;
}
}
......@@ -45,8 +45,9 @@ $(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_inbound_group_session.cpp
olm_jni_helper.cpp \
olm_inbound_group_session.cpp \
olm_outbound_group_session.cpp
LOCAL_LDLIBS := -llog
......
......@@ -15,7 +15,6 @@
*/
#include "olm_account.h"
#include "olm_utility.h"
/**
* Init memory allocation for account creation.
......@@ -85,9 +84,12 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(initNewAccountJni)(JNIEnv *env, jobject thi
}
else
{
// allocate random buffer
// get random buffer size
randomSize = olm_create_account_random_length(accountPtr);
if(!setRandomInBuffer(&randomBuffPtr, randomSize))
LOGD("## initNewAccount(): randomSize=%lu", randomSize);
// allocate random buffer
if((0!=randomSize) && !setRandomInBuffer(&randomBuffPtr, randomSize))
{
LOGE("## initNewAccount(): failure - random buffer init");
}
......@@ -219,7 +221,7 @@ JNIEXPORT jint OLM_ACCOUNT_FUNC_DEF(generateOneTimeKeys)(JNIEnv *env, jobject th
randomLength = olm_account_generate_one_time_keys_random_length(accountPtr, (size_t)aNumberOfKeys);
LOGD("## generateOneTimeKeys(): randomLength=%ld", randomLength);
if(!setRandomInBuffer(&randomBufferPtr, randomLength))
if((0!=randomLength) && !setRandomInBuffer(&randomBufferPtr, randomLength))
{
LOGE("## generateOneTimeKeys(): failure - random buffer init");
}
......
......@@ -15,7 +15,6 @@
*/
#include "olm_inbound_group_session.h"
#include "olm_utility.h"
/**
......@@ -123,45 +122,54 @@ JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSes
}
/**
* Get a base64-encoded identifier for this inbound group session.
*/
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);
LOGD("## sessionIdentifierJni(): inbound group session IN");
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())
// get the size to alloc
size_t lengthSessionId = olm_inbound_group_session_id_length(sessionPtr);
LOGD("## sessionIdentifierJni(): inbound group session lengthSessionId=%lu",lengthSessionId);
if(NULL == (sessionIdPtr = (uint8_t*)malloc(lengthSessionId*sizeof(uint8_t))))
{
const char *errorMsgPtr = olm_inbound_group_session_last_error(sessionPtr);
LOGE("## sessionIdentifierJni(): failure - get session identifier failure Msg=%s",errorMsgPtr);
LOGE("## sessionIdentifierJni(): failure - inbound group session identifier allocation OOM");
}
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);
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 inbound group session identifier failure Msg=%s",errorMsgPtr);
}
else
{
// update length
sessionIdPtr[result] = static_cast<char>('\0');
LOGD("## sessionIdentifierJni(): success - inbound group session result=%lu sessionId=%s",result, (char*)sessionIdPtr);
returnValueStr = env->NewStringUTF((const char*)sessionIdPtr);
}
free(sessionIdPtr);
}
free(sessionIdPtr);
}
return returnValueStr;
}
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg)
{
jstring decryptedMsgRetValue = 0;
......@@ -178,7 +186,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
}
else if(0 == aEncryptedMsg)
{
LOGE("## decryptMessageJni(): failure - invalid clear message");
LOGE("## decryptMessageJni(): failure - invalid encrypted message");
}
else if(0 == (encryptedMsgPtr = env->GetStringUTFChars(aEncryptedMsg, 0)))
{
......
......@@ -53,4 +53,21 @@ static const int ERROR_CODE_KO = -1;
// constants
static const int ACCOUNT_CREATION_RANDOM_MODULO = 256;
#ifdef __cplusplus
extern "C" {
#endif
// internal helper functions
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);
jlong getOutboundGroupSessionInstanceId(JNIEnv* aJniEnv, jobject aJavaObject);
#ifdef __cplusplus
}
#endif
#endif
/**
* 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"
/**
* Init a buffer with a given number of random values.
* @param aBuffer2Ptr the buffer to be initialized
* @param aRandomSize the number of random values to apply
* @return true if operation succeed, false otherwise
**/
bool setRandomInBuffer(uint8_t **aBuffer2Ptr, size_t aRandomSize)
{
bool retCode = false;
if(NULL == aBuffer2Ptr)
{
LOGD("## setRandomInBuffer(): failure - aBuffer=NULL");
}
else if(0 == aRandomSize)
{
LOGD("## setRandomInBuffer(): failure - random size=0");
}
else if(NULL == (*aBuffer2Ptr = (uint8_t*)malloc(aRandomSize*sizeof(uint8_t))))
{
LOGD("## setRandomInBuffer(): failure - alloc mem OOM");
}
else
{
LOGD("## setRandomInBuffer(): randomSize=%ld",aRandomSize);
srand(time(NULL)); // init seed
for(size_t i=0;i<aRandomSize;i++)
{
(*aBuffer2Ptr)[i] = (uint8_t)(rand()%ACCOUNT_CREATION_RANDOM_MODULO);
// debug purpose
//LOGD("## setRandomInBuffer(): randomBuffPtr[%ld]=%d",i, (*aBuffer2Ptr)[i]);
}
retCode = true;
}
return retCode;
}
/**
* Read the account instance ID of the calling object.
* @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 operation succeed, -1 if instance ID was not found.
**/
jlong getAccountInstanceId(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, "mNativeOlmAccountId", "J")))
{
instanceId = aJniEnv->GetLongField(aJavaObject, instanceIdField);
aJniEnv->DeleteLocalRef(loaderClass);
LOGD("## getAccountInstanceId(): read from java instanceId=%lld",instanceId);
}
else
{
LOGD("## getAccountInstanceId() ERROR! GetFieldID=null");
}
}
else
{
LOGD("## getAccountInstanceId() ERROR! GetObjectClass=null");
}
}
else
{
LOGD("## getAccountInstanceId() ERROR! aJniEnv=NULL");
}
LOGD("## getAccountInstanceId() success - instanceId=%lld",instanceId);
return instanceId;
}
/**
* 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.
**/
jlong getSessionInstanceId(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, "mNativeOlmSessionId", "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");
}
//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("## getInboundGroupSessionInstanceId() ERROR! GetFieldID=null");
}
}
else
{
LOGD("## getInboundGroupSessionInstanceId() ERROR! GetObjectClass=null");
}
}
else
{
LOGD("## getInboundGroupSessionInstanceId() 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);