diff options
Diffstat (limited to 'android/olm-sdk')
15 files changed, 293 insertions, 27 deletions
diff --git a/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmPkTest.java b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmPkTest.java index 04b2217..1577f3b 100644 --- a/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmPkTest.java +++ b/android/olm-sdk/src/androidTest/java/org/matrix/olm/OlmPkTest.java @@ -19,6 +19,8 @@ package org.matrix.olm; import android.support.test.runner.AndroidJUnit4; import android.util.Log; +import java.util.Arrays; + import org.junit.BeforeClass; import org.junit.FixMethodOrder; import org.junit.Test; @@ -91,4 +93,46 @@ public class OlmPkTest { assertTrue(mOlmPkEncryption.isReleased()); assertTrue(mOlmPkDecryption.isReleased()); } + + @Test + public void test02PrivateKey() { + try { + mOlmPkDecryption = new OlmPkDecryption(); + } catch (OlmException e) { + e.printStackTrace(); + assertTrue("OlmPkEncryption failed " + e.getMessage(), false); + } + + assertNotNull(mOlmPkDecryption); + + byte[] privateKey = { + (byte)0x77, (byte)0x07, (byte)0x6D, (byte)0x0A, + (byte)0x73, (byte)0x18, (byte)0xA5, (byte)0x7D, + (byte)0x3C, (byte)0x16, (byte)0xC1, (byte)0x72, + (byte)0x51, (byte)0xB2, (byte)0x66, (byte)0x45, + (byte)0xDF, (byte)0x4C, (byte)0x2F, (byte)0x87, + (byte)0xEB, (byte)0xC0, (byte)0x99, (byte)0x2A, + (byte)0xB1, (byte)0x77, (byte)0xFB, (byte)0xA5, + (byte)0x1D, (byte)0xB9, (byte)0x2C, (byte)0x2A + }; + + try { + mOlmPkDecryption.setPrivateKey(privateKey); + } catch (OlmException e) { + assertTrue("Exception in setPrivateKey, Exception code=" + e.getExceptionCode(), false); + } + + byte[] privateKeyCopy = null; + + try { + privateKeyCopy = mOlmPkDecryption.privateKey(); + } catch (OlmException e) { + assertTrue("Exception in privateKey, Exception code=" + e.getExceptionCode(), false); + } + + assertTrue(Arrays.equals(privateKey, privateKeyCopy)); + + mOlmPkDecryption.releaseDecryption(); + assertTrue(mOlmPkDecryption.isReleased()); + } } diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java index 26c3e60..98a3c5b 100644 --- a/android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmAccount.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; +import java.util.Arrays; import java.util.Map; /** @@ -290,9 +291,9 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { String result = null; if (null != aMessage) { + byte[] utf8String = null; try { - byte[] utf8String = aMessage.getBytes("UTF-8"); - + utf8String = aMessage.getBytes("UTF-8"); if (null != utf8String) { byte[] signedMessage = signMessageJni(utf8String); @@ -302,6 +303,10 @@ public class OlmAccount extends CommonSerializeUtils implements Serializable { } } catch (Exception e) { throw new OlmException(OlmException.EXCEPTION_CODE_ACCOUNT_SIGN_MESSAGE, e.getMessage()); + } finally { + if (null != utf8String) { + Arrays.fill(utf8String, (byte) 0); + } } } diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java index 31b5729..5b534d5 100644 --- a/android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmException.java @@ -68,6 +68,8 @@ public class OlmException extends IOException { public static final int EXCEPTION_CODE_PK_DECRYPTION_CREATION = 700; public static final int EXCEPTION_CODE_PK_DECRYPTION_GENERATE_KEY = 701; public static final int EXCEPTION_CODE_PK_DECRYPTION_DECRYPT = 702; + public static final int EXCEPTION_CODE_PK_DECRYPTION_SET_PRIVATE_KEY = 703; + public static final int EXCEPTION_CODE_PK_DECRYPTION_PRIVATE_KEY = 704; // exception human readable messages public static final String EXCEPTION_MSG_INVALID_PARAMS_DESERIALIZATION = "invalid de-serialized parameters"; diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java index b41c67a..2fc81ef 100644 --- a/android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmInboundGroupSession.java @@ -77,10 +77,16 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri Log.e(LOG_TAG, "## initInboundGroupSession(): invalid session key"); throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, "invalid session key"); } else { + byte[] sessionBuffer = null; try { + sessionBuffer = aSessionKey.getBytes("UTF-8"); mNativeId = createNewSessionJni(aSessionKey.getBytes("UTF-8"), isImported); } catch (Exception e) { throw new OlmException(OlmException.EXCEPTION_CODE_INIT_INBOUND_GROUP_SESSION, e.getMessage()); + } finally { + if (null != sessionBuffer) { + Arrays.fill(sessionBuffer, (byte) 0); + } } } } @@ -216,6 +222,7 @@ public class OlmInboundGroupSession extends CommonSerializeUtils implements Seri if (null != bytesBuffer) { result = new String(bytesBuffer, "UTF-8"); + Arrays.fill(bytesBuffer, (byte) 0); } } catch (Exception e) { Log.e(LOG_TAG, "## export() failed " + e.getMessage()); diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java index e4d4a44..55732fe 100644 --- a/android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmOutboundGroupSession.java @@ -142,7 +142,10 @@ public class OlmOutboundGroupSession extends CommonSerializeUtils implements Ser */ public String sessionKey() throws OlmException { try { - return new String(sessionKeyJni(), "UTF-8"); + byte[] sessionKeyBuffer = sessionKeyJni(); + String ret = new String(sessionKeyBuffer, "UTF-8"); + Arrays.fill(sessionKeyBuffer, (byte) 0); + return ret; } catch (Exception e) { Log.e(LOG_TAG, "## sessionKey() failed " + e.getMessage()); throw new OlmException(OlmException.EXCEPTION_CODE_OUTBOUND_GROUP_SESSION_KEY, e.getMessage()); diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkDecryption.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkDecryption.java index ea838f1..6522f70 100644 --- a/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkDecryption.java +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkDecryption.java @@ -51,6 +51,18 @@ public class OlmPkDecryption { return (0 == mNativeId); } + public String setPrivateKey(byte[] privateKey) throws OlmException { + try { + byte[] key = setPrivateKeyJni(privateKey); + return new String(key, "UTF-8"); + } catch (Exception e) { + Log.e(LOG_TAG, "## setPrivateKey(): failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_PK_DECRYPTION_SET_PRIVATE_KEY, e.getMessage()); + } + } + + private native byte[] setPrivateKeyJni(byte[] privateKey); + public String generateKey() throws OlmException { try { byte[] key = generateKeyJni(); @@ -63,19 +75,31 @@ public class OlmPkDecryption { private native byte[] generateKeyJni(); + public byte[] privateKey() throws OlmException { + try { + return privateKeyJni(); + } catch (Exception e) { + Log.e(LOG_TAG, "## privateKey(): failed " + e.getMessage()); + throw new OlmException(OlmException.EXCEPTION_CODE_PK_DECRYPTION_PRIVATE_KEY, e.getMessage()); + } + } + + private native byte[] privateKeyJni(); + public String decrypt(OlmPkMessage aMessage) throws OlmException { if (null == aMessage) { return null; } + byte[] plaintextBuffer = decryptJni(aMessage); try { - byte[] plaintextBuffer = decryptJni(aMessage); String plaintext = new String(plaintextBuffer, "UTF-8"); - Arrays.fill(plaintextBuffer, (byte) 0); return plaintext; } catch (Exception e) { Log.e(LOG_TAG, "## pkDecrypt(): failed " + e.getMessage()); throw new OlmException(OlmException.EXCEPTION_CODE_PK_DECRYPTION_DECRYPT, e.getMessage()); + } finally { + Arrays.fill(plaintextBuffer, (byte) 0); } } diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkEncryption.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkEncryption.java index a2ccf2e..01666fd 100644 --- a/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkEncryption.java +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmPkEncryption.java @@ -73,10 +73,10 @@ public class OlmPkEncryption { OlmPkMessage encryptedMsgRetValue = new OlmPkMessage(); + byte[] plaintextBuffer = null; try { - byte[] plaintextBuffer = aPlaintext.getBytes("UTF-8"); + plaintextBuffer = aPlaintext.getBytes("UTF-8"); byte[] ciphertextBuffer = encryptJni(plaintextBuffer, encryptedMsgRetValue); - Arrays.fill(plaintextBuffer, (byte) 0); if (null != ciphertextBuffer) { encryptedMsgRetValue.mCipherText = new String(ciphertextBuffer, "UTF-8"); @@ -84,6 +84,10 @@ public class OlmPkEncryption { } catch (Exception e) { Log.e(LOG_TAG, "## pkEncrypt(): failed " + e.getMessage()); throw new OlmException(OlmException.EXCEPTION_CODE_PK_ENCRYPTION_ENCRYPT, e.getMessage()); + } finally { + if (null != plaintextBuffer) { + Arrays.fill(plaintextBuffer, (byte) 0); + } } return encryptedMsgRetValue; diff --git a/android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java b/android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java index bf9ef90..250cfb1 100644 --- a/android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java +++ b/android/olm-sdk/src/main/java/org/matrix/olm/OlmUtility.java @@ -23,6 +23,7 @@ import android.util.Log; import org.json.JSONObject; import java.security.SecureRandom; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -81,17 +82,23 @@ public class OlmUtility { */ public void verifyEd25519Signature(String aSignature, String aFingerprintKey, String aMessage) throws OlmException { String errorMessage; + byte[] messageBuffer = null; try { if (TextUtils.isEmpty(aSignature) || TextUtils.isEmpty(aFingerprintKey) || TextUtils.isEmpty(aMessage)) { Log.e(LOG_TAG, "## verifyEd25519Signature(): invalid input parameters"); errorMessage = "JAVA sanity check failure - invalid input parameters"; } else { - errorMessage = verifyEd25519SignatureJni(aSignature.getBytes("UTF-8"), aFingerprintKey.getBytes("UTF-8"), aMessage.getBytes("UTF-8")); + messageBuffer = aMessage.getBytes("UTF-8"); + errorMessage = verifyEd25519SignatureJni(aSignature.getBytes("UTF-8"), aFingerprintKey.getBytes("UTF-8"), messageBuffer); } } catch (Exception e) { Log.e(LOG_TAG, "## verifyEd25519Signature(): failed " + e.getMessage()); errorMessage = e.getMessage(); + } finally { + if (messageBuffer != null) { + Arrays.fill(messageBuffer, (byte) 0); + } } if (!TextUtils.isEmpty(errorMessage)) { @@ -119,10 +126,16 @@ public class OlmUtility { String hashRetValue = null; if (null != aMessageToHash) { + byte[] messageBuffer = null; try { - hashRetValue = new String(sha256Jni(aMessageToHash.getBytes("UTF-8")), "UTF-8"); + messageBuffer = aMessageToHash.getBytes("UTF-8"); + hashRetValue = new String(sha256Jni(messageBuffer), "UTF-8"); } catch (Exception e) { Log.e(LOG_TAG, "## sha256(): failed " + e.getMessage()); + } finally { + if (null != messageBuffer) { + Arrays.fill(messageBuffer, (byte) 0); + } } } diff --git a/android/olm-sdk/src/main/jni/olm_account.cpp b/android/olm-sdk/src/main/jni/olm_account.cpp index 40081ac..00b1460 100644 --- a/android/olm-sdk/src/main/jni/olm_account.cpp +++ b/android/olm-sdk/src/main/jni/olm_account.cpp @@ -528,6 +528,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi const char* errorMessage = NULL; jbyteArray pickledDataRetValue = 0; jbyte* keyPtr = NULL; + jboolean keyIsCopied = JNI_FALSE; OlmAccount* accountPtr = NULL; LOGD("## serializeJni(): IN"); @@ -542,7 +543,7 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi LOGE(" ## serializeJni(): failure - invalid account ptr"); errorMessage = "invalid account ptr"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, NULL))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyIsCopied))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "keyPtr JNI allocation OOM"; @@ -586,6 +587,9 @@ JNIEXPORT jbyteArray OLM_ACCOUNT_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi // free alloc if (keyPtr) { + if (keyIsCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } @@ -610,6 +614,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, OlmAccount* accountPtr = NULL; jbyte* keyPtr = NULL; + jboolean keyIsCopied = JNI_FALSE; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); @@ -629,7 +634,7 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, LOGE(" ## deserializeJni(): failure - account failure OOM"); errorMessage = "account failure OOM"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyIsCopied))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "keyPtr JNI allocation OOM"; @@ -665,6 +670,9 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, // free alloc if (keyPtr) { + if (keyIsCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } @@ -684,4 +692,4 @@ JNIEXPORT jlong OLM_ACCOUNT_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, } return (jlong)(intptr_t)accountPtr; -}
\ No newline at end of file +} diff --git a/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp b/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp index 114b7cd..ae9ecf1 100644 --- a/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +++ b/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp @@ -62,6 +62,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * const char* errorMessage = NULL; OlmInboundGroupSession* sessionPtr = NULL; jbyte* sessionKeyPtr = NULL; + jboolean sessionWasCopied = JNI_FALSE; size_t sessionSize = olm_inbound_group_session_size(); LOGD("## createNewSessionJni(): inbound group session IN"); @@ -81,7 +82,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * LOGE(" ## createNewSessionJni(): failure - invalid aSessionKey"); errorMessage = "invalid aSessionKey"; } - else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, 0))) + else if (!(sessionKeyPtr = env->GetByteArrayElements(aSessionKeyBuffer, &sessionWasCopied))) { LOGE(" ## createNewSessionJni(): failure - session key JNI allocation OOM"); errorMessage = "Session key JNI allocation OOM"; @@ -119,6 +120,9 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(createNewSessionJni)(JNIEnv * if (sessionKeyPtr) { + if (sessionWasCopied) { + memset(sessionKeyPtr, 0, (size_t)env->GetArrayLength(aSessionKeyBuffer)); + } env->ReleaseByteArrayElements(aSessionKeyBuffer, sessionKeyPtr, JNI_ABORT); } @@ -474,6 +478,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en jbyteArray pickledDataRet = 0; jbyte* keyPtr = NULL; + jboolean keyWasCopied = JNI_FALSE; OlmInboundGroupSession* sessionPtr = getInboundGroupSessionInstanceId(env, thiz); LOGD("## inbound group session serializeJni(): IN"); @@ -488,7 +493,7 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en LOGE(" ## serializeJni(): failure - invalid key"); errorMessage = "invalid key"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyWasCopied))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "keyPtr JNI allocation OOM"; @@ -533,6 +538,9 @@ JNIEXPORT jbyteArray OLM_INBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *en // free alloc if (keyPtr) { + if (keyWasCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } @@ -558,6 +566,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, OlmInboundGroupSession* sessionPtr = NULL; size_t sessionSize = olm_inbound_group_session_size(); jbyte* keyPtr = NULL; + jboolean keyWasCopied = JNI_FALSE; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); @@ -582,7 +591,7 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, LOGE(" ## deserializeJni(): failure - serialized data"); errorMessage = "serialized data"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyWasCopied))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "keyPtr JNI allocation OOM"; @@ -620,6 +629,9 @@ JNIEXPORT jlong OLM_INBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, // free alloc if (keyPtr) { + if (keyWasCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } diff --git a/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp b/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp index b11c474..a22122a 100644 --- a/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +++ b/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp @@ -387,6 +387,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e jbyteArray returnValue = 0; jbyte* keyPtr = NULL; + jboolean keyWasCopied = JNI_FALSE; OlmOutboundGroupSession* sessionPtr = NULL; LOGD("## outbound group session serializeJni(): IN"); @@ -401,7 +402,7 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e LOGE(" ## serializeJni(): failure - invalid key"); errorMessage = "invalid key"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyWasCopied))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "keyPtr JNI allocation OOM"; @@ -446,6 +447,9 @@ JNIEXPORT jbyteArray OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(serializeJni)(JNIEnv *e // free alloc if (keyPtr) { + if (keyWasCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } @@ -471,6 +475,7 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, OlmOutboundGroupSession* sessionPtr = NULL; jbyte* keyPtr = NULL; + jboolean keyWasCopied = JNI_FALSE; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); @@ -495,7 +500,7 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, LOGE(" ## deserializeJni(): failure - serialized data"); errorMessage = "invalid serialized data"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyWasCopied))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "keyPtr JNI allocation OOM"; @@ -532,6 +537,9 @@ JNIEXPORT jlong OLM_OUTBOUND_GROUP_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, // free alloc if (keyPtr) { + if (keyWasCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } diff --git a/android/olm-sdk/src/main/jni/olm_pk.cpp b/android/olm-sdk/src/main/jni/olm_pk.cpp index bc78079..eff57a5 100644 --- a/android/olm-sdk/src/main/jni/olm_pk.cpp +++ b/android/olm-sdk/src/main/jni/olm_pk.cpp @@ -364,6 +364,79 @@ JNIEXPORT void OLM_PK_DECRYPTION_FUNC_DEF(releasePkDecryptionJni)(JNIEnv *env, j } } +JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(setPrivateKeyJni)(JNIEnv *env, jobject thiz, jbyteArray key) +{ + jbyteArray publicKeyRet = 0; + jbyte *keyPtr = NULL; + jboolean keyWasCopied = JNI_FALSE; + + const char* errorMessage = NULL; + + OlmPkDecryption* decryptionPtr = getPkDecryptionInstanceId(env, thiz); + + if (!decryptionPtr) + { + LOGE(" ## pkSetPrivateKeyJni(): failure - invalid Decryption ptr=NULL"); + } + else if (!key) + { + LOGE(" ## pkSetPrivateKeyJni(): failure - invalid key"); + errorMessage = "invalid key"; + } + else if (!(keyPtr = env->GetByteArrayElements(key, &keyWasCopied))) + { + LOGE(" ## pkSetPrivateKeyJni(): failure - key JNI allocation OOM"); + errorMessage = "key JNI allocation OOM"; + } + else + { + size_t publicKeyLength = olm_pk_key_length(); + uint8_t *publicKeyPtr = NULL; + size_t keyLength = (size_t)env->GetArrayLength(key); + if (!(publicKeyPtr = (uint8_t*)malloc(publicKeyLength))) + { + LOGE("## pkSetPrivateKeyJni(): failure - public key JNI allocation OOM"); + errorMessage = "public key JNI allocation OOM"; + } + else + { + size_t returnValue = olm_pk_key_from_private( + decryptionPtr, + publicKeyPtr, publicKeyLength, + keyPtr, keyLength + ); + if (returnValue == olm_error()) + { + errorMessage = olm_pk_decryption_last_error(decryptionPtr); + LOGE(" ## pkSetPrivateKeyJni(): failure - olm_pk_key_from_private Msg=%s", errorMessage); + } + else + { + publicKeyRet = env->NewByteArray(publicKeyLength); + env->SetByteArrayRegion( + publicKeyRet, 0, publicKeyLength, (jbyte*)publicKeyPtr + ); + } + } + } + + if (keyPtr) + { + if (keyWasCopied) + { + memset(keyPtr, 0, (size_t)env->GetArrayLength(key)); + } + env->ReleaseByteArrayElements(key, keyPtr, JNI_ABORT); + } + + if (errorMessage) + { + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return publicKeyRet; +} + JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(generateKeyJni)(JNIEnv *env, jobject thiz) { size_t randomLength = olm_pk_private_key_length(); @@ -414,16 +487,61 @@ JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(generateKeyJni)(JNIEnv *env, job if (errorMessage) { - // release the allocated data - if (decryptionPtr) + env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); + } + + return publicKeyRet; +} + +JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(privateKeyJni)(JNIEnv *env, jobject thiz) +{ + jbyteArray privateKeyRet = 0; + + const char* errorMessage = NULL; + + OlmPkDecryption* decryptionPtr = getPkDecryptionInstanceId(env, thiz); + + if (!decryptionPtr) + { + LOGE(" ## pkPrivateKeyJni(): failure - invalid Decryption ptr=NULL"); + } + else + { + size_t privateKeyLength = olm_pk_private_key_length(); + uint8_t *privateKeyPtr = NULL; + if (!(privateKeyPtr = (uint8_t*)malloc(privateKeyLength))) { - olm_clear_pk_decryption(decryptionPtr); - free(decryptionPtr); + LOGE("## pkPrivateKeyJni(): failure - private key JNI allocation OOM"); + errorMessage = "private key JNI allocation OOM"; + } + else + { + size_t returnValue = olm_pk_get_private_key( + decryptionPtr, + privateKeyPtr, privateKeyLength + ); + if (returnValue == olm_error()) + { + errorMessage = olm_pk_decryption_last_error(decryptionPtr); + LOGE(" ## pkPrivateKeyJni(): failure - olm_pk_get_private_key Msg=%s", errorMessage); + } + else + { + privateKeyRet = env->NewByteArray(privateKeyLength); + env->SetByteArrayRegion( + privateKeyRet, 0, privateKeyLength, (jbyte*)privateKeyPtr + ); + memset(privateKeyPtr, 0, privateKeyLength); + } } + } + + if (errorMessage) + { env->ThrowNew(env->FindClass("java/lang/Exception"), errorMessage); } - return publicKeyRet; + return privateKeyRet; } JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(decryptJni)( diff --git a/android/olm-sdk/src/main/jni/olm_pk.h b/android/olm-sdk/src/main/jni/olm_pk.h index 984c5f8..5f45462 100644 --- a/android/olm-sdk/src/main/jni/olm_pk.h +++ b/android/olm-sdk/src/main/jni/olm_pk.h @@ -35,7 +35,9 @@ JNIEXPORT jbyteArray OLM_PK_ENCRYPTION_FUNC_DEF(encryptJni)(JNIEnv *env, jobject JNIEXPORT jlong OLM_PK_DECRYPTION_FUNC_DEF(createNewPkDecryptionJni)(JNIEnv *env, jobject thiz); JNIEXPORT void OLM_PK_DECRYPTION_FUNC_DEF(releasePkDecryptionJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(setPrivateKeyJni)(JNIEnv *env, jobject thiz, jbyteArray key); JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(generateKeyJni)(JNIEnv *env, jobject thiz); +JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(privateKeyJni)(JNIEnv *env, jobject thiz); JNIEXPORT jbyteArray OLM_PK_DECRYPTION_FUNC_DEF(decryptJni)(JNIEnv *env, jobject thiz, jobject aEncryptedMsg); #ifdef __cplusplus diff --git a/android/olm-sdk/src/main/jni/olm_session.cpp b/android/olm-sdk/src/main/jni/olm_session.cpp index b9db286..15ad4fe 100644 --- a/android/olm-sdk/src/main/jni/olm_session.cpp +++ b/android/olm-sdk/src/main/jni/olm_session.cpp @@ -810,6 +810,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi jbyteArray returnValue = 0; jbyte* keyPtr = NULL; + jboolean keyWasCopied = JNI_FALSE; OlmSession* sessionPtr = getSessionInstanceId(env, thiz); LOGD("## serializeJni(): IN"); @@ -824,7 +825,7 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi LOGE(" ## serializeJni(): failure - invalid key"); errorMessage = "invalid key"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyWasCopied))) { LOGE(" ## serializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "ikeyPtr JNI allocation OOM"; @@ -869,6 +870,9 @@ JNIEXPORT jbyteArray OLM_SESSION_FUNC_DEF(serializeJni)(JNIEnv *env, jobject thi // free alloc if (keyPtr) { + if (keyWasCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } @@ -892,6 +896,7 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, const char* errorMessage = NULL; OlmSession* sessionPtr = initializeSessionMemory(); jbyte* keyPtr = NULL; + jboolean keyWasCopied = JNI_FALSE; jbyte* pickledPtr = NULL; LOGD("## deserializeJni(): IN"); @@ -911,7 +916,7 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, LOGE(" ## deserializeJni(): failure - serialized data"); errorMessage = "serialized data"; } - else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, 0))) + else if (!(keyPtr = env->GetByteArrayElements(aKeyBuffer, &keyWasCopied))) { LOGE(" ## deserializeJni(): failure - keyPtr JNI allocation OOM"); errorMessage = "keyPtr JNI allocation OOM"; @@ -947,6 +952,9 @@ JNIEXPORT jlong OLM_SESSION_FUNC_DEF(deserializeJni)(JNIEnv *env, jobject thiz, // free alloc if (keyPtr) { + if (keyWasCopied) { + memset(keyPtr, 0, (size_t)env->GetArrayLength(aKeyBuffer)); + } env->ReleaseByteArrayElements(aKeyBuffer, keyPtr, JNI_ABORT); } diff --git a/android/olm-sdk/src/main/jni/olm_utility.cpp b/android/olm-sdk/src/main/jni/olm_utility.cpp index f6fe719..da27eda 100644 --- a/android/olm-sdk/src/main/jni/olm_utility.cpp +++ b/android/olm-sdk/src/main/jni/olm_utility.cpp @@ -90,6 +90,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j jbyte* signaturePtr = NULL; jbyte* keyPtr = NULL; jbyte* messagePtr = NULL; + jboolean messageWasCopied = JNI_FALSE; LOGD("## verifyEd25519SignatureJni(): IN"); @@ -109,7 +110,7 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j { LOGE(" ## verifyEd25519SignatureJni(): failure - key JNI allocation OOM"); } - else if (!(messagePtr = env->GetByteArrayElements(aMessageBuffer, 0))) + else if (!(messagePtr = env->GetByteArrayElements(aMessageBuffer, &messageWasCopied))) { LOGE(" ## verifyEd25519SignatureJni(): failure - message JNI allocation OOM"); } @@ -152,6 +153,9 @@ JNIEXPORT jstring OLM_UTILITY_FUNC_DEF(verifyEd25519SignatureJni)(JNIEnv *env, j if (messagePtr) { + if (messageWasCopied) { + memset(messagePtr, 0, (size_t)env->GetArrayLength(aMessageBuffer)); + } env->ReleaseByteArrayElements(aMessageBuffer, messagePtr, JNI_ABORT); } @@ -171,6 +175,7 @@ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, OlmUtility* utilityPtr = getUtilityInstanceId(env, thiz); jbyte* messagePtr = NULL; + jboolean messageWasCopied = JNI_FALSE; LOGD("## sha256Jni(): IN"); @@ -182,7 +187,7 @@ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, { LOGE(" ## sha256Jni(): failure - invalid message parameters "); } - else if(!(messagePtr = env->GetByteArrayElements(aMessageToHashBuffer, 0))) + else if(!(messagePtr = env->GetByteArrayElements(aMessageToHashBuffer, &messageWasCopied))) { LOGE(" ## sha256Jni(): failure - message JNI allocation OOM"); } @@ -221,8 +226,11 @@ JNIEXPORT jbyteArray OLM_UTILITY_FUNC_DEF(sha256Jni)(JNIEnv *env, jobject thiz, if (messagePtr) { + if (messageWasCopied) { + memset(messagePtr, 0, (size_t)env->GetArrayLength(aMessageToHashBuffer)); + } env->ReleaseByteArrayElements(aMessageToHashBuffer, messagePtr, JNI_ABORT); } return sha256Ret; -}
\ No newline at end of file +} |