-> simplify OlmSession.DecryptMessage

-> Always use javaCStringToUtf8 to convert byte array to String
This commit is contained in:
ylecollen 2017-01-03 10:46:56 +01:00
parent 65352d05aa
commit c8c7a8ad19
11 changed files with 82 additions and 105 deletions

View file

@ -60,12 +60,8 @@ public class OlmAccountTest {
@BeforeClass @BeforeClass
public static void setUpClass(){ public static void setUpClass(){
// enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
// due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
// load native lib // load native lib
mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); mOlmManager = new OlmManager();
String olmLibVersion = mOlmManager.getOlmLibVersion(); String olmLibVersion = mOlmManager.getOlmLibVersion();
assertNotNull(olmLibVersion); assertNotNull(olmLibVersion);

View file

@ -61,13 +61,8 @@ public class OlmGroupSessionTest {
@BeforeClass @BeforeClass
public static void setUpClass(){ public static void setUpClass(){
// enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
// due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
// load native lib // load native lib
mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); mOlmManager = new OlmManager();
String version = mOlmManager.getOlmLibVersion(); String version = mOlmManager.getOlmLibVersion();
assertNotNull(version); assertNotNull(version);
@ -151,13 +146,18 @@ public class OlmGroupSessionTest {
@Test @Test
public void test10InboundDecryptMessage() { public void test10InboundDecryptMessage() {
// test decrypted message mBobDecryptedMessage = null;
StringBuffer errorMsg = new StringBuffer(); OlmInboundGroupSession.DecryptMessageResult result = null;
OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex();
mBobDecryptedMessage = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage, index, errorMsg); try {
result = mBobInboundGroupSession.decryptMessage(mAliceToBobMessage);
} catch (Exception e) {
}
// test decrypted message
mBobDecryptedMessage = result.mDecryptedMessage;
assertFalse(TextUtils.isEmpty(mBobDecryptedMessage)); assertFalse(TextUtils.isEmpty(mBobDecryptedMessage));
assertTrue(0==index.mIndex); assertTrue(0 == result.mIndex);
} }
@Test @Test
@ -440,15 +440,18 @@ public class OlmGroupSessionTest {
assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false); assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getExceptionCode(), false);
} }
StringBuffer errorMsg = new StringBuffer(); OlmInboundGroupSession.DecryptMessageResult result = null;
OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex();
String decryptedMessage = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji, index, errorMsg); try {
assertNotNull(decryptedMessage); result = bobInboundGroupSession.decryptMessage(msgToDecryptWithEmoji);
assertTrue(13==index.mIndex); } catch (Exception e) {
assertTrue("Exception in test18TestBadCharacterCrashInDecrypt, Exception code=" + e.getMessage(), false);
}
assertNotNull(result.mDecryptedMessage);
assertTrue(13 == result.mIndex);
} }
/** /**
* Specific test to check an error message is returned by decryptMessage() API.<br> * Specific test to check an error message is returned by decryptMessage() API.<br>
* A corrupted encrypted message is passed, and a INVALID_BASE64 is * A corrupted encrypted message is passed, and a INVALID_BASE64 is
@ -458,8 +461,6 @@ public class OlmGroupSessionTest {
public void test19TestErrorMessageReturnedInDecrypt() { public void test19TestErrorMessageReturnedInDecrypt() {
OlmInboundGroupSession bobInboundGroupSession=null; OlmInboundGroupSession bobInboundGroupSession=null;
final String EXPECTED_ERROR_MESSAGE= "INVALID_BASE64"; final String EXPECTED_ERROR_MESSAGE= "INVALID_BASE64";
StringBuffer errorMsg = new StringBuffer();
OlmInboundGroupSession.DecryptIndex index = new OlmInboundGroupSession.DecryptIndex();
String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA"; String sessionKeyRef = "AgAAAAycZE6AekIctJWYxd2AWLOY15YmxZODm/WkgbpWkyycp6ytSp/R+wo84jRrzBNWmv6ySLTZ9R0EDOk9VI2eZyQ6Efdwyo1mAvrWvTkZl9yALPdkOIVHywyG65f1SNiLrnsln3hgsT1vUrISGyKtsljoUgQpr3JDPEhD0ilAi63QBjhnGCW252b+7nF+43rb6O6lwm93LaVwe2341Gdp6EkhTUvetALezEqDOtKN00wVqAbq0RQAnUJIowxHbMswg+FyoR1K1oCjnVEoF23O9xlAn5g1XtuBZP3moJlR2lwsBA";
String corruptedEncryptedMsg = "AwgANYTHINGf87ge45ge7gr*/rg5ganything4gr41rrgr4re55tanythingmcsXUkhDv0UePj922kgf+"; String corruptedEncryptedMsg = "AwgANYTHINGf87ge45ge7gr*/rg5ganything4gr41rrgr4re55tanythingmcsXUkhDv0UePj922kgf+";
@ -471,12 +472,15 @@ public class OlmGroupSessionTest {
assertTrue("Exception in test19TestErrorMessageReturnedInDecrypt, Exception code=" + e.getExceptionCode(), false); assertTrue("Exception in test19TestErrorMessageReturnedInDecrypt, Exception code=" + e.getExceptionCode(), false);
} }
String decryptedMessage = bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg, index, errorMsg); String exceptionMessage = null;
assertTrue(0!=EXPECTED_ERROR_MESSAGE.length()); try {
assertTrue(EXPECTED_ERROR_MESSAGE.equals(errorMsg.toString())); bobInboundGroupSession.decryptMessage(corruptedEncryptedMsg);
assertTrue(null==decryptedMessage); } catch (OlmInboundGroupSession.DecryptMessageException e) {
assertTrue(0==index.mIndex); exceptionMessage = e.getMessage();
} }
assertTrue(0!=EXPECTED_ERROR_MESSAGE.length());
assertTrue(EXPECTED_ERROR_MESSAGE.equals(exceptionMessage));
}
} }

View file

@ -53,12 +53,8 @@ public class OlmSessionTest {
@BeforeClass @BeforeClass
public static void setUpClass(){ public static void setUpClass(){
// enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
// due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
// load native lib // load native lib
mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); mOlmManager = new OlmManager();
String version = mOlmManager.getOlmLibVersion(); String version = mOlmManager.getOlmLibVersion();
assertNotNull(version); assertNotNull(version);

View file

@ -44,12 +44,8 @@ public class OlmUtilityTest {
@BeforeClass @BeforeClass
public static void setUpClass(){ public static void setUpClass(){
// enable UTF-8 specific conversion for pre Marshmallow(23) android versions,
// due to issue described here: https://github.com/eclipsesource/J2V8/issues/142
boolean isSpecificUtf8ConversionEnabled = android.os.Build.VERSION.SDK_INT < 23;
// load native lib // load native lib
mOlmManager = new OlmManager(isSpecificUtf8ConversionEnabled); mOlmManager = new OlmManager();
String version = mOlmManager.getOlmLibVersion(); String version = mOlmManager.getOlmLibVersion();
assertNotNull(version); assertNotNull(version);

View file

@ -42,13 +42,25 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
private transient long mNativeId; private transient long mNativeId;
/** /**
* Wrapper class to be used in {@link #decryptMessage(String, DecryptIndex, StringBuffer)} * Result in {@link #decryptMessage(String)}
*/ */
static public class DecryptIndex { static class DecryptMessageResult {
/** decrypt message **/
public String mDecryptedMessage;
/** decrypt index **/ /** decrypt index **/
public long mIndex; public long mIndex;
} }
/**
* Exception triggered in {@link #decryptMessage(String)}
*/
static public class DecryptMessageException extends Exception {
public DecryptMessageException(String message) {
super(message);
}
}
/** /**
* Constructor.<br> * Constructor.<br>
* Create and save a new native session instance ID and start a new inbound group session. * Create and save a new native session instance ID and start a new inbound group session.
@ -59,7 +71,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
*/ */
public OlmInboundGroupSession(String aSessionKey) throws OlmException { public OlmInboundGroupSession(String aSessionKey) throws OlmException {
if(createNewSession()) { if(createNewSession()) {
if( 0 != initInboundGroupSessionWithSessionKey(aSessionKey)) { if (0 != initInboundGroupSessionWithSessionKey(aSessionKey)) {
releaseSession();// prevent memory leak before throwing releaseSession();// prevent memory leak before throwing
throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION,OlmException.EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION); throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION,OlmException.EXCEPTION_MSG_INIT_INBOUND_GROUP_SESSION);
} }
@ -137,24 +149,24 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri
* Decrypt the message passed in parameter.<br> * Decrypt the message passed in parameter.<br>
* In case of error, null is returned and an error message description is provided in aErrorMsg. * In case of error, null is returned and an error message description is provided in aErrorMsg.
* @param aEncryptedMsg the message to be decrypted * @param aEncryptedMsg the message to be decrypted
* @param aDecryptIndex_out decrypted message index * @return the decrypted message information
* @param aErrorMsg error message description * @exception DecryptMessageException if there is an error while
* @return the decrypted message if operation succeed, null otherwise.
*/ */
public String decryptMessage(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, StringBuffer aErrorMsg) { public DecryptMessageResult decryptMessage(String aEncryptedMsg) throws DecryptMessageException {
String decryptedMessage = null; DecryptMessageResult result = new DecryptMessageResult();
// sanity check StringBuffer errorMsg = new StringBuffer();
if(null == aErrorMsg) { result.mDecryptedMessage = decryptMessageJni(aEncryptedMsg, result, errorMsg);
Log.e(LOG_TAG,"## decryptMessage(): invalid parameter - aErrorMsg=null");
} else { // check if there is an error while decrypting
aErrorMsg.setLength(0); if (0 != errorMsg.length()) {
decryptedMessage = decryptMessageJni(aEncryptedMsg, aDecryptIndex_out, aErrorMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); throw new DecryptMessageException(errorMsg.toString());
} }
return decryptedMessage;
}
private native String decryptMessageJni(String aEncryptedMsg, DecryptIndex aDecryptIndex_out, StringBuffer aErrorMsg, boolean aIsUtf8ConversionRequired);
return result;
}
private native String decryptMessageJni(String aEncryptedMsg, DecryptMessageResult aDecryptMessageResult, StringBuffer aErrorMsg);
/** /**
* Kick off the serialization mechanism. * Kick off the serialization mechanism.

View file

@ -26,17 +26,11 @@ import android.util.Log;
public class OlmManager { public class OlmManager {
private static final String LOG_TAG = "OlmManager"; private static final String LOG_TAG = "OlmManager";
private static final String SDK_OLM_VERSION = "V0.1.0_1"; private static final String SDK_OLM_VERSION = "V0.1.0_1";
/** specific flag to enable UTF-8 specific conversion for pre Marshmallow(23) android versions.<br>
* <a href="https://github.com/eclipsesource/J2V8/issues/142">NDK NewStringUTF() UTF8 issue</a>
**/
public static boolean ENABLE_STRING_UTF8_SPECIFIC_CONVERSION;
/** /**
* Constructor. * Constructor.
* @param aIsUtf8SpecificConversionEnabled true to enable JNI specific UTF-8 conversion, false otherwie
*/ */
public OlmManager(boolean aIsUtf8SpecificConversionEnabled) { public OlmManager() {
ENABLE_STRING_UTF8_SPECIFIC_CONVERSION = aIsUtf8SpecificConversionEnabled;
} }
static { static {

View file

@ -351,10 +351,10 @@ public class OlmSession extends CommonSerializeUtils implements Serializable {
* @return the decrypted message if operation succeed, null otherwise * @return the decrypted message if operation succeed, null otherwise
*/ */
public String decryptMessage(OlmMessage aEncryptedMsg) { public String decryptMessage(OlmMessage aEncryptedMsg) {
return decryptMessageJni(aEncryptedMsg, OlmManager.ENABLE_STRING_UTF8_SPECIFIC_CONVERSION); return decryptMessageJni(aEncryptedMsg);
} }
private native String decryptMessageJni(OlmMessage aEncryptedMsg, boolean aIsUtf8ConversionRequired); private native String decryptMessageJni(OlmMessage aEncryptedMsg);
/** /**
* Return true the object resources have been released.<br> * Return true the object resources have been released.<br>

View file

@ -183,7 +183,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(sessionIdentifierJni)(JNIEn
} }
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg, jboolean aIsUtf8ConversionRequired) JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptionResult, jobject aErrorMsg)
{ {
jstring decryptedMsgRetValue = 0; jstring decryptedMsgRetValue = 0;
OlmInboundGroupSession *sessionPtr = NULL; OlmInboundGroupSession *sessionPtr = NULL;
@ -204,7 +204,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
{ {
LOGE(" ## decryptMessageJni(): failure - invalid encrypted message"); LOGE(" ## decryptMessageJni(): failure - invalid encrypted message");
} }
else if (!aDecryptIndex) else if (!aDecryptionResult)
{ {
LOGE(" ## decryptMessageJni(): failure - invalid index object"); LOGE(" ## decryptMessageJni(): failure - invalid index object");
} }
@ -224,7 +224,7 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
{ {
LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM"); LOGE(" ## decryptMessageJni(): failure - encrypted message JNI allocation OOM");
} }
else if (!(indexObjJClass = env->GetObjectClass(aDecryptIndex))) else if (!(indexObjJClass = env->GetObjectClass(aDecryptionResult)))
{ {
LOGE("## decryptMessageJni(): failure - unable to get index class"); LOGE("## decryptMessageJni(): failure - unable to get index class");
} }
@ -296,28 +296,18 @@ JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *
else else
{ {
// update index // update index
env->SetLongField(aDecryptIndex, indexMsgFieldId, (jlong)messageIndex); env->SetLongField(aDecryptionResult, indexMsgFieldId, (jlong)messageIndex);
// UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) // convert to utf8
if (aIsUtf8ConversionRequired) decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength);
if (!decryptedMsgRetValue)
{ {
decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null");
if(0 == decryptedMsgRetValue)
{
LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null");
}
else
{
LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast<long unsigned int>(plaintextLength));
}
} }
else else
{ {
// update decrypted buffer size LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast<long unsigned int>(plaintextLength));
plainTextMsgPtr[plaintextLength] = static_cast<char>('\0');
LOGD(" ## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast<long unsigned int>(plaintextLength), (char*)plainTextMsgPtr);
decryptedMsgRetValue = env->NewStringUTF((const char*)plainTextMsgPtr);
} }
} }

View file

@ -34,7 +34,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv *
JNIEXPORT jint OLM_INBOUND_GROUP_SESSION_FUNC_DEF(initInboundGroupSessionWithSessionKeyJni)(JNIEnv *env, jobject thiz, jstring aSessionKey); 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(sessionIdentifierJni)(JNIEnv *env, jobject thiz);
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg, jboolean aIsUtf8ConversionRequired); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jstring aEncryptedMsg, jobject aDecryptIndex, jobject aErrorMsg);
// serialization // serialization
JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg); JNIEXPORT jstring OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeDataWithKeyJni)(JNIEnv *env, jobject thiz, jstring aKey, jobject aErrorMsg);

View file

@ -580,7 +580,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz
* @param aEncryptedMsg message to decrypt * @param aEncryptedMsg message to decrypt
* @return decrypted message if operation succeed, null otherwise * @return decrypted message if operation succeed, null otherwise
*/ */
JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg, jboolean aIsUtf8ConversionRequired) JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg)
{ {
jstring decryptedMsgRetValue = 0; jstring decryptedMsgRetValue = 0;
jclass encryptedMsgJClass = 0; jclass encryptedMsgJClass = 0;
@ -668,26 +668,15 @@ JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject t
} }
else else
{ {
// UTF-8 conversion workaround for issue on Android versions older than Marshmallow (23) decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength);
if (aIsUtf8ConversionRequired)
if (!decryptedMsgRetValue)
{ {
decryptedMsgRetValue = javaCStringToUtf8(env, plainTextMsgPtr, plaintextLength); LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null");
if(0 == decryptedMsgRetValue)
{
LOGE(" ## decryptMessageJni(): UTF-8 Conversion failure - javaCStringToUtf8() returns null");
}
else
{
LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast<long unsigned int>(plaintextLength));
}
} }
else else
{ {
// update decrypted buffer size LOGD(" ## decryptMessageJni(): UTF-8 Conversion - decrypted returnedLg=%lu OK",static_cast<long unsigned int>(plaintextLength));
plainTextMsgPtr[plaintextLength] = static_cast<char>('\0');
LOGD("## decryptMessageJni(): decrypted returnedLg=%lu plainTextMsgPtr=%s",static_cast<long unsigned int>(plaintextLength), (char*)(plainTextMsgPtr));
decryptedMsgRetValue = env->NewStringUTF((const char*)(plainTextMsgPtr));
} }
} }
} }

View file

@ -45,7 +45,7 @@ JNIEXPORT jint OLM_SESSION_FUNC_DEF(matchesInboundSessionFromIdKeyJni)(JNIEnv *e
// encrypt/decrypt // encrypt/decrypt
JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg); JNIEXPORT jint OLM_SESSION_FUNC_DEF(encryptMessageJni)(JNIEnv *env, jobject thiz, jstring aClearMsg, jobject aEncryptedMsg);
JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg, jboolean aIsUtf8ConversionRequired); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(decryptMessageJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg);
JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz); JNIEXPORT jstring OLM_SESSION_FUNC_DEF(getSessionIdentifierJni)(JNIEnv *env, jobject thiz);